PageSourceSearch

https://www.pentair.com/etc.clientlibs/settings/wcm/designs/pentair/clientlib-all.min.js

js pentair.com collected 2026-09-24 08:48:16 UTC 1,741,739 bytes, 29,643 lines download raw bytes

vendor: 16,316 bytes, lines 1-3
1/* Chosen v1.8.2 | (c) 2011-2017 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
2
3(function(){var t,e,s,i,n=function(t,e){return function(){return t.apply(e,arguments)}},r=function(t,e){function s(){this.constructor=t}for(var i in e)o.call(e,i)&&(t[i]=e[i]);return s.prototype=e.prototype,t.prototype=new s,t.__super__=e.prototype,t},o={}.hasOwnProperty;(i=function(){function t(){this.options_index=0,this.parsed=[]}return t.prototype.add_node=function(t){return"OPTGROUP"===t.nodeName.toUpperCase()?this.add_group(t):this.add_option(t)},t.prototype.add_group=function(t){var e,s,i,n,r,o;for(e=this.parsed.length,this.parsed.push({array_index:e,group:!0,label:t.label,title:t.title?t.title:void 0,children:0,disabled:t.disabled,classes:t.className}),o=[],s=0,i=(r=t.childNodes).length;s<i;s++)n=r[s],o.push(this.add_option(n,e,t.disabled));return o},t.prototype.add_option=function(t,e,s){if("OPTION"===t.nodeName.toUpperCase())return""!==t.text?(null!=e&&(this.parsed[e].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:t.value,text:t.text,html:t.innerHTML,title:t.title?t.title:void 0,selected:t.selected,disabled:!0===s?s:t.disabled,group_array_index:e,group_label:null!=e?this.parsed[e].label:null,classes:t.className,style:t.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1},t}()).select_to_array=function(t){var e,s,n,r,o;for(r=new i,s=0,n=(o=t.childNodes).length;s<n;s++)e=o[s],r.add_node(e);return r.parsed},e=function(){function t(e,s){this.form_field=e,this.options=null!=s?s:{},this.label_click_handler=n(this.label_click_handler,this),t.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers(),this.on_ready())}return t.prototype.set_default_values=function(){return this.click_test_action=function(t){return function(e){return t.test_active_click(e)}}(this),this.activate_action=function(t){return function(e){return t.activate_field(e)}}(this),this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.is_rtl=this.options.rtl||/\bchosen-rtl\b/.test(this.form_field.className),this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text&&this.options.allow_single_deselect,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null==this.options.enable_split_word_search||this.options.enable_split_word_search,this.group_search=null==this.options.group_search||this.options.group_search,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null==this.options.single_backstroke_delete||this.options.single_backstroke_delete,this.max_selected_options=this.options.max_selected_options||Infinity,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null==this.options.display_selected_options||this.options.display_selected_options,this.display_disabled_options=null==this.options.display_disabled_options||this.options.display_disabled_options,this.include_group_label_in_selected=this.options.include_group_label_in_selected||!1,this.max_shown_results=this.options.max_shown_results||Number.POSITIVE_INFINITY,this.case_sensitive_search=this.options.case_sensitive_search||!1,this.hide_results_on_select=null==this.options.hide_results_on_select||this.options.hide_results_on_select},t.prototype.set_default_text=function(){return this.form_field.getAttribute("data-placeholder")?this.default_text=this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.default_text=this.options.placeholder_text_multiple||this.options.placeholder_text||t.default_multiple_text:this.default_text=this.options.placeholder_text_single||this.options.placeholder_text||t.default_single_text,this.default_text=this.escape_html(this.default_text),this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||t.default_no_result_text},t.prototype.choice_label=function(t){return this.include_group_label_in_selected&&null!=t.group_label?"<b class='group-name'>"+t.group_label+"</b>"+t.html:t.html},t.prototype.mouse_enter=function(){return this.mouse_on_container=!0},t.prototype.mouse_leave=function(){return this.mouse_on_container=!1},t.prototype.input_focus=function(t){if(this.is_multiple){if(!this.active_field)return setTimeout(function(t){return function(){return t.container_mousedown()}}(this),50)}else if(!this.active_field)return this.activate_field()},t.prototype.input_blur=function(t){if(!this.mouse_on_container)return this.active_field=!1,setTimeout(function(t){return function(){return t.blur_test()}}(this),100)},t.prototype.label_click_handler=function(t){return this.is_multiple?this.container_mousedown(t):this.activate_field()},t.prototype.results_option_build=function(t){var e,s,i,n,r,o,h;for(e="",h=0,n=0,r=(o=this.results_data).length;n<r&&(s=o[n],i="",""!==(i=s.group?this.result_add_group(s):this.result_add_option(s))&&(h++,e+=i),(null!=t?t.first:void 0)&&(s.selected&&this.is_multiple?this.choice_build(s):s.selected&&!this.is_multiple&&this.single_set_selected_text(this.choice_label(s))),!(h>=this.max_shown_results));n++);return e},t.prototype.result_add_option=function(t){var e,s;return t.search_match&&this.include_option_in_results(t)?(e=[],t.disabled||t.selected&&this.is_multiple||e.push("active-result"),!t.disabled||t.selected&&this.is_multiple||e.push("disabled-result"),t.selected&&e.push("result-selected"),null!=t.group_array_index&&e.push("group-option"),""!==t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.style.cssText=t.style,s.setAttribute("data-option-array-index",t.array_index),s.innerHTML=t.highlighted_html||t.html,t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.result_add_group=function(t){var e,s;return(t.search_match||t.group_match)&&t.active_options>0?((e=[]).push("group-result"),t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.innerHTML=t.highlighted_html||this.escape_html(t.label),t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.results_update_field=function(){if(this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing)return this.winnow_results()},t.prototype.reset_single_select_options=function(){var t,e,s,i,n;for(n=[],t=0,e=(s=this.results_data).length;t<e;t++)(i=s[t]).selected?n.push(i.selected=!1):n.push(void 0);return n},t.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},t.prototype.results_search=function(t){return this.results_showing?this.winnow_results():this.results_show()},t.prototype.winnow_results=function(){var t,e,s,i,n,r,o,h,l,c,_,a,u,d,p;for(this.no_results_clear(),c=0,t=(o=this.get_search_text()).replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),l=this.get_search_regex(t),s=0,i=(h=this.results_data).length;s<i;s++)(n=h[s]).search_match=!1,_=null,a=null,n.highlighted_html="",this.include_option_in_results(n)&&(n.group&&(n.group_match=!1,n.active_options=0),null!=n.group_array_index&&this.results_data[n.group_array_index]&&(0===(_=this.results_data[n.group_array_index]).active_options&&_.search_match&&(c+=1),_.active_options+=1),p=n.group?n.label:n.text,n.group&&!this.group_search||(a=this.search_string_match(p,l),n.search_match=null!=a,n.search_match&&!n.group&&(c+=1),n.search_match?(o.length&&(u=a.index,r=p.slice(0,u),e=p.slice(u,u+o.length),d=p.slice(u+o.length),n.highlighted_html=this.escape_html(r)+"<em>"+this.escape_html(e)+"</em>"+this.escape_html(d)),null!=_&&(_.group_match=!0)):null!=n.group_array_index&&this.results_data[n.group_array_index].search_match&&(n.search_match=!0)));return this.result_clear_highlight(),c<1&&o.length?(this.update_results_content(""),this.no_results(o)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},t.prototype.get_search_regex=function(t){var e,s;return s=this.search_contains?t:"(^|\\s|\\b)"+t+"[^\\s]*",this.enable_split_word_search||this.search_contains||(s="^"+s),e=this.case_sensitive_search?"":"i",new RegExp(s,e)},t.prototype.search_string_match=function(t,e){var s;return s=e.exec(t),!this.search_contains&&(null!=s?s[1]:void 0)&&(s.index+=1),s},t.prototype.choices_count=function(){var t,e,s;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,t=0,e=(s=this.form_field.options).length;t<e;t++)s[t].selected&&(this.selected_option_count+=1);return this.selected_option_count},t.prototype.choices_click=function(t){if(t.preventDefault(),this.activate_field(),!this.results_showing&&!this.is_disabled)return this.results_show()},t.prototype.keydown_checker=function(t){var e,s;switch(s=null!=(e=t.which)?e:t.keyCode,this.search_field_scale(),8!==s&&this.pending_backstroke&&this.clear_backstroke(),s){case 8:this.backstroke_length=this.get_search_field_value().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(t),this.mouse_on_container=!1;break;case 13:case 27:this.results_showing&&t.preventDefault();break;case 32:this.disable_search&&t.preventDefault();break;case 38:t.preventDefault(),this.keyup_arrow();break;case 40:t.preventDefault(),this.keydown_arrow()}},t.prototype.keyup_checker=function(t){var e,s;switch(s=null!=(e=t.which)?e:t.keyCode,this.search_field_scale(),s){case 8:this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0?this.keydown_backstroke():this.pending_backstroke||(this.result_clear_highlight(),this.results_search());break;case 13:t.preventDefault(),this.results_showing&&this.result_select(t);break;case 27:this.results_showing&&this.results_hide();break;case 9:case 16:case 17:case 18:case 38:case 40:case 91:break;default:this.results_search()}},t.prototype.clipboard_event_checker=function(t){if(!this.is_disabled)return setTimeout(function(t){return function(){return t.results_search()}}(this),50)},t.prototype.container_width=function(){return null!=this.options.width?this.options.width:this.form_field.offsetWidth+"px"},t.prototype.include_option_in_results=function(t){return!(this.is_multiple&&!this.display_selected_options&&t.selected)&&(!(!this.display_disabled_options&&t.disabled)&&!t.empty)},t.prototype.search_results_touchstart=function(t){return this.touch_started=!0,this.search_results_mouseover(t)},t.prototype.search_results_touchmove=function(t){return this.touch_started=!1,this.search_results_mouseout(t)},t.prototype.search_results_touchend=function(t){if(this.touch_started)return this.search_results_mouseup(t)},t.prototype.outerHTML=function(t){var e;return t.outerHTML?t.outerHTML:((e=document.createElement("div")).appendChild(t),e.innerHTML)},t.prototype.get_single_html=function(){return'<a class="chosen-single chosen-default">\n  <span>'+this.default_text+'</span>\n  <div><b></b></div>\n</a>\n<div class="chosen-drop">\n  <div class="chosen-search">\n    <input class="chosen-search-input" aria-label="Chosen Search" type="text" autocomplete="off" />\n  </div>\n  <ul class="chosen-results"></ul>\n</div>'},t.prototype.get_multi_html=function(){return'<ul class="chosen-choices">\n  <li class="search-field">\n    <input class="chosen-search-input" type="text" autocomplete="off" value="'+this.default_text+'" />\n  </li>\n</ul>\n<div class="chosen-drop">\n  <ul class="chosen-results"></ul>\n</div>'},t.prototype.get_no_results_html=function(t){return'<li class="no-results">\n  '+this.results_none_found+" <span>"+this.escape_html(t)+"</span>\n</li>"},t.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!(/iP(od|ad|hone)/i.test(window.navigator.userAgent)||/IEMobile/i.test(window.navigator.userAgent)||/Windows Phone/i.test(window.navigator.userAgent)||/BlackBerry/i.test(window.navigator.userAgent)||/BB10/i.test(window.navigator.userAgent)||/Android.*Mobile/i.test(window.navigator.userAgent))},t.default_multiple_text="Select Some Options",t.default_single_text="Select an Option",t.default_no_result_text="No results match",t}(),(t=jQuery).fn.extend({chosen:function(i){return e.browser_is_supported()?this.each(function(e){var n,r;r=(n=t(this)).data("chosen"),"destroy"!==i?r instanceof s||n.data("chosen",new s(this,i)):r instanceof s&&r.destroy()}):this}}),s=function(s){function n(){return n.__super__.constructor.apply(this,arguments)}return r(n,e),n.prototype.setup=function(){return this.form_field_jq=t(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex},n.prototype.set_up_html=function(){var e,s;return(e=["chosen-container"]).push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&e.push(this.form_field.className),this.is_rtl&&e.push("chosen-rtl"),s={"class":e.join(" "),title:this.form_field.title},this.form_field.id.length&&(s.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=t("<div />",s),this.container.width(this.container_width()),this.is_multiple?this.container.html(this.get_multi_html()):this.container.html(this.get_single_html()),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior()},n.prototype.on_ready=function(){return this.form_field_jq.trigger("chosen:ready",{chosen:this})},n.prototype.register_observers=function(){return this.container.on("touchstart.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("touchend.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mousedown.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("mouseup.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mouseenter.chosen",function(t){return function(e){t.mouse_enter(e)}}(this)),this.container.on("mouseleave.chosen",function(t){return function(e){t.mouse_leave(e)}}(this)),this.search_results.on("mouseup.chosen",function(t){return function(e){t.search_results_mouseup(e)}}(this)),this.search_results.on("mouseover.chosen",function(t){return function(e){t.search_results_mouseover(e)}}(this)),this.search_results.on("mouseout.chosen",function(t){return function(e){t.search_results_mouseout(e)}}(this)),this.search_results.on("mousewheel.chosen DOMMouseScroll.chosen",function(t){return function(e){t.search_results_mousewheel(e)}}(this)),this.search_results.on("touchstart.chosen",function(t){return function(e){t.search_results_touchstart(e)}}(this)),this.search_results.on("touchmove.chosen",function(t){return function(e){t.search_results_touchmove(e)}}(this)),this.search_results.on("touchend.chosen",function(t){return function(e){t.search_results_touchend(e)}}(this)),this.form_field_jq.on("chosen:updated.chosen",function(t){return function(e){t.results_update_field(e)}}(this)),this.form_field_jq.on("chosen:activate.chosen",function(t){return function(e){t.activate_field(e)}}(this)),this.form_field_jq.on("chosen:open.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.form_field_jq.on("chosen:close.chosen",function(t){return function(e){t.close_field(e)}}(this)),this.search_field.on("blur.chosen",function(t){return function(e){t.input_blur(e)}}(this)),this.search_field.on("keyup.chosen",function(t){return function(e){t.ke
3yup_checker(e)}}(this)),this.search_field.on("keydown.chosen",function(t){return function(e){t.keydown_checker(e)}}(this)),this.search_field.on("focus.chosen",function(t){return function(e){t.input_focus(e)}}(this)),this.search_field.on("cut.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.search_field.on("paste.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.is_multiple?this.search_choices.on("click.chosen",function(t){return function(e){t.choices_click(e)}}(this)):this.container.on("click.chosen",function(t){t.preventDefault()})},n.prototype.destroy=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.form_field_label.length>0&&this.form_field_label.off("click.chosen"),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},n.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field.disabled||this.form_field_jq.parents("fieldset").is(":disabled"),this.container.toggleClass("chosen-disabled",this.is_disabled),this.search_field[0].disabled=this.is_disabled,this.is_multiple||this.selected_item.off("focus.chosen",this.activate_field),this.is_disabled?this.close_field():this.is_multiple?void 0:this.selected_item.on("focus.chosen",this.activate_field)},n.prototype.container_mousedown=function(e){var s;if(!this.is_disabled)return!e||"mousedown"!==(s=e.type)&&"touchstart"!==s||this.results_showing||e.preventDefault(),null!=e&&t(e.target).hasClass("search-choice-close")?void 0:(this.active_field?this.is_multiple||!e||t(e.target)[0]!==this.selected_item[0]&&!t(e.target).parents("a.chosen-single").length||(e.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),t(this.container[0].ownerDocument).on("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},n.prototype.container_mouseup=function(t){if("ABBR"===t.target.nodeName&&!this.is_disabled)return this.results_reset(t)},n.prototype.search_results_mousewheel=function(t){var e;if(t.originalEvent&&(e=t.originalEvent.deltaY||-t.originalEvent.wheelDelta||t.originalEvent.detail),null!=e)return t.preventDefault(),"DOMMouseScroll"===t.type&&(e*=40),this.search_results.scrollTop(e+this.search_results.scrollTop())},n.prototype.blur_test=function(t){if(!this.active_field&&this.container.hasClass("chosen-container-active"))return this.close_field()},n.prototype.close_field=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale(),this.search_field.blur()},n.prototype.activate_field=function(){if(!this.is_disabled)return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},n.prototype.test_active_click=function(e){var s;return(s=t(e.target).closest(".chosen-container")).length&&this.container[0]===s[0]?this.active_field=!0:this.close_field()},n.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=i.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},n.prototype.result_do_highlight=function(t){var e,s,i,n,r;if(t.length){if(this.result_clear_highlight(),this.result_highlight=t,this.result_highlight.addClass("highlighted"),i=parseInt(this.search_results.css("maxHeight"),10),r=this.search_results.scrollTop(),n=i+r,s=this.result_highlight.position().top+this.search_results.scrollTop(),(e=s+this.result_highlight.outerHeight())>=n)return this.search_results.scrollTop(e-i>0?e-i:0);if(s<r)return this.search_results.scrollTop(s)}},n.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},n.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.container.addClass("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.get_search_field_value()),this.winnow_results(),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this}))},n.prototype.update_results_content=function(t){return this.search_results.html(t)},n.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},n.prototype.set_tab_index=function(t){var e;if(this.form_field.tabIndex)return e=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=e},n.prototype.set_label_behavior=function(){if(this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=t("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0)return this.form_field_label.on("click.chosen",this.label_click_handler)},n.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},n.prototype.search_results_mouseup=function(e){var s;if((s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first()).length)return this.result_highlight=s,this.result_select(e),this.search_field.focus()},n.prototype.search_results_mouseover=function(e){var s;if(s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first())return this.result_do_highlight(s)},n.prototype.search_results_mouseout=function(e){if(t(e.target).hasClass("active-result")||t(e.target).parents(".active-result").first())return this.result_clear_highlight()},n.prototype.choice_build=function(e){var s,i;return s=t("<li />",{"class":"search-choice"}).html("<span>"+this.choice_label(e)+"</span>"),e.disabled?s.addClass("search-choice-disabled"):((i=t("<a />",{"class":"search-choice-close","data-option-array-index":e.array_index})).on("click.chosen",function(t){return function(e){return t.choice_destroy_link_click(e)}}(this)),s.append(i)),this.search_container.before(s)},n.prototype.choice_destroy_link_click=function(e){if(e.preventDefault(),e.stopPropagation(),!this.is_disabled)return this.choice_destroy(t(e.target))},n.prototype.choice_destroy=function(t){if(this.result_deselect(t[0].getAttribute("data-option-array-index")))return this.active_field?this.search_field.focus():this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.get_search_field_value().length<1&&this.results_hide(),t.parents("li").first().remove(),this.search_field_scale()},n.prototype.results_reset=function(){if(this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.trigger_form_field_change(),this.active_field)return this.results_hide()},n.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},n.prototype.result_select=function(t){var e,s;if(this.result_highlight)return e=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?e.removeClass("active-result"):this.reset_single_select_options(),e.addClass("result-selected"),s=this.results_data[e[0].getAttribute("data-option-array-index")],s.selected=!0,this.form_field.options[s.options_index].selected=!0,this.selected_option_count=null,this.search_field.val(""),this.is_multiple?this.choice_build(s):this.single_set_selected_text(this.choice_label(s)),this.is_multiple&&(!this.hide_results_on_select||t.metaKey||t.ctrlKey)?this.winnow_results():(this.results_hide(),this.show_search_field_default()),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.trigger_form_field_change({selected:this.form_field.options[s.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,t.preventDefault(),this.search_field_scale())},n.prototype.single_set_selected_text=function(t){return null==t&&(t=this.default_text),t===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").html(t)},n.prototype.result_deselect=function(t){var e;return e=this.results_data[t],!this.form_field.options[e.options_index].disabled&&(e.selected=!1,this.form_field.options[e.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.trigger_form_field_change({deselected:this.form_field.options[e.options_index].value}),this.search_field_scale(),!0)},n.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect)return this.selected_item.find("abbr").length||this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>'),this.selected_item.addClass("chosen-single-with-deselect")},n.prototype.get_search_field_value=function(){return this.search_field.val()},n.prototype.get_search_text=function(){return t.trim(this.get_search_field_value())},n.prototype.escape_html=function(e){return t("<div/>").text(e).html()},n.prototype.winnow_results_set_highlight=function(){var t,e;if(e=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),null!=(t=e.length?e.first():this.search_results.find(".active-result").first()))return this.result_do_highlight(t)},n.prototype.no_results=function(t){var e;return e=this.get_no_results_html(t),this.search_results.append(e),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},n.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},n.prototype.keydown_arrow=function(){var t;return this.results_showing&&this.result_highlight?(t=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(t):void 0:this.results_show()},n.prototype.keyup_arrow=function(){var t;return this.results_showing||this.is_multiple?this.result_highlight?(t=this.result_highlight.prevAll("li.active-result")).length?this.result_do_highlight(t.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight()):void 0:this.results_show()},n.prototype.keydown_backstroke=function(){var t;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(t=this.search_container.siblings("li.search-choice").last()).length&&!t.hasClass("search-choice-disabled")?(this.pending_backstroke=t,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0},n.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},n.prototype.search_field_scale=function(){var e,s,i,n,r,o,h;if(this.is_multiple){for(r={position:"absolute",left:"-1000px",top:"-1000px",display:"none",whiteSpace:"pre"},s=0,i=(o=["fontSize","fontStyle","fontWeight","fontFamily","lineHeight","textTransform","letterSpacing"]).length;s<i;s++)r[n=o[s]]=this.search_field.css(n);return(e=t("<div />").css(r)).text(this.get_search_field_value()),t("body").append(e),h=e.width()+25,e.remove(),this.container.is(":visible")&&(h=Math.min(this.container.outerWidth()-10,h)),this.search_field.width(h)}},n.prototype.trigger_form_field_change=function(t){return this.form_field_jq.trigger("input",t),this.form_field_jq.trigger("change",t)},n}()}).call(this);
4/**
5 * Owl Carousel v2.2.1
6 * Copyright 2013-2017 David Deutsch
7 * Licensed under  ()
8 */
9!function(a,b,c,d){function e(b,c){this.settings=null,this.options=a.extend({},e.Defaults,c),this.$element=a(b),this._handlers={},this._plugins={},this._supress={},this._current=null,this._speed=null,this._coordinates=[],this._breakpoint=null,this._width=null,this._items=[],this._clones=[],this._mergers=[],this._widths=[],this._invalidated={},this._pipe=[],this._drag={time:null,target:null,pointer:null,stage:{start:null,current:null},direction:null},this._states={current:{},tags:{initializing:["busy"],animating:["busy"],dragging:["interacting"]}},a.each(["onResize","onThrottledResize"],a.proxy(function(b,c){this._handlers[c]=a.proxy(this[c],this)},this)),a.each(e.Plugins,a.proxy(function(a,b){this._plugins[a.charAt(0).toLowerCase()+a.slice(1)]=new b(this)},this)),a.each(e.Workers,a.proxy(function(b,c){this._pipe.push({filter:c.filter,run:a.proxy(c.run,this)})},this)),this.setup(),this.initialize()}e.Defaults={items:3,loop:!1,center:!1,rewind:!1,mouseDrag:!0,touchDrag:!0,pullDrag:!0,freeDrag:!1,margin:0,stagePadding:0,merge:!1,mergeFit:!0,autoWidth:!1,startPosition:0,rtl:!1,smartSpeed:250,fluidSpeed:!1,dragEndSpeed:!1,responsive:{},responsiveRefreshRate:200,responsiveBaseElement:b,fallbackEasing:"swing",info:!1,nestedItemSelector:!1,itemElement:"div",stageElement:"div",refreshClass:"owl-refresh",loadedClass:"owl-loaded",loadingClass:"owl-loading",rtlClass:"owl-rtl",responsiveClass:"owl-responsive",dragClass:"owl-drag",itemClass:"owl-item",stageClass:"owl-stage",stageOuterClass:"owl-stage-outer",grabClass:"owl-grab"},e.Width={Default:"default",Inner:"inner",Outer:"outer"},e.Type={Event:"event",State:"state"},e.Plugins={},e.Workers=[{filter:["width","settings"],run:function(){this._width=this.$element.width()}},{filter:["width","items","settings"],run:function(a){a.current=this._items&&this._items[this.relative(this._current)]}},{filter:["items","settings"],run:function(){this.$stage.children(".cloned").remove()}},{filter:["width","items","settings"],run:function(a){var b=this.settings.margin||"",c=!this.settings.autoWidth,d=this.settings.rtl,e={width:"auto","margin-left":d?b:"","margin-right":d?"":b};!c&&this.$stage.children().css(e),a.css=e}},{filter:["width","items","settings"],run:function(a){var b=(this.width()/this.settings.items).toFixed(3)-this.settings.margin,c=null,d=this._items.length,e=!this.settings.autoWidth,f=[];for(a.items={merge:!1,width:b};d--;)c=this._mergers[d],c=this.settings.mergeFit&&Math.min(c,this.settings.items)||c,a.items.merge=c>1||a.items.merge,f[d]=e?b*c:this._items[d].width();this._widths=f}},{filter:["items","settings"],run:function(){var b=[],c=this._items,d=this.settings,e=Math.max(2*d.items,4),f=2*Math.ceil(c.length/2),g=d.loop&&c.length?d.rewind?e:Math.max(e,f):0,h="",i="";for(g/=2;g--;)b.push(this.normalize(b.length/2,!0)),h+=c[b[b.length-1]][0].outerHTML,b.push(this.normalize(c.length-1-(b.length-1)/2,!0)),i=c[b[b.length-1]][0].outerHTML+i;this._clones=b,a(h).addClass("cloned").appendTo(this.$stage),a(i).addClass("cloned").prependTo(this.$stage)}},{filter:["width","items","settings"],run:function(){for(var a=this.settings.rtl?1:-1,b=this._clones.length+this._items.length,c=-1,d=0,e=0,f=[];++c<b;)d=f[c-1]||0,e=this._widths[this.relative(c)]+this.settings.margin,f.push(d+e*a);this._coordinates=f}},{filter:["width","items","settings"],run:function(){var a=this.settings.stagePadding,b=this._coordinates,c={width:Math.ceil(Math.abs(b[b.length-1]))+2*a,"padding-left":a||"","padding-right":a||""};this.$stage.css(c)}},{filter:["width","items","settings"],run:function(a){var b=this._co
vendor: 7,667 bytes, line 9
9ordinates.length,c=!this.settings.autoWidth,d=this.$stage.children();if(c&&a.items.merge)for(;b--;)a.css.width=this._widths[this.relative(b)],d.eq(b).css(a.css);else c&&(a.css.width=a.items.width,d.css(a.css))}},{filter:["items"],run:function(){this._coordinates.length<1&&this.$stage.removeAttr("style")}},{filter:["width","items","settings"],run:function(a){a.current=a.current?this.$stage.children().index(a.current):0,a.current=Math.max(this.minimum(),Math.min(this.maximum(),a.current)),this.reset(a.current)}},{filter:["position"],run:function(){this.animate(this.coordinates(this._current))}},{filter:["width","position","items","settings"],run:function(){var a,b,c,d,e=this.settings.rtl?1:-1,f=2*this.settings.stagePadding,g=this.coordinates(this.current())+f,h=g+this.width()*e,i=[];for(c=0,d=this._coordinates.length;c<d;c++)a=this._coordinates[c-1]||0,b=Math.abs(this._coordinates[c])+f*e,(this.op(a,"<=",g)&&this.op(a,">",h)||this.op(b,"<",g)&&this.op(b,">",h))&&i.push(c);this.$stage.children(".active").removeClass("active"),this.$stage.children(":eq("+i.join("), :eq(")+")").addClass("active"),this.settings.center&&(this.$stage.children(".center").removeClass("center"),this.$stage.children().eq(this.current()).addClass("center"))}}],e.prototype.initialize=function(){if(this.enter("initializing"),this.trigger("initialize"),this.$element.toggleClass(this.settings.rtlClass,this.settings.rtl),this.settings.autoWidth&&!this.is("pre-loading")){var b,c,e;b=this.$element.find("img"),c=this.settings.nestedItemSelector?"."+this.settings.nestedItemSelector:d,e=this.$element.children(c).width(),b.length&&e<=0&&this.preloadAutoWidthImages(b)}this.$element.addClass(this.options.loadingClass),this.$stage=a("<"+this.settings.stageElement+' class="'+this.settings.stageClass+'"/>').wrap('<div class="'+this.settings.stageOuterClass+'"/>'),this.$element.append(this.$stage.parent()),this.replace(this.$element.children().not(this.$stage.parent())),this.$element.is(":visible")?this.refresh():this.invalidate("width"),this.$element.removeClass(this.options.loadingClass).addClass(this.options.loadedClass),this.registerEventHandlers(),this.leave("initializing"),this.trigger("initialized")},e.prototype.setup=function(){var b=this.viewport(),c=this.options.responsive,d=-1,e=null;c?(a.each(c,function(a){a<=b&&a>d&&(d=Number(a))}),e=a.extend({},this.options,c[d]),"function"==typeof e.stagePadding&&(e.stagePadding=e.stagePadding()),delete e.responsive,e.responsiveClass&&this.$element.attr("class",this.$element.attr("class").replace(new RegExp("("+this.options.responsiveClass+"-)\\S+\\s","g"),"$1"+d))):e=a.extend({},this.options),this.trigger("change",{property:{name:"settings",value:e}}),this._breakpoint=d,this.settings=e,this.invalidate("settings"),this.trigger("changed",{property:{name:"settings",value:this.settings}})},e.prototype.optionsLogic=function(){this.settings.autoWidth&&(this.settings.stagePadding=!1,this.settings.merge=!1)},e.prototype.prepare=function(b){var c=this.trigger("prepare",{content:b});return c.data||(c.data=a("<"+this.settings.itemElement+"/>").addClass(this.options.itemClass).append(b)),this.trigger("prepared",{content:c.data}),c.data},e.prototype.update=function(){for(var b=0,c=this._pipe.length,d=a.proxy(function(a){return this[a]},this._invalidated),e={};b<c;)(this._invalidated.all||a.grep(this._pipe[b].filter,d).length>0)&&this._pipe[b].run(e),b++;this._invalidated={},!this.is("valid")&&this.enter("valid")},e.prototype.width=function(a){switch(a=a||e.Width.Default){case e.Width.Inner:case e.Width.Outer:return this._width;default:return this._width-2*this.settings.stagePadding+this.settings.margin}},e.prototype.refresh=function(){this.enter("refreshing"),this.trigger("refresh"),this.setup(),this.optionsLogic(),this.$element.addClass(this.options.refreshClass),this.update(),this.$element.removeClass(this.options.refreshClass),this.leave("refreshing"),this.trigger("refreshed")},e.prototype.onThrottledResize=function(){b.clearTimeout(this.resizeTimer),this.resizeTimer=b.setTimeout(this._handlers.onResize,this.settings.responsiveRefreshRate)},e.prototype.onResize=function(){return!!this._items.length&&(this._width!==this.$element.width()&&(!!this.$element.is(":visible")&&(this.enter("resizing"),this.trigger("resize").isDefaultPrevented()?(this.leave("resizing"),!1):(this.invalidate("width"),this.refresh(),this.leave("resizing"),void this.trigger("resized")))))},e.prototype.registerEventHandlers=function(){a.support.transition&&this.$stage.on(a.support.transition.end+".owl.core",a.proxy(this.onTransitionEnd,this)),this.settings.responsive!==!1&&this.on(b,"resize",this._handlers.onThrottledResize),this.settings.mouseDrag&&(this.$element.addClass(this.options.dragClass),this.$stage.on("mousedown.owl.core",a.proxy(this.onDragStart,this)),this.$stage.on("dragstart.owl.core selectstart.owl.core",function(){return!1})),this.settings.touchDrag&&(this.$stage.on("touchstart.owl.core",a.proxy(this.onDragStart,this)),this.$stage.on("touchcancel.owl.core",a.proxy(this.onDragEnd,this)))},e.prototype.onDragStart=function(b){var d=null;3!==b.which&&(a.support.transform?(d=this.$stage.css("transform").replace(/.*\(|\)| /g,"").split(","),d={x:d[16===d.length?12:4],y:d[16===d.length?13:5]}):(d=this.$stage.position(),d={x:this.settings.rtl?d.left+this.$stage.width()-this.width()+this.settings.margin:d.left,y:d.top}),this.is("animating")&&(a.support.transform?this.animate(d.x):this.$stage.stop(),this.invalidate("position")),this.$element.toggleClass(this.options.grabClass,"mousedown"===b.type),this.speed(0),this._drag.time=(new Date).getTime(),this._drag.target=a(b.target),this._drag.stage.start=d,this._drag.stage.current=d,this._drag.pointer=this.pointer(b),a(c).on("mouseup.owl.core touchend.owl.core",a.proxy(this.onDragEnd,this)),a(c).one("mousemove.owl.core touchmove.owl.core",a.proxy(function(b){var d=this.difference(this._drag.pointer,this.pointer(b));a(c).on("mousemove.owl.core touchmove.owl.core",a.proxy(this.onDragMove,this)),Math.abs(d.x)<Math.abs(d.y)&&this.is("valid")||(b.preventDefault(),this.enter("dragging"),this.trigger("drag"))},this)))},e.prototype.onDragMove=function(a){var b=null,c=null,d=null,e=this.difference(this._drag.pointer,this.pointer(a)),f=this.difference(this._drag.stage.start,e);this.is("dragging")&&(a.preventDefault(),this.settings.loop?(b=this.coordinates(this.minimum()),c=this.coordinates(this.maximum()+1)-b,f.x=((f.x-b)%c+c)%c+b):(b=this.settings.rtl?this.coordinates(this.maximum()):this.coordinates(this.minimum()),c=this.settings.rtl?this.coordinates(this.minimum()):this.coordinates(this.maximum()),d=this.settings.pullDrag?-1*e.x/5:0,f.x=Math.max(Math.min(f.x,b+d),c+d)),this._drag.stage.current=f,this.animate(f.x))},e.prototype.onDragEnd=function(b){var d=this.difference(this._drag.pointer,this.pointer(b)),e=this._drag.stage.current,f=d.x>0^this.settings.rtl?"left":"right";a(c).off(".owl.core"),this.$element.removeClass(this.options.grabClass),(0!==d.x&&this.is("dragging")||!this.is("valid"))&&(this.speed(this.settings.dragEndSpeed||this.settings.smartSpeed),this.current(this.closest(e.x,0!==d.x?f:this._drag.direction)),this.invalidate("position"),this.update(),this._drag.direction=f,(Math.abs(d.x)>3||(new Date).getTime()-this._drag.time>300)&&this._drag.target.one("click.owl.core",function(){return!1})),this.is("dragging")&&(this.leave("dragging"),this.trigger("dragged"))},e.prototype.closest=function(b,c){var d=-1,e=30,f=this.width(),g=this.coordinates();return this.settings.freeDrag||a.each(g,a.proxy(function(a,h){return"left"===c&&b>h-e&&b<h+e?d=a:"right"===c&&b>h-f-e&&b<h-f+e?d=a+1:this.op(b,"<",h)&&this.op(b,">
9",g[a+1]||h-f)&&(d="left"===c?a+1:a),d===-1},this)),this.settings.loop||(this.op(b,">",g[this.minimum()])?d=b=this.minimum():this.op(b,"<",g[this.maximum()])&&(d=b=this.maximum())),d},e.prototype.animate=function(b){var c=this.speed()>0;this.is("animating")&&this.onTransitionEnd(),c&&(this.enter("animating"),this.trigger("translate")),a.support.transform3d&&a.support.transition?this.$stage.css({transform:"translate3d("+b+"px,0px,0px)",transition:this.speed()/1e3+"s"}):c?this.$stage.animate({left:b+"px"},this.speed(),this.settings.fallbackEasing,a.proxy(this.onTransitionEnd,this)):this.$stage.css({left:b+"px"})},e.prototype.is=function(a){return this._states.current[a]&&this._states.current[a]>0},e.prototype.current=function(a){if(a===d)return this._current;if(0===this._items.length)return d;if(a=this.normalize(a),this._current!==a){var b=this.trigger("change",{property:{name:"position",value:a}});b.data!==d&&(a=this.normalize(b.data)),this._current=a,this.invalidate("position"),this.trigger("changed",{property:{name:"position",value:this._current}})}return this._current},e.prototype.invalidate=function(b){return"string"===a.type(b)&&(this._invalidated[b]=!0,this.is("valid")&&this.leave("valid")),a.map(this._invalidated,function(a,b){return b})},e.prototype.reset=function(a){a=this.normalize(a),a!==d&&(this._speed=0,this._current=a,this.suppress(["translate","translated"]),this.animate(this.coordinates(a)),this.release(["translate","translated"]))},e.prototype.normalize=function(a,b){var c=this._items.length,e=b?0:this._clones.length;return!this.isNumeric(a)||c<1?a=d:(a<0||a>=c+e)&&(a=((a-e/2)%c+c)%c+e/2),a},e.prototype.relative=function(a){return a-=this._clones.length/2,this.normalize(a,!0)},e.prototype.maximum=function(a){var b,c,d,e=this.settings,f=this._coordinates.length;if(e.loop)f=this._clones.length/2+this._items.length-1;else if(e.autoWidth||e.merge){for(b=this._items.length,c=this._items[--b].width(),d=this.$element.width();b--&&(c+=this._items[b].width()+this.settings.margin,!(c>d)););f=b+1}else f=e.center?this._items.length-1:this._items.length-e.items;return a&&(f-=this._clones.length/2),Math.max(f,0)},e.prototype.minimum=function(a){return a?0:this._clones.length/2},e.prototype.items=function(a){return a===d?this._items.slice():(a=this.normalize(a,!0),this._items[a])},e.prototype.mergers=function(a){return a===d?this._mergers.slice():(a=this.normalize(a,!0),this._mergers[a])},e.prototype.clones=function(b){var c=this._clones.length/2,e=c+this._items.length,f=function(a){return a%2===0?e+a/2:c-(a+1)/2};return b===d?a.map(this._clones,function(a,b){return f(b)}):a.map(this._clones,function(a,c){return a===b?f(c):null})},e.prototype.speed=function(a){return a!==d&&(this._speed=a),this._speed},e.prototype.coordinates=function(b){var c,e=1,f=b-1;return b===d?a.map(this._coordinates,a.proxy(function(a,b){return this.coordinates(b)},this)):(this.settings.center?(this.settings.rtl&&(e=-1,f=b+1),c=this._coordinates[b],c+=(this.width()-c+(this._coordinates[f]||0))/2*e):c=this._coordinates[f]||0,c=Math.ceil(c))},e.prototype.duration=function(a,b,c){return 0===c?0:Math.min(Math.max(Math.abs(b-a),1),6)*Math.abs(c||this.settings.smartSpeed)},e.prototype.to=function(a,b){var c=this.current(),d=null,e=a-this.relative(c),f=(e>0)-(e<0),g=this._items.length,h=this.minimum(),i=this.maximum();this.settings.loop?(!this.settings.rewind&&Math.abs(e)>g/2&&(e+=f*-1*g),a=c+e,d=((a-h)%g+g)%g+h,d!==a&&d-e<=i&&d-e>0&&(c=d-e,a=d,this.reset(c))):this.settings.rewind?(i+=1,a=(a%i+i)%i):a=Math.max(h,Math.min(i,a)),this.speed(this.duration(c,a,b)),this.current(a),this.$element.is(":visible")&&this.update()},e.prototype.next=function(a){a=a||!1,this.to(this.relative(this.current())+1,a)},e.prototype.prev=function(a){a=a||!1,this.to(this.relative(this.current())-1,a)},e.prototype.onTransitionEnd=function(a){if(a!==d&&(a.stopPropagation(),(a.target||a.srcElement||a.originalTarget)!==this.$stage.get(0)))return!1;this.leave("animating"),this.trigger("translated")},e.prototype.viewport=function(){var d;return this.options.responsiveBaseElement!==b?d=a(this.options.responsiveBaseElement).width():b.innerWidth?d=b.innerWidth:c.documentElement&&c.documentElement.clientWidth?d=c.documentElement.clientWidth:console.warn("Can not detect viewport width."),d}
vendor: 28,387 bytes, lines 9-54
9,e.prototype.replace=function(b){this.$stage.empty(),this._items=[],b&&(b=b instanceof jQuery?b:a(b)),this.settings.nestedItemSelector&&(b=b.find("."+this.settings.nestedItemSelector)),b.filter(function(){return 1===this.nodeType}).each(a.proxy(function(a,b){b=this.prepare(b),this.$stage.append(b),this._items.push(b),this._mergers.push(1*b.find("[data-merge]").addBack("[data-merge]").attr("data-merge")||1)},this)),this.reset(this.isNumeric(this.settings.startPosition)?this.settings.startPosition:0),this.invalidate("items")},e.prototype.add=function(b,c){var e=this.relative(this._current);c=c===d?this._items.length:this.normalize(c,!0),b=b instanceof jQuery?b:a(b),this.trigger("add",{content:b,position:c}),b=this.prepare(b),0===this._items.length||c===this._items.length?(0===this._items.length&&this.$stage.append(b),0!==this._items.length&&this._items[c-1].after(b),this._items.push(b),this._mergers.push(1*b.find("[data-merge]").addBack("[data-merge]").attr("data-merge")||1)):(this._items[c].before(b),this._items.splice(c,0,b),this._mergers.splice(c,0,1*b.find("[data-merge]").addBack("[data-merge]").attr("data-merge")||1)),this._items[e]&&this.reset(this._items[e].index()),this.invalidate("items"),this.trigger("added",{content:b,position:c})},e.prototype.remove=function(a){a=this.normalize(a,!0),a!==d&&(this.trigger("remove",{content:this._items[a],position:a}),this._items[a].remove(),this._items.splice(a,1),this._mergers.splice(a,1),this.invalidate("items"),this.trigger("removed",{content:null,position:a}))},e.prototype.preloadAutoWidthImages=function(b){b.each(a.proxy(function(b,c){this.enter("pre-loading"),c=a(c),a(new Image).one("load",a.proxy(function(a){c.attr("src",a.target.src),c.css("opacity",1),this.leave("pre-loading"),!this.is("pre-loading")&&!this.is("initializing")&&this.refresh()},this)).attr("src",c.attr("src")||c.attr("data-src")||c.attr("data-src-retina"))},this))},e.prototype.destroy=function(){this.$element.off(".owl.core"),this.$stage.off(".owl.core"),a(c).off(".owl.core"),this.settings.responsive!==!1&&(b.clearTimeout(this.resizeTimer),this.off(b,"resize",this._handlers.onThrottledResize));for(var d in this._plugins)this._plugins[d].destroy();this.$stage.children(".cloned").remove(),this.$stage.unwrap(),this.$stage.children().contents().unwrap(),this.$stage.children().unwrap(),this.$element.removeClass(this.options.refreshClass).removeClass(this.options.loadingClass).removeClass(this.options.loadedClass).removeClass(this.options.rtlClass).removeClass(this.options.dragClass).removeClass(this.options.grabClass).attr("class",this.$element.attr("class").replace(new RegExp(this.options.responsiveClass+"-\\S+\\s","g"),"")).removeData("owl.carousel")},e.prototype.op=function(a,b,c){var d=this.settings.rtl;switch(b){case"<":return d?a>c:a<c;case">":return d?a<c:a>c;case">=":return d?a<=c:a>=c;case"<=":return d?a>=c:a<=c}},e.prototype.on=function(a,b,c,d){a.addEventListener?a.addEventListener(b,c,d):a.attachEvent&&a.attachEvent("on"+b,c)},e.prototype.off=function(a,b,c,d){a.removeEventListener?a.removeEventListener(b,c,d):a.detachEvent&&a.detachEvent("on"+b,c)},e.prototype.trigger=function(b,c,d,f,g){var h={item:{count:this._items.length,index:this.current()}},i=a.camelCase(a.grep(["on",b,d],function(a){return a}).join("-").toLowerCase()),j=a.Event([b,"owl",d||"carousel"].join(".").toLowerCase(),a.extend({relatedTarget:this},h,c));return this._supress[b]||(a.each(this._plugins,function(a,b){b.onTrigger&&b.onTrigger(j)}),this.register({type:e.Type.Event,name:b}),this.$element.trigger(j),this.settings&&"function"==typeof this.settings[i]&&this.settings[i].call(this,j)),j},e.prototype.enter=function(b){a.each([b].concat(this._states.tags[b]||[]),a.proxy(function(a,b){this._states.current[b]===d&&(this._states.current[b]=0),this._states.current[b]++},this))},e.prototype.leave=function(b){a.each([b].concat(this._states.tags[b]||[]),a.proxy(function(a,b){this._states.current[b]--},this))},e.prototype.register=function(b){if(b.type===e.Type.Event){if(a.event.special[b.name]||(a.event.special[b.name]={}),!a.event.special[b.name].owl){var c=a.event.special[b.name]._default;a.event.special[b.name]._default=function(a){return!c||!c.apply||a.namespace&&a.namespace.indexOf("owl")!==-1?a.namespace&&a.namespace.indexOf("owl")>-1:c.apply(this,arguments)},a.event.special[b.name].owl=!0}}else b.type===e.Type.State&&(this._states.tags[b.name]?this._states.tags[b.name]=this._states.tags[b.name].concat(b.tags):this._states.tags[b.name]=b.tags,this._states.tags[b.name]=a.grep(this._states.tags[b.name],a.proxy(function(c,d){return a.inArray(c,this._states.tags[b.name])===d},this)))},e.prototype.suppress=function(b){a.each(b,a.proxy(function(a,b){this._supress[b]=!0},this))},e.prototype.release=function(b){a.each(b,a.proxy(function(a,b){delete this._supress[b]},this))},e.prototype.pointer=function(a){var c={x:null,y:null};return a=a.originalEvent||a||b.event,a=a.touches&&a.touches.length?a.touches[0]:a.changedTouches&&a.changedTouches.length?a.changedTouches[0]:a,a.pageX?(c.x=a.pageX,c.y=a.pageY):(c.x=a.clientX,c.y=a.clientY),c},e.prototype.isNumeric=function(a){return!isNaN(parseFloat(a))},e.prototype.difference=function(a,b){return{x:a.x-b.x,y:a.y-b.y}},a.fn.owlCarousel=function(b){var c=Array.prototype.slice.call(arguments,1);return this.each(function(){var d=a(this),f=d.data("owl.carousel");f||(f=new e(this,"object"==typeof b&&b),d.data("owl.carousel",f),a.each(["next","prev","to","destroy","refresh","replace","add","remove"],function(b,c){f.register({type:e.Type.Event,name:c}),f.$element.on(c+".owl.carousel.core",a.proxy(function(a){a.namespace&&a.relatedTarget!==this&&(this.suppress([c]),f[c].apply(this,[].slice.call(arguments,1)),this.release([c]))},f))})),"string"==typeof b&&"_"!==b.charAt(0)&&f[b].apply(f,c)})},a.fn.owlCarousel.Constructor=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this._core=b,this._interval=null,this._visible=null,this._handlers={"initialized.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.autoRefresh&&this.watch()},this)},this._core.options=a.extend({},e.Defaults,this._core.options),this._core.$element.on(this._handlers)};e.Defaults={autoRefresh:!0,autoRefreshInterval:500},e.prototype.watch=function(){this._interval||(this._visible=this._core.$element.is(":visible"),this._interval=b.setInterval(a.proxy(this.refresh,this),this._core.settings.autoRefreshInterval))},e.prototype.refresh=function(){this._core.$element.is(":visible")!==this._visible&&(this._visible=!this._visible,this._core.$element.toggleClass("owl-hidden",!this._visible),this._visible&&this._core.invalidate("width")&&this._core.refresh())},e.prototype.destroy=function(){var a,c;b.clearInterval(this._interval);for(a in this._handlers)this._core.$element.off(a,this._handlers[a]);for(c in Object.getOwnPropertyNames(this))"function"!=typeof this[c]&&(this[c]=null)},a.fn.owlCarousel.Constructor.Plugins.AutoRefresh=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this._core=b,this._loaded=[],this._handlers={"initialized.owl.carousel change.owl.carousel resized.owl.carousel":a.proxy(function(b){if(b.namespace&&this._core.settings&&this._core.settings.lazyLoad&&(b.property&&"position"==b.property.name||"initialized"==b.type))for(var c=this._core.settings,e=c.center&&Math.ceil(c.items/2)||c.items,f=c.center&&e*-1||0,g=(b.property&&b.property.value!==d?b.property.value:this._core.current())+f,h=this._core.clones().length,i=a.proxy(function(a,b){this.load(b)},this);f++<e;)this.load(h/2+this._core.relative(g)),h&&a.each(this._core.clones(this._core.relative(g)),i),g++},this)},this._core.options=a.extend({},e.Defaults,this._core.options),this._core.$element.on(this._handlers)};e.Defaults={lazyLoad:!1},e.prototype.load=function(c){var d=this._core.$stage.children().eq(c),e=d&&d.find(".owl-lazy");!e||a.inArray(d.get(0),this._loaded)>-1||(e.each(a.proxy(function(c,d){var e,f=a(d),g=b.devicePixelRatio>1&&f.attr("data-src-retina")||f.attr("data-src");this._core.trigger("load",{element:f,url:g},"lazy"),f.is("img")?f.one("load.owl.lazy",a.proxy(function(){f.css("opacity",1),this._core.trigger("loaded",{element:f,url:g},"lazy")},this)).attr("src",g):(e=new Image,e.onload=a.proxy(function(){f.css({"background-image":'url("'+g+'")',opacity:"1"}),this._core.trigger("loaded",{element:f,url:g},"lazy")},this),e.src=g)},this)),this._loaded.push(d.get(0)))},e.prototype.destroy=function(){var a,b;for(a in this.handlers)this._core.$element.off(a,this.handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.Lazy=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this._core=b,this._handlers={"initialized.owl.carousel refreshed.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.autoHeight&&this.update()},this),"changed.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.autoHeight&&"position"==a.property.name&&this.update()},this),"loaded.owl.lazy":a.proxy(function(a){a.namespace&&this._core.settings.autoHeight&&a.element.closest("."+this._core.settings.itemClass).index()===this._core.current()&&this.update()},this)},this._core.options=a.extend({},e.Defaults,this._core.options),this._core.$element.on(this._handlers)};e.Defaults={autoHeight:!1,autoHeightClass:"owl-height"},e.prototype.update=function(){var b=this._core._current,c=b+this._core.settings.items,d=this._core.$stage.children().toArray().slice(b,c),e=[],f=0;a.each(d,function(b,c){e.push(a(c).height())}),f=Math.max.apply(null,e),this._core.$stage.parent().height(f).addClass(this._core.settings.autoHeightClass)},e.prototype.destroy=function(){var a,b;for(a in this._handlers)this._core.$element.off(a,this._handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.AutoHeight=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this._core=b,this._videos={},this._playing=null,this._handlers={"initialized.owl.carousel":a.proxy(function(a){a.namespace&&this._core.register({type:"state",name:"playing",tags:["interacting"]})},this),"resize.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.video&&this.isInFullScreen()&&a.preventDefault()},this),"refreshed.owl.carousel":a.proxy(function(a){a.namespace&&this._core.is("resizing")&&this._core.$stage.find(".cloned .owl-video-frame").remove()},this),"changed.owl.carousel":a.proxy(function(a){a.namespace&&"position"===a.property.name&&this._playing&&this.stop()},this),"prepared.owl.carousel":a.proxy(function(b){if(b.namespace){var c=a(b.content).find(".owl-video");c.length&&(c.css("display","none"),this.fetch(c,a(b.content)))}},this)},this._core.options=a.extend({},e.Defaults,this._core.options),this._core.$element.on(this._handlers),this._core.$element.on("click.owl.video",".owl-video-play-icon",a.proxy(function(a){this.play(a)},this))};e.Defaults={video:!1,videoHeight:!1,videoWidth:!1},e.prototype.fetch=function(a,b){var c=function(){return a.attr("data-vimeo-id")?"vimeo":a.attr("data-vzaar-id")?"vzaar":"youtube"}(),d=a.attr("data-vimeo-id")||a.attr("data-youtube-id")||a.attr("data-vzaar-id"),e=a.attr("data-width")||this._core.settings.videoWidth,f=a.attr("data-height")||this._core.settings.videoHeight,g=a.attr("href");if(!g)throw new Error("Missing video URL.");if(d=g.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/),d[3].indexOf("youtu")>-1)c="youtube";else if(d[3].indexOf("vimeo")>-1)c="vimeo";else{if(!(d[3].indexOf("vzaar")>-1))throw new Error("Video URL not supported.");c="vzaar"}d=d[6],this._videos[g]={type:c,id:d,width:e,height:f},b.attr("data-video",g),this.thumbnail(a,this._videos[g])},e.prototype.thumbnail=function(b,c){var d,e,f,g=c.width&&c.height?'style="width:'+c.width+"px;height:"+c.height+'px;"':"",h=b.find("img"),i="src",j="",k=this._core.settings,l=function(a){e='<div class="owl-video-play-icon"></div>',d=k.lazyLoad?'<div class="owl-video-tn '+j+'" '+i+'="'+a+'"></div>':'<div class="owl-video-tn" style="opacity:1;background-image:url('+a+')"></div>',b.after(d),b.after(e)};if(b.wrap('<div class="owl-video-wrapper"'+g+"></div>"),this._core.settings.lazyLoad&&(i="data-src",j="owl-lazy"),h.length)return l(h.attr(i)),h.remove(),!1;"youtube"===c.type?(f="//img.youtube.com/vi/"+c.id+"/hqdefault.jpg",l(f)):"vimeo"===c.type?a.ajax({type:"GET",url:"//vimeo.com/api/v2/video/"+c.id+".json",jsonp:"callback",dataType:"jsonp",success:function(a){f=a[0].thumbnail_large,l(f)}}):"vzaar"===c.type&&a.ajax({type:"GET",url:"//vzaar.com/api/videos/"+c.id+".json",jsonp:"callback",dataType:"jsonp",success:function(a){f=a.framegrab_url,l(f)}})},e.prototype.stop=function(){this._core.trigger("stop",null,"video"),this._playing.find(".owl-video-frame").remove(),this._playing.removeClass("owl-video-playing"),this._playing=null,this._core.leave("playing"),this._core.trigger("stopped",null,"video")},e.prototype.play=function(b){var c,d=a(b.target),e=d.closest("."+this._core.settings.itemClass),f=this._videos[e.attr("data-video")],g=f.width||"100%",h=f.height||this._core.$stage.height();this._playing||(this._core.enter("playing"),this._core.trigger("play",null,"video"),e=this._core.items(this._core.relative(e.index())),this._core.reset(e.index()),"youtube"===f.type?c='<iframe width="'+g+'" height="'+h+'" src="//www.youtube.com/embed/'+f.id+"?autoplay=1&rel=0&v="+f.id+'" frameborder="0" allowfullscreen></iframe>':"vimeo"===f.type?c='<iframe src="//player.vimeo.com/video/'+f.id+'?autoplay=1" width="'+g+'" height="'+h+'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>':"vzaar"===f.type&&(c='<iframe frameborder="0"height="'+h+'"width="'+g+'" allowfullscreen mozallowfullscreen webkitAllowFullScreen src="//view.vzaar.com/'+f.id+'/player?autoplay=true"></iframe>'),a('<div class="owl-video-frame">'+c+"</div>").insertAfter(e.find(".owl-video")),this._playing=e.addClass("owl-video-playing"))},e.prototype.isInFullScreen=function(){var b=c.fullscreenElement||c.mozFullScreenElement||c.webkitFullscreenElement;return b&&a(b).parent().hasClass("owl-video-frame")},e.prototype.destroy=function(){var a,b;this._core.$element.off("click.owl.video");for(a in this._handlers)this._core.$element.off(a,this._handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.Video=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this.core=b,this.core.options=a.extend({},e.Defaults,this.core.options),this.swapping=!0,this.previous=d,this.next=d,this.handlers={"change.owl.carousel":a.proxy(function(a){a.namespace&&"position"==a.property.name&&(this.previous=this.core.current(),this.next=a.property.value)},this),"drag.owl.carousel dragged.owl.carousel translated.owl.carousel":a.proxy(function(a){a.namespace&&(this.swapping="translated"==a.type)},this),"translate.owl.carousel":a.proxy(function(a){a.namespace&&this.swapping&&(this.core.options.animateOut||this.core.options.animateIn)&&this.swap()},this)},this.core.$element.on(this.handlers)};e.Defaults={animateOut:!1,animateIn:!1},e.prototype.swap=function(){if(1===this.core.settings.items&&a.support.animation&&a.support.transition){this.core.speed(0);var b,c=a.proxy(this.clear,this),d=this.core.$stage.children().eq(this.previous),e=this.core.$stage.children().eq(this.next),f=this.core.settings.animateIn,g=this.core.settings.animateOut;this.core.current()!==this.previous&&(g&&(b=this.core.coordinates(this.previous)-this.core.coordinates(this.next),d.one(a.support.animation.end,c).css({left:b+"px"}).addClass("animated owl-animated-out").addClass(g)),f&&e.one(a.support.animation.end,c).addClass("animated owl-animated-in").addClass(f))}},e.prototype.clear=function(b){a(b.target).css({left:""}).removeClass("animated owl-animated-out owl-animated-in").removeClass(this.core.settings.animateIn).removeClass(this.core.settings.animateOut),this.core.onTransitionEnd()},e.prototype.destroy=function(){var a,b;for(a in this.handlers)this.core.$element.off(a,this.handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},
10    a.fn.owlCarousel.Constructor.Plugins.Animate=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this._core=b,this._timeout=null,this._paused=!1,this._handlers={"changed.owl.carousel":a.proxy(function(a){a.namespace&&"settings"===a.property.name?this._core.settings.autoplay?this.play():this.stop():a.namespace&&"position"===a.property.name&&this._core.settings.autoplay&&this._setAutoPlayInterval()},this),"initialized.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.autoplay&&this.play()},this),"play.owl.autoplay":a.proxy(function(a,b,c){a.namespace&&this.play(b,c)},this),"stop.owl.autoplay":a.proxy(function(a){a.namespace&&this.stop()},this),"mouseover.owl.autoplay":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.pause()},this),"mouseleave.owl.autoplay":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.play()},this),"touchstart.owl.core":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.pause()},this),"touchend.owl.core":a.proxy(function(){this._core.settings.autoplayHoverPause&&this.play()},this)},this._core.$element.on(this._handlers),this._core.options=a.extend({},e.Defaults,this._core.options)};e.Defaults={autoplay:!1,autoplayTimeout:5e3,autoplayHoverPause:!1,autoplaySpeed:!1},e.prototype.play=function(a,b){this._paused=!1,this._core.is("rotating")||(this._core.enter("rotating"),this._setAutoPlayInterval())},e.prototype._getNextTimeout=function(d,e){return this._timeout&&b.clearTimeout(this._timeout),b.setTimeout(a.proxy(function(){this._paused||this._core.is("busy")||this._core.is("interacting")||c.hidden||this._core.next(e||this._core.settings.autoplaySpeed)},this),d||this._core.settings.autoplayTimeout)},e.prototype._setAutoPlayInterval=function(){this._timeout=this._getNextTimeout()},e.prototype.stop=function(){this._core.is("rotating")&&(b.clearTimeout(this._timeout),this._core.leave("rotating"))},e.prototype.pause=function(){this._core.is("rotating")&&(this._paused=!0)},e.prototype.destroy=function(){var a,b;this.stop();for(a in this._handlers)this._core.$element.off(a,this._handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.autoplay=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){"use strict";var e=function(b){this._core=b,this._initialized=!1,this._pages=[],this._controls={},this._templates=[],this.$element=this._core.$element,this._overrides={next:this._core.next,prev:this._core.prev,to:this._core.to},this._handlers={"prepared.owl.carousel":a.proxy(function(b){b.namespace&&this._core.settings.dotsData&&this._templates.push('<div class="'+this._core.settings.dotClass+'">'+a(b.content).find("[data-dot]").addBack("[data-dot]").attr("data-dot")+"</div>")},this),"added.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.dotsData&&this._templates.splice(a.position,0,this._templates.pop())},this),"remove.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.dotsData&&this._templates.splice(a.position,1)},this),"changed.owl.carousel":a.proxy(function(a){a.namespace&&"position"==a.property.name&&this.draw()},this),"initialized.owl.carousel":a.proxy(function(a){a.namespace&&!this._initialized&&(this._core.trigger("initialize",null,"navigation"),this.initialize(),this.update(),this.draw(),this._initialized=!0,this._core.trigger("initialized",null,"navigation"))},this),"refreshed.owl.carousel":a.proxy(function(a){a.namespace&&this._initialized&&(this._core.trigger("refresh",null,"navigation"),this.update(),this.draw(),this._core.trigger("refreshed",null,"navigation"))},this)},this._core.options=a.extend({},e.Defaults,this._core.options),this.$element.on(this._handlers)};e.Defaults={nav:!1,navText:["prev","next"],navSpeed:!1,navElement:"div",navContainer:!1,navContainerClass:"owl-nav",navClass:["owl-prev","owl-next"],slideBy:1,dotClass:"owl-dot",dotsClass:"owl-dots",dots:!0,dotsEach:!1,dotsData:!1,dotsSpeed:!1,dotsContainer:!1},e.prototype.initialize=function(){var b,c=this._core.settings;this._controls.$relative=(c.navContainer?a(c.navContainer):a("<div>").addClass(c.navContainerClass).appendTo(this.$element)).addClass("disabled"),this._controls.$previous=a("<"+c.navElement+">").addClass(c.navClass[0]).html(c.navText[0]).prependTo(this._controls.$relative).on("click",a.proxy(function(a){this.prev(c.navSpeed)},this)),this._controls.$next=a("<"+c.navElement+">").addClass(c.navClass[1]).html(c.navText[1]).appendTo(this._controls.$relative).on("click",a.proxy(function(a){this.next(c.navSpeed)},this)),c.dotsData||(this._templates=[a("<div>").addClass(c.dotClass).append(a("<span>")).prop("outerHTML")]),this._controls.$absolute=(c.dotsContainer?a(c.dotsContainer):a("<div>").addClass(c.dotsClass).appendTo(this.$element)).addClass("disabled"),this._controls.$absolute.on("click","div",a.proxy(function(b){var d=a(b.target).parent().is(this._controls.$absolute)?a(b.target).index():a(b.target).parent().index();b.preventDefault(),this.to(d,c.dotsSpeed)},this));for(b in this._overrides)this._core[b]=a.proxy(this[b],this)},e.prototype.destroy=function(){var a,b,c,d;for(a in this._handlers)this.$element.off(a,this._handlers[a]);for(b in this._controls)this._controls[b].remove();for(d in this.overides)this._core[d]=this._overrides[d];for(c in Object.getOwnPropertyNames(this))"function"!=typeof this[c]&&(this[c]=null)},e.prototype.update=function(){var a,b,c,d=this._core.clones().length/2,e=d+this._core.items().length,f=this._core.maximum(!0),g=this._core.settings,h=g.center||g.autoWidth||g.dotsData?1:g.dotsEach||g.items;if("page"!==g.slideBy&&(g.slideBy=Math.min(g.slideBy,g.items)),g.dots||"page"==g.slideBy)for(this._pages=[],a=d,b=0,c=0;a<e;a++){if(b>=h||0===b){if(this._pages.push({start:Math.min(f,a-d),end:a-d+h-1}),Math.min(f,a-d)===f)break;b=0,++c}b+=this._core.mergers(this._core.relative(a))}},e.prototype.draw=function(){var b,c=this._core.settings,d=this._core.items().length<=c.items,e=this._core.relative(this._core.current()),f=c.loop||c.rewind;this._controls.$relative.toggleClass("disabled",!c.nav||d),c.nav&&(this._controls.$previous.toggleClass("disabled",!f&&e<=this._core.minimum(!0)),this._controls.$next.toggleClass("disabled",!f&&e>=this._core.maximum(!0))),this._controls.$absolute.toggleClass("disabled",!c.dots||d),c.dots&&(b=this._pages.length-this._controls.$absolute.children().length,c.dotsData&&0!==b?this._controls.$absolute.html(this._templates.join("")):b>0?this._controls.$absolute.append(new Array(b+1).join(this._templates[0])):b<0&&this._controls.$absolute.children().slice(b).remove(),this._controls.$absolute.find(".active").removeClass("active"),this._controls.$absolute.children().eq(a.inArray(this.current(),this._pages)).addClass("active"))},e.prototype.onTrigger=function(b){var c=this._core.settings;b.page={index:a.inArray(this.current(),this._pages),count:this._pages.length,size:c&&(c.center||c.autoWidth||c.dotsData?1:c.dotsEach||c.items)}},e.prototype.current=function(){var b=this._core.relative(this._core.current());return a.grep(this._pages,a.proxy(function(a,c){return a.start<=b&&a.end>=b},this)).pop()},e.prototype.getPosition=function(b){var c,d,e=this._core.settings;return"page"==e.slideBy?(c=a.inArray(this.current(),this._pages),d=this._pages.length,b?++c:--c,c=this._pages[(c%d+d)%d].start):(c=this._core.relative(this._core.current()),d=this._core.items().length,b?c+=e.slideBy:c-=e.slideBy),c},e.prototype.next=function(b){a.proxy(this._overrides.to,this._core)(this.getPosition(!0),b)},e.prototype.prev=function(b){a.proxy(this._overrides.to,this._core)(this.getPosition(!1),b)},e.prototype.to=function(b,c,d){var e;!d&&this._pages.length?(e=this._pages.length,a.proxy(this._overrides.to,this._core)(this._pages[(b%e+e)%e].start,c)):a.proxy(this._overrides.to,this._core)(b,c)},a.fn.owlCarousel.Constructor.Plugins.Navigation=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){"use strict";var e=function(c){this._core=c,this._hashes={},this.$element=this._core.$element,this._handlers={"initialized.owl.carousel":a.proxy(function(c){c.namespace&&"URLHash"===this._core.settings.startPosition&&a(b).trigger("hashchange.owl.navigation")},this),"prepared.owl.carousel":a.proxy(function(b){if(b.namespace){var c=a(b.content).find("[data-hash]").addBack("[data-hash]").attr("data-hash");if(!c)return;this._hashes[c]=b.content}},this),"changed.owl.carousel":a.proxy(function(c){if(c.namespace&&"position"===c.property.name){var d=this._core.items(this._core.relative(this._core.current())),e=a.map(this._hashes,function(a,b){return a===d?b:null}).join();if(!e||b.location.hash.slice(1)===e)return;b.location.hash=e}},this)},this._core.options=a.extend({},e.Defaults,this._core.options),this.$element.on(this._handlers),a(b).on("hashchange.owl.navigation",a.proxy(function(a){var c=b.location.hash.substring(1),e=this._core.$stage.children(),f=this._hashes[c]&&e.index(this._hashes[c]);f!==d&&f!==this._core.current()&&this._core.to(this._core.relative(f),!1,!0)},this))};e.Defaults={URLhashListener:!1},e.prototype.destroy=function(){var c,d;a(b).off("hashchange.owl.navigation");for(c in this._handlers)this._core.$element.off(c,this._handlers[c]);for(d in Object.getOwnPropertyNames(this))"function"!=typeof this[d]&&(this[d]=null)},a.fn.owlCarousel.Constructor.Plugins.Hash=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){function e(b,c){var e=!1,f=b.charAt(0).toUpperCase()+b.slice(1);return a.each((b+" "+h.join(f+" ")+f).split(" "),function(a,b){if(g[b]!==d)return e=!c||b,!1}),e}function f(a){return e(a,!0)}var g=a("<support>").get(0).style,h="Webkit Moz O ms".split(" "),i={transition:{end:{WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"}},animation:{end:{WebkitAnimation:"webkitAnimationEnd",MozAnimation:"animationend",OAnimation:"oAnimationEnd",animation:"animationend"}}},j={csstransforms:function(){return!!e("transform")},csstransforms3d:function(){return!!e("perspective")},csstransitions:function(){return!!e("transition")},cssanimations:function(){return!!e("animation")}};j.csstransitions()&&(a.support.transition=new String(f("transition")),a.support.transition.end=i.transition.end[a.support.transition]),j.cssanimations()&&(a.support.animation=new String(f("animation")),a.support.animation.end=i.animation.end[a.support.animation]),j.csstransforms()&&(a.support.transform=new String(f("transform")),a.support.transform3d=j.csstransforms3d())}(window.Zepto||window.jQuery,window,document);
11	;(function($, window, document, undefined) {
12    /**
13     * Creates the Linked plugin.
14     * @class The Linked Plugin
15     * @param {Owl} carousel - The Owl Carousel
16     */
17    var Linked = function(carousel) {
18        /**
19         * Reference to the core.
20         * @protected
21         * @type {Owl}
22         */
23        this._core = carousel;
24
25        /**
26         * All event handlers.
27         * @protected
28         * @type {Object}
29         */
30        this._handlers = {
31            'dragged.owl.carousel changed.owl.carousel': $.proxy(function(e) {
32                if (e.namespace && this._core.settings.linked) {
33                    this.update(e);
34                }
35            }, this),
36            'linked.to.owl.carousel': $.proxy(function(e, index, speed, standard, propagate) {
37                if (e.namespace && this._core.settings.linked) {
38                    this.toSlide(index, speed, propagate);
39                }
40            }, this)
41        };
42
43        // register event handlers
44        this._core.$element.on(this._handlers);
45
46        // set default options
47        this._core.options = $.extend({}, Linked.Defaults, this._core.options);
48    };
49
50    /**
51     * Default options.
52     * @public
53     */
54    Linked.Defaults = {
55        linked: false
56    };
57
58    /**
59     * Updated linked instances
60     */
61    Linked.prototype.update = function(e) {
62        this.toSlide( e.relatedTarget.relative(e.item.index) );
63    };
64
65    /**
66     * Carry out the to.owl.carousel proxy function
67     * @param {int} index
68     * @param {int} speed
69     * @param {bool} propagate
70     */
71    Linked.prototype.toSlide = function(index, speed, propagate) {
72        var id = this._core.$element.attr('id'),
73            linked = this._core.settings.linked.split(',');
74
75        if ( typeof propagate == 'undefined' ) {
76            propagate = true;
77        }
78
79        index = index || 0;
80
81        if ( propagate ) {
82            $.each(linked, function(i, el){
83                $(el).trigger('linked.to.owl.carousel', [index, 300, true, false]);
84            });
85        } else {
86            this._core.$element.trigger('to.owl.carousel', [index, 300, true]);
87
88            if ( this._core.settings.current ) {
89                this._core._plugins.current.switchTo(index);
90            }
91        }
92    };
93
94    /**
95     * Destroys the plugin.
96     * @protected
97     */
98    Linked.prototype.destroy = function() {
99        var handler, property;
100
101        for (handler in this._handlers) {
102            this.$element.off(handler, this._handlers[handler]);
103        }
104        for (property in Object.getOwnPropertyNames(this)) {
105            typeof this[property] != 'function' && (this[property] = null);
106        }
107    };
108
109    $.fn.owlCarousel.Constructor.Plugins.linked = Linked;
110
111})(window.Zepto || window.jQuery, window, document);
112/*! Copyright (c) 2010-2012 Pathable
113 * Permission is hereby granted, free of charge, to any person
114 * obtaining a copy of this software and associated documentation
115 * files (the "Software"), to deal in the Software without
116 * restriction, including without limitation the rights to use,
117 * copy, modify, merge, publish, distribute, sublicense, and/or sell
118 * copies of the Software, and to permit persons to whom the
119 * Software is furnished to do so, subject to the following
120 * conditions:
121 *
122 * The above copyright notice and this permission notice shall be
123 * included in all copies or substantial portions of the Software.
124 *
125 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
126 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
127 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
128 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
129 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
130 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
131 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
132 * OTHER DEALINGS IN THE SOFTWARE.
133 */
134/** @preserve 
135 * Copyright (c) 2010-2012 Pathable
136 * Permission is hereby granted, free of charge, to any person
137 * obtaining a copy of this software and associated documentation
138 * files (the "Software"), to deal in the Software without
139 * restriction, including without limitation the rights to use,
140 * copy, modify, merge, publish, distribute, sublicense, and/or sell
141 * copies of the Software, and to permit persons to whom the
142 * Software is furnished to do so, subject to the following
143 * conditions:
144 *
145 * The above copyright notice and this permission notice shall be
146 * included in all copies or substantial portions of the Software.
147 *
148 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
149 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
150 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
151 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
152 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
153 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
154 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
155 * OTHER DEALINGS IN THE SOFTWARE.
156 */
157(function($) {
158
159  // Matches trailing non-space characters.
160  var chop = /(\s*\S+|\s)$/;
161
162  // Return a truncated html string.  Delegates to $.fn.truncate.
163  $.truncate = function(html, options) {
164    return $('<div></div>').append(html).truncate(options).html();
165  };
166
167  // Truncate the contents of an element in place.
168  $.fn.truncate = function(options) {
169    if ($.isNumeric(options)) options = {length: options};
170    var o = $.extend({}, $.truncate.defaults, options);
171
172    return this.each(function() {
173      var self = $(this);
174
175      if (o.noBreaks) self.find('br').replaceWith(' ');
176
177      var text = self.text();
178      var excess = text.length - o.length;
179
180      if (o.stripTags) self.text(text);
181
182      // Chop off any partial words if appropriate.
183      if (o.words && excess > 0) {
184        excess = text.length - text.slice(0, o.length).replace(chop, '').length - 1;
185      }
186
187      if (excess < 0 || !excess && !o.truncated) return;
188
189      // Iterate over each child node in reverse, removing excess text.
190      $.each(self.contents().get().reverse(), function(i, el) {
191        var $el = $(el);
192        var text = $el.text();
193        var length = text.length;
194
195        // If the text is longer than the excess, remove the node and continue.
196        if (length <= excess) {
197          o.truncated = true;
198          excess -= length;
199          $el.remove();
200          return;
201        }
202
203        // Remove the excess text and append the ellipsis.
204        if (el.nodeType === 3) {
205          $(el.splitText(length - excess - 1)).replaceWith(o.ellipsis);
206          return false;
207        }
208
209        // Recursively truncate child nodes.
210        $el.truncate($.extend(o, {length: length - excess}));
211        return false;
212      });
213    });
214  };
215
216  $.truncate.defaults = {
217
218    // Strip all html elements, leaving only plain text.
219    stripTags: false,
220
221    // Only truncate at word boundaries.
222    words: false,
223
224    // Replace instances of <br> with a single space.
225    noBreaks: false,
226
227    // The maximum length of the truncated html.
228    length: Infinity,
229
230    // The character to use as the ellipsis.  The word joiner (U+2060) can be
231    // used to prevent a hanging ellipsis, but displays incorrectly in Chrome
232    // on Windows 7.
233    // http://code.google.com/p/chromium/issues/detail?id=68323
234    ellipsis: '\u2026' // '\u2060\u2026'
235
236  };
237
238})(jQuery);
239
240/*
241jquery-watcher
242Version 1.21 - 1/19/2016
243© 2014-2016 Rick Strahl, West Wind Technologies
244www.west-wind.com
245Licensed under MIT License
246http://en.wikipedia.org/wiki/MIT_License
247*/
248(function ($, undefined) {
249        $.fn.watch = function (options) {
250            /// <summary>
251            /// Allows you to monitor changes in a specific
252            /// CSS property of an element by polling the value.
253            /// You can also monitor attributes (using attr_ prefix)
254            /// or property changes (using prop_ prefix).
255            /// when the value changes a function is called.
256            /// The callback is fired in the context
257            /// of the selected element (ie. this)
258            ///
259            /// Uses the MutationObserver API of the DOM and
260            /// falls back to setInterval to poll for changes
261            /// for non-compliant browsers (pre IE 11)
262            /// </summary>
263            /// <param name="options" type="Object">
264            /// Option to set - see comments in code below.
265            /// </param>
266            /// <returns type="jQuery" />
267            var opt = $.extend({
268                // CSS styles or Attributes to monitor as comma delimited list
269                // For attributes use a attr_ prefix
270                // Example: "top,left,opacity,attr_class"
271                properties: null,
272
273                // interval for 'manual polling' (IE 10 and older)
274                interval: 100,
275
276                // a unique id for this watcher instance
277                id: "_watcher_" + new Date().getTime(),
278
279                // flag to determine whether child elements are watched
280                watchChildren: false,
281
282                // Callback function if not passed in callback parameter
283                callback: null
284            }, options);
285
286            return this.each(function () {
287                var el = this;
288                var el$ = $(this);
289                var fnc = function (mRec, mObs) {
290                    __watcher.call(el, opt.id, mRec, mObs);
291                };
292
293                var data = {
294                    id: opt.id,
295                    props: opt.properties.split(','),
296                    vals: [opt.properties.split(',').length],
297                    func: opt.callback, // user function
298                    fnc: fnc, // __watcher internal
299                    origProps: opt.properties,
300                    interval: opt.interval,
301                    intervalId: null
302                };
303                // store initial props and values
304                $.each(data.props, function (i) {
305                    var propName = data.props[i];
306                    if (data.props[i].startsWith('attr_'))
307                        data.vals[i] = el$.attr(propName.replace('attr_', ''));
308                    else if (propName.startsWith('prop_'))
309                        data.vals[i] = el$.prop(propName.replace('props_', ''));
310                    else
311                        data.vals[i] = el$.css(propName);
312                });
313
314                el$.data(opt.id, data);
315
316                hookChange(el$, opt.id, data);
317            });
318
319            function hookChange(element$, id, data) {
320                element$.each(function () {
321                    var el$ = $(this);
322
323                    if (window.MutationObserver) {
324                        var observer = el$.data('__watcherObserver' + opt.id);
325                        if (observer == null) {
326                            observer = new MutationObserver(data.fnc);
327                            el$.data('__watcherObserver' + opt.id, observer);
328                        }
329                        observer.observe(this, {
330                            attributes: true,
331                            subtree: opt.watchChildren,
332                            childList: opt.watchChildren,
333                            characterData: true
334                        });
335                    } else
336                        data.intervalId = setInterval(data.fnc, opt.interval);
337                });
338            }
339
340            function __watcher(id, mRec, mObs) {
341                var el$ = $(this);
342                var w = el$.data(id);
343                if (!w) return;
344                var el = this;
345
346                if (!w.func)
347                    return;
348
349                var changed = false;
350                var i = 0;
351                for (i; i < w.props.length; i++) {
352                    var key = w.props[i];
353
354                    var newVal = "";
355                    if (key.startsWith('attr_'))
356                        newVal = el$.attr(key.replace('attr_', ''));
357                    else if (key.startsWith('prop_'))
358                        newVal = el$.prop(key.replace('prop_', ''));
359                    else
360                        newVal = el$.css(key);
361
362                    if (newVal == undefined)
363                        continue;
364
365                    if (w.vals[i] != newVal) {
366                        w.vals[i] = newVal;
367                        changed = true;
368                        break;
369                    }
370                }
371                if (changed) {
372                    // unbind to avoid recursive events
373                    el$.unwatch(id);
374
375                    // call the user handler
376                    w.func.call(el, w, i, mRec, mObs);
377
378                    // rebind the events
379                    hookChange(el$, id, w);
380                }
381            }
382        };
383        $.fn.unwatch = function (id) {
384            this.each(function () {
385                var el = $(this);
386                var data = el.data(id);
387                try {
388                    if (window.MutationObserver) {
389                        var observer = el.data("__watcherObserver" + id);
390                        if (observer) {
391                            observer.disconnect();
392                            el.removeData("__watcherObserver" + id);
393                        }
394                    } else
395                        clearInterval(data.intervalId);
396                }
397                    // ignore if element was already unbound
398                catch (e) {
399                }
400            });
401            return this;
402        };
403        String.prototype.startsWith = function (sub) {
404            if (sub === null || sub === undefined) return false;
405            return sub == this.substr(0, sub.length);
406        }
407    }
408)(jQuery, undefined);
409
410/*!
411* Parsley.js
412* Version 2.8.1 - built Sat, Feb 3rd 2018, 2:27 pm
413* http://parsleyjs.org
414* Guillaume Potier - <[email protected]>
415* Marc-Andre Lafortune - <[email protected]>
416* MIT Licensed
417*/
418function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t<e.length;t++)i[t]=e[t];return i}return Array.from(e)}var _slice=Array.prototype.slice,_slicedToArray=function(){function e(e,t){var i=[],n=!0,r=!1,s=void 0;try{for(var a,o=e[Symbol.iterator]();!(n=(a=o.next()).done)&&(i.push(a.value),!t||i.length!==t);n=!0);}catch(l){r=!0,s=l}finally{try{!n&&o["return"]&&o["return"]()}finally{if(r)throw s}}return i}return function(t,i){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),_extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var i=arguments[t];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n])}return e};!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],t):e.parsley=t(e.jQuery)}(this,function(e){"use strict";function t(e,t){return e.parsleyAdaptedCallback||(e.parsleyAdaptedCallback=function(){var i=Array.prototype.slice.call(arguments,0);i.unshift(this),e.apply(t||M,i)}),e.parsleyAdaptedCallback}function i(e){return 0===e.lastIndexOf(D,0)?e.substr(D.length):e}/**
419 * inputevent - Alleviate browser bugs for input events
420 * https://github.com/marcandre/inputevent
421 * @version v0.0.3 - (built Thu, Apr 14th 2016, 5:58 pm)
422 * @author Marc-Andre Lafortune <[email protected]>
423 * @license MIT
424 */
425function n(){var t=this,i=window||global;_extends(this,{isNativeEvent:function(e){return e.originalEvent&&e.originalEvent.isTrusted!==!1},fakeInputEvent:function(i){t.isNativeEvent(i)&&e(i.target).trigger("input")},misbehaves:function(i){t.isNativeEvent(i)&&(t.behavesOk(i),e(document).on("change.inputevent",i.data.selector,t.fakeInputEvent),t.fakeInputEvent(i))},behavesOk:function(i){t.isNativeEvent(i)&&e(document).off("input.inputevent",i.data.selector,t.behavesOk).off("change.inputevent",i.data.selector,t.misbehaves)},install:function(){if(!i.inputEventPatched){i.inputEventPatched="0.0.3";for(var n=["select",'input[type="checkbox"]','input[type="radio"]','input[type="file"]'],r=0;r<n.length;r++){var s=n[r];e(document).on("input.inputevent",s,{selector:s},t.behavesOk).on("change.inputevent",s,{selector:s},t.misbehaves)}}},uninstall:function(){delete i.inputEventPatched,e(document).off(".inputevent")}})}var r=1,s={},a={attr:function(e,t,i){var n,r,s,a=new RegExp("^"+t,"i");if("undefined"==typeof i)i={};else for(n in i)i.hasOwnProperty(n)&&delete i[n];if(!e)return i;for(s=e.attributes,n=s.length;n--;)r=s[n],r&&r.specified&&a.test(r.name)&&(i[this.camelize(r.name.slice(t.length))]=this.deserializeValue(r.value));return i},checkAttr:function(e,t,i){return e.hasAttribute(t+i)},setAttr:function(e,t,i,n){e.setAttribute(this.dasherize(t+i),String(n))},getType:function(e){return e.getAttribute("type")||"text"},generateID:function(){return""+r++},deserializeValue:function(e){var t;try{return e?"true"==e||"false"!=e&&("null"==e?null:isNaN(t=Number(e))?/^[\[\{]/.test(e)?JSON.parse(e):e:t):e}catch(i){return e}},camelize:function(e){return e.replace(/-+(.)?/g,function(e,t){return t?t.toUpperCase():""})},dasherize:function(e){return e.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()},warn:function(){var e;window.console&&"function"==typeof window.console.warn&&(e=window.console).warn.apply(e,arguments)},warnOnce:function(e){s[e]||(s[e]=!0,this.warn.apply(this,arguments))},_resetWarnings:function(){s={}},trimString:function(e){return e.replace(/^\s+|\s+$/g,"")},parse:{date:function S(e){var t=e.match(/^(\d{4,})-(\d\d)-(\d\d)$/);if(!t)return null;var i=t.map(function(e){return parseInt(e,10)}),n=_slicedToArray(i,4),r=(n[0],n[1]),s=n[2],a=n[3],S=new Date(r,s-1,a);return S.getFullYear()!==r||S.getMonth()+1!==s||S.getDate()!==a?null:S}
425,string:function(e){return e},integer:function(e){return isNaN(e)?null:parseInt(e,10)},number:function(e){if(isNaN(e))throw null;return parseFloat(e)},"boolean":function(e){return!/^\s*false\s*$/i.test(e)},object:function(e){return a.deserializeValue(e)},regexp:function(e){var t="";return/^\/.*\/(?:[gimy]*)$/.test(e)?(t=e.replace(/.*\/([gimy]*)$/,"$1"),e=e.replace(new RegExp("^/(.*?)/"+t+"$"),"$1")):e="^"+e+"$",new RegExp(e,t)}},parseRequirement:function(e,t){var i=this.parse[e||"string"];if(!i)throw'Unknown requirement specification: "'+e+'"';var n=i(t);if(null===n)throw"Requirement is not a "+e+': "'+t+'"';return n},namespaceEvents:function(t,i){return t=this.trimString(t||"").split(/\s+/),t[0]?e.map(t,function(e){return e+"."+i}).join(" "):""},difference:function(t,i){var n=[];return e.each(t,function(e,t){i.indexOf(t)==-1&&n.push(t)}),n},all:function(t){return e.when.apply(e,_toConsumableArray(t).concat([42,42]))},objectCreate:Object.create||function(){var e=function(){};return function(t){if(arguments.length>1)throw Error("Second argument not supported");if("object"!=typeof t)throw TypeError("Argument must be an object");e.prototype=t;var i=new e;return e.prototype=null,i}}(),_SubmitSelector:'input[type="submit"], button:submit'},o={namespace:"data-parsley-",inputs:"input, textarea, select",excluded:"input[type=button], input[type=submit], input[type=reset], input[type=hidden]",priorityEnabled:!0,multiple:null,group:null,uiEnabled:!0,validationThreshold:3,focus:"first",trigger:!1,triggerAfterFailure:"input",errorClass:"parsley-error",successClass:"parsley-success",classHandler:function(e){},errorsContainer:function(e){},errorsWrapper:'<ul class="parsley-errors-list"></ul>',errorTemplate:"<li></li>"},l=function(){this.__id__=a.generateID()};l.prototype={asyncSupport:!0,_pipeAccordingToValidationResult:function(){var t=this,i=function(){var i=e.Deferred();return!0!==t.validationResult&&i.reject(),i.resolve().promise()};return[i,i]},actualizeOptions:function(){return a.attr(this.element,this.options.namespace,this.domOptions),this.parent&&this.parent.actualizeOptions&&this.parent.actualizeOptions(),this},_resetOptions:function(e){this.domOptions=a.objectCreate(this.parent.options),this.options=a.objectCreate(this.domOptions);for(var t in e)e.hasOwnProperty(t)&&(this.options[t]=e[t]);this.actualizeOptions()},_listeners:null,on:function(e,t){this._listeners=this._listeners||{};var i=this._listeners[e]=this._listeners[e]||[];return i.push(t),this},subscribe:function(t,i){e.listenTo(this,t.toLowerCase(),i)},off:function(e,t){var i=this._listeners&&this._listeners[e];if(i)if(t)for(var n=i.length;n--;)i[n]===t&&i.splice(n,1);else delete this._listeners[e];return this},unsubscribe:function(t,i){e.unsubscribeTo(this,t.toLowerCase())},trigger:function(e,t,i){t=t||this;var n,r=this._listeners&&this._listeners[e];if(r)for(var s=r.length;s--;)if(n=r[s].call(t,t,i),n===!1)return n;return!this.parent||this.parent.trigger(e,t,i)},asyncIsValid:function(e,t){return a.warnOnce("asyncIsValid is deprecated; please use whenValid instead"),this.whenValid({group:e,force:t})},_findRelated:function(){return this.options.multiple?e(this.parent.element.querySelectorAll("["+this.options.namespace+'multiple="'+this.options.multiple+'"]')):this.$element}};var u=function(e,t){var i=e.match(/^\s*\[(.*)\]\s*$/);if(!i)throw'Requirement is not an array: "'+e+'"';var n=i[1].split(",").map(a.trimString);if(n.length!==t)throw"Requirement has "+n.length+" values when "+t+" are needed";return n},d=function(e,t,i){var n=null,r={};for(var s in e)if(s){var o=i(s);"string"==typeof o&&(o=a.parseRequirement(e[s],o)),r[s]=o}else n=a.parseRequirement(e[s],t);return[n,r]},h=function(t){e.extend(!0,this,t)};h.prototype={validate:function(e,t){if(this.fn)return arguments.length>3&&(t=[].slice.call(arguments,1,-1)),this.fn(e,t);if(Array.isArray(e)){if(!this.validateMultiple)throw"Validator `"+this.name+"` does not handle multiple values";return this.validateMultiple.apply(this,arguments)}var i=arguments[arguments.length-1];if(this.validateDate&&i._isDateInput())return arguments[0]=a.parse.date(arguments[0]),null!==arguments[0]&&this.validateDate.apply(this,arguments);if(this.validateNumber)return!isNaN(e)&&(arguments[0]=parseFloat(arguments[0]),this.validateNumber.apply(this,arguments));if(this.validateString)return this.validateString.apply(this,arguments);throw"Validator `"+this.name+"` only handles multiple values"},parseRequirements:function(t,i){if("string"!=typeof t)return Array.isArray(t)?t:[t];var n=this.requirementType;if(Array.isArray(n)){for(var r=u(t,n.length),s=0;s<r.length;
425s++)r[s]=a.parseRequirement(n[s],r[s]);return r}return e.isPlainObject(n)?d(n,t,i):[a.parseRequirement(n,t)]},requirementType:"string",priority:2};var p=function(e,t){this.__class__="ValidatorRegistry",this.locale="en",this.init(e||{},t||{})},c={email:/^((([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/,number:/^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,integer:/^-?\d+$/,digits:/^\d+$/,alphanum:/^\w+$/i,date:{test:function(e){return null!==a.parse.date(e)}},url:new RegExp("^(?:(?:https?|ftp)://)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-zA-Z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/\\S*)?$")};c.range=c.number;var f=function(e){var t=(""+e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0},m=function(e,t){return t.map(a.parse[e])},g=function(e,t){return function(i){for(var n=arguments.length,r=Array(n>1?n-1:0),s=1;s<n;s++)r[s-1]=arguments[s];return r.pop(),t.apply(void 0,[i].concat(_toConsumableArray(m(e,r))))}},v=function(e){return{validateDate:g("date",e),validateNumber:g("number",e),requirementType:e.length<=2?"string":["string","string"],priority:30}};p.prototype={init:function(e,t){this.catalog=t,this.validators=_extends({},this.validators);for(var i in e)this.addValidator(i,e[i].fn,e[i].priority);window.Parsley.trigger("parsley:validator:init")},setLocale:function(e){if("undefined"==typeof this.catalog[e])throw new Error(e+" is not available in the catalog");return this.locale=e,this},addCatalog:function(e,t,i){return"object"==typeof t&&(this.catalog[e]=t),!0===i?this.setLocale(e):this},addMessage:function(e,t,i){return"undefined"==typeof this.catalog[e]&&(this.catalog[e]={}),this.catalog[e][t]=i,this},addMessages:function(e,t){for(var i in t)this.addMessage(e,i,t[i]);return this},addValidator:function(e,t,i){if(this.validators[e])a.warn('Validator "'+e+'" is already defined.');else if(o.hasOwnProperty(e))return void a.warn('"'+e+'" is a restricted keyword and is not a valid validator name.');return this._setValidator.apply(this,arguments)},hasValidator:function(e){return!!this.validators[e]},updateValidator:function(e,t,i){return this.validators[e]?this._setValidator.apply(this,arguments):(a.warn('Validator "'+e+'" is not already defined.'),this.addValidator.apply(this,arguments))},removeValidator:function(e){return this.validators[e]||a.warn('Validator "'+e+'" is not defined.'),delete this.validators[e],this},_setValidator:function(e,t,i){"object"!=typeof t&&(t={fn:t,priority:i}),t.validate||(t=new h(t)),this.validators[e]=t;for(var n in t.messages||{})this.addMessage(n,e,t.messages[n]);return this},getErrorMessage:function(e){var t;if("type"===e.name){var i=this.catalog[this.locale][e.name]||{};t=i[e.requirements]}else t=this.formatMessage(this.catalog[this.locale][e.name],e.requirements);return t||this.catalog[this.locale].defaultMessage||this.catalog.en.defaultMessage},formatMessage:function(e,t){if("object"==typeof t){for(var i in t)e=this.formatMessage(e,t[i]);return e}return"string"==typeof e?e.replace(/%s/i,t):""},validators:{notblank:{validateString:function(e){return/\S/.test(e)},priority:2},required:{validateMultiple:function(e){return e.length>0},validateString:function(e){return/\S/.test(e)},priority:512},type:{validateString:function(e,t){var i=arguments.length<=2||void 0===arguments[2]?{}:arguments[2],n=i.step,r=void 0===n?"any":n,s=i.base,a=void 0===s?0:s,o=c[t];if(!o)throw new Error("validator type `"+t+"` is not supported");if(!o.test(e))return!1;if("number"===t&&!/^any$/i.test(r||"")){var l=Number(e),u=Math.max(f(r),f(a));if(f(l)>u)return!1;var d=function(e){return Math.round(e*Math.pow(10,u))};
vendor: 12,666 bytes, line 425
425if((d(l)-d(a))%d(r)!=0)return!1}return!0},requirementType:{"":"string",step:"string",base:"number"},priority:256},pattern:{validateString:function(e,t){return t.test(e)},requirementType:"regexp",priority:64},minlength:{validateString:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxlength:{validateString:function(e,t){return e.length<=t},requirementType:"integer",priority:30},length:{validateString:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},mincheck:{validateMultiple:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxcheck:{validateMultiple:function(e,t){return e.length<=t},requirementType:"integer",priority:30},check:{validateMultiple:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},min:v(function(e,t){return e>=t}),max:v(function(e,t){return e<=t}),range:v(function(e,t,i){return e>=t&&e<=i}),equalto:{validateString:function(t,i){var n=e(i);return n.length?t===n.val():t===i},priority:256}}};var y={},_=function k(e,t,i){for(var n=[],r=[],s=0;s<e.length;s++){for(var a=!1,o=0;o<t.length;o++)if(e[s].assert.name===t[o].assert.name){a=!0;break}a?r.push(e[s]):n.push(e[s])}return{kept:r,added:n,removed:i?[]:k(t,e,!0).added}};y.Form={_actualizeTriggers:function(){var e=this;this.$element.on("submit.Parsley",function(t){e.onSubmitValidate(t)}),this.$element.on("click.Parsley",a._SubmitSelector,function(t){e.onSubmitButton(t)}),!1!==this.options.uiEnabled&&this.element.setAttribute("novalidate","")},focus:function(){if(this._focusedField=null,!0===this.validationResult||"none"===this.options.focus)return null;for(var e=0;e<this.fields.length;e++){var t=this.fields[e];if(!0!==t.validationResult&&t.validationResult.length>0&&"undefined"==typeof t.options.noFocus&&(this._focusedField=t.$element,"first"===this.options.focus))break}return null===this._focusedField?null:this._focusedField.focus()},_destroyUI:function(){this.$element.off(".Parsley")}},y.Field={_reflowUI:function(){if(this._buildUI(),this._ui){var e=_(this.validationResult,this._ui.lastValidationResult);this._ui.lastValidationResult=this.validationResult,this._manageStatusClass(),this._manageErrorsMessages(e),this._actualizeTriggers(),!e.kept.length&&!e.added.length||this._failedOnce||(this._failedOnce=!0,this._actualizeTriggers())}},getErrorsMessages:function(){if(!0===this.validationResult)return[];for(var e=[],t=0;t<this.validationResult.length;t++)e.push(this.validationResult[t].errorMessage||this._getErrorMessage(this.validationResult[t].assert));return e},addError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r||r;this._buildUI(),this._addError(e,{message:i,assert:n}),s&&this._errorClass()},updateError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r||r;this._buildUI(),this._updateError(e,{message:i,assert:n}),s&&this._errorClass()},removeError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.updateClass,n=void 0===i||i;this._buildUI(),this._removeError(e),n&&this._manageStatusClass()},_manageStatusClass:function(){this.hasConstraints()&&this.needsValidation()&&!0===this.validationResult?this._successClass():this.validationResult.length>0?this._errorClass():this._resetClass()},_manageErrorsMessages:function(t){if("undefined"==typeof this.options.errorsMessagesDisabled){if("undefined"!=typeof this.options.errorMessage)return t.added.length||t.kept.length?(this._insertErrorWrapper(),0===this._ui.$errorsWrapper.find(".parsley-custom-error-message").length&&this._ui.$errorsWrapper.append(e(this.options.errorTemplate).addClass("parsley-custom-error-message")),this._ui.$errorsWrapper.addClass("filled").find(".parsley-custom-error-message").html(this.options.errorMessage)):this._ui.$errorsWrapper.removeClass("filled").find(".parsley-custom-error-message").remove();for(var i=0;i<t.removed.length;i++)this._removeError(t.removed[i].assert.name);for(i=0;i<t.added.length;i++)this._addError(t.added[i].assert.name,{message:t.added[i].errorMessage,assert:t.added[i].assert});for(i=0;i<t.kept.length;i++)this._updateError(t.kept[i].assert.name,{message:t.kept[i].errorMessage,assert:t.kept[i].assert})}},_addError:function(t,i){var n=i.message,r=i.assert;this._insertErrorWrapper(),this._ui.$errorClassHandler.attr("aria-describedby",this._ui.errorsWrapperId),this._ui.$errorsWrapper.addClass("filled").append(e(this.options.errorTemplate).addClass("parsley-"+t).html(n||this._getErrorMessage(r)))},_updateError:function(e,t){var i=t.message,n=t.assert;this._ui.$errorsWrapper.addClass("filled").find(".parsley-"+e).html(i||this._getErrorMessage(n))},_removeError:function(e){this._ui.$errorClassHandler.removeAttr("aria-describedby"),this._ui.$errorsWrapper.removeClass("filled").find(".parsley-"+e).remove()},_getErrorMessage:function(e){var t=e.name+"Message";return"undefined"!=typeof this.options[t]?window.Parsley.formatMessage(this.options[t],e.requirements):window.Parsley.getErrorMessage(e)},_buildUI:function(){if(!this._ui&&!1!==this.options.uiEnabled){var t={};this.element.setAttribute(this.options.namespace+"id",this.__id__),t.$errorClassHandler=this._manageClassHandler(),t.errorsWrapperId="parsley-id-"+(this.options.multiple?"multiple-"+this.options.multiple:this.__id__),t.$errorsWrapper=e(this.options.errorsWrapper).attr("id",t.errorsWrapperId),t.lastValidationResult=[],t.validationInformationVisible=!1,this._ui=t}},_manageClassHandler:function(){if("string"==typeof this.options.classHandler&&e(this.options.classHandler).length)return e(this.options.classHandler);var t=this.options.classHandler;if("string"==typeof this.options.classHandler&&"function"==typeof window[this.options.classHandler]&&(t=window[this.options.classHandler]),"function"==typeof t){var i=t.call(this,this);if("undefined"!=typeof i&&i.length)return i}else{if("object"==typeof t&&t instanceof jQuery&&t.length)return t;t&&a.warn("The class handler `"+t+"` does not exist in DOM nor as a global JS function")}return this._inputHolder()},_inputHolder:function(){return this.options.multiple&&"SELECT"!==this.element.nodeName?this.$element.parent():this.$element},_insertErrorWrapper:function(){var t=this.options.errorsContainer;if(0!==this._ui.$errorsWrapper.parent().length)return this._ui.$errorsWrapper.parent();if("string"==typeof t){if(e(t).length)return e(t).append(this._ui.$errorsWrapper);"function"==typeof window[t]?t=window[t]:a.warn("The errors container `"+t+"` does not exist in DOM nor as a global JS function")}return"function"==typeof t&&(t=t.call(this,this)),"object"==typeof t&&t.length?t.append(this._ui.$errorsWrapper):this._inputHolder().after(this._ui.$errorsWrapper)},_actualizeTriggers:function(){var e,t=this,i=this._findRelated();i.off(".Parsley"),this._failedOnce?i.on(a.namespaceEvents(this.options.triggerAfterFailure,"Parsley"),function(){t._validateIfNeeded()}):(e=a.namespaceEvents(this.options.trigger,"Parsley"))&&i.on(e,function(e){t._validateIfNeeded(e)})},_validateIfNeeded:function(e){var t=this;e&&/key|input/.test(e.type)&&(!this._ui||!this._ui.validationInformationVisible)&&this.getValue().length<=this.options.validationThreshold||(this.options.debounce?(window.clearTimeout(this._debounced),this._debounced=window.setTimeout(function(){return t.validate()},this.options.debounce)):this.validate())},_resetUI:function(){this._failedOnce=!1,this._actualizeTriggers(),"undefined"!=typeof this._ui&&(this._ui.$errorsWrapper.removeClass("filled").children().remove(),this._resetClass(),this._ui.lastValidationResult=[],this._ui.validationInformationVisible=!1)},_destroyUI:function(){this._resetUI(),"undefined"!=typeof this._ui&&this._ui.$errorsWrapper.remove(),delete this._ui},_successClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass)},_errorClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass)},_resetClass:function(){this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass)}};var w=function(t,i,n){this.__class__="Form",this.element=t,this.$element=e(t),this.domOptions=i,this.options=n,this.parent=window.Parsley,this.fields=[],this.validationResult=null},b={pending:null,resolved:!0,rejected:!1};w.prototype={onSubmitValidate:function(e){var t=this;if(!0!==e.parsley){var i=this._submitSource||this.$element.find(a._SubmitSelector)[0];if(this._submitSource=null,this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!0),!i||null===i.getAttribute("formnovalidate")){window.Parsley._remoteCache={};var n=this.whenValidate({event:e});"resolved"===n.state()&&!1!==this._trigger("submit")||(e.stopImmediatePropagation(),e.preventDefault(),"pending"===n.state()&&n.done(function(){t._submit(i)}))}}},onSubmitButton:function(e){this._submitSource=e.currentTarget},_submit:function(t){if(!1!==this._trigger("submit")){if(t){var i=this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!1);0===i.length&&(i=e('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element)),i.attr({name:t.getAttribute("name"),value:t.getAttribute("value")})}this.$element.trigger(_extends(e.Event("submit"),{parsley:!0}))}},validate:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling validate on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1],s=i[2];t={group:n,force:r,event:s}}return b[this.whenValidate(t).state()]},whenValidate:function(){var t,i=this,n=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],r=n.group,s=n.force,o=n.event;this.submitEvent=o,o&&(this.submitEvent=_extends({},o,{preventDefault:function(){a.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`"),i.validationResult=!1}})),this.validationResult=!0,this._trigger("validate"),this._refreshFields();var l=this._withoutReactualizingFormOptions(function(){return e.map(i.fields,function(e){return e.whenValidate({force:s,group:r})})});return(t=a.all(l).done(function(){i._trigger("success")}).fail(function(){i.validationResult=!1,i.focus(),i._trigger("error")}).always(function(){i._trigger("validated")})).pipe.apply(t,_toConsumableArray(this._pipeAccordingToValidationResult()))},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={group:n,force:r}}return b[this.whenValid(t).state()]},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force;this._refreshFields();var s=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValid({group:n,force:r})})});return a.all(s)},refresh:function(){return this._refreshFields(),this},reset:function(){for(var e=0;e<this.fields.length;e++)this.fields[e].reset();this._trigger("reset")},destroy:function(){this._destroyUI();for(var e=0;e<this.fields.length;e++)this.fields[e].destroy();this.$element.removeData("Parsley"),this._trigger("destroy")},_refreshFields:function(){return this.actualizeOptions()._bindFields()},_bindFields:function(){var t=this,i=this.fields;return this.fields=[],this.fieldsMappedById={},this._withoutReactualizingFormOptions(function(){t.$element.find(t.options.inputs).not(t.options.excluded).each(function(e,i){var n=new window.Parsley.Factory(i,{},t);if(("Field"===n.__class__||"FieldMultiple"===n.__class__)&&!0!==n.options.excluded){var r=n.__class__+"-"+n.__id__;"undefined"==typeof t.fieldsMappedById[r]&&(t.fieldsMappedById[r]=n,t.fields.push(n))}}),e.each(a.difference(i,t.fields),function(e,t){t.reset()})}),this},_withoutReactualizingFormOptions:function(e){var t=this.actualizeOptions;this.actualizeOptions=function(){return this};var i=e();return this.actualizeOptions=t,i},_trigger:function(e){return this.trigger("form:"+e)}};var F=function(e,t,i,n,r){var s=window.Parsley._validatorRegistry.validators[t],a=new h(s);n=n||e.options[t+"Priority"]||a.priority,r=!0===r,_extends(this,{validator:a,name:t,requirements:i,priority:n,isDomConstraint:r}),this._parseRequirements(e.options)},C=function(e){var t=e[0].toUpperCase();return t+e.slice(1)};F.prototype={validate:function(e,t){var i;
425return(i=this.validator).validate.apply(i,[e].concat(_toConsumableArray(this.requirementList),[t]))},_parseRequirements:function(e){var t=this;this.requirementList=this.validator.parseRequirements(this.requirements,function(i){return e[t.name+C(i)]})}};var A=function(t,i,n,r){this.__class__="Field",this.element=t,this.$element=e(t),"undefined"!=typeof r&&(this.parent=r),this.options=n,this.domOptions=i,this.constraints=[],this.constraintsByName={},this.validationResult=!0,this._bindConstraints()},E={pending:null,resolved:!0,rejected:!1};A.prototype={validate:function(t){arguments.length>=1&&!e.isPlainObject(t)&&(a.warnOnce("Calling validate on a parsley field without passing arguments as an object is deprecated."),t={options:t});var i=this.whenValidate(t);if(!i)return!0;switch(i.state()){case"pending":return null;case"resolved":return!0;case"rejected":return this.validationResult}},whenValidate:function(){var e,t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.force,r=i.group;if(this.refresh(),!r||this._isInGroup(r))return this.value=this.getValue(),this._trigger("validate"),(e=this.whenValid({force:n,value:this.value,_refreshed:!0}).always(function(){t._reflowUI()}).done(function(){t._trigger("success")}).fail(function(){t._trigger("error")}).always(function(){t._trigger("validated")})).pipe.apply(e,_toConsumableArray(this._pipeAccordingToValidationResult()))},hasConstraints:function(){return 0!==this.constraints.length},needsValidation:function(e){return"undefined"==typeof e&&(e=this.getValue()),!(!e.length&&!this._isRequired()&&"undefined"==typeof this.options.validateIfEmpty)},_isInGroup:function(t){return Array.isArray(this.options.group)?-1!==e.inArray(t,this.options.group):this.options.group===t},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley field without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={force:n,value:r}}var s=this.whenValid(t);return!s||E[s.state()]},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.force,r=void 0!==n&&n,s=i.value,o=i.group,l=i._refreshed;if(l||this.refresh(),!o||this._isInGroup(o)){if(this.validationResult=!0,!this.hasConstraints())return e.when();if("undefined"!=typeof s&&null!==s||(s=this.getValue()),!this.needsValidation(s)&&!0!==r)return e.when();var u=this._getGroupedConstraints(),d=[];return e.each(u,function(i,n){var r=a.all(e.map(n,function(e){return t._validateConstraint(s,e)}));if(d.push(r),"rejected"===r.state())return!1}),a.all(d)}},_validateConstraint:function(t,i){var n=this,r=i.validate(t,this);return!1===r&&(r=e.Deferred().reject()),a.all([r]).fail(function(e){n.validationResult instanceof Array||(n.validationResult=[]),n.validationResult.push({assert:i,errorMessage:"string"==typeof e&&e})})},getValue:function(){var e;return e="function"==typeof this.options.value?this.options.value(this):"undefined"!=typeof this.options.value?this.options.value:this.$element.val(),"undefined"==typeof e||null===e?"":this._handleWhitespace(e)},reset:function(){return this._resetUI(),this._trigger("reset")},destroy:function(){this._destroyUI(),this.$element.removeData("Parsley"),this.$element.removeData("FieldMultiple"),this._trigger("destroy")},refresh:function(){return this._refreshConstraints(),this},_refreshConstraints:function(){return this.actualizeOptions()._bindConstraints()},refreshConstraints:function(){return a.warnOnce("Parsley's refreshConstraints is deprecated. Please use refresh"),this.refresh()},addConstraint:function(e,t,i,n){if(window.Parsley._validatorRegistry.validators[e]){var r=new F(this,e,t,i,n);"undefined"!==this.constraintsByName[r.name]&&this.removeConstraint(r.name),this.constraints.push(r),this.constraintsByName[r.name]=r}return this},removeConstraint:function(e){for(var t=0;t<this.constraints.length;t++)if(e===this.constraints[t].name){this.constraints.splice(t,1);break}return delete this.constraintsByName[e],this},updateConstraint:function(e,t,i){return this.removeConstraint(e).addConstraint(e,t,i)},_bindConstraints:function(){for(var e=[],t={},i=0;i<this.constraints.length;i++)!1===this.constraints[i].isDomConstraint&&(e.push(this.constraints[i]),t[this.constraints[i].name]=this.constraints[i]);this.constraints=e,this.constraintsByName=t;for(var n in this.options)this.addConstraint(n,this.options[n],void 0,!0);return this._bindHtml5Constraints()},_bindHtml5Constraints:function(){null!==this.element.getAttribute("required")&&this.addConstraint("required",!0,void 0,!0),null!==this.element.getAttribute("pattern")&&this.addConstraint("pattern",this.element.getAttribute("pattern"),void 0,!0);var e=this.element.getAttribute("min"),t=this.element.getAttribute("max");null!==e&&null!==t?this.addConstraint("range",[e,t],void 0,!0):null!==e?this.addConstraint("min",e,void 0,!0):null!==t&&this.addConstraint("max",t,void 0,!0),null!==this.element.getAttribute("minlength")&&null!==this.element.getAttribute("maxlength")?this.addConstraint("length",[this.element.getAttribute("minlength"),this.element.getAttribute("maxlength")],void 0,!0):null!==this.element.getAttribute("minlength")?this.addConstraint("minlength",this.element.getAttribute("minlength"),void 0,!0):null!==this.element.getAttribute("maxlength")&&this.addConstraint("maxlength",this.element.getAttribute("maxlength"),void 0,!0);var i=a.getType(this.element);return"number"===i?this.addConstraint("type",["number",{step:this.element.getAttribute("step")||"1",base
vendor: 5,155 bytes, lines 425-426
425:e||this.element.getAttribute("value")}],void 0,!0):/^(email|url|range|date)$/i.test(i)?this.addConstraint("type",i,void 0,!0):this},_isRequired:function(){return"undefined"!=typeof this.constraintsByName.required&&!1!==this.constraintsByName.required.requirements},_trigger:function(e){return this.trigger("field:"+e)},_handleWhitespace:function(e){return!0===this.options.trimValue&&a.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"'),"squish"===this.options.whitespace&&(e=e.replace(/\s{2,}/g," ")),"trim"!==this.options.whitespace&&"squish"!==this.options.whitespace&&!0!==this.options.trimValue||(e=a.trimString(e)),e},_isDateInput:function(){var e=this.constraintsByName.type;return e&&"date"===e.requirements},_getGroupedConstraints:function(){if(!1===this.options.priorityEnabled)return[this.constraints];for(var e=[],t={},i=0;i<this.constraints.length;i++){var n=this.constraints[i].priority;t[n]||e.push(t[n]=[]),t[n].push(this.constraints[i])}return e.sort(function(e,t){return t[0].priority-e[0].priority}),e}};var x=A,$=function(){this.__class__="FieldMultiple"};$.prototype={addElement:function(e){return this.$elements.push(e),this},_refreshConstraints:function(){var t;if(this.constraints=[],"SELECT"===this.element.nodeName)return this.actualizeOptions()._bindConstraints(),this;for(var i=0;i<this.$elements.length;i++)if(e("html").has(this.$elements[i]).length){t=this.$elements[i].data("FieldMultiple")._refreshConstraints().constraints;for(var n=0;n<t.length;n++)this.addConstraint(t[n].name,t[n].requirements,t[n].priority,t[n].isDomConstraint)}else this.$elements.splice(i,1);return this},getValue:function(){if("function"==typeof this.options.value)return this.options.value(this);if("undefined"!=typeof this.options.value)return this.options.value;if("INPUT"===this.element.nodeName){var t=a.getType(this.element);if("radio"===t)return this._findRelated().filter(":checked").val()||"";if("checkbox"===t){
426    var i=[];return this._findRelated().filter(":checked").each(function(){i.push(e(this).val())}),i}}return"SELECT"===this.element.nodeName&&null===this.$element.val()?[]:this.$element.val()},_init:function(){return this.$elements=[this.$element],this}};var P=function(t,i,n){this.element=t,this.$element=e(t);var r=this.$element.data("Parsley");if(r)return"undefined"!=typeof n&&r.parent===window.Parsley&&(r.parent=n,r._resetOptions(r.options)),"object"==typeof i&&_extends(r.options,i),r;if(!this.$element.length)throw new Error("You must bind Parsley on an existing element.");if("undefined"!=typeof n&&"Form"!==n.__class__)throw new Error("Parent instance must be a Form instance");return this.parent=n||window.Parsley,this.init(i)};P.prototype={init:function(e){return this.__class__="Parsley",this.__version__="2.8.1",this.__id__=a.generateID(),this._resetOptions(e),"FORM"===this.element.nodeName||a.checkAttr(this.element,this.options.namespace,"validate")&&!this.$element.is(this.options.inputs)?this.bind("parsleyForm"):this.isMultiple()?this.handleMultiple():this.bind("parsleyField")},isMultiple:function(){var e=a.getType(this.element);return"radio"===e||"checkbox"===e||"SELECT"===this.element.nodeName&&null!==this.element.getAttribute("multiple")},handleMultiple:function(){var t,i,n=this;if(this.options.multiple=this.options.multiple||(t=this.element.getAttribute("name"))||this.element.getAttribute("id"),"SELECT"===this.element.nodeName&&null!==this.element.getAttribute("multiple"))return this.options.multiple=this.options.multiple||this.__id__,this.bind("parsleyFieldMultiple");if(!this.options.multiple)return a.warn("To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.",this.$element),this;this.options.multiple=this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g,""),t&&e('input[name="'+t+'"]').each(function(e,t){var i=a.getType(t);"radio"!==i&&"checkbox"!==i||t.setAttribute(n.options.namespace+"multiple",n.options.multiple)});for(var r=this._findRelated(),s=0;s<r.length;s++)if(i=e(r.get(s)).data("Parsley"),"undefined"!=typeof i){this.$element.data("FieldMultiple")||i.addElement(this.$element);break}return this.bind("parsleyField",!0),i||this.bind("parsleyFieldMultiple")},bind:function(t,i){var n;switch(t){case"parsleyForm":n=e.extend(new w(this.element,this.domOptions,this.options),new l,window.ParsleyExtend)._bindFields();break;case"parsleyField":n=e.extend(new x(this.element,this.domOptions,this.options,this.parent),new l,window.ParsleyExtend);break;case"parsleyFieldMultiple":n=e.extend(new x(this.element,this.domOptions,this.options,this.parent),new $,new l,window.ParsleyExtend)._init();break;default:throw new Error(t+"is not a supported Parsley type")}return this.options.multiple&&a.setAttr(this.element,this.options.namespace,"multiple",this.options.multiple),"undefined"!=typeof i?(this.$element.data("FieldMultiple",n),n):(this.$element.data("Parsley",n),n._actualizeTriggers(),n._trigger("init"),n)}};var V=e.fn.jquery.split(".");if(parseInt(V[0])<=1&&parseInt(V[1])<8)throw"The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
426V.forEach||a.warn("Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim");var T=_extends(new l,{element:document,$element:e(document),actualizeOptions:null,_resetOptions:null,Factory:P,version:"2.8.1"});_extends(x.prototype,y.Field,l.prototype),_extends(w.prototype,y.Form,l.prototype),_extends(P.prototype,l.prototype),e.fn.parsley=e.fn.psly=function(t){if(this.length>1){var i=[];return this.each(function(){i.push(e(this).parsley(t))}),i}if(0!=this.length)return new P(this[0],t)},"undefined"==typeof window.ParsleyExtend&&(window.ParsleyExtend={}),T.options=_extends(a.objectCreate(o),window.ParsleyConfig),window.ParsleyConfig=T.options,window.Parsley=window.psly=T,T.Utils=a,window.ParsleyUtils={},e.each(a,function(e,t){"function"==typeof t&&(window.ParsleyUtils[e]=function(){return a.warnOnce("Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead."),a[e].apply(a,arguments)})});var O=window.Parsley._validatorRegistry=new p(window.ParsleyConfig.validators,window.ParsleyConfig.i18n);window.ParsleyValidator={},e.each("setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator hasValidator".split(" "),function(e,t){window.Parsley[t]=function(){return O[t].apply(O,arguments)},window.ParsleyValidator[t]=function(){var e;return a.warnOnce("Accessing the method '"+t+"' through Validator is deprecated. Simply call 'window.Parsley."+t+"(...)'"),(e=window.Parsley)[t].apply(e,arguments)}}),window.Parsley.UI=y,window.ParsleyUI={removeError:function(e,t,i){var n=!0!==i;return a.warnOnce("Accessing UI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e.removeError(t,{updateClass:n})},getErrorsMessages:function(e){return a.warnOnce("Accessing UI is deprecated. Call 'getErrorsMessages' on the instance directly."),e.getErrorsMessages()}},e.each("addError updateError".split(" "),function(e,t){window.ParsleyUI[t]=function(e,i,n,r,s){var o=!0!==s;return a.warnOnce("Accessing UI is deprecated. Call '"+t+"' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e[t](i,{message:n,assert:r,updateClass:o})}}),!1!==window.ParsleyConfig.autoBind&&e(function(){e("[data-parsley-validate]").length&&e("[data-parsley-validate]").parsley()});var M=e({}),R=function(){a.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley")},D="parsley:";e.listen=function(e,n){var r;if(R(),"object"==typeof arguments[1]&&"function"==typeof arguments[2]&&(r=arguments[1],n=arguments[2]),"function"!=typeof n)throw new Error("Wrong parameters");window.Parsley.on(i(e),t(n,r))},e.listenTo=function(e,n,r){if(R(),!(e instanceof x||e instanceof w))throw new Error("Mu
426st give Parsley instance");if("string"!=typeof n||"function"!=typeof r)throw new Error("Wrong parameters");e.on(i(n),t(r))},e.unsubscribe=function(e,t){if(R(),"string"!=typeof e||"function"!=typeof t)throw new Error("Wrong arguments");window.Parsley.off(i(e),t.parsleyAdaptedCallback)},e.unsubscribeTo=function(e,t){if(R(),!(e instanceof x||e instanceof w))throw new Error("Must give Parsley instance");e.off(i(t))},e.unsubscribeAll=function(t){R(),window.Parsley.off(i(t)),e("form,input,textarea,select").each(function(){var n=e(this).data("Parsley");n&&n.off(i(t))})},e.emit=function(e,t){var n;R();var r=t instanceof x||t instanceof w,s=Array.prototype.slice.call(arguments,r?2:1);s.unshift(i(e)),r||(t=window.Parsley),(n=t).trigger.apply(n,_toConsumableArray(s))};e.extend(!0,T,{asyncValidators:{"default":{fn:function(e){return e.status>=200&&e.status<300},url:!1},reverse:{fn:function(e){return e.status<200||e.status>=300},url:!1}},addAsyncValidator:function(e,t,i,n){return T.asyncValidators[e]={fn:t,url:i||!1,options:n||{}},this}}),T.addValidator("remote",{requirementType:{"":"string",validator:"string",reverse:"boolean",options:"object"},validateString:function(t,i,n,r){var s,a,o={},l=n.validator||(!0===n.reverse?"reverse":"default");if("undefined"==typeof T.asyncValidators[l])throw new Error("Calling an undefined async validator: `"+l+"`");i=T.asyncValidators[l].url||i,i.indexOf("{value}")>-1?i=i.replace("{value}",encodeURIComponent(t)):o[r.element.getAttribute("name")||r.element.getAttribute("id")]=t;var u=e.extend(!0,n.options||{},T.asyncValidators[l].options);s=e.extend(!0,{},{url:i,data:o,type:"GET"},u),r.trigger("field:ajaxoptions",r,s),a=e.param(s),"undefined"==typeof T._remoteCache&&(T._remoteCache={});var d=T._remoteCache[a]=T._remoteCache[a]||e.ajax(s),h=function(){var t=T.asyncValidators[l].fn.call(r,d,i,n);return t||(t=e.Deferred().reject()),e.when(t)};return d.then(h,h)},priority:-1}),T.on("form:submit",function(){T._remoteCache={}}),l.prototype.addAsyncValidator=function(){return a.warnOnce("Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`"),T.addAsyncValidator.apply(T,arguments)},T.addMessages("en",{defaultMessage:"This value seems to be invalid.",type:{email:"This value should be a valid email.",url:"This value should be a valid url.",number:"This value should be a valid number.",integer:"This value should be a valid integer.",digits:"This value should be digits.",alphanum:"This value should be alphanumeric."},notblank:"This value should not be blank.",required:"This value is required.",pattern:"This value seems to be invalid.",min:"This value should be greater than or equal to %s.",max:"This value should be lower than or equal to %s.",range:"This value should be between %s and %s.",minlength:"This value is too short. It should have %s characters or more.",maxlength:"This value is too long. It should have %s characters or fewer.",length:"This value length is invalid. It should be between %s and %s characters long.",mincheck:"You must select at least %s choices.",maxcheck:"You must select %s choices or fewer.",check:"You must select between %s and %s choices.",equalto:"This value should be the same."}),T.setLocale("en");var I=new n;I.install();var q=T;return q});
427//# sourceMappingURL=parsley.min.js.map
428/*
429 * Copyright (c) 2014 Mike King (@micjamking)
430 *
431 * jQuery Succinct plugin
432 * Version 1.1.0 (October 2014)
433 *
434 * Licensed under the MIT License
435 */
436/*global jQuery*/
437!function(a){"use strict";a.fn.succinct=function(b){var c=a.extend({size:240,omission:"...",ignore:!0},b);return this.each(function(){var b,d,e=a(this),f=/[!-\/:-@\[-`{-~]$/,g=function(){e.each(function(){b=a(this).html(),b.length>c.size&&(d=a.trim(b).substring(0,c.size).split(" ").slice(0,-1).join(" "),c.ignore&&(d=d.replace(f,"")),a(this).html(d+c.omission))})};g()})}}(jQuery);
438/*!
439 * JavaScript Cookie v2.2.0
440 * https://github.com/js-cookie/js-cookie
441 *
442 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
443 * Released under the MIT license
444 */
445;(function (factory) {
446	var registeredInModuleLoader;
447	if (typeof define === 'function' && define.amd) {
448		define(factory);
449		registeredInModuleLoader = true;
450	}
451	if (typeof exports === 'object') {
452		module.exports = factory();
453		registeredInModuleLoader = true;
454	}
455	if (!registeredInModuleLoader) {
456		var OldCookies = window.Cookies;
457		var api = window.Cookies = factory();
458		api.noConflict = function () {
459			window.Cookies = OldCookies;
460			return api;
461		};
462	}
463}(function () {
464	function extend () {
465		var i = 0;
466		var result = {};
467		for (; i < arguments.length; i++) {
468			var attributes = arguments[ i ];
469			for (var key in attributes) {
470				result[key] = attributes[key];
471			}
472		}
473		return result;
474	}
475
476	function init (converter) {
477		function api (key, value, attributes) {
478			if (typeof document === 'undefined') {
479				return;
480			}
481
482			// Write
483
484			if (arguments.length > 1) {
485				attributes = extend({
486					path: '/'
487				}, api.defaults, attributes);
488
489				if (typeof attributes.expires === 'number') {
490					attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
491				}
492
493				// We're using "expires" because "max-age" is not supported by IE
494				attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
495
496				try {
497					var result = JSON.stringify(value);
498					if (/^[\{\[]/.test(result)) {
499						value = result;
500					}
501				} catch (e) {}
502
503				value = converter.write ?
504					converter.write(value, key) :
505					encodeURIComponent(String(value))
506						.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
507
508				key = encodeURIComponent(String(key))
509					.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
510					.replace(/[\(\)]/g, escape);
511
512				var stringifiedAttributes = '';
513				for (var attributeName in attributes) {
514					if (!attributes[attributeName]) {
515						continue;
516					}
517					stringifiedAttributes += '; ' + attributeName;
518					if (attributes[attributeName] === true) {
519						continue;
520					}
521
522					// Considers RFC 6265 section 5.2:
523					// ...
524					// 3.  If the remaining unparsed-attributes contains a %x3B (";")
525					//     character:
526					// Consume the characters of the unparsed-attributes up to,
527					// not including, the first %x3B (";") character.
528					// ...
529					stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
530				}
531
532				return (document.cookie = key + '=' + value + stringifiedAttributes);
533			}
534
535			// Read
536
537			var jar = {};
538			var decode = function (s) {
539				return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
540			};
541			// To prevent the for loop in the first place assign an empty array
542			// in case there are no cookies at all.
543			var cookies = document.cookie ? document.cookie.split('; ') : [];
544			var i = 0;
545
546			for (; i < cookies.length; i++) {
547				var parts = cookies[i].split('=');
548				var cookie = parts.slice(1).join('=');
549
550				if (!this.json && cookie.charAt(0) === '"') {
551					cookie = cookie.slice(1, -1);
552				}
553
554				try {
555					var name = decode(parts[0]);
556					cookie = (converter.read || converter)(cookie, name) ||
557						decode(cookie);
558
559					if (this.json) {
560						try {
561							cookie = JSON.parse(cookie);
562						} catch (e) {}
563					}
564
565					jar[name] = cookie;
566
567					if (key === name) {
568						break;
569					}
570				} catch (e) {}
571			}
572
573			return key ? jar[key] : jar;
574		}
575
576		api.set = api;
577		api.get = function (key) {
578			return api.call(api, key);
579		};
580		api.getJSON = function () {
581			return api.apply({
582				json: true
583			}, arguments);
584		};
585		api.remove = function (key, attributes) {
586			api(key, '', extend(attributes, {
587				expires: -1
588			}));
589		};
590
591		api.defaults = {};
592
593		api.withConverter = init;
594
595		return api;
596	}
597
598	return init(function () {});
599}));
600/**
601 * Debounce and throttle function's decorator plugin 1.0.5
602 *
603 * Copyright (c) 2009 Filatov Dmitry ([email protected])
604 * Dual licensed under the MIT and GPL licenses:
605 * http://www.opensource.org/licenses/mit-license.php
606 * http://www.gnu.org/licenses/gpl.html
607 *
608 */
609
610(function($) {
611
612$.extend({
613
614	debounce : function(fn, timeout, invokeAsap, ctx) {
615
616		if(arguments.length == 3 && typeof invokeAsap != 'boolean') {
617			ctx = invokeAsap;
618			invokeAsap = false;
619		}
620
621		var timer;
622
623		return function() {
624
625			var args = arguments;
626            ctx = ctx || this;
627
628			invokeAsap && !timer && fn.apply(ctx, args);
629
630			clearTimeout(timer);
631
632			timer = setTimeout(function() {
633				!invokeAsap && fn.apply(ctx, args);
634				timer = null;
635			}, timeout);
636
637		};
638
639	},
640
641	throttle : function(fn, timeout, ctx) {
642
643		var timer, args, needInvoke;
644
645		return function() {
646
647			args = arguments;
648			needInvoke = true;
649			ctx = ctx || this;
650
651			if(!timer) {
652				(function() {
653					if(needInvoke) {
654						fn.apply(ctx, args);
655						needInvoke = false;
656						timer = setTimeout(arguments.callee, timeout);
657					}
658					else {
659						timer = null;
660					}
661				})();
662			}
663
664		};
665
666	}
667
668});
669
670})(jQuery);
671!function(n,r){var t,e;"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define("underscore",r):(t=n._,e=r(),(n._=e).noConflict=function(){return n._=t,e})}(this,function(){
672//     Underscore.js 1.10.2
673//     https://underscorejs.org
674//     (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
675//     Underscore may be freely distributed under the MIT license.
676var n="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||Function("return this")()||{},e=Array.prototype,i=Object.prototype,p="undefined"!=typeof Symbol?Symbol.prototype:null,u=e.push,f=e.slice,s=i.toString,o=i.hasOwnProperty,r=Array.isArray,a=Object.keys,t=Object.create,c=n.isNaN,l=n.isFinite,v=function(){};function h(n){return n instanceof h?n:this instanceof h?void(this._wrapped=n):new h(n)}var g=h.VERSION="1.10.2";function y(u,o,n){if(void 0===o)return u;switch(null==n?3:n){case 1:return function(n){return u.call(o,n)};case 3:return function(n,r,t){return u.call(o,n,r,t)};case 4:return function(n,r,t,e){return u.call(o,n,r,t,e)}}return function(){return u.apply(o,arguments)}}function d(n,r,t){return null==n?ur:Cn(n)?y(n,r,t):Ln(n)&&!Kn(n)?ir(n):or(n)}function m(n,r){return d(n,r,1/0)}function b(n,r,t){return h.iteratee!==m?h.iteratee(n,r):d(n,r,t)}function j(u,o){return o=null==o?u.length-1:+o,function(){for(var n=Math.max(arguments.length-o,0),r=Array(n),t=0;t<n;t++)r[t]=arguments[t+o];switch(o){case 0:return u.call(this,r);case 1:return u.call(this,arguments[0],r);case 2:return u.call(this,arguments[0],arguments[1],r)}var e=Array(o+1);for(t=0;t<o;t++)e[t]=arguments[t];return e[o]=r,u.apply(this,e)}}function _(n){if(!Ln(n))return{};if(t)return t(n);v.prototype=n;var r=new v;return v.prototype=null,r}function w(r){return function(n){return null==n?void 0:n[r]}}function x(n,r){return null!=n&&o.call(n,r)}function S(n,r){for(var t=r.length,e=0;e<t;e++){if(null==n)return;n=n[r[e]]}return t?n:void 0}h.iteratee=m;var A=Math.pow(2,53)-1,O=w("length");function M(n){var r=O(n);return"number"==typeof r&&0<=r&&r<=A}function E(n,r,t){var e,u;if(r=y(r,t),M(n))for(e=0,u=n.length;e<u;e++)r(n[e],e,n);else{var o=Sn(n);for(e=0,u=o.length;e<u;e++)r(n[o[e]],o[e],n)}return n}function N(n,r,t){r=b(r,t);for(var e=!M(n)&&Sn(n),u=(e||n).length,o=Array(u),i=0;i<u;i++){var a=e?e[i]:i;o[i]=r(n[a],a,n)}return o}function k(f){return function(n,r,t,e){var u=3<=arguments.length;return function(n,r,t,e){var u=!M(n)&&Sn(n),o=(u||n).length,i=0<f?0:o-1;for(e||(t=n[u?u[i]:i],i+=f);0<=i&&i<o;i+=f){var a=u?u[i]:i;t=r(t,n[a],a,n)}return t}(n,y(r,e,4),t,u)}}var I=k(1),T=k(-1);function B(n,r,t){var e=(M(n)?on:Tn)(n,r,t);if(void 0!==e&&-1!==e)return n[e]}function R(n,e,r){var u=[];return e=b(e,r),E(n,function(n,r,t){e(n,r,t)&&u.push(n)}),u}function F(n,r,t){r=b(r,t);for(var e=!M(n)&&Sn(n),u=(e||n).length,o=0;o<u;o++){var i=e?e[o]:o;if(!r(n[i],i,n))return!1}return!0}function q(n,r,t){r=b(r,t);for(var e=!M(n)&&Sn(n),u=(e||n).length,o=0;o<u;o++){var i=e?e[o]:o;if(r(n[i],i,n))return!0}return!1}function D(n,r,t,e){return M(n)||(n=On(n)),("number"!=typeof t||e)&&(t=0),0<=ln(n,r,t)}var W=j(function(n,t,e){var u,o;return Cn(t)?o=t:Kn(t)&&(u=t.slice(0,-1),t=t[t.length-1]),N(n,function(n){var r=o;if(!r){if(u&&u.length&&(n=S(n,u)),null==n)return;r=n[t]}return null==r?r:r.apply(n,e)})});function z(n,r){return N(n,or(r))}function P(n,e,r){var t,u,o=-1/0,i=-1/0;if(null==e||"number"==typeof e&&"object"!=typeof n[0]&&null!=n)for(var a=0,f=(n=M(n)?n:On(n)).length;a<f;a++)null!=(t=n[a])&&o<t&&(o=t);else e=b(e,r),E(n,function(n,r,t){u=e(n,r,t),(i<u||u===-1/0&&o===-1/0)&&(o=n,i=u)});return o}function K(n,r,t){if(null==r||t)return M(n)||(n=On(n)),n[ar(n.length-1)];var e=M(n)?Dn(n):On(n),u=O(e);r=Math.max(Math.min(r,u),0);for(var o=u-1,i=0;i<r;i++){var a=ar(i,o),f=e[i];e[i]=e[a],e[a]=f}return e.slice(0,r)}function L(i,r){return function(e,u,n){var o=r?[[],[]]:{};return u=b(u,n),E(e,function(n,r){var t=u(n,r,e);i(o,n,t)}),o}}var V=L(function(n,r,t){x(n,t)?n[t].push(r):n[t]=[r]}),C=L(function(n,r,t){n[t]=r}),J=L(function(n,r,t){x(n,t)?n[t]++:n[t]=1}),U=/[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;var $=L(function(n,r,t){n[t?0:1].push(r)},!0);function G(n,r,t){return null==n||n.length<1?null==r?void 0:[]:null==r||t?n[0]:H(n,n.length-r)}function H(n,r,t){return f.call(n,0,Math.max(0,n.length-(null==r||t?1:r)))}function Q(n,r,t){return f.call(n,null==r||t?1:r)}function X(n,r,t,e){for(var u=(e=e||[]).length,o=0,i=O(n);o<i;o++){var a=n[o];if(M(a)&&(Kn(a)||Vn(a)))if(r)for(var f=0,c=a.length;f<c;)e[u++]=a[f++];else X(a,r,t,e),u=e.length;else t||(e[u++]=a)}return e}var Y=j(function(n,r){return rn(n,r)});function Z(n,r,t,e){er(r)||(e=t,t=r,r=!1),null!=t&&(t=b(t,e));for(var u=[],o=[],i=0,a=O(n);i<a;i++){var f=n[i],c=t?t(f,i,n):f;r&&!t?(i&&o===c||u.push(f),o=c):t?D(o,c)||(o.push(c),u.push(f)):D(u,f)||u.push(f)}return u}var nn=j(function(n){return Z(X(n,!0,!0))});
vendor: 8,939 bytes, line 676
676var rn=j(function(n,r){return r=X(r,!0,!0),R(n,function(n){return!D(r,n)})});function tn(n){for(var r=n&&P(n,O).length||0,t=Array(r),e=0;e<r;e++)t[e]=z(n,e);return t}var en=j(tn);function un(o){return function(n,r,t){r=b(r,t);for(var e=O(n),u=0<o?0:e-1;0<=u&&u<e;u+=o)if(r(n[u],u,n))return u;return-1}}var on=un(1),an=un(-1);function fn(n,r,t,e){for(var u=(t=b(t,e,1))(r),o=0,i=O(n);o<i;){var a=Math.floor((o+i)/2);t(n[a])<u?o=a+1:i=a}return o}function cn(o,i,a){return function(n,r,t){var e=0,u=O(n);if("number"==typeof t)0<o?e=0<=t?t:Math.max(t+u,e):u=0<=t?Math.min(t+1,u):t+u+1;else if(a&&t&&u)return n[t=a(n,r)]===r?t:-1;if(r!=r)return 0<=(t=i(f.call(n,e,u),tr))?t+e:-1;for(t=0<o?e:u-1;0<=t&&t<u;t+=o)if(n[t]===r)return t;return-1}}var ln=cn(1,on,fn),pn=cn(-1,an);function sn(n,r,t,e,u){if(!(e instanceof r))return n.apply(t,u);var o=_(n.prototype),i=n.apply(o,u);return Ln(i)?i:o}var vn=j(function(r,t,e){if(!Cn(r))throw new TypeError("Bind must be called on a function");var u=j(function(n){return sn(r,u,t,this,e.concat(n))});return u}),hn=j(function(u,o){var i=hn.placeholder,a=function(){for(var n=0,r=o.length,t=Array(r),e=0;e<r;e++)t[e]=o[e]===i?arguments[n++]:o[e];for(;n<arguments.length;)t.push(arguments[n++]);return sn(u,a,this,this,t)};return a});hn.placeholder=h;var gn=j(function(n,r){var t=(r=X(r,!1,!1)).length;if(t<1)throw new Error("bindAll must be passed function names");for(;t--;){var e=r[t];n[e]=vn(n[e],n)}});var yn=j(function(n,r,t){return setTimeout(function(){return n.apply(null,t)},r)}),dn=hn(yn,h,1);function mn(n){return function(){return!n.apply(this,arguments)}}function bn(n,r){var t;return function(){return 0<--n&&(t=r.apply(this,arguments)),n<=1&&(r=null),t}}var jn=hn(bn,2),_n=!{toString:null}.propertyIsEnumerable("toString"),wn=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];function xn(n,r){var t=wn.length,e=n.constructor,u=Cn(e)&&e.prototype||i,o="constructor";for(x(n,o)&&!D(r,o)&&r.push(o);t--;)(o=wn[t])in n&&n[o]!==u[o]&&!D(r,o)&&r.push(o)}function Sn(n){if(!Ln(n))return[];if(a)return a(n);var r=[];for(var t in n)x(n,t)&&r.push(t);return _n&&xn(n,r),r}function An(n){if(!Ln(n))return[];var r=[];for(var t in n)r.push(t);return _n&&xn(n,r),r}function On(n){for(var r=Sn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=n[r[u]];return e}function Mn(n){for(var r={},t=Sn(n),e=0,u=t.length;e<u;e++)r[n[t[e]]]=t[e];return r}function En(n){var r=[];for(var t in n)Cn(n[t])&&r.push(t);return r.sort()}function Nn(f,c){return function(n){var r=arguments.length;if(c&&(n=Object(n)),r<2||null==n)return n;for(var t=1;t<r;t++)for(var e=arguments[t],u=f(e),o=u.length,i=0;i<o;i++){var a=u[i];c&&void 0!==n[a]||(n[a]=e[a])}return n}}var kn=Nn(An),In=Nn(Sn);function Tn(n,r,t){r=b(r,t);for(var e,u=Sn(n),o=0,i=u.length;o<i;o++)if(r(n[e=u[o]],e,n))return e}function Bn(n,r,t){return r in t}var Rn=j(function(n,r){var t={},e=r[0];if(null==n)return t;Cn(e)?(1<r.length&&(e=y(e,r[1])),r=An(n)):(e=Bn,r=X(r,!1,!1),n=Object(n));for(var u=0,o=r.length;u<o;u++){var i=r[u],a=n[i];e(a,i,n)&&(t[i]=a)}return t}),Fn=j(function(n,t){var r,e=t[0];return Cn(e)?(e=mn(e),1<t.length&&(r=t[1])):(t=N(X(t,!1,!1),String),e=function(n,r){return!D(t,r)}),Rn(n,e,r)}),qn=Nn(An,!0);function Dn(n){return Ln(n)?Kn(n)?n.slice():kn({},n):n}function Wn(n,r){var t=Sn(r),e=t.length;if(null==n)return!e;for(var u=Object(n),o=0;o<e;o++){var i=t[o];if(r[i]!==u[i]||!(i in u))return!1}return!0}function zn(n,r,t,e){if(n===r)return 0!==n||1/n==1/r;if(null==n||null==r)return!1;if(n!=n)return r!=r;var u=typeof n;return("function"===u||"object"===u||"object"==typeof r)&&function(n,r,t,e){n instanceof h&&(n=n._wrapped);r instanceof h&&(r=r._wrapped);var u=s.call(n);if(u!==s.call(r))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+r;case"[object Number]":return+n!=+n?+r!=+r:0==+n?1/+n==1/r:+n==+r;case"[object Date]":case"[object Boolean]":return+n==+r;case"[object Symbol]":return p.valueOf.call(n)===p.valueOf.call(r)}var o="[object Array]"===u;if(!o){if("object"!=typeof n||"object"!=typeof r)return!1;var i=n.constructor,a=r.constructor;if(i!==a&&!(Cn(i)&&i instanceof i&&Cn(a)&&a instanceof a)&&"constructor"in n&&"constructor"in r)return!1}e=e||[];var f=(t=t||[]).length;for(;f--;)if(t[f]===n)return e[f]===r;if(t.push(n),e.push(r),o){if((f=n.length)!==r.length)return!1;for(;f--;)if(!zn(n[f],r[f],t,e))return!1}else{var c,l=Sn(n);if(f=l.length,Sn(r).length!==f)return!1;for(;f--;)if(c=l[f],!x(r,c)||!zn(n[c],r[c],t,e))return!1}return t.pop(),e.pop(),!0}(n,r,t,e)}function Pn(r){return function(n){return s.call(n)==="[object "+r+"]"}}var Kn=r||Pn("Array");function Ln(n){var r=typeof n;return"function"===r||"object"===r&&!!n}var Vn=Pn("Arguments"),Cn=Pn("Function"),Jn=Pn("String"),Un=Pn("Number"),$n=Pn("Date"),Gn=Pn("RegExp"),Hn=Pn("Error"),Qn=Pn("Symbol"),Xn=Pn("Map"),Yn=Pn("WeakMap"),Zn=Pn("Set"),nr=Pn("WeakSet");!function(){Vn(arguments)||(Vn=function(n){return x(n,"callee")})}();var rr=n.document&&n.document.childNodes;function tr(n){return Un(n)&&c(n)}function er(n){return!0===n||!1===n||"[object Boolean]"===s.call(n)}function ur(n){return n}function or(r){return Kn(r)?function(n){return S(n,r)}:w(r)}function ir(r){return r=In({},r),function(n){return Wn(n,r)}}function ar(n,r){return null==r&&(r=n,n=0),n+Math.floor(Math.random()*(r-n+1))}"function"!=typeof/./&&"object"!=typeof Int8Array&&"function"!=typeof rr&&(Cn=function(n){return"function"==typeof n||!1});var fr=Date.now||function(){return(new Date).getTime()},cr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},lr=Mn(cr);function pr(r){var t=function(n){return r[n]},n="(?:"+Sn(r).join("|")+")",e=RegExp(n),u=RegExp(n,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}}var sr=pr(cr),vr=pr(lr);var hr=0;var gr=h.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g},yr=/(.)^/,dr={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},mr=/\\|'|\r|\n|\u2028|\u2029/g,br=function(n){return"\\"+dr[n]};function jr(n,r){return n._chain?h(r).chain():r}function _r(t){return E(En(t),function(n){var r=h[n]=t[n];h.prototype[n]=function(){var n=[this._wrapped];return u.apply(n,arguments),jr(this,r.apply(h,n))}}),h}E(["pop","push","reverse","shift","sort","splice","unshift"],function(r){var t=e[r];h.prototype[r]=function(){var n=this._wrapped;return t.apply(n,arguments),"shift"!==r&&"splice"!==r||0!==n.length||delete n[0],jr(this,n)}}),E(["concat","join","slice"],function(n){var r=e[n];h.prototype[n]=function(){return jr(this,r.apply(this._wrapped,arguments))}}),h.prototype.valueOf=h.prototype.toJSON=h.prototype.value=function(){return this._wrapped},h.prototype.toString=function(){return String(this._wrapped)};var wr=_r({default:h,VERSION:g,iteratee:m,restArguments:j,each:E,forEach:E,map:N,collect:N,reduce:I,foldl:I,inject:I,reduceRight:T,foldr:T,find:B,detect:B,filter:R,select:R,reject:function(n,r,t){return R(n,mn(b(r)),t)},every:F,all:F,some:q,any:q,contains:D,includes:D,include:D,invoke:W,pluck:z,where:function(n,r){return R(n,ir(r))},findWhere:function(n,r){return B(n,ir(r))},max:P,min:function(n,e,r){var t,u,o=1/0,i=1/0;if(null==e||"number"==typeof e&&"object"!=typeof n[0]&&null!=n)for(var a=0,f=(n=M(n)?n:On(n)).length;a<f;a++)null!=(t=n[a])&&t<o&&(o=t);else e=b(e,r),E(n,function(n,r,t){((u=e(n,r,t))<i||u===1/0&&o===1/0)&&(o=n,i=u)});return o},shuffle:function(n){return K(n,1/0)},sample:K,sortBy:function(n,e,r){var u=0;return e=b(e,r),z(N(n,function(n,r,t){return{value:n,index:u++,criteria:e(n,r,t)}}).sort(function(n,r){var t=n.criteria,e=r.criteria;if(t!==e){if(e<t||void 0===t)return 1;if(t<e||void 0===e)return-1}return n.index-r.index}),"value")},groupBy:V,indexBy:C,countBy:J,toArray:function(n){return n?Kn(n)?f.call(n):Jn(n)?n.match(U):M(n)?N(n,ur):On(n):[]},size:function(n){return null==n?0:M(n)?n.length:Sn(n).length},partition:$,first:G,head:G,take:G,initial:H,last:function(n,r,t){return null==n||n.length<1?null==r?void 0:[]:null==r||t?n[n.length-1]:Q(n,Math.max(0,n.length-r))},rest:Q,tail:Q,drop:Q,compact:function(n){return R(n,Boolean)},flatten:function(n,r){return X(n,r,!1)},without:Y,uniq:Z,unique:Z,union:nn,intersection:function(n){for(var r=[],t=arguments.length,e=0,u=O(n);e<u;e++){var o=n[e];if(!D(r,o)){var i;for(i=1;i<t&&D(arguments[i],o);i++);i===t&&r.push(o)}}return r},difference:rn,unzip:tn,zip:en,object:function(n,r){for(var t={},e=0,u=O(n);e<u;e++)r?t[n[e]]=r[e]:t[n[e][0]]=n[e][1];return t},findIndex:on,findLastIndex:an,sortedIndex:fn,indexOf:ln,lastIndexOf:pn,range:function(n,r,t){null==r&&(r=n||0,n=0),t||(t=r<n?-1:1);for(var e=Math.max(Math.ceil((r-n)/t),0),u=Array(e),o=0;o<e;o++,n+=t)u[o]=n;return u},chunk:function(n,r){if(null==r||r<1)return[];for(var t=[],e=0,u=n.length;e<u;)t.push(f.call(n,e,e+=r));return t},bind:vn,partial:hn,bindAll:gn,memoize:function(e,u){var o=function(n){var r=o.c
676ache,t=""+(u?u.apply(this,arguments):n);return x(r,t)||(r[t]=e.apply(this,arguments)),r[t]};return o.cache={},o},delay:yn,defer:dn,throttle:function(t,e,u){var o,i,a,f,c=0;u||(u={});var l=function(){c=!1===u.leading?0:fr(),o=null,f=t.apply(i,a),o||(i=a=null)},n=function(){var n=fr();c||!1!==u.leading||(c=n);var r=e-(n-c);return i=this,a=arguments,r<=0||e<r?(o&&(clearTimeout(o),o=null),c=n,f=t.apply(i,a),o||(i=a=null)):o||!1===u.trailing||(o=setTimeout(l,r)),f};return n.cancel=function(){clearTimeout(o),c=0,o=i=a=null},n},debounce:function(t,e,u){var o,i,a=function(n,r){o=null,r&&(i=t.apply(n,r))},n=j(function(n){if(o&&clearTimeout(o),u){var r=!o;o=setTimeout(a,e),r&&(i=t.apply(this,n))}else o=yn(a,e,this,n);return i});return n.cancel=function(){clearTimeout(o),o=null},n},wrap:function(n,r){return hn(r,n)},negate:mn,compose:function(){var t=arguments,e=t.length-1;return function(){for(var n=e,r=t[e].apply(this,arguments);n--;)r=t[n].call(this,r);return r}},after:function(n,r){return function(){if(--n<1)return r.apply(this,arguments)}},before:bn,once:jn,keys:Sn,allKeys:An,values:On,mapObject:function(n,r,t){r=b(r,t);for(var e=Sn(n),u=e.length,o={},i=0;i<u;i++){var a=e[i];o[a]=r(n[a],a,n)}return o},pairs:function(n){for(var r=Sn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=[r[u],n[r[u]]];return e},invert:Mn,functions:En,methods:En,extend:kn,extendOwn:In,assign:In,findKey:Tn,pick:Rn,omit:Fn,defaults:qn,create:function(n,r){var t=_(n);return r&&In(t,r),t},clone:Dn,tap:function(n,r){return r(n),n},isMatch:Wn,isEqual:function(n,r){return zn(n,r)},isEmpty:function(n){return null==n||(M(n)&&(Kn(n)||Jn(n)||Vn(n))?0===n.length:0===Sn(n).length)},isElement:function(n){return!(!n||1!==n.nodeType)},isArray:Kn,isObject:Ln,isArguments:Vn,isFunction:Cn,isString:Jn,isNumber:Un,isDate:$n,isRegExp:Gn,isError:Hn,isSymbol:Qn,isMap:Xn,isWeakMap:Yn,isSet:Zn,isWeakSet:nr,isFinite:function(n){return!Qn(n)&&l(n)&&!c(parseFloat(n))},isNaN:tr,isBoolean:er,isNull:function(n){return null===n},isUndefined:function(n){return void 0===n},has:function(n,r){if(!Kn(r))return x(n,r);for(var t=r.length,e=0;e<t;e++){var u=r[e];if(null==n||!o.call(n,u))return!1;n=n[u]}return!!t},identity:ur,constant:function(n){return function(){return n}},noop:function(){},property:or,propertyOf:function(r){return null==r?function(){}:function(n){return Kn(n)?S(r,n):r[n]}},matcher:ir,matches:ir,times:function(n,r,t){var e=Array(Math.max(0,n));r=y(r,t,1);for(var u=0;u<n;u++)e[u]=r(u);return e},random:ar,now:fr,escape:sr,unescape:vr,result:function(n,r,t){Kn(r)||(r=[r]);var e=r.length;if(!e)return Cn(t)?t.call(n):t;for(var u=0;u<e;u++){var o=null==n?void 0:n[r[u]];void 0===o&&(o=t,u=e),n=Cn(o)?o.call(n):o}return n},uniqueId:function(n){var r=++hr+"";return n?n+r:r},templateSettings:gr,template:function(o,n,r){!n&&r&&(n=r),n=qn({},n,h.templateSettings);var t,e=RegExp([(n.escape||yr).source,(n.interpolate||yr).source,(n.evaluate||yr).source].join("|")+"|$","g"),i=0,a="__p+='";o.replace(e,function(n,r,t,e,u){return a+=o.slice(i,u).replace(mr,br),i=u+n.length,r?a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":t?a+="'+\n((__t=("+t+"))==null?'':__t)+\n'":e&&(a+="';\n"+e+"\n__p+='"),n}),a+="';\n",n.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{t=new Function(n.variable||"obj","_",a)}catch(n){throw n.source=a,n}var u=function(n){return t.call(this,n,h)},f=n.variable||"obj";return u.source="function("+f+"){\n"+a+"}",u},chain:function(n){var r=h(n);return r._chain=!0,r},mixin:_r});return wr._=wr});
677/*!
678 * Knockout JavaScript library v3.5.0
679 * (c) The Knockout.js team - http://knockoutjs.com/
680 * License: MIT (http://www.opensource.org/licenses/mit-license.php)
681 */
682
683(function() {(function(p){var z=this||(0,eval)("this"),w=z.document,R=z.navigator,v=z.jQuery,H=z.JSON;v||"undefined"===typeof jQuery||(v=jQuery);(function(p){"function"===typeof define&&define.amd?define(["exports","require"],p):"object"===typeof exports&&"object"===typeof module?p(module.exports||exports):p(z.ko={})})(function(S,T){function K(a,c){return null===a||typeof a in W?a===c:!1}function X(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=p;b()},c))}}function Y(b,c){var d;return function(){clearTimeout(d);
684d=a.a.setTimeout(b,c)}}function Z(a,c){c&&"change"!==c?"beforeChange"===c?this.oc(a):this.bb(a,c):this.pc(a)}function aa(a,c){null!==c&&c.s&&c.s()}function ba(a,c){var d=this.pd,e=d[t];e.qa||(this.Pb&&this.kb[c]?(d.tc(c,a,this.kb[c]),this.kb[c]=null,--this.Pb):e.F[c]||d.tc(c,a,e.G?{da:a}:d.Zc(a)),a.Ka&&a.fd())}var a="undefined"!==typeof S?S:{};a.b=function(b,c){for(var d=b.split("."),e=a,f=0;f<d.length-1;f++)e=e[d[f]];e[d[d.length-1]]=c};a.J=function(a,c,d){a[c]=d};a.version="3.5.0";a.b("version",
685a.version);a.options={deferUpdates:!1,useOnlyNativeEvents:!1,foreachHidesDestroyed:!1};a.a=function(){function b(a,b){for(var c in a)f.call(a,c)&&b(c,a[c])}function c(a,b){if(b)for(var c in b)f.call(b,c)&&(a[c]=b[c]);return a}function d(a,b){a.__proto__=b;return a}function e(b,c,d,e){var k=b[c].match(n)||[];a.a.C(d.match(n),function(b){a.a.Oa(k,b,e)});b[c]=k.join(" ")}var f=Object.prototype.hasOwnProperty,g={__proto__:[]}instanceof Array,h="function"===typeof Symbol,m={},l={};m[R&&/Firefox\/2/i.test(R.userAgent)?
686"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];m.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(m,function(a,b){if(b.length)for(var c=0,d=b.length;c<d;c++)l[b[c]]=a});var k={propertychange:!0},q=w&&function(){for(var a=3,b=w.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:p}(),n=/\S+/g,r;return{Ic:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],
687C:function(a,b,c){for(var d=0,e=a.length;d<e;d++)b.call(c,a[d],d,a)},A:"function"==typeof Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b)}:function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},Lb:function(a,b,c){for(var d=0,e=a.length;d<e;d++)if(b.call(c,a[d],d,a))return a[d];return p},hb:function(b,c){var d=a.a.A(b,c);0<d?b.splice(d,1):0===d&&b.shift()},vc:function(b){var c=[];b&&a.a.C(b,function(b){0>a.a.A(c,b)&&c.push(b)});return c},Mb:function(a,
688b,c){var d=[];if(a)for(var e=0,k=a.length;e<k;e++)d.push(b.call(c,a[e],e));return d},fb:function(a,b,c){var d=[];if(a)for(var e=0,k=a.length;e<k;e++)b.call(c,a[e],e)&&d.push(a[e]);return d},gb:function(a,b){if(b instanceof Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<d;c++)a.push(b[c]);return a},Oa:function(b,c,d){var e=a.a.A(a.a.$b(b),c);0>e?d&&b.push(c):d||b.splice(e,1)},Ba:g,extend:c,setPrototypeOf:d,zb:g?d:c,O:b,Ha:function(a,b,c){if(!a)return a;var d={},e;
vendor: 62,666 bytes, lines 688-810
688for(e in a)f.call(a,e)&&(d[e]=
689b.call(c,a[e],e,a));return d},Sb:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},Xb:function(b){b=a.a.la(b);for(var c=(b[0]&&b[0].ownerDocument||w).createElement("div"),d=0,e=b.length;d<e;d++)c.appendChild(a.na(b[d]));return c},Ca:function(b,c){for(var d=0,e=b.length,k=[];d<e;d++){var f=b[d].cloneNode(!0);k.push(c?a.na(f):f)}return k},ua:function(b,c){a.a.Sb(b);if(c)for(var d=0,e=c.length;d<e;d++)b.appendChild(c[d])},Wc:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var e=d[0],
690k=e.parentNode,f=0,l=c.length;f<l;f++)k.insertBefore(c[f],e);f=0;for(l=d.length;f<l;f++)a.removeNode(d[f])}},Ua:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.splice(0,1);for(;1<a.length&&a[a.length-1].parentNode!==b;)a.length--;if(1<a.length){var c=a[0],d=a[a.length-1];for(a.length=0;c!==d;)a.push(c),c=c.nextSibling;a.push(d)}}return a},Yc:function(a,b){7>q?a.setAttribute("selected",b):a.selected=b},Cb:function(a){return null===a||a===p?"":a.trim?
691a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},Td:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},ud:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(1!==a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;return!!a},Rb:function(b){return a.a.ud(b,b.ownerDocument.documentElement)},jd:function(b){return!!a.a.Lb(b,a.a.Rb)},P:function(a){return a&&
692a.tagName&&a.tagName.toLowerCase()},zc:function(b){return a.onError?function(){try{return b.apply(this,arguments)}catch(c){throw a.onError&&a.onError(c),c;}}:b},setTimeout:function(b,c){return setTimeout(a.a.zc(b),c)},Fc:function(b){setTimeout(function(){a.onError&&a.onError(b);throw b;},0)},H:function(b,c,d){var e=a.a.zc(d);d=k[c];if(a.options.useOnlyNativeEvents||d||!v)if(d||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var f=function(a){e.call(b,a)},l="on"+c;b.attachEvent(l,
693f);a.a.I.za(b,function(){b.detachEvent(l,f)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,e,!1);else r||(r="function"==typeof v(b).on?"on":"bind"),v(b)[r](c,e)},Fb:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.P(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(a.options.useOnlyNativeEvents||!v||d)if("function"==typeof w.createEvent)if("function"==
694typeof b.dispatchEvent)d=w.createEvent(l[c]||"HTMLEvents"),d.initEvent(c,!0,!0,z,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");else v(b).trigger(c)},c:function(b){return a.N(b)?b():b},$b:function(b){return a.N(b)?b.w():b},Eb:function(b,c,d){var k;c&&("object"===typeof b.classList?
695(k=b.classList[d?"add":"remove"],a.a.C(c.match(n),function(a){k.call(b.classList,a)})):"string"===typeof b.className.baseVal?e(b.className,"baseVal",c,d):e(b,"className",c,d))},Ab:function(b,c){var d=a.a.c(c);if(null===d||d===p)d="";var e=a.h.firstChild(b);!e||3!=e.nodeType||a.h.nextSibling(e)?a.h.ua(b,[b.ownerDocument.createTextNode(d)]):e.data=d;a.a.zd(b)},Xc:function(a,b){a.name=b;if(7>=q)try{var c=a.name.replace(/[&<>'"]/g,function(a){return"&#"+a.charCodeAt(0)+";"});a.mergeAttributes(w.createElement("<input name='"+
696c+"'/>"),!1)}catch(d){}},zd:function(a){9<=q&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},vd:function(a){if(q){var b=a.style.width;a.style.width=0;a.style.width=b}},Od:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var d=[],e=b;e<=c;e++)d.push(e);return d},la:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},Da:function(a){return h?Symbol(a):a},Xd:6===q,Yd:7===q,W:q,Kc:function(b,c){for(var d=a.a.la(b.getElementsByTagName("input")).concat(a.a.la(b.getElementsByTagName("textarea"))),
697e="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},k=[],f=d.length-1;0<=f;f--)e(d[f])&&k.push(d[f]);return k},Md:function(b){return"string"==typeof b&&(b=a.a.Cb(b))?H&&H.parse?H.parse(b):(new Function("return "+b))():null},fc:function(b,c,d){if(!H||!H.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
698return H.stringify(a.a.c(b),c,d)},Nd:function(c,d,e){e=e||{};var k=e.params||{},f=e.includeFields||this.Ic,l=c;if("object"==typeof c&&"form"===a.a.P(c))for(var l=c.action,h=f.length-1;0<=h;h--)for(var g=a.a.Kc(c,f[h]),m=g.length-1;0<=m;m--)k[g[m].name]=g[m].value;d=a.a.c(d);var n=w.createElement("form");n.style.display="none";n.action=l;n.method="post";for(var q in d)c=w.createElement("input"),c.type="hidden",c.name=q,c.value=a.a.fc(a.a.c(d[q])),n.appendChild(c);b(k,function(a,b){var c=w.createElement("input");
699c.type="hidden";c.name=a;c.value=b;n.appendChild(c)});w.body.appendChild(n);e.submitter?e.submitter(n):n.submit();setTimeout(function(){n.parentNode.removeChild(n)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.C);a.b("utils.arrayFirst",a.a.Lb);a.b("utils.arrayFilter",a.a.fb);a.b("utils.arrayGetDistinctValues",a.a.vc);a.b("utils.arrayIndexOf",a.a.A);a.b("utils.arrayMap",a.a.Mb);a.b("utils.arrayPushAll",a.a.gb);a.b("utils.arrayRemoveItem",a.a.hb);a.b("utils.cloneNodes",a.a.Ca);a.b("utils.createSymbolOrString",
700a.a.Da);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",a.a.Ic);a.b("utils.getFormFields",a.a.Kc);a.b("utils.objectMap",a.a.Ha);a.b("utils.peekObservable",a.a.$b);a.b("utils.postJson",a.a.Nd);a.b("utils.parseJson",a.a.Md);a.b("utils.registerEventHandler",a.a.H);a.b("utils.stringifyJson",a.a.fc);a.b("utils.range",a.a.Od);a.b("utils.toggleDomNodeCssClass",a.a.Eb);a.b("utils.triggerEvent",a.a.Fb);a.b("utils.unwrapObservable",a.a.c);a.b("utils.objectForEach",a.a.O);a.b("utils.addOrRemoveItem",
701a.a.Oa);a.b("utils.setTextContent",a.a.Ab);a.b("unwrap",a.a.c);Function.prototype.bind||(Function.prototype.bind=function(a){var c=this;if(1===arguments.length)return function(){return c.apply(a,arguments)};var d=Array.prototype.slice.call(arguments,1);return function(){var e=d.slice(0);e.push.apply(e,arguments);return c.apply(a,e)}});a.a.g=new function(){var b=0,c="__ko__"+(new Date).getTime(),d={},e,f;a.a.W?(e=function(a,e){var f=a[c];if(!f||"null"===f||!d[f]){if(!e)return p;f=a[c]="ko"+b++;d[f]=
702{}}return d[f]},f=function(a){var b=a[c];return b?(delete d[b],a[c]=null,!0):!1}):(e=function(a,b){var d=a[c];!d&&b&&(d=a[c]={});return d},f=function(a){return a[c]?(delete a[c],!0):!1});return{get:function(a,b){var c=e(a,!1);return c&&c[b]},set:function(a,b,c){(a=e(a,c!==p))&&(a[b]=c)},Tb:function(a,b,c){a=e(a,!0);return a[b]||(a[b]=c)},clear:f,Z:function(){return b++ +c}}};a.b("utils.domData",a.a.g);a.b("utils.domData.clear",a.a.g.clear);a.a.I=new function(){function b(b,c){var d=a.a.g.get(b,e);
703d===p&&c&&(d=[],a.a.g.set(b,e,d));return d}function c(c){var e=b(c,!1);if(e)for(var e=e.slice(0),f=0;f<e.length;f++)e[f](c);a.a.g.clear(c);a.a.I.cleanExternalData(c);g[c.nodeType]&&d(c.childNodes,!0)}function d(b,d){for(var e=[],k,f=0;f<b.length;f++)if(!d||8===b[f].nodeType)if(c(e[e.length]=k=b[f]),b[f]!==k)for(;f--&&-1==a.a.A(e,b[f]););}var e=a.a.g.Z(),f={1:!0,8:!0,9:!0},g={1:!0,9:!0};return{za:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function");b(a,!0).push(c)},xb:function(c,
704d){var f=b(c,!1);f&&(a.a.hb(f,d),0==f.length&&a.a.g.set(c,e,p))},na:function(a){f[a.nodeType]&&(c(a),g[a.nodeType]&&d(a.getElementsByTagName("*")));return a},removeNode:function(b){a.na(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){v&&"function"==typeof v.cleanData&&v.cleanData([a])}}};a.na=a.a.I.na;a.removeNode=a.a.I.removeNode;a.b("cleanNode",a.na);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",a.a.I);a.b("utils.domNodeDisposal.addDisposeCallback",a.a.I.za);
705a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.I.xb);(function(){var b=[0,"",""],c=[1,"<table>","</table>"],d=[3,"<table><tbody><tr>","</tr></tbody></table>"],e=[1,"<select multiple='multiple'>","</select>"],f={thead:c,tbody:c,tfoot:c,tr:[2,"<table><tbody>","</tbody></table>"],td:d,th:d,option:e,optgroup:e},g=8>=a.a.W;a.a.ta=function(c,d){var e;if(v)if(v.parseHTML)e=v.parseHTML(c,d)||[];else{if((e=v.clean([c],d))&&e[0]){for(var k=e[0];k.parentNode&&11!==k.parentNode.nodeType;)k=k.parentNode;
706k.parentNode&&k.parentNode.removeChild(k)}}else{(e=d)||(e=w);var k=e.parentWindow||e.defaultView||z,q=a.a.Cb(c).toLowerCase(),n=e.createElement("div"),r;r=(q=q.match(/^(?:\x3c!--.*?--\x3e\s*?)*?<([a-z]+)[\s>]/))&&f[q[1]]||b;q=r[0];r="ignored<div>"+r[1]+c+r[2]+"</div>";"function"==typeof k.innerShiv?n.appendChild(k.innerShiv(r)):(g&&e.body.appendChild(n),n.innerHTML=r,g&&n.parentNode.removeChild(n));for(;q--;)n=n.lastChild;e=a.a.la(n.lastChild.childNodes)}return e};a.a.Ld=function(b,c){var d=a.a.ta(b,
707c);return d.length&&d[0].parentElement||a.a.Xb(d)};a.a.dc=function(b,c){a.a.Sb(b);c=a.a.c(c);if(null!==c&&c!==p)if("string"!=typeof c&&(c=c.toString()),v)v(b).html(c);else for(var d=a.a.ta(c,b.ownerDocument),e=0;e<d.length;e++)b.appendChild(d[e])}})();a.b("utils.parseHtmlFragment",a.a.ta);a.b("utils.setHtml",a.a.dc);a.aa=function(){function b(c,e){if(c)if(8==c.nodeType){var f=a.aa.Tc(c.nodeValue);null!=f&&e.push({sd:c,Jd:f})}else if(1==c.nodeType)for(var f=0,g=c.childNodes,h=g.length;f<h;f++)b(g[f],
708e)}var c={};return{Wb:function(a){if("function"!=typeof a)throw Error("You can only pass a function to ko.memoization.memoize()");var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);c[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},ad:function(a,b){var f=c[a];if(f===p)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return f.apply(null,b||[]),!0}finally{delete c[a]}},bd:function(c,e){var f=
709[];b(c,f);for(var g=0,h=f.length;g<h;g++){var m=f[g].sd,l=[m];e&&a.a.gb(l,e);a.aa.ad(f[g].Jd,l);m.nodeValue="";m.parentNode&&m.parentNode.removeChild(m)}},Tc:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.aa);a.b("memoization.memoize",a.aa.Wb);a.b("memoization.unmemoize",a.aa.ad);a.b("memoization.parseMemoText",a.aa.Tc);a.b("memoization.unmemoizeDomNodeAndDescendants",a.aa.bd);a.ma=function(){function b(){if(f)for(var b=f,c=0,d;h<f;)if(d=e[h++]){if(h>b){if(5E3<=
710++c){h=f;a.a.Fc(Error("'Too much recursion' after processing "+c+" task groups."));break}b=f}try{d()}catch(g){a.a.Fc(g)}}}function c(){b();h=f=e.length=0}var d,e=[],f=0,g=1,h=0;z.MutationObserver?d=function(a){var b=w.createElement("div");(new MutationObserver(a)).observe(b,{attributes:!0});return function(){b.classList.toggle("foo")}}(c):d=w&&"onreadystatechange"in w.createElement("script")?function(a){var b=w.createElement("script");b.onreadystatechange=function(){b.onreadystatechange=null;w.documentElement.removeChild(b);
711b=null;a()};w.documentElement.appendChild(b)}:function(a){setTimeout(a,0)};return{scheduler:d,yb:function(b){f||a.ma.scheduler(c);e[f++]=b;return g++},cancel:function(a){a=a-(g-f);a>=h&&a<f&&(e[a]=null)},resetForTesting:function(){var a=f-h;h=f=e.length=0;return a},Rd:b}}();a.b("tasks",a.ma);a.b("tasks.schedule",a.ma.yb);a.b("tasks.runEarly",a.ma.Rd);a.Ta={throttle:function(b,c){b.throttleEvaluation=c;var d=null;return a.$({read:b,write:function(e){clearTimeout(d);d=a.a.setTimeout(function(){b(e)},
712c)}})},rateLimit:function(a,c){var d,e,f;"number"==typeof c?d=c:(d=c.timeout,e=c.method);a.Hb=!1;f="function"==typeof e?e:"notifyWhenChangesStop"==e?Y:X;a.tb(function(a){return f(a,d,c)})},deferred:function(b,c){if(!0!==c)throw Error("The 'deferred' extender only accepts the value 'true', because it is not supported to turn deferral off once enabled.");b.Hb||(b.Hb=!0,b.tb(function(c){var e,f=!1;return function(){if(!f){a.ma.cancel(e);e=a.ma.yb(c);try{f=!0,b.notifySubscribers(p,"dirty")}finally{f=
713!1}}}}))},notify:function(a,c){a.equalityComparer="always"==c?null:K}};var W={undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.Ta);a.gc=function(b,c,d){this.da=b;this.kc=c;this.lc=d;this.Ib=!1;this.ab=this.Jb=null;a.J(this,"dispose",this.s);a.J(this,"disposeWhenNodeIsRemoved",this.l)};a.gc.prototype.s=function(){this.Ib||(this.ab&&a.a.I.xb(this.Jb,this.ab),this.Ib=!0,this.lc(),this.da=this.kc=this.lc=this.Jb=this.ab=null)};a.gc.prototype.l=function(b){this.Jb=b;a.a.I.za(b,this.ab=this.s.bind(this))};
714a.R=function(){a.a.zb(this,D);D.ob(this)};var D={ob:function(a){a.S={change:[]};a.rc=1},subscribe:function(b,c,d){var e=this;d=d||"change";var f=new a.gc(e,c?b.bind(c):b,function(){a.a.hb(e.S[d],f);e.cb&&e.cb(d)});e.Qa&&e.Qa(d);e.S[d]||(e.S[d]=[]);e.S[d].push(f);return f},notifySubscribers:function(b,c){c=c||"change";"change"===c&&this.Gb();if(this.Wa(c)){var d="change"===c&&this.dd||this.S[c].slice(0);try{a.v.wc();for(var e=0,f;f=d[e];++e)f.Ib||f.kc(b)}finally{a.v.end()}}},mb:function(){return this.rc},
715Cd:function(a){return this.mb()!==a},Gb:function(){++this.rc},tb:function(b){var c=this,d=a.N(c),e,f,g,h,m;c.bb||(c.bb=c.notifySubscribers,c.notifySubscribers=Z);var l=b(function(){c.Ka=!1;d&&h===c&&(h=c.mc?c.mc():c());var a=f||m&&c.qb(g,h);m=f=e=!1;a&&c.bb(g=h)});c.pc=function(a,b){b&&c.Ka||(m=!b);c.dd=c.S.change.slice(0);c.Ka=e=!0;h=a;l()};c.oc=function(a){e||(g=a,c.bb(a,"beforeChange"))};c.qc=function(){m=!0};c.fd=function(){c.qb(g,c.w(!0))&&(f=!0)}},Wa:function(a){return this.S[a]&&this.S[a].length},
716Ad:function(b){if(b)return this.S[b]&&this.S[b].length||0;var c=0;a.a.O(this.S,function(a,b){"dirty"!==a&&(c+=b.length)});return c},qb:function(a,c){return!this.equalityComparer||!this.equalityComparer(a,c)},toString:function(){return"[object Object]"},extend:function(b){var c=this;b&&a.a.O(b,function(b,e){var f=a.Ta[b];"function"==typeof f&&(c=f(c,e)||c)});return c}};a.J(D,"init",D.ob);a.J(D,"subscribe",D.subscribe);a.J(D,"extend",D.extend);a.J(D,"getSubscriptionsCount",D.Ad);a.a.Ba&&a.a.setPrototypeOf(D,
717Function.prototype);a.R.fn=D;a.Pc=function(a){return null!=a&&"function"==typeof a.subscribe&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.R);a.b("isSubscribable",a.Pc);a.U=a.v=function(){function b(a){d.push(e);e=a}function c(){e=d.pop()}var d=[],e,f=0;return{wc:b,end:c,ac:function(b){if(e){if(!a.Pc(b))throw Error("Only subscribable things can act as dependencies");e.nd.call(e.od,b,b.ed||(b.ed=++f))}},K:function(a,d,e){try{return b(),a.apply(d,e||[])}finally{c()}},pa:function(){if(e)return e.o.pa()},
718Va:function(){if(e)return e.o.Va()},rb:function(){if(e)return e.rb},o:function(){if(e)return e.o}}}();a.b("computedContext",a.U);a.b("computedContext.getDependenciesCount",a.U.pa);a.b("computedContext.getDependencies",a.U.Va);a.b("computedContext.isInitial",a.U.rb);a.b("computedContext.registerDependency",a.U.ac);a.b("ignoreDependencies",a.Wd=a.v.K);var I=a.a.Da("_latestValue");a.sa=function(b){function c(){if(0<arguments.length)return c.qb(c[I],arguments[0])&&(c.xa(),c[I]=arguments[0],c.wa()),this;
719a.v.ac(c);return c[I]}c[I]=b;a.a.Ba||a.a.extend(c,a.R.fn);a.R.fn.ob(c);a.a.zb(c,F);a.options.deferUpdates&&a.Ta.deferred(c,!0);return c};var F={equalityComparer:K,w:function(){return this[I]},wa:function(){this.notifySubscribers(this[I],"spectate");this.notifySubscribers(this[I])},xa:function(){this.notifySubscribers(this[I],"beforeChange")}};a.a.Ba&&a.a.setPrototypeOf(F,a.R.fn);var G=a.sa.Na="__ko_proto__";F[G]=a.sa;a.N=function(b){if((b="function"==typeof b&&b[G])&&b!==F[G]&&b!==a.o.fn[G])throw Error("Invalid object that looks like an observable; possibly from another Knockout instance");
720return!!b};a.Ya=function(b){return"function"==typeof b&&(b[G]===F[G]||b[G]===a.o.fn[G]&&b.Mc)};a.b("observable",a.sa);a.b("isObservable",a.N);a.b("isWriteableObservable",a.Ya);a.b("isWritableObservable",a.Ya);a.b("observable.fn",F);a.J(F,"peek",F.w);a.J(F,"valueHasMutated",F.wa);a.J(F,"valueWillMutate",F.xa);a.Ia=function(b){b=b||[];if("object"!=typeof b||!("length"in b))throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");b=a.sa(b);a.a.zb(b,
721a.Ia.fn);return b.extend({trackArrayChanges:!0})};a.Ia.fn={remove:function(b){for(var c=this.w(),d=[],e="function"!=typeof b||a.N(b)?function(a){return a===b}:b,f=0;f<c.length;f++){var g=c[f];if(e(g)){0===d.length&&this.xa();if(c[f]!==g)throw Error("Array modified during remove; cannot remove item");d.push(g);c.splice(f,1);f--}}d.length&&this.wa();return d},removeAll:function(b){if(b===p){var c=this.w(),d=c.slice(0);this.xa();c.splice(0,c.length);this.wa();return d}return b?this.remove(function(c){return 0<=
722a.a.A(b,c)}):[]},destroy:function(b){var c=this.w(),d="function"!=typeof b||a.N(b)?function(a){return a===b}:b;this.xa();for(var e=c.length-1;0<=e;e--){var f=c[e];d(f)&&(f._destroy=!0)}this.wa()},destroyAll:function(b){return b===p?this.destroy(function(){return!0}):b?this.destroy(function(c){return 0<=a.a.A(b,c)}):[]},indexOf:function(b){var c=this();return a.a.A(c,b)},replace:function(a,c){var d=this.indexOf(a);0<=d&&(this.xa(),this.w()[d]=c,this.wa())},sorted:function(a){var c=this().slice(0);
723return a?c.sort(a):c.sort()},reversed:function(){return this().slice(0).reverse()}};a.a.Ba&&a.a.setPrototypeOf(a.Ia.fn,a.sa.fn);a.a.C("pop push reverse shift sort splice unshift".split(" "),function(b){a.Ia.fn[b]=function(){var a=this.w();this.xa();this.yc(a,b,arguments);var d=a[b].apply(a,arguments);this.wa();return d===a?this:d}});a.a.C(["slice"],function(b){a.Ia.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.Oc=function(b){return a.N(b)&&"function"==typeof b.remove&&"function"==
724typeof b.push};a.b("observableArray",a.Ia);a.b("isObservableArray",a.Oc);a.Ta.trackArrayChanges=function(b,c){function d(){function c(){if(h){var d=[].concat(b.w()||[]);if(b.Wa("arrayChange")){var e;if(!f||1<h)f=a.a.Ob(m,d,b.Nb);e=f}m=d;f=null;h=0;e&&e.length&&b.notifySubscribers(e,"arrayChange")}}e?c():(e=!0,l=b.notifySubscribers,b.notifySubscribers=function(a,b){b&&"change"!==b||++h;return l.apply(this,arguments)},m=[].concat(b.w()||[]),f=null,g=b.subscribe(c))}b.Nb={};c&&"object"==typeof c&&a.a.extend(b.Nb,
725c);b.Nb.sparse=!0;if(!b.yc){var e=!1,f=null,g,h=0,m,l,k=b.Qa,q=b.cb;b.Qa=function(a){k&&k.call(b,a);"arrayChange"===a&&d()};b.cb=function(a){q&&q.call(b,a);"arrayChange"!==a||b.Wa("arrayChange")||(l&&(b.notifySubscribers=l,l=p),g&&g.s(),g=null,e=!1,m=p)};b.yc=function(b,c,d){function k(a,b,c){return l[l.length]={status:a,value:b,index:c}}if(e&&!h){var l=[],g=b.length,q=d.length,m=0;switch(c){case "push":m=g;case "unshift":for(c=0;c<q;c++)k("added",d[c],m+c);break;case "pop":m=g-1;case "shift":g&&
726k("deleted",b[m],m);break;case "splice":c=Math.min(Math.max(0,0>d[0]?g+d[0]:d[0]),g);for(var g=1===q?g:Math.min(c+(d[1]||0),g),q=c+q-2,m=Math.max(g,q),U=[],L=[],p=2;c<m;++c,++p)c<g&&L.push(k("deleted",b[c],c)),c<q&&U.push(k("added",d[p],c));a.a.Jc(L,U);break;default:return}f=l}}}};var t=a.a.Da("_state");a.o=a.$=function(b,c,d){function e(){if(0<arguments.length){if("function"===typeof f)f.apply(g.lb,arguments);else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
727return this}g.qa||a.v.ac(e);(g.ka||g.G&&e.Xa())&&e.ha();return g.X}"object"===typeof b?d=b:(d=d||{},b&&(d.read=b));if("function"!=typeof d.read)throw Error("Pass a function that returns the value of the ko.computed");var f=d.write,g={X:p,ra:!0,ka:!0,pb:!1,hc:!1,qa:!1,vb:!1,G:!1,Vc:d.read,lb:c||d.owner,l:d.disposeWhenNodeIsRemoved||d.l||null,Sa:d.disposeWhen||d.Sa,Qb:null,F:{},V:0,Hc:null};e[t]=g;e.Mc="function"===typeof f;a.a.Ba||a.a.extend(e,a.R.fn);a.R.fn.ob(e);a.a.zb(e,C);d.pure?(g.vb=!0,g.G=!0,
728a.a.extend(e,da)):d.deferEvaluation&&a.a.extend(e,ea);a.options.deferUpdates&&a.Ta.deferred(e,!0);g.l&&(g.hc=!0,g.l.nodeType||(g.l=null));g.G||d.deferEvaluation||e.ha();g.l&&e.ja()&&a.a.I.za(g.l,g.Qb=function(){e.s()});return e};var C={equalityComparer:K,pa:function(){return this[t].V},Va:function(){var b=[];a.a.O(this[t].F,function(a,d){b[d.La]=d.da});return b},Ub:function(b){if(!this[t].V)return!1;var c=this.Va();return-1!==a.a.A(c,b)?!0:!!a.a.Lb(c,function(a){return a.Ub&&a.Ub(b)})},tc:function(a,
729c,d){if(this[t].vb&&c===this)throw Error("A 'pure' computed must not be called recursively");this[t].F[a]=d;d.La=this[t].V++;d.Ma=c.mb()},Xa:function(){var a,c,d=this[t].F;for(a in d)if(Object.prototype.hasOwnProperty.call(d,a)&&(c=d[a],this.Ja&&c.da.Ka||c.da.Cd(c.Ma)))return!0},Id:function(){this.Ja&&!this[t].pb&&this.Ja(!1)},ja:function(){var a=this[t];return a.ka||0<a.V},Qd:function(){this.Ka?this[t].ka&&(this[t].ra=!0):this.Gc()},Zc:function(a){if(a.Hb){var c=a.subscribe(this.Id,this,"dirty"),
730d=a.subscribe(this.Qd,this);return{da:a,s:function(){c.s();d.s()}}}return a.subscribe(this.Gc,this)},Gc:function(){var b=this,c=b.throttleEvaluation;c&&0<=c?(clearTimeout(this[t].Hc),this[t].Hc=a.a.setTimeout(function(){b.ha(!0)},c)):b.Ja?b.Ja(!0):b.ha(!0)},ha:function(b){var c=this[t],d=c.Sa,e=!1;if(!c.pb&&!c.qa){if(c.l&&!a.a.Rb(c.l)||d&&d()){if(!c.hc){this.s();return}}else c.hc=!1;c.pb=!0;try{e=this.yd(b)}finally{c.pb=!1}return e}},yd:function(b){var c=this[t],d=!1,e=c.vb?p:!c.V,d={pd:this,kb:c.F,
731Pb:c.V};a.v.wc({od:d,nd:ba,o:this,rb:e});c.F={};c.V=0;var f=this.xd(c,d);c.V?d=this.qb(c.X,f):(this.s(),d=!0);d&&(c.G?this.Gb():this.notifySubscribers(c.X,"beforeChange"),c.X=f,this.notifySubscribers(c.X,"spectate"),!c.G&&b&&this.notifySubscribers(c.X),this.qc&&this.qc());e&&this.notifySubscribers(c.X,"awake");return d},xd:function(b,c){try{var d=b.Vc;return b.lb?d.call(b.lb):d()}finally{a.v.end(),c.Pb&&!b.G&&a.a.O(c.kb,aa),b.ra=b.ka=!1}},w:function(a){var c=this[t];(c.ka&&(a||!c.V)||c.G&&this.Xa())&&
732this.ha();return c.X},tb:function(b){a.R.fn.tb.call(this,b);this.mc=function(){this[t].G||(this[t].ra?this.ha():this[t].ka=!1);return this[t].X};this.Ja=function(a){this.oc(this[t].X);this[t].ka=!0;a&&(this[t].ra=!0);this.pc(this,!a)}},s:function(){var b=this[t];!b.G&&b.F&&a.a.O(b.F,function(a,b){b.s&&b.s()});b.l&&b.Qb&&a.a.I.xb(b.l,b.Qb);b.F=p;b.V=0;b.qa=!0;b.ra=!1;b.ka=!1;b.G=!1;b.l=p;b.Sa=p;b.Vc=p;this.Mc||(b.lb=p)}},da={Qa:function(b){var c=this,d=c[t];if(!d.qa&&d.G&&"change"==b){d.G=!1;if(d.ra||
733c.Xa())d.F=null,d.V=0,c.ha()&&c.Gb();else{var e=[];a.a.O(d.F,function(a,b){e[b.La]=a});a.a.C(e,function(a,b){var e=d.F[a],m=c.Zc(e.da);m.La=b;m.Ma=e.Ma;d.F[a]=m});c.Xa()&&c.ha()&&c.Gb()}d.qa||c.notifySubscribers(d.X,"awake")}},cb:function(b){var c=this[t];c.qa||"change"!=b||this.Wa("change")||(a.a.O(c.F,function(a,b){b.s&&(c.F[a]={da:b.da,La:b.La,Ma:b.Ma},b.s())}),c.G=!0,this.notifySubscribers(p,"asleep"))},mb:function(){var b=this[t];b.G&&(b.ra||this.Xa())&&this.ha();return a.R.fn.mb.call(this)}},
734ea={Qa:function(a){"change"!=a&&"beforeChange"!=a||this.w()}};a.a.Ba&&a.a.setPrototypeOf(C,a.R.fn);var N=a.sa.Na;C[N]=a.o;a.Nc=function(a){return"function"==typeof a&&a[N]===C[N]};a.Ed=function(b){return a.Nc(b)&&b[t]&&b[t].vb};a.b("computed",a.o);a.b("dependentObservable",a.o);a.b("isComputed",a.Nc);a.b("isPureComputed",a.Ed);a.b("computed.fn",C);a.J(C,"peek",C.w);a.J(C,"dispose",C.s);a.J(C,"isActive",C.ja);a.J(C,"getDependenciesCount",C.pa);a.J(C,"getDependencies",C.Va);a.wb=function(b,c){if("function"===
735typeof b)return a.o(b,c,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.o(b,c)};a.b("pureComputed",a.wb);(function(){function b(a,f,g){g=g||new d;a=f(a);if("object"!=typeof a||null===a||a===p||a instanceof RegExp||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var h=a instanceof Array?[]:{};g.save(a,h);c(a,function(c){var d=f(a[c]);switch(typeof d){case "boolean":case "number":case "string":case "function":h[c]=d;break;case "object":case "undefined":var k=
736g.get(d);h[c]=k!==p?k:b(d,f,g)}});return h}function c(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function d(){this.keys=[];this.values=[]}a.$c=function(c){if(0==arguments.length)throw Error("When calling ko.toJS, pass the object you want to convert.");return b(c,function(b){for(var c=0;a.N(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.$c(b);return a.a.fc(b,c,d)};d.prototype={constructor:d,save:function(b,
737c){var d=a.a.A(this.keys,b);0<=d?this.values[d]=c:(this.keys.push(b),this.values.push(c))},get:function(b){b=a.a.A(this.keys,b);return 0<=b?this.values[b]:p}}})();a.b("toJS",a.$c);a.b("toJSON",a.toJSON);a.Vd=function(b,c,d){function e(c){var e=a.wb(b,d).extend({Ga:"always"}),h=e.subscribe(function(a){a&&(h.s(),c(a))});e.notifySubscribers(e.w());return h}return"function"!==typeof Promise||c?e(c.bind(d)):new Promise(e)};a.b("when",a.Vd);(function(){a.u={L:function(b){switch(a.a.P(b)){case "option":return!0===
738b.__ko__hasDomDataOptionValue__?a.a.g.get(b,a.f.options.Yb):7>=a.a.W?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.u.L(b.options[b.selectedIndex]):p;default:return b.value}},ya:function(b,c,d){switch(a.a.P(b)){case "option":"string"===typeof c?(a.a.g.set(b,a.f.options.Yb,p),"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__,b.value=c):(a.a.g.set(b,a.f.options.Yb,c),b.__ko__hasDomDataOptionValue__=
739!0,b.value="number"===typeof c?c:"");break;case "select":if(""===c||null===c)c=p;for(var e=-1,f=0,g=b.options.length,h;f<g;++f)if(h=a.u.L(b.options[f]),h==c||""===h&&c===p){e=f;break}if(d||0<=e||c===p&&1<b.size)b.selectedIndex=e,6===a.a.W&&a.a.setTimeout(function(){b.selectedIndex=e},0);break;default:if(null===c||c===p)c="";b.value=c}}}})();a.b("selectExtensions",a.u);a.b("selectExtensions.readValue",a.u.L);a.b("selectExtensions.writeValue",a.u.ya);a.m=function(){function b(b){b=a.a.Cb(b);123===b.charCodeAt(0)&&
740(b=b.slice(1,-1));b+="\n,";var c=[],d=b.match(e),q,n=[],h=0;if(1<d.length){for(var y=0,A;A=d[y];++y){var u=A.charCodeAt(0);if(44===u){if(0>=h){c.push(q&&n.length?{key:q,value:n.join("")}:{unknown:q||n.join("")});q=h=0;n=[];continue}}else if(58===u){if(!h&&!q&&1===n.length){q=n.pop();continue}}else if(47===u&&1<A.length&&(47===A.charCodeAt(1)||42===A.charCodeAt(1)))continue;else 47===u&&y&&1<A.length?(u=d[y-1].match(f))&&!g[u[0]]&&(b=b.substr(b.indexOf(A)+1),d=b.match(e),y=-1,A="/"):40===u||123===
741u||91===u?++h:41===u||125===u||93===u?--h:q||n.length||34!==u&&39!==u||(A=A.slice(1,-1));n.push(A)}if(0<h)throw Error("Unbalanced parentheses, braces, or brackets");}return c}var c=["true","false","null","undefined"],d=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:\\\\.|[^\"])*\"|'(?:\\\\.|[^'])*'|`(?:\\\\.|[^`])*`|/\\*(?:[^*]|\\*+[^*/])*\\*+/|//.*\n|/(?:\\\\.|[^/])+/w*|[^\\s:,/][^,\"'`{}()/:[\\]]*[^\\s,\"'`{}()/:[\\]]|[^\\s]","g"),f=/[\])"'A-Za-z0-9_$]+$/,g={"in":1,"return":1,
742"typeof":1},h={};return{Ra:[],va:h,Zb:b,ub:function(e,f){function k(b,e){var f;if(!y){var l=a.getBindingHandler(b);if(l&&l.preprocess&&!(e=l.preprocess(e,b,k)))return;if(l=h[b])f=e,0<=a.a.A(c,f)?f=!1:(l=f.match(d),f=null===l?!1:l[1]?"Object("+l[1]+")"+l[2]:f),l=f;l&&n.push("'"+("string"==typeof h[b]?h[b]:b)+"':function(_z){"+f+"=_z}")}g&&(e="function(){return "+e+" }");q.push("'"+b+"':"+e)}f=f||{};var q=[],n=[],g=f.valueAccessors,y=f.bindingParams,A="string"===typeof e?b(e):e;a.a.C(A,function(a){k(a.key||
743a.unknown,a.value)});n.length&&k("_ko_property_writers","{"+n.join(",")+" }");return q.join(",")},Hd:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key==b)return!0;return!1},$a:function(b,c,d,e,f){if(b&&a.N(b))!a.Ya(b)||f&&b.w()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.m);a.b("expressionRewriting.bindingRewriteValidators",a.m.Ra);a.b("expressionRewriting.parseObjectLiteral",a.m.Zb);a.b("expressionRewriting.preProcessBindings",a.m.ub);a.b("expressionRewriting._twoWayBindings",
744a.m.va);a.b("jsonExpressionRewriting",a.m);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.m.ub);(function(){function b(a){return 8==a.nodeType&&g.test(f?a.text:a.nodeValue)}function c(a){return 8==a.nodeType&&h.test(f?a.text:a.nodeValue)}function d(d,e){for(var f=d,g=1,h=[];f=f.nextSibling;){if(c(f)&&(a.a.g.set(f,l,!0),g--,0===g))return h;h.push(f);b(f)&&g++}if(!e)throw Error("Cannot find closing comment tag to match: "+d.nodeValue);return null}function e(a,b){var c=d(a,b);return c?
7450<c.length?c[c.length-1].nextSibling:a.nextSibling:null}var f=w&&"\x3c!--test--\x3e"===w.createComment("test").text,g=f?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,h=f?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,m={ul:!0,ol:!0},l="__ko_matchedEndComment__";a.h={ea:{},childNodes:function(a){return b(a)?d(a):a.childNodes},Ea:function(c){if(b(c)){c=a.h.childNodes(c);for(var d=0,e=c.length;d<e;d++)a.removeNode(c[d])}else a.a.Sb(c)},ua:function(c,d){if(b(c)){a.h.Ea(c);for(var e=
746c.nextSibling,f=0,l=d.length;f<l;f++)e.parentNode.insertBefore(d[f],e)}else a.a.ua(c,d)},Uc:function(a,c){b(a)?a.parentNode.insertBefore(c,a.nextSibling):a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c)},Vb:function(c,d,e){e?b(c)?c.parentNode.insertBefore(d,e.nextSibling):e.nextSibling?c.insertBefore(d,e.nextSibling):c.appendChild(d):a.h.Uc(c,d)},firstChild:function(a){if(b(a))return!a.nextSibling||c(a.nextSibling)?null:a.nextSibling;if(a.firstChild&&c(a.firstChild))throw Error("Found invalid end comment, as the first child of "+
747a);return a.firstChild},nextSibling:function(d){b(d)&&(d=e(d));if(d.nextSibling&&c(d.nextSibling)){var f=d.nextSibling;if(c(f)&&!a.a.g.get(f,l))throw Error("Found end comment without a matching opening comment, as child of "+d);return null}return d.nextSibling},Bd:b,Ud:function(a){return(a=(f?a.text:a.nodeValue).match(g))?a[1]:null},Rc:function(d){if(m[a.a.P(d)]){var f=d.firstChild;if(f){do if(1===f.nodeType){var l;l=f.firstChild;var g=null;if(l){do if(g)g.push(l);else if(b(l)){var h=e(l,!0);h?l=
748h:g=[l]}else c(l)&&(g=[l]);while(l=l.nextSibling)}if(l=g)for(g=f.nextSibling,h=0;h<l.length;h++)g?d.insertBefore(l[h],g):d.appendChild(l[h])}while(f=f.nextSibling)}}}}})();a.b("virtualElements",a.h);a.b("virtualElements.allowedBindings",a.h.ea);a.b("virtualElements.emptyNode",a.h.Ea);a.b("virtualElements.insertAfter",a.h.Vb);a.b("virtualElements.prepend",a.h.Uc);a.b("virtualElements.setDomNodeChildren",a.h.ua);(function(){a.ga=function(){this.md={}};a.a.extend(a.ga.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!=
749b.getAttribute("data-bind")||a.i.getComponentNameForNode(b);case 8:return a.h.Bd(b);default:return!1}},getBindings:function(b,c){var d=this.getBindingsString(b,c),d=d?this.parseBindingsString(d,c,b):null;return a.i.sc(d,b,c,!1)},getBindingAccessors:function(b,c){var d=this.getBindingsString(b,c),d=d?this.parseBindingsString(d,c,b,{valueAccessors:!0}):null;return a.i.sc(d,b,c,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");case 8:return a.h.Ud(b);default:return null}},
750parseBindingsString:function(b,c,d,e){try{var f=this.md,g=b+(e&&e.valueAccessors||""),h;if(!(h=f[g])){var m,l="with($context){with($data||{}){return{"+a.m.ub(b,e)+"}}}";m=new Function("$context","$element",l);h=f[g]=m}return h(c,d)}catch(k){throw k.message="Unable to parse bindings.\nBindings value: "+b+"\nMessage: "+k.message,k;}}});a.ga.instance=new a.ga})();a.b("bindingProvider",a.ga);(function(){function b(b){var c=(b=a.a.g.get(b,B))&&b.M;c&&(b.M=null,c.Sc())}function c(c,d,e){this.node=c;this.xc=
751d;this.ib=[];this.T=!1;d.M||a.a.I.za(c,b);e&&e.M&&(e.M.ib.push(c),this.Kb=e)}function d(a){return function(){return a}}function e(a){return a()}function f(b){return a.a.Ha(a.v.K(b),function(a,c){return function(){return b()[c]}})}function g(b,c,e){return"function"===typeof b?f(b.bind(null,c,e)):a.a.Ha(b,d)}function h(a,b){return f(this.getBindings.bind(this,a,b))}function m(b,c){var d=a.h.firstChild(c);if(d){var e,f=a.ga.instance,k=f.preprocessNode;if(k){for(;e=d;)d=a.h.nextSibling(e),k.call(f,e);
752d=a.h.firstChild(c)}for(;e=d;)d=a.h.nextSibling(e),l(b,e)}a.j.Ga(c,a.j.T)}function l(b,c){var d=b,e=1===c.nodeType;e&&a.h.Rc(c);if(e||a.ga.instance.nodeHasBindings(c))d=q(c,null,b).bindingContextForDescendants;d&&!u[a.a.P(c)]&&m(d,c)}function k(b){var c=[],d={},e=[];a.a.O(b,function ca(f){if(!d[f]){var l=a.getBindingHandler(f);l&&(l.after&&(e.push(f),a.a.C(l.after,function(c){if(b[c]){if(-1!==a.a.A(e,c))throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+e.join(", "));
753ca(c)}}),e.length--),c.push({key:f,Lc:l}));d[f]=!0}});return c}function q(b,c,d){var f=a.a.g.Tb(b,B,{}),l=f.gd;if(!c){if(l)throw Error("You cannot apply bindings multiple times to the same element.");f.gd=!0}l||(f.context=d);var g;if(c&&"function"!==typeof c)g=c;else{var q=a.ga.instance,n=q.getBindingAccessors||h,m=a.$(function(){if(g=c?c(d,b):n.call(q,b,d)){if(d[r])d[r]();if(d[A])d[A]()}return g},null,{l:b});g&&m.ja()||(m=null)}var y=d,u;if(g){var J=function(){return a.a.Ha(m?m():g,e)},t=m?function(a){return function(){return e(m()[a])}}:
754function(a){return g[a]};J.get=function(a){return g[a]&&e(t(a))};J.has=function(a){return a in g};a.j.T in g&&a.j.subscribe(b,a.j.T,function(){var c=(0,g[a.j.T])();if(c){var d=a.h.childNodes(b);d.length&&c(d,a.Dc(d[0]))}});a.j.oa in g&&(y=a.j.Bb(b,d),a.j.subscribe(b,a.j.oa,function(){var c=(0,g[a.j.oa])();c&&a.h.firstChild(b)&&c(b)}));f=k(g);a.a.C(f,function(c){var d=c.Lc.init,e=c.Lc.update,f=c.key;if(8===b.nodeType&&!a.h.ea[f])throw Error("The binding '"+f+"' cannot be used with virtual elements");
755try{"function"==typeof d&&a.v.K(function(){var a=d(b,t(f),J,y.$data,y);if(a&&a.controlsDescendantBindings){if(u!==p)throw Error("Multiple bindings ("+u+" and "+f+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");u=f}}),"function"==typeof e&&a.$(function(){e(b,t(f),J,y.$data,y)},null,{l:b})}catch(l){throw l.message='Unable to process binding "'+f+": "+g[f]+'"\nMessage: '+l.message,l;}})}f=u===p;return{shouldBindDescendants:f,
756bindingContextForDescendants:f&&y}}function n(b,c){return b&&b instanceof a.fa?b:new a.fa(b,p,p,c)}var r=a.a.Da("_subscribable"),y=a.a.Da("_ancestorBindingInfo"),A=a.a.Da("_dataDependency");a.f={};var u={script:!0,textarea:!0,template:!0};a.getBindingHandler=function(b){return a.f[b]};var J={};a.fa=function(b,c,d,e,f){function l(){var b=q?h():h,f=a.a.c(b);c?(a.a.extend(k,c),y in c&&(k[y]=c[y])):(k.$parents=[],k.$root=f,k.ko=a);k[r]=n;g?f=k.$data:(k.$rawData=b,k.$data=f);d&&(k[d]=f);e&&e(k,c,f);if(c&&
757c[r]&&!a.U.o().Ub(c[r]))c[r]();m&&(k[A]=m);return k.$data}var k=this,g=b===J,h=g?p:b,q="function"==typeof h&&!a.N(h),n,m=f&&f.dataDependency;f&&f.exportDependencies?l():(n=a.wb(l),n.w(),n.ja()?n.equalityComparer=null:k[r]=p)};a.fa.prototype.createChildContext=function(b,c,d,e){!e&&c&&"object"==typeof c&&(e=c,c=e.as,d=e.extend);if(c&&e&&e.noChildContext){var f="function"==typeof b&&!a.N(b);return new a.fa(J,this,null,function(a){d&&d(a);a[c]=f?b():b},e)}return new a.fa(b,this,c,function(a,b){a.$parentContext=
758b;a.$parent=b.$data;a.$parents=(b.$parents||[]).slice(0);a.$parents.unshift(a.$parent);d&&d(a)},e)};a.fa.prototype.extend=function(b,c){return new a.fa(J,this,null,function(c){a.a.extend(c,"function"==typeof b?b(c):b)},c)};var B=a.a.g.Z();c.prototype.Sc=function(){this.Kb&&this.Kb.M&&this.Kb.M.rd(this.node)};c.prototype.rd=function(b){a.a.hb(this.ib,b);!this.ib.length&&this.T&&this.Bc()};c.prototype.Bc=function(){this.T=!0;this.xc.M&&!this.ib.length&&(this.xc.M=null,a.a.I.xb(this.node,b),a.j.Ga(this.node,
759a.j.oa),this.Sc())};a.j={T:"childrenComplete",oa:"descendantsComplete",subscribe:function(b,c,d,e){b=a.a.g.Tb(b,B,{});b.Fa||(b.Fa=new a.R);return b.Fa.subscribe(d,e,c)},Ga:function(b,c){var d=a.a.g.get(b,B);if(d&&(d.Fa&&d.Fa.notifySubscribers(b,c),c==a.j.T))if(d.M)d.M.Bc();else if(d.M===p&&d.Fa&&d.Fa.Wa(a.j.oa))throw Error("descendantsComplete event not supported for bindings on this node");},Bb:function(b,d){var e=a.a.g.Tb(b,B,{});e.M||(e.M=new c(b,e,d[y]));return d[y]==e?d:d.extend(function(a){a[y]=
760e})}};a.Sd=function(b){return(b=a.a.g.get(b,B))&&b.context};a.eb=function(b,c,d){1===b.nodeType&&a.h.Rc(b);return q(b,c,n(d))};a.kd=function(b,c,d){d=n(d);return a.eb(b,g(c,d,b),d)};a.Pa=function(a,b){1!==b.nodeType&&8!==b.nodeType||m(n(a),b)};a.uc=function(a,b,c){!v&&z.jQuery&&(v=z.jQuery);if(2>arguments.length){if(b=w.body,!b)throw Error("ko.applyBindings: could not find document.body; has the document been loaded?");}else if(!b||1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
761l(n(a,c),b)};a.Cc=function(b){return!b||1!==b.nodeType&&8!==b.nodeType?p:a.Sd(b)};a.Dc=function(b){return(b=a.Cc(b))?b.$data:p};a.b("bindingHandlers",a.f);a.b("bindingEvent",a.j);a.b("bindingEvent.subscribe",a.j.subscribe);a.b("bindingEvent.startPossiblyAsyncContentBinding",a.j.Bb);a.b("applyBindings",a.uc);a.b("applyBindingsToDescendants",a.Pa);a.b("applyBindingAccessorsToNode",a.eb);a.b("applyBindingsToNode",a.kd);a.b("contextFor",a.Cc);a.b("dataFor",a.Dc)})();(function(b){function c(c,e){var l=
762Object.prototype.hasOwnProperty.call(f,c)?f[c]:b,k;l?l.subscribe(e):(l=f[c]=new a.R,l.subscribe(e),d(c,function(b,d){var e=!(!d||!d.synchronous);g[c]={definition:b,Fd:e};delete f[c];k||e?l.notifySubscribers(b):a.ma.yb(function(){l.notifySubscribers(b)})}),k=!0)}function d(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a,c)}):b(null,null)})}function e(c,d,f,k){k||(k=a.i.loaders.slice(0));var g=k.shift();if(g){var n=g[c];if(n){var r=!1;if(n.apply(g,d.concat(function(a){r?
763f(null):null!==a?f(a):e(c,d,f,k)}))!==b&&(r=!0,!g.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");}else e(c,d,f,k)}else f(null)}var f={},g={};a.i={get:function(d,e){var f=Object.prototype.hasOwnProperty.call(g,d)?g[d]:b;f?f.Fd?a.v.K(function(){e(f.definition)}):a.ma.yb(function(){e(f.definition)}):c(d,e)},Ac:function(a){delete g[a]},nc:e};a.i.loaders=[];a.b("components",a.i);a.b("components.get",a.i.get);
764a.b("components.clearCachedDefinition",a.i.Ac)})();(function(){function b(b,c,d,e){function g(){0===--A&&e(h)}var h={},A=2,u=d.template;d=d.viewModel;u?f(c,u,function(c){a.i.nc("loadTemplate",[b,c],function(a){h.template=a;g()})}):g();d?f(c,d,function(c){a.i.nc("loadViewModel",[b,c],function(a){h[m]=a;g()})}):g()}function c(a,b,d){if("function"===typeof b)d(function(a){return new b(a)});else if("function"===typeof b[m])d(b[m]);else if("instance"in b){var e=b.instance;d(function(){return e})}else"viewModel"in
765b?c(a,b.viewModel,d):a("Unknown viewModel value: "+b)}function d(b){switch(a.a.P(b)){case "script":return a.a.ta(b.text);case "textarea":return a.a.ta(b.value);case "template":if(e(b.content))return a.a.Ca(b.content.childNodes)}return a.a.Ca(b.childNodes)}function e(a){return z.DocumentFragment?a instanceof DocumentFragment:a&&11===a.nodeType}function f(a,b,c){"string"===typeof b.require?T||z.require?(T||z.require)([b.require],c):a("Uses require, but no AMD loader is present"):c(b)}function g(a){return function(b){throw Error("Component '"+
766a+"': "+b);}}var h={};a.i.register=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.i.sb(b))throw Error("Component "+b+" is already registered");h[b]=c};a.i.sb=function(a){return Object.prototype.hasOwnProperty.call(h,a)};a.i.unregister=function(b){delete h[b];a.i.Ac(b)};a.i.Ec={getConfig:function(b,c){c(a.i.sb(b)?h[b]:null)},loadComponent:function(a,c,d){var e=g(a);f(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,c,f){b=g(b);if("string"===typeof c)f(a.a.ta(c));else if(c instanceof
767Array)f(c);else if(e(c))f(a.a.la(c.childNodes));else if(c.element)if(c=c.element,z.HTMLElement?c instanceof HTMLElement:c&&c.tagName&&1===c.nodeType)f(d(c));else if("string"===typeof c){var h=w.getElementById(c);h?f(d(h)):b("Cannot find element with ID "+c)}else b("Unknown element type: "+c);else b("Unknown template value: "+c)},loadViewModel:function(a,b,d){c(g(a),b,d)}};var m="createViewModel";a.b("components.register",a.i.register);a.b("components.isRegistered",a.i.sb);a.b("components.unregister",
768a.i.unregister);a.b("components.defaultLoader",a.i.Ec);a.i.loaders.push(a.i.Ec);a.i.cd=h})();(function(){function b(b,e){var f=b.getAttribute("params");if(f){var f=c.parseBindingsString(f,e,b,{valueAccessors:!0,bindingParams:!0}),f=a.a.Ha(f,function(c){return a.o(c,null,{l:b})}),g=a.a.Ha(f,function(c){var e=c.w();return c.ja()?a.o({read:function(){return a.a.c(c())},write:a.Ya(e)&&function(a){c()(a)},l:b}):e});Object.prototype.hasOwnProperty.call(g,"$raw")||(g.$raw=f);return g}return{$raw:{}}}a.i.getComponentNameForNode=
769function(b){var c=a.a.P(b);if(a.i.sb(c)&&(-1!=c.indexOf("-")||"[object HTMLUnknownElement]"==""+b||8>=a.a.W&&b.tagName===c))return c};a.i.sc=function(c,e,f,g){if(1===e.nodeType){var h=a.i.getComponentNameForNode(e);if(h){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');var m={name:h,params:b(e,f)};c.component=g?function(){return m}:m}}return c};var c=new a.ga;9>a.a.W&&(a.i.register=function(a){return function(b){return a.apply(this,
770arguments)}}(a.i.register),w.createDocumentFragment=function(b){return function(){var c=b(),f=a.i.cd,g;for(g in f);return c}}(w.createDocumentFragment))})();(function(){function b(b,c,d){c=c.template;if(!c)throw Error("Component '"+b+"' has no template");b=a.a.Ca(c);a.h.ua(d,b)}function c(a,b,c){var d=a.createViewModel;return d?d.call(a,b,c):b}var d=0;a.f.component={init:function(e,f,g,h,m){function l(){var a=k&&k.dispose;"function"===typeof a&&a.call(k);n&&n.s();q=k=n=null}var k,q,n,r=a.a.la(a.h.childNodes(e));
771a.h.Ea(e);a.a.I.za(e,l);a.o(function(){var g=a.a.c(f()),h,u;"string"===typeof g?h=g:(h=a.a.c(g.name),u=a.a.c(g.params));if(!h)throw Error("No component name specified");var p=a.j.Bb(e,m),B=q=++d;a.i.get(h,function(d){if(q===B){l();if(!d)throw Error("Unknown component '"+h+"'");b(h,d,e);var f=c(d,u,{element:e,templateNodes:r});d=p.createChildContext(f,{extend:function(a){a.$component=f;a.$componentTemplateNodes=r}});f&&f.koDescendantsComplete&&(n=a.j.subscribe(e,a.j.oa,f.koDescendantsComplete,f));
772k=f;a.Pa(d,e)}})},null,{l:e});return{controlsDescendantBindings:!0}}};a.h.ea.component=!0})();var V={"class":"className","for":"htmlFor"};a.f.attr={update:function(b,c){var d=a.a.c(c())||{};a.a.O(d,function(c,d){d=a.a.c(d);var g=c.indexOf(":"),g="lookupNamespaceURI"in b&&0<g&&b.lookupNamespaceURI(c.substr(0,g)),h=!1===d||null===d||d===p;h?g?b.removeAttributeNS(g,c):b.removeAttribute(c):d=d.toString();8>=a.a.W&&c in V?(c=V[c],h?b.removeAttribute(c):b[c]=d):h||(g?b.setAttributeNS(g,c,d):b.setAttribute(c,
773d));"name"===c&&a.a.Xc(b,h?"":d)})}};(function(){a.f.checked={after:["value","attr"],init:function(b,c,d){function e(){var e=b.checked,f=g();if(!a.U.rb()&&(e||!m&&!a.U.pa())){var l=a.v.K(c);if(k){var n=q?l.w():l,B=r;r=f;B!==f?e&&(a.a.Oa(n,f,!0),a.a.Oa(n,B,!1)):a.a.Oa(n,f,e);q&&a.Ya(l)&&l(n)}else h&&(f===p?f=e:e||(f=p)),a.m.$a(l,d,"checked",f,!0)}}function f(){var d=a.a.c(c()),e=g();k?(b.checked=0<=a.a.A(d,e),r=e):b.checked=h&&e===p?!!d:g()===d}var g=a.wb(function(){if(d.has("checkedValue"))return a.a.c(d.get("checkedValue"));
774if(n)return d.has("value")?a.a.c(d.get("value")):b.value}),h="checkbox"==b.type,m="radio"==b.type;if(h||m){var l=c(),k=h&&a.a.c(l)instanceof Array,q=!(k&&l.push&&l.splice),n=m||k,r=k?g():p;m&&!b.name&&a.f.uniqueName.init(b,function(){return!0});a.o(e,null,{l:b});a.a.H(b,"click",e);a.o(f,null,{l:b});l=p}}};a.m.va.checked=!0;a.f.checkedValue={update:function(b,c){b.value=a.a.c(c())}}})();a.f["class"]={update:function(b,c){var d=a.a.Cb(a.a.c(c()));a.a.Eb(b,b.__ko__cssValue,!1);b.__ko__cssValue=d;a.a.Eb(b,
775d,!0)}};a.f.css={update:function(b,c){var d=a.a.c(c());null!==d&&"object"==typeof d?a.a.O(d,function(c,d){d=a.a.c(d);a.a.Eb(b,c,d)}):a.f["class"].update(b,c)}};a.f.enable={update:function(b,c){var d=a.a.c(c());d&&b.disabled?b.removeAttribute("disabled"):d||b.disabled||(b.disabled=!0)}};a.f.disable={update:function(b,c){a.f.enable.update(b,function(){return!a.a.c(c())})}};a.f.event={init:function(b,c,d,e,f){var g=c()||{};a.a.O(g,function(g){"string"==typeof g&&a.a.H(b,g,function(b){var l,k=c()[g];
776if(k){try{var q=a.a.la(arguments);e=f.$data;q.unshift(e);l=k.apply(e,q)}finally{!0!==l&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===d.get(g+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.f.foreach={Qc:function(b){return function(){var c=b(),d=a.a.$b(c);if(!d||"number"==typeof d.length)return{foreach:c,templateEngine:a.ba.Na};a.a.c(c);return{foreach:d.data,as:d.as,noChildContext:d.noChildContext,includeDestroyed:d.includeDestroyed,afterAdd:d.afterAdd,
777beforeRemove:d.beforeRemove,afterRender:d.afterRender,beforeMove:d.beforeMove,afterMove:d.afterMove,templateEngine:a.ba.Na}}},init:function(b,c){return a.f.template.init(b,a.f.foreach.Qc(c))},update:function(b,c,d,e,f){return a.f.template.update(b,a.f.foreach.Qc(c),d,e,f)}};a.m.Ra.foreach=!1;a.h.ea.foreach=!0;a.f.hasfocus={init:function(b,c,d){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(k){g=f.body}e=g===b}f=c();a.m.$a(f,
778d,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var f=e.bind(null,!0),g=e.bind(null,!1);a.a.H(b,"focus",f);a.a.H(b,"focusin",f);a.a.H(b,"blur",g);a.a.H(b,"focusout",g);b.__ko_hasfocusLastValue=!1},update:function(b,c){var d=!!a.a.c(c());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===d||(d?b.focus():b.blur(),!d&&b.__ko_hasfocusLastValue&&b.ownerDocument.body.focus(),a.v.K(a.a.Fb,null,[b,d?"focusin":"focusout"]))}};a.m.va.hasfocus=!0;a.f.hasFocus=a.f.hasfocus;a.m.va.hasFocus=
779"hasfocus";a.f.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.dc(b,c())}};(function(){function b(b,d,e){a.f[b]={init:function(b,c,h,m,l){var k,q,n={},r,p,A;if(d){m=h.get("as");var u=h.get("noChildContext");A=!(m&&u);n={as:m,noChildContext:u,exportDependencies:A}}p=(r="render"==h.get("completeOn"))||h.has(a.j.oa);a.o(function(){var h=a.a.c(c()),m=!e!==!h,u=!q,t;if(A||m!==k){p&&(l=a.j.Bb(b,l));if(m){if(!d||A)n.dataDependency=a.U.o();t=d?l.createChildContext("function"==
780typeof h?h:c,n):a.U.pa()?l.extend(null,n):l}u&&a.U.pa()&&(q=a.a.Ca(a.h.childNodes(b),!0));m?(u||a.h.ua(b,a.a.Ca(q)),a.Pa(t,b)):(a.h.Ea(b),r||a.j.Ga(b,a.j.T));k=m}},null,{l:b});return{controlsDescendantBindings:!0}}};a.m.Ra[b]=!1;a.h.ea[b]=!0}b("if");b("ifnot",!1,!0);b("with",!0)})();a.f.let={init:function(b,c,d,e,f){c=f.extend(c);a.Pa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.let=!0;var Q={};a.f.options={init:function(b){if("select"!==a.a.P(b))throw Error("options binding applies only to SELECT elements");
781for(;0<b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,c,d){function e(){return a.a.fb(b.options,function(a){return a.selected})}function f(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function g(c,e){if(y&&k)a.u.ya(b,a.a.c(d.get("value")),!0);else if(r.length){var f=0<=a.a.A(r,a.u.L(e[0]));a.a.Yc(e[0],f);y&&!f&&a.v.K(a.a.Fb,null,[b,"change"])}}var h=b.multiple,m=0!=b.length&&h?b.scrollTop:null,l=a.a.c(c()),k=d.get("valueAllowUnset")&&d.has("value"),
782q=d.get("optionsIncludeDestroyed");c={};var n,r=[];k||(h?r=a.a.Mb(e(),a.u.L):0<=b.selectedIndex&&r.push(a.u.L(b.options[b.selectedIndex])));l&&("undefined"==typeof l.length&&(l=[l]),n=a.a.fb(l,function(b){return q||b===p||null===b||!a.a.c(b._destroy)}),d.has("optionsCaption")&&(l=a.a.c(d.get("optionsCaption")),null!==l&&l!==p&&n.unshift(Q)));var y=!1;c.beforeRemove=function(a){b.removeChild(a)};l=g;d.has("optionsAfterRender")&&"function"==typeof d.get("optionsAfterRender")&&(l=function(b,c){g(0,c);
783a.v.K(d.get("optionsAfterRender"),null,[c[0],b!==Q?b:p])});a.a.cc(b,n,function(c,e,g){g.length&&(r=!k&&g[0].selected?[a.u.L(g[0])]:[],y=!0);e=b.ownerDocument.createElement("option");c===Q?(a.a.Ab(e,d.get("optionsCaption")),a.u.ya(e,p)):(g=f(c,d.get("optionsValue"),c),a.u.ya(e,a.a.c(g)),c=f(c,d.get("optionsText"),g),a.a.Ab(e,c));return[e]},c,l);a.v.K(function(){if(k)a.u.ya(b,a.a.c(d.get("value")),!0);else{var c;h?c=r.length&&e().length<r.length:c=r.length&&0<=b.selectedIndex?a.u.L(b.options[b.selectedIndex])!==
784r[0]:r.length||0<=b.selectedIndex;c&&a.a.Fb(b,"change")}});a.a.vd(b);m&&20<Math.abs(m-b.scrollTop)&&(b.scrollTop=m)}};a.f.options.Yb=a.a.g.Z();a.f.selectedOptions={after:["options","foreach"],init:function(b,c,d){a.a.H(b,"change",function(){var e=c(),f=[];a.a.C(b.getElementsByTagName("option"),function(b){b.selected&&f.push(a.u.L(b))});a.m.$a(e,d,"selectedOptions",f)})},update:function(b,c){if("select"!=a.a.P(b))throw Error("values binding applies only to SELECT elements");var d=a.a.c(c()),e=b.scrollTop;
785d&&"number"==typeof d.length&&a.a.C(b.getElementsByTagName("option"),function(b){var c=0<=a.a.A(d,a.u.L(b));b.selected!=c&&a.a.Yc(b,c)});b.scrollTop=e}};a.m.va.selectedOptions=!0;a.f.style={update:function(b,c){var d=a.a.c(c()||{});a.a.O(d,function(c,d){d=a.a.c(d);if(null===d||d===p||!1===d)d="";if(v)v(b).css(c,d);else if(/^--/.test(c))b.style.setProperty(c,d);else{c=c.replace(/-(\w)/g,function(a,b){return b.toUpperCase()});var g=b.style[c];b.style[c]=d;d===g||b.style[c]!=g||isNaN(d)||(b.style[c]=
786d+"px")}})}};a.f.submit={init:function(b,c,d,e,f){if("function"!=typeof c())throw Error("The value for a submit binding must be a function");a.a.H(b,"submit",function(a){var d,e=c();try{d=e.call(f.$data,b)}finally{!0!==d&&(a.preventDefault?a.preventDefault():a.returnValue=!1)}})}};a.f.text={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.Ab(b,c())}};a.h.ea.text=!0;(function(){if(z&&z.navigator){var b=function(a){if(a)return parseFloat(a[1])},c=z.navigator.userAgent,
787d,e,f,g,h;(d=z.opera&&z.opera.version&&parseInt(z.opera.version()))||(h=b(c.match(/Edge\/([^ ]+)$/)))||b(c.match(/Chrome\/([^ ]+)/))||(e=b(c.match(/Version\/([^ ]+) Safari/)))||(f=b(c.match(/Firefox\/([^ ]+)/)))||(g=a.a.W||b(c.match(/MSIE ([^ ]+)/)))||(g=b(c.match(/rv:([^ )]+)/)))}if(8<=g&&10>g)var m=a.a.g.Z(),l=a.a.g.Z(),k=function(b){var c=this.activeElement;(c=c&&a.a.g.get(c,l))&&c(b)},q=function(b,c){var d=b.ownerDocument;a.a.g.get(d,m)||(a.a.g.set(d,m,!0),a.a.H(d,"selectionchange",k));a.a.g.set(b,
788l,c)};a.f.textInput={init:function(b,c,l){function k(c,d){a.a.H(b,c,d)}function m(){var d=a.a.c(c());if(null===d||d===p)d="";L!==p&&d===L?a.a.setTimeout(m,4):b.value!==d&&(x=!0,b.value=d,x=!1,v=b.value)}function t(){w||(L=b.value,w=a.a.setTimeout(B,4))}function B(){clearTimeout(w);L=w=p;var d=b.value;v!==d&&(v=d,a.m.$a(c(),l,"textInput",d))}var v=b.value,w,L,z=9==a.a.W?t:B,x=!1;g&&k("keypress",B);11>g&&k("propertychange",function(a){x||"value"!==a.propertyName||z(a)});8==g&&(k("keyup",B),k("keydown",
789B));q&&(q(b,z),k("dragend",t));(!g||9<=g)&&k("input",z);5>e&&"textarea"===a.a.P(b)?(k("keydown",t),k("paste",t),k("cut",t)):11>d?k("keydown",t):4>f?(k("DOMAutoComplete",B),k("dragdrop",B),k("drop",B)):h&&"number"===b.type&&k("keydown",t);k("change",B);k("blur",B);a.o(m,null,{l:b})}};a.m.va.textInput=!0;a.f.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.f.uniqueName={init:function(b,c){if(c()){var d="ko_unique_"+ ++a.f.uniqueName.qd;a.a.Xc(b,d)}}};a.f.uniqueName.qd=0;a.f.using={init:function(b,
790c,d,e,f){var g;d.has("as")&&(g={as:d.get("as"),noChildContext:d.get("noChildContext")});c=f.createChildContext(c,g);a.Pa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.using=!0;a.f.value={after:["options","foreach"],init:function(b,c,d){var e=a.a.P(b),f="input"==e;if(!f||"checkbox"!=b.type&&"radio"!=b.type){var g=["change"],h=d.get("valueUpdate"),m=!1,l=null;h&&("string"==typeof h&&(h=[h]),a.a.gb(g,h),g=a.a.vc(g));var k=function(){l=null;m=!1;var e=c(),f=a.u.L(b);a.m.$a(e,d,"value",f)};!a.a.W||
791!f||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.A(g,"propertychange")||(a.a.H(b,"propertychange",function(){m=!0}),a.a.H(b,"focus",function(){m=!1}),a.a.H(b,"blur",function(){m&&k()}));a.a.C(g,function(c){var d=k;a.a.Td(c,"after")&&(d=function(){l=a.u.L(b);a.a.setTimeout(k,0)},c=c.substring(5));a.a.H(b,c,d)});var q;q=f&&"file"==b.type?function(){var d=a.a.c(c());null===d||d===p||""===d?b.value="":a.v.K(k)}:function(){var f=a.a.c(c()),g=a.u.L(b);if(null!==l&&
792f===l)a.a.setTimeout(q,0);else if(f!==g||g===p)"select"===e?(g=d.get("valueAllowUnset"),a.u.ya(b,f,g),g||f===a.u.L(b)||a.v.K(k)):a.u.ya(b,f)};a.o(q,null,{l:b})}else a.eb(b,{checkedValue:c})},update:function(){}};a.m.va.value=!0;a.f.visible={update:function(b,c){var d=a.a.c(c()),e="none"!=b.style.display;d&&!e?b.style.display="":!d&&e&&(b.style.display="none")}};a.f.hidden={update:function(b,c){a.f.visible.update(b,function(){return!a.a.c(c())})}};(function(b){a.f[b]={init:function(c,d,e,f,g){return a.f.event.init.call(this,
793c,function(){var a={};a[b]=d();return a},e,f,g)}}})("click");a.ca=function(){};a.ca.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.ca.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.ca.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){c=c||w;var d=c.getElementById(b);if(!d)throw Error("Cannot find template with ID "+b);return new a.B.D(d)}if(1==b.nodeType||8==b.nodeType)return new a.B.ia(b);
794throw Error("Unknown template type: "+b);};a.ca.prototype.renderTemplate=function(a,c,d,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,c,d,e)};a.ca.prototype.isTemplateRewritten=function(a,c){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,c).data("isRewritten")};a.ca.prototype.rewriteTemplate=function(a,c,d){a=this.makeTemplateSource(a,d);c=c(a.text());a.text(c);a.data("isRewritten",!0)};a.b("templateEngine",a.ca);a.ic=function(){function b(b,c,d,h){b=a.m.Zb(b);
795for(var m=a.m.Ra,l=0;l<b.length;l++){var k=b[l].key;if(Object.prototype.hasOwnProperty.call(m,k)){var q=m[k];if("function"===typeof q){if(k=q(b[l].value))throw Error(k);}else if(!q)throw Error("This template engine does not support the '"+k+"' binding within its templates");}}d="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+a.m.ub(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+"')";return h.createJavaScriptEvaluatorBlock(d)+c}var c=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'|[^>]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,
796d=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{wd:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.ic.Kd(b,c)},d)},Kd:function(a,f){return a.replace(c,function(a,c,d,e,k){return b(k,c,d,f)}).replace(d,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",f)})},ld:function(b,c){return a.aa.Wb(function(d,h){var m=d.nextSibling;m&&m.nodeName.toLowerCase()===c&&a.eb(m,b,h)})}}}();a.b("__tr_ambtns",a.ic.ld);(function(){a.B={};a.B.D=function(b){if(this.D=b){var c=
797a.a.P(b);this.Db="script"===c?1:"textarea"===c?2:"template"==c&&b.content&&11===b.content.nodeType?3:4}};a.B.D.prototype.text=function(){var b=1===this.Db?"text":2===this.Db?"value":"innerHTML";if(0==arguments.length)return this.D[b];var c=arguments[0];"innerHTML"===b?a.a.dc(this.D,c):this.D[b]=c};var b=a.a.g.Z()+"_";a.B.D.prototype.data=function(c){if(1===arguments.length)return a.a.g.get(this.D,b+c);a.a.g.set(this.D,b+c,arguments[1])};var c=a.a.g.Z();a.B.D.prototype.nodes=function(){var b=this.D;
798if(0==arguments.length){var e=a.a.g.get(b,c)||{},f=e.jb||(3===this.Db?b.content:4===this.Db?b:p);if(!f||e.hd)if(e=this.text())f=a.a.Ld(e,b.ownerDocument),this.text(""),a.a.g.set(b,c,{jb:f,hd:!0});return f}a.a.g.set(b,c,{jb:arguments[0]})};a.B.ia=function(a){this.D=a};a.B.ia.prototype=new a.B.D;a.B.ia.prototype.constructor=a.B.ia;a.B.ia.prototype.text=function(){if(0==arguments.length){var b=a.a.g.get(this.D,c)||{};b.jc===p&&b.jb&&(b.jc=b.jb.innerHTML);return b.jc}a.a.g.set(this.D,c,{jc:arguments[0]})};
799a.b("templateSources",a.B);a.b("templateSources.domElement",a.B.D);a.b("templateSources.anonymousTemplate",a.B.ia)})();(function(){function b(b,c,d){var e;for(c=a.h.nextSibling(c);b&&(e=b)!==c;)b=a.h.nextSibling(e),d(e,b)}function c(c,d){if(c.length){var e=c[0],f=c[c.length-1],g=e.parentNode,h=a.ga.instance,m=h.preprocessNode;if(m){b(e,f,function(a,b){var c=a.previousSibling,d=m.call(h,a);d&&(a===e&&(e=d[0]||b),a===f&&(f=d[d.length-1]||c))});c.length=0;if(!e)return;e===f?c.push(e):(c.push(e,f),a.a.Ua(c,
800g))}b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.uc(d,b)});b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.aa.bd(b,[d])});a.a.Ua(c,g)}}function d(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,f,h,m){m=m||{};var p=(b&&d(b)||f||{}).ownerDocument,A=m.templateEngine||g;a.ic.wd(f,A,p);f=A.renderTemplate(f,h,m,p);if("number"!=typeof f.length||0<f.length&&"number"!=typeof f[0].nodeType)throw Error("Template engine must return an array of DOM nodes");p=!1;switch(e){case "replaceChildren":a.h.ua(b,
801f);p=!0;break;case "replaceNode":a.a.Wc(b,f);p=!0;break;case "ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+e);}p&&(c(f,h),m.afterRender&&a.v.K(m.afterRender,null,[f,h[m.as||"$data"]]),"replaceChildren"==e&&a.j.Ga(b,a.j.T));return f}function f(b,c,d){return a.N(b)?b():"function"===typeof b?b(c,d):b}var g;a.ec=function(b){if(b!=p&&!(b instanceof a.ca))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.bc=function(b,c,h,m,r){h=h||{};if((h.templateEngine||g)==
802p)throw Error("Set a template engine before calling renderTemplate");r=r||"replaceChildren";if(m){var y=d(m);return a.$(function(){var g=c&&c instanceof a.fa?c:new a.fa(c,null,null,null,{exportDependencies:!0}),p=f(b,g.$data,g),g=e(m,r,p,g,h);"replaceNode"==r&&(m=g,y=d(m))},null,{Sa:function(){return!y||!a.a.Rb(y)},l:y&&"replaceNode"==r?y.parentNode:y})}return a.aa.Wb(function(d){a.bc(b,c,h,d,"replaceNode")})};a.Pd=function(b,d,g,h,m){function y(b,c){a.v.K(a.a.cc,null,[h,b,u,g,t,c]);a.j.Ga(h,a.j.T)}
803function t(a,b){c(b,v);g.afterRender&&g.afterRender(b,a);v=null}function u(a,c){v=m.createChildContext(a,{as:B,noChildContext:g.noChildContext,extend:function(a){a.$index=c;B&&(a[B+"Index"]=c)}});var d=f(b,a,v);return e(h,"ignoreTargetNode",d,v,g)}var v,B=g.as,w=!1===g.includeDestroyed||a.options.foreachHidesDestroyed&&!g.includeDestroyed;if(w||g.beforeRemove||!a.Oc(d))return a.$(function(){var b=a.a.c(d)||[];"undefined"==typeof b.length&&(b=[b]);w&&(b=a.a.fb(b,function(b){return b===p||null===b||
804!a.a.c(b._destroy)}));y(b)},null,{l:h});y(d.w());var z=d.subscribe(function(a){y(d(),a)},null,"arrayChange");z.l(h);return z};var h=a.a.g.Z(),m=a.a.g.Z();a.f.template={init:function(b,c){var d=a.a.c(c());if("string"==typeof d||d.name)a.h.Ea(b);else if("nodes"in d){d=d.nodes||[];if(a.N(d))throw Error('The "nodes" option must be a plain, non-observable array.');var e=d[0]&&d[0].parentNode;e&&a.a.g.get(e,m)||(e=a.a.Xb(d),a.a.g.set(e,m,!0));(new a.B.ia(b)).nodes(e)}else if(d=a.h.childNodes(b),0<d.length)e=
805a.a.Xb(d),(new a.B.ia(b)).nodes(e);else throw Error("Anonymous template defined, but no template content was provided");return{controlsDescendantBindings:!0}},update:function(b,c,d,e,f){var g=c();c=a.a.c(g);d=!0;e=null;"string"==typeof c?c={}:(g=c.name,"if"in c&&(d=a.a.c(c["if"])),d&&"ifnot"in c&&(d=!a.a.c(c.ifnot)));"foreach"in c?e=a.Pd(g||b,d&&c.foreach||[],c,b,f):d?(d=f,"data"in c&&(d=f.createChildContext(c.data,{as:c.as,noChildContext:c.noChildContext,exportDependencies:!0})),e=a.bc(g||b,d,c,
806b)):a.h.Ea(b);f=e;(c=a.a.g.get(b,h))&&"function"==typeof c.s&&c.s();a.a.g.set(b,h,!f||f.ja&&!f.ja()?p:f)}};a.m.Ra.template=function(b){b=a.m.Zb(b);return 1==b.length&&b[0].unknown||a.m.Hd(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.h.ea.template=!0})();a.b("setTemplateEngine",a.ec);a.b("renderTemplate",a.bc);a.a.Jc=function(a,c,d){if(a.length&&c.length){var e,f,g,h,m;for(e=f=0;(!d||e<d)&&(h=a[f]);++f){for(g=0;m=c[g];++g)if(h.value===m.value){h.moved=
807m.index;m.moved=h.index;c.splice(g,1);e=g=0;break}e+=g}}};a.a.Ob=function(){function b(b,d,e,f,g){var h=Math.min,m=Math.max,l=[],k,p=b.length,n,r=d.length,t=r-p||1,A=p+r+1,u,v,w;for(k=0;k<=p;k++)for(v=u,l.push(u=[]),w=h(r,k+t),n=m(0,k-1);n<=w;n++)u[n]=n?k?b[k-1]===d[n-1]?v[n-1]:h(v[n]||A,u[n-1]||A)+1:n+1:k+1;h=[];m=[];t=[];k=p;for(n=r;k||n;)r=l[k][n]-1,n&&r===l[k][n-1]?m.push(h[h.length]={status:e,value:d[--n],index:n}):k&&r===l[k-1][n]?t.push(h[h.length]={status:f,value:b[--k],index:k}):(--n,--k,
808g.sparse||h.push({status:"retained",value:d[n]}));a.a.Jc(t,m,!g.dontLimitMoves&&10*p);return h.reverse()}return function(a,d,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];d=d||[];return a.length<d.length?b(a,d,"added","deleted",e):b(d,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.Ob);(function(){function b(b,c,d,h,m){var l=[],k=a.$(function(){var k=c(d,m,a.a.Ua(l,b))||[];0<l.length&&(a.a.Wc(l,k),h&&a.v.K(h,null,[d,k,m]));l.length=0;a.a.gb(l,k)},null,{l:b,Sa:function(){return!a.a.jd(l)}});
809return{Y:l,$:k.ja()?k:p}}var c=a.a.g.Z(),d=a.a.g.Z();a.a.cc=function(e,f,g,h,m,l){function k(b){x={Aa:b,nb:a.sa(w++)};v.push(x);t||F.push(x)}function q(b){x=r[b];w!==x.nb.w()&&D.push(x);x.nb(w++);a.a.Ua(x.Y,e);v.push(x)}function n(b,c){if(b)for(var d=0,e=c.length;d<e;d++)a.a.C(c[d].Y,function(a){b(a,d,c[d].Aa)})}f=f||[];"undefined"==typeof f.length&&(f=[f]);h=h||{};var r=a.a.g.get(e,c),t=!r,v=[],u=0,w=0,B=[],z=[],C=[],D=[],F=[],x,I=0;if(t)a.a.C(f,k);else{if(!l||r&&r._countWaitingForRemove){var E=
810a.a.Mb(r,function(a){return a.Aa});l=a.a.Ob(E,f,{dontLimitMoves:h.dontLimitMoves,sparse:!0})}for(var E=0,G,H,K;G=l[E];E++)switch(H=G.moved,K=G.index,G.status){case "deleted":for(;u<K;)q(u++);H===p&&(x=r[u],x.$&&(x.$.s(),x.$=p),a.a.Ua(x.Y,e).length&&(h.beforeRemove&&(v.push(x),I++,x.Aa===d?x=null:C.push(x)),x&&B.push.apply(B,x.Y)));u++;break;case "added":for(;w<K;)q(u++);H!==p?(z.push(v.length),q(H)):k(G.value)}for(;w<f.length;)q(u++);v._countWaitingForRemove=I}a.a.g.set(e,c,v);
810n(h.beforeMove,D);a.a.C(B,
811h.beforeRemove?a.na:a.removeNode);var M,O,P;try{P=e.ownerDocument.activeElement}catch(N){}if(z.length)for(;(E=z.shift())!=p;){x=v[E];for(M=p;E;)if((O=v[--E].Y)&&O.length){M=O[O.length-1];break}for(f=0;u=x.Y[f];M=u,f++)a.h.Vb(e,u,M)}E=0;for(z=a.h.firstChild(e);x=v[E];E++){x.Y||a.a.extend(x,b(e,g,x.Aa,m,x.nb));for(f=0;u=x.Y[f];z=u.nextSibling,M=u,f++)u!==z&&a.h.Vb(e,u,M);!x.Dd&&m&&(m(x.Aa,x.Y,x.nb),x.Dd=!0,M=x.Y[x.Y.length-1])}P&&e.ownerDocument.activeElement!=P&&P.focus();n(h.beforeRemove,C);for(E=
8120;E<C.length;++E)C[E].Aa=d;n(h.afterMove,D);n(h.afterAdd,F)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.cc);a.ba=function(){this.allowTemplateRewriting=!1};a.ba.prototype=new a.ca;a.ba.prototype.constructor=a.ba;a.ba.prototype.renderTemplateSource=function(b,c,d,e){if(c=(9>a.a.W?0:b.nodes)?b.nodes():null)return a.a.la(c.cloneNode(!0).childNodes);b=b.text();return a.a.ta(b,e)};a.ba.Na=new a.ba;a.ec(a.ba.Na);a.b("nativeTemplateEngine",a.ba);(function(){a.Za=function(){var a=this.Gd=function(){if(!v||
813!v.tmpl)return 0;try{if(0<=v.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,f,g){g=g||w;f=f||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=v.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=v.extend({koBindingContext:e},f.templateOptions);e=v.tmpl(h,b,e);e.appendTo(g.createElement("div"));
814v.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){w.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(v.tmpl.tag.ko_code={open:"__.push($1 || '');"},v.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.Za.prototype=new a.ca;a.Za.prototype.constructor=a.Za;var b=new a.Za;0<b.Gd&&a.ec(b);a.b("jqueryTmplTemplateEngine",a.Za)})()})})();})();
815/*
816* jquery-match-height 0.7.2 by @liabru
817* http://brm.io/jquery-match-height/
818* License MIT
819*/
820!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):t(jQuery)}(function(t){var e=-1,o=-1,n=function(t){return parseFloat(t)||0},a=function(e){var o=1,a=t(e),i=null,r=[];return a.each(function(){var e=t(this),a=e.offset().top-n(e.css("margin-top")),s=r.length>0?r[r.length-1]:null;null===s?r.push(e):Math.floor(Math.abs(i-a))<=o?r[r.length-1]=s.add(e):r.push(e),i=a}),r},i=function(e){var o={
821    byRow:!0,property:"height",target:null,remove:!1};return"object"==typeof e?t.extend(o,e):("boolean"==typeof e?o.byRow=e:"remove"===e&&(o.remove=!0),o)},r=t.fn.matchHeight=function(e){var o=i(e);if(o.remove){var n=this;return this.css(o.property,""),t.each(r._groups,function(t,e){e.elements=e.elements.not(n)}),this}return this.length<=1&&!o.target?this:(r._groups.push({elements:this,options:o}),r._apply(this,o),this)};r.version="0.7.2",r._groups=[],r._throttle=80,r._maintainScroll=!1,r._beforeUpdate=null,
822    r._afterUpdate=null,r._rows=a,r._parse=n,r._parseOptions=i,r._apply=function(e,o){var s=i(o),h=t(e),l=[h],c=t(window).scrollTop(),p=t("html").outerHeight(!0),u=h.parents().filter(":hidden");return u.each(function(){var e=t(this);e.data("style-cache",e.attr("style"))}),u.css("display","block"),s.byRow&&!s.target&&(h.each(function(){var e=t(this),o=e.css("display");"inline-block"!==o&&"flex"!==o&&"inline-flex"!==o&&(o="block"),e.data("style-cache",e.attr("style")),e.css({display:o,"padding-top":"0",
823    "padding-bottom":"0","margin-top":"0","margin-bottom":"0","border-top-width":"0","border-bottom-width":"0",height:"100px",overflow:"hidden"})}),l=a(h),h.each(function(){var e=t(this);e.attr("style",e.data("style-cache")||"")})),t.each(l,function(e,o){var a=t(o),i=0;if(s.target)i=s.target.outerHeight(!1);else{if(s.byRow&&a.length<=1)return void a.css(s.property,"");a.each(function(){var e=t(this),o=e.attr("style"),n=e.css("display");"inline-block"!==n&&"flex"!==n&&"inline-flex"!==n&&(n="block");var a={
824    display:n};a[s.property]="",e.css(a),e.outerHeight(!1)>i&&(i=e.outerHeight(!1)),o?e.attr("style",o):e.css("display","")})}a.each(function(){var e=t(this),o=0;s.target&&e.is(s.target)||("border-box"!==e.css("box-sizing")&&(o+=n(e.css("border-top-width"))+n(e.css("border-bottom-width")),o+=n(e.css("padding-top"))+n(e.css("padding-bottom"))),e.css(s.property,i-o+"px"))})}),u.each(function(){var e=t(this);e.attr("style",e.data("style-cache")||null)}),r._maintainScroll&&t(window).scrollTop(c/p*t("html").outerHeight(!0)),
825    this},r._applyDataApi=function(){var e={};t("[data-match-height], [data-mh]").each(function(){var o=t(this),n=o.attr("data-mh")||o.attr("data-match-height");n in e?e[n]=e[n].add(o):e[n]=o}),t.each(e,function(){this.matchHeight(!0)})};var s=function(e){r._beforeUpdate&&r._beforeUpdate(e,r._groups),t.each(r._groups,function(){r._apply(this.elements,this.options)}),r._afterUpdate&&r._afterUpdate(e,r._groups)};r._update=function(n,a){if(a&&"resize"===a.type){var i=t(window).width();if(i===e)return;e=i;
826}n?o===-1&&(o=setTimeout(function(){s(a),o=-1},r._throttle)):s(a)},t(r._applyDataApi);var h=t.fn.on?"on":"bind";t(window)[h]("load",function(t){r._update(!1,t)}),t(window)[h]("resize orientationchange",function(t){r._update(!0,t)})});
827/**
828* simplePagination.js v1.6
829* A simple jQuery pagination plugin.
830* http://flaviusmatis.github.com/simplePagination.js/
831*
832* Copyright 2012, Flavius Matis
833* Released under the MIT license.
834* http://flaviusmatis.github.com/license.html
835*/
836
837(function($){
838
839	var methods = {
840		init: function(options) {
841			var o = $.extend({
842				items: 1,
843				itemsOnPage: 1,
844				pages: 0,
845				displayedPages: 5,
846				edges: 2,
847				currentPage: 0,
848				useAnchors: true,
849				hrefTextPrefix: '#page-',
850				hrefTextSuffix: '',
851				prevText: 'Prev',
852				nextText: 'Next',
853				ellipseText: '&hellip;',
854				ellipsePageSet: true,
855				cssStyle: 'light-theme',
856				listStyle: '',
857				labelMap: [],
858				selectOnClick: true,
859				nextAtFront: false,
860				invertPageOrder: false,
861				useStartEdge : true,
862				useEndEdge : true,
863				onPageClick: function(pageNumber, event) {
864					// Callback triggered when a page is clicked
865					// Page number is given as an optional parameter
866				},
867				onInit: function() {
868					// Callback triggered immediately after initialization
869				}
870			}, options || {});
871
872			var self = this;
873
874			o.pages = o.pages ? o.pages : Math.ceil(o.items / o.itemsOnPage) ? Math.ceil(o.items / o.itemsOnPage) : 1;
875			if (o.currentPage)
876				o.currentPage = o.currentPage - 1;
877			else
878				o.currentPage = !o.invertPageOrder ? 0 : o.pages - 1;
879			o.halfDisplayed = o.displayedPages / 2;
880
881			this.each(function() {
882				self.addClass(o.cssStyle + ' simple-pagination').data('pagination', o);
883				methods._draw.call(self);
884			});
885
886			o.onInit();
887
888			return this;
889		},
890
891		selectPage: function(page) {
892			methods._selectPage.call(this, page - 1);
893			return this;
894		},
895
896		prevPage: function() {
897			var o = this.data('pagination');
898			if (!o.invertPageOrder) {
899				if (o.currentPage > 0) {
900					methods._selectPage.call(this, o.currentPage - 1);
901				}
902			} else {
903				if (o.currentPage < o.pages - 1) {
904					methods._selectPage.call(this, o.currentPage + 1);
905				}
906			}
907			return this;
908		},
909
910		nextPage: function() {
911			var o = this.data('pagination');
912			if (!o.invertPageOrder) {
913				if (o.currentPage < o.pages - 1) {
914					methods._selectPage.call(this, o.currentPage + 1);
915				}
916			} else {
917				if (o.currentPage > 0) {
918					methods._selectPage.call(this, o.currentPage - 1);
919				}
920			}
921			return this;
922		},
923
924		getPagesCount: function() {
925			return this.data('pagination').pages;
926		},
927
928		setPagesCount: function(count) {
929			this.data('pagination').pages = count;
930		},
931
932		getCurrentPage: function () {
933			return this.data('pagination').currentPage + 1;
934		},
935
936		destroy: function(){
937			this.empty();
938			return this;
939		},
940
941		drawPage: function (page) {
942			var o = this.data('pagination');
943			o.currentPage = page - 1;
944			this.data('pagination', o);
945			methods._draw.call(this);
946			return this;
947		},
948
949		redraw: function(){
950			methods._draw.call(this);
951			return this;
952		},
953
954		disable: function(){
955			var o = this.data('pagination');
956			o.disabled = true;
957			this.data('pagination', o);
958			methods._draw.call(this);
959			return this;
960		},
961
962		enable: function(){
963			var o = this.data('pagination');
964			o.disabled = false;
965			this.data('pagination', o);
966			methods._draw.call(this);
967			return this;
968		},
969
970		updateItems: function (newItems) {
971			var o = this.data('pagination');
972			o.items = newItems;
973			o.pages = methods._getPages(o);
974			this.data('pagination', o);
975			methods._draw.call(this);
976		},
977
978		updateItemsOnPage: function (itemsOnPage) {
979			var o = this.data('pagination');
980			o.itemsOnPage = itemsOnPage;
981			o.pages = methods._getPages(o);
982			this.data('pagination', o);
983			methods._selectPage.call(this, 0);
984			return this;
985		},
986
987		getItemsOnPage: function() {
988			return this.data('pagination').itemsOnPage;
989		},
990
991		_draw: function() {
992			var	o = this.data('pagination'),
993				interval = methods._getInterval(o),
994				i,
995				tagName;
996
997			methods.destroy.call(this);
998
999			tagName = (typeof this.prop === 'function') ? this.prop('tagName') : this.attr('tagName');
1000
1001			var $panel = tagName === 'UL' ? this : $('<ul' + (o.listStyle ? ' class="' + o.listStyle + '"' : '') + '></ul>').appendTo(this);
1002
1003			// Generate Prev link
1004			if (o.prevText) {
1005				methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage - 1 : o.currentPage + 1, {text: o.prevText, classes: 'prev'});
1006			}
1007
1008			// Generate Next link (if option set for at front)
1009			if (o.nextText && o.nextAtFront) {
1010				methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage + 1 : o.currentPage - 1, {text: o.nextText, classes: 'next'});
1011			}
1012
1013			// Generate start edges
1014			if (!o.invertPageOrder) {
1015				if (interval.start > 0 && o.edges > 0) {
1016					if(o.useStartEdge) {
1017						var end = Math.min(o.edges, interval.start);
1018						for (i = 0; i < end; i++) {
1019							methods._appendItem.call(this, i);
1020						}
1021					}
1022					if (o.edges < interval.start && (interval.start - o.edges != 1)) {
1023						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
1024					} else if (interval.start - o.edges == 1) {
1025						methods._appendItem.call(this, o.edges);
1026					}
1027				}
1028			} else {
1029				if (interval.end < o.pages && o.edges > 0) {
1030					if(o.useStartEdge) {
1031						var begin = Math.max(o.pages - o.edges, interval.end);
1032						for (i = o.pages - 1; i >= begin; i--) {
1033							methods._appendItem.call(this, i);
1034						}
1035					}
1036
1037					if (o.pages - o.edges > interval.end && (o.pages - o.edges - interval.end != 1)) {
1038						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
1039					} else if (o.pages - o.edges - interval.end == 1) {
1040						methods._appendItem.call(this, interval.end);
1041					}
1042				}
1043			}
1044
1045			// Generate interval links
1046			if (!o.invertPageOrder) {
1047				for (i = interval.start; i < interval.end; i++) {
1048					methods._appendItem.call(this, i);
1049				}
1050			} else {
1051				for (i = interval.end - 1; i >= interval.start; i--) {
1052					methods._appendItem.call(this, i);
1053				}
1054			}
1055
1056			// Generate end edges
1057			if (!o.invertPageOrder) {
1058				if (interval.end < o.pages && o.edges > 0) {
1059					if (o.pages - o.edges > interval.end && (o.pages - o.edges - interval.end != 1)) {
1060						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
1061					} else if (o.pages - o.edges - interval.end == 1) {
1062						methods._appendItem.call(this, interval.end);
1063					}
1064					if(o.useEndEdge) {
1065						var begin = Math.max(o.pages - o.edges, interval.end);
1066						for (i = begin; i < o.pages; i++) {
1067							methods._appendItem.call(this, i);
1068						}
1069					}
1070				}
1071			} else {
1072				if (interval.start > 0 && o.edges > 0) {
1073					if (o.edges < interval.start && (interval.start - o.edges != 1)) {
1074						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
1075					} else if (interval.start - o.edges == 1) {
1076						methods._appendItem.call(this, o.edges);
1077					}
1078
1079					if(o.useEndEdge) {
1080						var end = Math.min(o.edges, interval.start);
1081						for (i = end - 1; i >= 0; i--) {
1082							methods._appendItem.call(this, i);
1083						}
1084					}
1085				}
1086			}
1087
1088			// Generate Next link (unless option is set for at front)
1089			if (o.nextText && !o.nextAtFront) {
1090				methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage + 1 : o.currentPage - 1, {text: o.nextText, classes: 'next'});
1091			}
1092
1093			if (o.ellipsePageSet && !o.disabled) {
1094				methods._ellipseClick.call(this, $panel);
1095			}
1096
1097		},
1098
1099		_getPages: function(o) {
1100			var pages = Math.ceil(o.items / o.itemsOnPage);
1101			return pages || 1;
1102		},
1103
1104		_getInterval: function(o) {
1105			return {
1106				start: Math.ceil(o.currentPage > o.halfDisplayed ? Math.max(Math.min(o.currentPage - o.halfDisplayed, (o.pages - o.displayedPages)
1106), 0) : 0),
1107				end: Math.ceil(o.currentPage > o.halfDisplayed ? Math.min(o.currentPage + o.halfDisplayed, o.pages) : Math.min(o.displayedPages, o.pages))
1108			};
1109		},
1110
1111		_appendItem: function(pageIndex, opts) {
1112			var self = this, options, $link, o = self.data('pagination'), $linkWrapper = $('<li></li>'), $ul = self.find('ul');
1113
1114			pageIndex = pageIndex < 0 ? 0 : (pageIndex < o.pages ? pageIndex : o.pages - 1);
1115
1116			options = {
1117				text: pageIndex + 1,
1118				classes: ''
1119			};
1120
1121			if (o.labelMap.length && o.labelMap[pageIndex]) {
1122				options.text = o.labelMap[pageIndex];
1123			}
1124
1125			options = $.extend(options, opts || {});
1126
1127			if (pageIndex == o.currentPage || o.disabled) {
1128				if (o.disabled || options.classes === 'prev' || options.classes === 'next') {
1129					$linkWrapper.addClass('disabled');
1130				} else {
1131					$linkWrapper.addClass('active');
1132				}
1133				$link = $('<span class="current">' + (options.text) + '</span>');
1134			} else {
1135				if (o.useAnchors) {
1136					$link = $('<a class="page-link">' + (options.text) + '</a>');
1137				} else {
1138					$link = $('<span >' + (options.text) + '</span>');
1139				}
1140				$link.click(function(event){
1141					return methods._selectPage.call(self, pageIndex, event);
1142				});
1143			}
1144
1145			if (options.classes) {
1146				$link.addClass(options.classes);
1147			}
1148
1149			$linkWrapper.append($link);
1150
1151			if ($ul.length) {
1152				$ul.append($linkWrapper);
1153			} else {
1154				self.append($linkWrapper);
1155			}
1156		},
1157
1158		_selectPage: function(pageIndex, event) {
1159			var o = this.data('pagination');
1160			o.currentPage = pageIndex;
1161			if (o.selectOnClick) {
1162				methods._draw.call(this);
1163			}
1164			return o.onPageClick(pageIndex + 1, event);
1165		},
1166
1167
1168		_ellipseClick: function($panel) {
1169			var self = this,
1170				o = this.data('pagination'),
1171				$ellip = $panel.find('.ellipse');
1172			$ellip.addClass('clickable').parent().removeClass('disabled');
1173			$ellip.click(function(event) {
1174				if (!o.disable) {
1175					var $this = $(this),
1176						val = (parseInt($this.parent().prev().text(), 10) || 0) + 1;
1177					$this
1178						.html('<input type="number" min="1" max="' + o.pages + '" step="1" value="' + val + '">')
1179						.find('input')
1180						.focus()
1181						.click(function(event) {
1182							// prevent input number arrows from bubbling a click event on $ellip
1183							event.stopPropagation();
1184						})
1185						.keyup(function(event) {
1186							var val = $(this).val();
1187							if (event.which === 13 && val !== '') {
1188								// enter to accept
1189								if ((val>0)&&(val<=o.pages))
1190								methods._selectPage.call(self, val - 1);
1191							} else if (event.which === 27) {
1192								// escape to cancel
1193								$ellip.empty().html(o.ellipseText);
1194							}
1195						})
1196						.bind('blur', function(event) {
1197							var val = $(this).val();
1198							if (val !== '') {
1199								methods._selectPage.call(self, val - 1);
1200							}
1201							$ellip.empty().html(o.ellipseText);
1202							return false;
1203						});
1204				}
1205				return false;
1206			});
1207		}
1208
1209	};
1210
1211	$.fn.pagination = function(method) {
1212
1213		// Method calling logic
1214		if (methods[method] && method.charAt(0) != '_') {
1215			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
1216		} else if (typeof method === 'object' || !method) {
1217			return methods.init.apply(this, arguments);
1218		} else {
1219			$.error('Method ' +  method + ' does not exist on jQuery.pagination');
1220		}
1221
1222	};
1223
1224})(jQuery);
1225
1226!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?module.exports=e(jQuery||require("jquery")):e(jQuery)}(function(be){be.fn.jScrollPane=function(o){function s(w,e){var y,b,k,T,C,S,x,D,B,H,P,z,A,W,Y,M,X,L,R,t,E,I,F,V,q,O,G,N,K,Q,U,$,J,Z,_=this,r=!0,a=!0,l=!1,c=!1,o=w.clone(!1,!1).empty(),ee=!1,te=be.fn.mwheelIntent?"mwheelIntent.jsp":"mousewheel.jsp",oe=function(){0<y.resizeSensorDelay?setTimeout(function(){se(y)},y.resizeSensorDelay):se(y)};function se(e){var t,o,s,i,n,r,a,l,c,p,u,d,f,h,g,j,v=!1,m=!1;if(y=e,void 0===b)n=w.scrollTop(),r=w.scrollLeft(),w.css({overflow:"hidden",padding:0}),k=w.innerWidth()+J,T=w.innerHeight(),w.width(k),b=be('<div class="jspPane" />').css("padding",$).append(w.children()),C=be('<div class="jspContainer" />').css({width:k+"px",height:T+"px"}).append(b).appendTo(w);else{if(w.css("width",""),C.css({width:"auto",height:"auto"}),b.css("position","static"),a=w.innerWidth()+J,l=w.innerHeight(),b.css("position","absolute"),v=y.stickToBottom&&(20<(p=x-T)&&p-we()<10),m=y.stickToRight&&(20<(c=S-k)&&c-me()<10),i=a!==k||l!==T,k=a,T=l,C.css({width:k,height:T}),!i&&Z==S&&b.outerHeight()==x)return void w.width(k);Z=S,b.css("width",""),w.width(k),C.find(">.jspVerticalBar,>.jspHorizontalBar").remove().end()}b.css("overflow","auto"),S=e.contentWidth?e.contentWidth:b[0].scrollWidth,x=b[0].scrollHeight,b.css("overflow",""),D=S/k,H=1<(B=x/T)||y.alwaysShowVScroll,(P=1<D||y.alwaysShowHScroll)||H?(w.addClass("jspScrollable"),(t=y.maintainPosition&&(W||X))&&(o=me(),s=we()),H&&(C.append(be('<div class="jspVerticalBar" />').append(be('<div class="jspCap jspCapTop" />'),be('<div class="jspTrack" />').append(be('<div class="jspDrag" />').append(be('<div class="jspDragTop" />'),be('<div class="jspDragBottom" />'))),be('<div class="jspCap jspCapBottom" />'))),L=C.find(">.jspVerticalBar"),R=L.find(">.jspTrack"),z=R.find(">
1226.jspDrag"),y.showArrows&&(F=be('<a class="jspArrow jspArrowUp" />').on("mousedown.jsp",le(0,-1)).on("click.jsp",ye),V=be('<a class="jspArrow jspArrowDown" />').on("mousedown.jsp",le(0,1)).on("click.jsp",ye),y.arrowScrollOnHover&&(F.on("mouseover.jsp",le(0,-1,F)),V.on("mouseover.jsp",le(0,1,V))),ae(R,y.verticalArrowPositions,F,V)),E=T,C.find(">.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow").each(function(){E-=be(this).outerHeight()}),z.on("mouseenter",function(){z.addClass("jspHover")}).on("mouseleave",function(){z.removeClass("jspHover")}).on("mousedown.jsp",function(e){be("html").on("dragstart.jsp selectstart.jsp",ye),z.addClass("jspActive");var t=e.pageY-z.position().top;return be("html").on("mousemove.jsp",function(e){ue(e.pageY-t,!1)}).on("mouseup.jsp mouseleave.jsp",pe),!1}),ne()),P&&(C.append(be('<div class="jspHorizontalBar" />').append(be('<div class="jspCap jspCapLeft" />'),be('<div class="jspTrack" />').append(be('<div class="jspDrag" />').append(be('<div class="jspDragLeft" />'),be('<div class="jspDragRight" />'))),be('<div class="jspCap jspCapRight" />'))),q=C.find(">.jspHorizontalBar"),O=q.find(">.jspTrack"),Y=O.find(">.jspDrag"),y.showArrows&&(K=be('<a class="jspArrow jspArrowLeft" />').on("mousedown.jsp",le(-1,0)).on("click.jsp",ye),Q=be('<a class="jspArrow jspArrowRight" />').on("mousedown.jsp",le(1,0)).on("click.jsp",ye),y.arrowScrollOnHover&&(K.on("mouseover.jsp",le(-1,0,K)),Q.on("mouseover.jsp",le(1,0,Q))),ae(O,y.horizontalArrowPositions,K,Q)),Y.on("mouseenter",function(){Y.addClass("jspHover")}).on("mouseleave",function(){Y.removeClass("jspHover")}).on("mousedown.jsp",function(e){be("html").on("dragstart.jsp selectstart.jsp",ye),Y.addClass("jspActive");var t=e.pageX-Y.position().left;return be("html").on("mousemove.jsp",function(e){fe(e.pageX-t,!1)}).on("mouseup.jsp mouseleave.jsp",pe),!1}),G=C.innerWidth(),re()),function(){if(P&&H){var e=O.outerHeight(),t=R.outerWidth();E-=e,be(q).find(">.jspCap:visible,>.jspArrow").each(function(){G+=be(this).outerWidth()}),G-=t,T-=t,k-=e,O.parent().append(be('<div class="jspCorner" />').css("width",e+"px")),ne(),re()}P&&b.width(C.outerWidth()-J+"px");x=b.outerHeight(),B=x/T,P&&((N=Math.ceil(1/D*G))>y.horizontalDragMaxWidth?N=y.horizontalDragMaxWidth:N<y.horizontalDragMinWidth&&(N=y.horizontalDragMinWidth),Y.css("width",N+"px"),M=G-N,he(X));H&&((I=Math.ceil(1/B*E))>y.verticalDragMaxHeight?I=y.verticalDragMaxHeight:I<y.verticalDragMinHeight&&(I=y.verticalDragMinHeight),z.css("height",I+"px"),A=E-I,de(W))}(),t&&(je(m?S-k:o,!1),ge(v?x-T:s,!1)),b.find(":input,a").off("focus.jsp").on("focus.jsp",function(e){ve(e.target,!1)}),C.off(te).on(te,function(e,t,o,s){X||(X=0),W||(W=0);var i=X,n=W,r=e.deltaFactor||y.mouseWheelSpeed;return _.scrollBy(o*r,-s*r,!1),i==X&&n==W}),j=!1,C.off("touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick").on("touchstart.jsp",function(e){var t=e.originalEvent.touches[0];u=me(),d=we(),f=t.pageX,h=t.pageY,j=!(g=!1)}).on("touchmove.jsp",function(e){if(j){var t=e.originalEvent.touches[0],o=X,s=W;return _.scrollTo(u+f-t.pageX,d+h-t.pageY),g=g||5<Math.abs(f-t.pageX)||5<Math.abs(h-t.pageY),o==X&&s==W}}).on("touchend.jsp",function(e){j=!1}).on("click.jsp-touchclick",function(e){if(g)return g=!1}),y.enableKeyboardNavigation&&function(){var s,i,n=[];P&&n.push(q[0]);H&&n.push(L[0]);b.on("focus.jsp",function(){w.focus()}),w.attr("tabindex",0).off("keydown.jsp keypress.jsp").on("keydown.jsp",function(e){if(e.target===this||n.length&&be(e.target).closest(n).length){var t=X,o=W;switch(e.keyCode){case 40:case 38:case 34:case 32:case 33:case 39:case 37:s=e.keyCode,r();break;case 35:ge(x-T),s=null;break;case 36:ge(0),s=null}return!(i=e.keyCode==s&&t!=X||o!=W)}}).on("keypress.jsp",function(e){if(e.keyCode==s&&r(),e.target===this||n.length&&be(e.target).closest(n).length)return!i}),y.hideFocus?(w.css("outline","none"),"hideFocus"in C[0]&&w.attr("hideFocus",!0)):(w.css("outline",""),"hideFocus"in C[0]&&w.attr("hideFocus",!1));function r(){var e=X,t=W;switch(s){case 40:_.scrollByY(y.keyboardSpeed,!1);break;case 38:_.scrollByY(-y.keyboardSpeed,!1);break;case 34:case 32:_.scrollByY(T*y.scrollPagePercent,!1);break;case 33:_.scrollByY(-T*y.scrollPagePercent,!1);break;case 39:_.scrollByX(y.keyboardSpeed,!1);break;case 37:_.scrollByX(-y.keyboardSpeed,!1)}return i=e!=X||t!=W}}(),y.clickOnTrack&&function(){ce(),H&&R.on("mousedown.jsp",function(i){if(void 0===i.originalTarget||i.originalTarget==i.currentTarget){var n,r=be(this),e=r.offset(),a=i.pageY-e.top-W,l=!0,c=function(){var e=r.offset(),t=i.pageY-e.top-I/2,o=T*y.scrollPagePercent,s=A*o/(x-T);if(a<0)t<W-s?_.scrollByY(-o):ue(t);else{if(!(0<a))return void p();W+s<t?_.scrollByY(o):ue(t)}n=setTimeout(c,l?y.initialDelay:y.trackClickRepeatFreq),l=!1},p=function(){n&&clearTimeout(n),n=null,be(document).off("mouseup.jsp",p)};return c(),be(document).on("mouseup.jsp",p),!1}});P&&O.on("mousedown.jsp",function(i){if(void 0===i.originalTarget||i.originalTarget==i.currentTarget){var n,r=be(this),e=r.offset(),a=i.pageX-e.left-X,l=!0,c=function(){var e=r.offset(),t=i.pageX-e.left-N/2,o=k*y.scrollPagePercent,s=M*o/(S-k);if(a<0)t<X-s?_.scrollByX(-o):fe(t);else{if(!(0<a))return void p();X+s<t?_.scrollByX(o):fe(t)}
vendor: 4,570 bytes, line 1226
1226n=setTimeout(c,l?y.initialDelay:y.trackClickRepeatFreq),l=!1},p=function(){n&&clearTimeout(n),n=null,be(document).off("mouseup.jsp",p)};return c(),be(document).on("mouseup.jsp",p),!1}})}(),function(){if(location.hash&&1<location.hash.length){var e,t,o=escape(location.hash.substr(1));try{e=be("#"+o+', a[name="'+o+'"]')}catch(e){return}e.length&&b.find(o)&&(0===C.scrollTop()?t=setInterval(function(){0<C.scrollTop()&&(ve(e,!0),be(document).scrollTop(C.position().top),clearInterval(t))},50):(ve(e,!0),be(document).scrollTop(C.position().top)))}}(),y.hijackInternalLinks&&function(){if(be(document.body).data("jspHijack"))return;be(document.body).data("jspHijack",!0),be(document.body).delegate('a[href*="#"]',"click",function(e){var t,o,s,i,n,r=this.href.substr(0,this.href.indexOf("#")),a=location.href;if(-1!==location.href.indexOf("#")&&(a=location.href.substr(0,location.href.indexOf("#"))),r===a){t=escape(this.href.substr(this.href.indexOf("#")+1));try{o=be("#"+t+', a[name="'+t+'"]')}catch(e){return}o.length&&(s=o.closest(".jspScrollable"),s.data("jsp").scrollToElement(o,!0),s[0].scrollIntoView&&(i=be(window).scrollTop(),((n=o.offset().top)<i||n>i+be(window).height())&&s[0].scrollIntoView()),e.preventDefault())}})}()):(w.removeClass("jspScrollable"),b.css({top:0,left:0,width:C.width()-J}),C.off(te),b.find(":input,a").off("focus.jsp"),w.attr("tabindex","-1").removeAttr("tabindex").off("keydown.jsp keypress.jsp"),b.off(".jsp"),ce()),y.resizeSensor||!y.autoReinitialise||U?y.resizeSensor||y.autoReinitialise||!U||clearInterval(U):U=setInterval(function(){se(y)},y.autoReinitialiseDelay),y.resizeSensor&&!ee&&(ie(b,oe),ie(w,oe),ie(w.parent(),oe),window.addEventListener("resize",oe),ee=!0),n&&w.scrollTop(0)&&ge(n,!1),r&&w.scrollLeft(0)&&je(r,!1),w.trigger("jsp-initialised",[P||H])}function ie(e,t){var o,s,i=document.createElement("div"),n=document.createElement("div"),r=document.createElement("div"),a=document.createElement("div"),l=document.createElement("div");i.style.cssText="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;",n.style.cssText="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;",a.style.cssText="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;",r.style.cssText="position: absolute; left: 0; top: 0;",l.style.cssText="position: absolute; left: 0; top: 0; width: 200%; height: 200%;";var c=function(){r.style.width=n.offsetWidth+10+"px",r.style.height=n.offsetHeight+10+"px",n.scrollLeft=n.scrollWidth,n.scrollTop=n.scrollHeight,a.scrollLeft=a.scrollWidth,a.scrollTop=a.scrollHeight,o=e.width(),s=e.height()};n.addEventListener("scroll",function(){(e.width()>o||e.height()>s)&&t.apply(this,[]),c()}.bind(this)),a.addEventListener("scroll",function(){(e.width()<o||e.height()<s)&&t.apply(this,[]),c()}.bind(this)),n.appendChild(r),a.appendChild(l),i.appendChild(n),i.appendChild(a),e.append(i),"static"===window.getComputedStyle(e[0],null).getPropertyValue("position")&&(e[0].style.position="relative"),c()}function ne(){R.height(E+"px"),W=0,t=y.verticalGutter+R.outerWidth(),b.width(k-t-J);try{0===L.position().left&&b.css("margin-left",t+"px")}catch(e){}}function re(){C.find(">.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow").each(function(){G-=be(this).outerWidth()}),O.width(G+"px"),X=0}function ae(e,t,o,s){var i,n="before",r="after";"os"==t&&(t=/Mac/.test(navigator.platform)?"after":"split"),t==n?r=t:t==r&&(n=t,i=o,o=s,s=i),e[n](o)[r](s)}function le(e,t,o){return function(){return function(e,t,o,s){o=be(o).addClass("jspActive");var i,n,r=!0,a=function(){0!==e&&_.scrollByX(e*y.arrowButtonSpeed),0!==t&&_.scrollByY(t*y.arrowButtonSpeed),n=setTimeout(a,r?y.initialDelay:y.arrowRepeatFreq),r=!1};a(),i=s?"mouseout.jsp":"mouseup.jsp",(s=s||be("html")).on(i,function(){o.removeClass("jspActive"),n&&clearTimeout(n),n=null,s.off(i)})}(e,t,this,o),this.blur(),!1}}function ce(){O&&O.off("mousedown.jsp"),R&&R.off("mousedown.jsp")}function pe(){be("html").off("dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp"),z&&z.removeClass("jspActive"),Y&&Y.removeClass("jspActive")}function ue(e,t){if(H){e<0?e=0:A<e&&(e=A);var o=new be.Event("jsp-will-scroll-y");if(w.trigger(o,[e]),!o.isDefaultPrevented()){var s=e||0,i=0===s,n=s==A,r=-(e/A)*(x-T);void 0===t&&(t=y.animateScroll),t?_.animate(z,"top",e,de,function(){w.trigger("jsp-user-scroll-y",[-r,i,n])}):(z.css("top",e),de(e),w.trigger("jsp-user-scroll-y",[-r,i,n]))}}}
1226function de(e){void 0===e&&(e=z.position().top),C.scrollTop(0);var t,o,s=0===(W=e||0),i=W==A,n=-(e/A)*(x-T);r==s&&l==i||(r=s,l=i,w.trigger("jsp-arrow-change",[r,l,a,c])),t=s,o=i,y.showArrows&&(F[t?"addClass":"removeClass"]("jspDisabled"),V[o?"addClass":"removeClass"]("jspDisabled")),b.css("top",n),w.trigger("jsp-scroll-y",[-n,s,i]).trigger("scroll")}function fe(e,t){if(P){e<0?e=0:M<e&&(e=M);var o=new be.Event("jsp-will-scroll-x");if(w.trigger(o,[e]),!o.isDefaultPrevented()){var s=e||0,i=0===s,n=s==M,r=-(e/M)*(S-k);void 0===t&&(t=y.animateScroll),t?_.animate(Y,"left",e,he,function(){w.trigger("jsp-user-scroll-x",[-r,i,n])}):(Y.css("left",e),he(e),w.trigger("jsp-user-scroll-x",[-r,i,n]))}}}function he(e){void 0===e&&(e=Y.position().left),C.scrollTop(0);var t,o,s=0===(X=e||0),i=X==M,n=-(e/M)*(S-k);a==s&&c==i||(a=s,c=i,w.trigger("jsp-arrow-change",[r,l,a,c])),t=s,o=i,y.showArrows&&(K[t?"addClass":"removeClass"]("jspDisabled"),Q[o?"addClass":"removeClass"]("jspDisabled")),b.css("left",n),w.trigger("jsp-scroll-x",[-n,s,i]).trigger("scroll")}function ge(e,t){ue(e/(x-T)*A,t)}function je(e,t){fe(e/(S-k)*M,t)}function ve(e,t,o){var s,i,n,r,a,l,c,p,u,d=0,f=0;try{s=be(e)}catch(e){return}for(i=s.outerHeight(),n=s.outerWidth(),C.scrollTop(0),C.scrollLeft(0);!s.is(".jspPane");)if(d+=s.position().top,f+=s.position().left,s=s.offsetParent(),/^body|html$/i.test(s[0].nodeName))return;l=(r=we())+T,d<r||t?p=d-y.horizontalGutter:l<d+i&&(p=d-T+i+y.horizontalGutter),isNaN(p)||ge(p,o),c=(a=me())+k,f<a||t?u=f-y.horizontalGutter:c<f+n&&(u=f-k+n+y.horizontalGutter),isNaN(u)||je(u,o)}function me(){return-b.position().left}function we(){return-b.position().top}function ye(){return!1}"border-box"===w.css("box-sizing")?J=$=0:($=w.css("paddingTop")+" "+w.css("paddingRight")+" "+w.css("paddingBottom")+" "+w.css("paddingLeft"),J=(parseInt(w.css("paddingLeft"),10)||0)+(parseInt(w.css("paddingRight"),10)||0)),be.extend(_,{reinitialise:function(e){se(e=be.extend({},y,e))},scrollToElement:function(e,t,o){ve(e,t,o)},scrollTo:function(e,t,o){je(e,o),ge(t,o)},scrollToX:function(e,t){je(e,t)},scrollToY:function(e,t){ge(e,t)},scrollToPercentX:function(e,t){je(e*(S-k),t)},scrollToPercentY:function(e,t){ge(e*(x-T),t)},scrollBy:function(e,t,o){_.scrollByX(e,o),_.scrollByY(t,o)},scrollByX:function(e,t){fe((me()+Math[e<0?"floor":"ceil"](e))/(S-k)*M,t)},scrollByY:function(e,t){ue((we()+Math[e<0?"floor":"ceil"](e))/(x-T)*A,t)},positionDragX:function(e,t){fe(e,t)},positionDragY:function(e,t){ue(e,t)},animate:function(e,t,o,s,i){var n={};n[t]=o,e.animate(n,{duration:y.animateDuration,easing:y.animateEase,queue:!1,step:s,complete:i})},getContentPositionX:function(){return me()},getContentPositionY:function(){return we()},getContentWidth:function(){return S},getContentHeight:function(){return x},getPercentScrolledX:function(){return me()/(S-k)},getPercentScrolledY:function(){return we()/(x-T)},getIsScrollableH:function(){return P},getIsScrollableV:function(){return H},getContentPane:function(){return b},scrollToBottom:function(e){ue(A,e)},hijackInternalLinks:be.noop,destroy:function(){var e,t;e=we(),t=me(),w.removeClass("jspScrollable").off(".jsp"),b.off(".jsp"),w.replaceWith(o.append(b.children())),o.scrollTop(e),o.scrollLeft(t),U&&clearInterval(U)}}),se(e)}return o=be.extend({},be.fn.jScrollPane.defaults,o),be.each(["arrowButtonSpeed","trackClickSpeed","keyboardSpeed"],function(){o[this]=o[this]||o.speed}),this.each(function(){var e=be(this),t=e.data("jsp");t?t.reinitialise(o):(be("script",e).filter('[type="text/javascript"],:not([type])').remove(),t=new s(e,o),e.data("jsp",t))})},be.fn.jScrollPane.defaults={showArrows:!1,maintainPosition:!0,stickToBottom:!1,stickToRight:!1,clickOnTrack:!0,autoReinitialise:!1,autoReinitialiseDelay:500,verticalDragMinHeight:0,verticalDragMaxHeight:99999,horizontalDragMinWidth:0,horizontalDragMaxWidth:99999,contentWidth:void 0,animateScroll:!1,animateDuration:300,animateEase:"linear",hijackInternalLinks:!1,verticalGutter:4,horizontalGutter:4,mouseWheelSpeed:3,arrowButtonSpeed:0,arrowRepeatFreq:50,arrowScrollOnHover:!1,trackClickSpeed:0,trackClickRepeatFreq:70,verticalArrowPositions:"split",horizontalArrowPositions:"split",enableKeyboardNavigation:!0,hideFocus:!1,keyboardSpeed:0,initialDelay:300,speed:30,scrollPagePercent:.8,alwaysShowVScroll:!1,alwaysShowHScroll:!1,resizeSensor:!1,resizeSensorDelay:0}});
1227/*!
1228 * jQuery Mousewheel 3.1.12
1229 *
1230 * Copyright 2014 jQuery Foundation and other contributors
1231 * Released under the MIT license.
1232 * http://jquery.org/license
1233 */
1234
1235(function (factory) {
1236    if ( typeof define === 'function' && define.amd ) {
1237        // AMD. Register as an anonymous module.
1238        define(['jquery'], factory);
1239    } else if (typeof exports === 'object') {
1240        // Node/CommonJS style for Browserify
1241        module.exports = factory;
1242    } else {
1243        // Browser globals
1244        factory(jQuery);
1245    }
1246}(function ($) {
1247
1248    var toFix  = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
1249        toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
1250            ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
1251        slice  = Array.prototype.slice,
vendor: 6,451 bytes, lines 1252-1425
1252        nullLowestDeltaTimeout, lowestDelta;
1253
1254    if ( $.event.fixHooks ) {
1255        for ( var i = toFix.length; i; ) {
1256            $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
1257        }
1258    }
1259
1260    var special = $.event.special.mousewheel = {
1261        version: '3.1.12',
1262
1263        setup: function() {
1264            if ( this.addEventListener ) {
1265                for ( var i = toBind.length; i; ) {
1266                    this.addEventListener( toBind[--i], handler, false );
1267                }
1268            } else {
1269                this.onmousewheel = handler;
1270            }
1271            // Store the line height and page height for this particular element
1272            $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
1273            $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
1274        },
1275
1276        teardown: function() {
1277            if ( this.removeEventListener ) {
1278                for ( var i = toBind.length; i; ) {
1279                    this.removeEventListener( toBind[--i], handler, false );
1280                }
1281            } else {
1282                this.onmousewheel = null;
1283            }
1284            // Clean up the data we added to the element
1285            $.removeData(this, 'mousewheel-line-height');
1286            $.removeData(this, 'mousewheel-page-height');
1287        },
1288
1289        getLineHeight: function(elem) {
1290            var $elem = $(elem),
1291                $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
1292            if (!$parent.length) {
1293                $parent = $('body');
1294            }
1295            return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
1296        },
1297
1298        getPageHeight: function(elem) {
1299            return $(elem).height();
1300        },
1301
1302        settings: {
1303            adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
1304            normalizeOffset: true  // calls getBoundingClientRect for each event
1305        }
1306    };
1307
1308    $.fn.extend({
1309        mousewheel: function(fn) {
1310            return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
1311        },
1312
1313        unmousewheel: function(fn) {
1314            return this.unbind('mousewheel', fn);
1315        }
1316    });
1317
1318
1319    function handler(event) {
1320        var orgEvent   = event || window.event,
1321            args       = slice.call(arguments, 1),
1322            delta      = 0,
1323            deltaX     = 0,
1324            deltaY     = 0,
1325            absDelta   = 0,
1326            offsetX    = 0,
1327            offsetY    = 0;
1328        event = $.event.fix(orgEvent);
1329        event.type = 'mousewheel';
1330
1331        // Old school scrollwheel delta
1332        if ( 'detail'      in orgEvent ) { deltaY = orgEvent.detail * -1;      }
1333        if ( 'wheelDelta'  in orgEvent ) { deltaY = orgEvent.wheelDelta;       }
1334        if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY;      }
1335        if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
1336
1337        // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
1338        if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
1339            deltaX = deltaY * -1;
1340            deltaY = 0;
1341        }
1342
1343        // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
1344        delta = deltaY === 0 ? deltaX : deltaY;
1345
1346        // New school wheel delta (wheel event)
1347        if ( 'deltaY' in orgEvent ) {
1348            deltaY = orgEvent.deltaY * -1;
1349            delta  = deltaY;
1350        }
1351        if ( 'deltaX' in orgEvent ) {
1352            deltaX = orgEvent.deltaX;
1353            if ( deltaY === 0 ) { delta  = deltaX * -1; }
1354        }
1355
1356        // No change actually happened, no reason to go any further
1357        if ( deltaY === 0 && deltaX === 0 ) { return; }
1358
1359        // Need to convert lines and pages to pixels if we aren't already in pixels
1360        // There are three delta modes:
1361        //   * deltaMode 0 is by pixels, nothing to do
1362        //   * deltaMode 1 is by lines
1363        //   * deltaMode 2 is by pages
1364        if ( orgEvent.deltaMode === 1 ) {
1365            var lineHeight = $.data(this, 'mousewheel-line-height');
1366            delta  *= lineHeight;
1367            deltaY *= lineHeight;
1368            deltaX *= lineHeight;
1369        } else if ( orgEvent.deltaMode === 2 ) {
1370            var pageHeight = $.data(this, 'mousewheel-page-height');
1371            delta  *= pageHeight;
1372            deltaY *= pageHeight;
1373            deltaX *= pageHeight;
1374        }
1375
1376        // Store lowest absolute delta to normalize the delta values
1377        absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
1378
1379        if ( !lowestDelta || absDelta < lowestDelta ) {
1380            lowestDelta = absDelta;
1381
1382            // Adjust older deltas if necessary
1383            if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
1384                lowestDelta /= 40;
1385            }
1386        }
1387
1388        // Adjust older deltas if necessary
1389        if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
1390            // Divide all the things by 40!
1391            delta  /= 40;
1392            deltaX /= 40;
1393            deltaY /= 40;
1394        }
1395
1396        // Get a whole, normalized value for the deltas
1397        delta  = Math[ delta  >= 1 ? 'floor' : 'ceil' ](delta  / lowestDelta);
1398        deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
1399        deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
1400
1401        // Normalise offsetX and offsetY properties
1402        if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
1403            var boundingRect = this.getBoundingClientRect();
1404            offsetX = event.clientX - boundingRect.left;
1405            offsetY = event.clientY - boundingRect.top;
1406        }
1407
1408        // Add information to the event object
1409        event.deltaX = deltaX;
1410        event.deltaY = deltaY;
1411        event.deltaFactor = lowestDelta;
1412        event.offsetX = offsetX;
1413        event.offsetY = offsetY;
1414        // Go ahead and set deltaMode to 0 since we converted to pixels
1415        // Although this is a little odd since we overwrite the deltaX/Y
1416        // properties with normalized deltas.
1417        event.deltaMode = 0;
1418
1419        // Add event and delta to the front of the arguments
1420        args.unshift(event, delta, deltaX, deltaY);
1421
1422        // Clearout lowestDelta after sometime to better
1423        // handle multiple device types that give different
1424        // a different lowestDelta
1425        // Ex: trackpad = 3 and mouse wheel = 120
1426        if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
1427        nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
1428
1429        return ($.event.dispatch || $.event.handle).apply(this, args);
1430    }
1431
1432    function nullLowestDelta() {
1433        lowestDelta = null;
1434    }
1435
1436    function shouldAdjustOldDeltas(orgEvent, absDelta) {
1437        // If this is an older event and the delta is divisable by 120,
1438        // then we are assuming that the browser is treating this as an
1439        // older mouse wheel event and that we should divide the deltas
1440        // by 40 to try and get a more usable deltaFactor.
1441        // Side note, this actually impacts the reported scroll distance
1442        // in older browsers and can cause scrolling to be slower than native.
1443        // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
1444        return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
1445    }
1446
1447}));
1448/*!
1449 * jQuery BBQ: Back Button & Query Library - v1.3pre - 8/26/2010
1450 * http://benalman.com/projects/jquery-bbq-plugin/
1451 *
1452 * Copyright (c) 2010 "Cowboy" Ben Alman
1453 * Dual licensed under the MIT and GPL licenses.
1454 * http://benalman.com/about/license/
1455 */
1456
1457// Script: jQuery BBQ: Back Button & Query Library
1458//
1459// *Version: 1.3pre, Last updated: 8/26/2010*
1460//
1461// Project Home - http://benalman.com/projects/jquery-bbq-plugin/
1462// GitHub       - http://github.com/cowboy/jquery-bbq/
1463// Source       - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.js
1464// (Minified)   - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.min.js (2.2kb gzipped)
1465//
1466// About: License
1467//
1468// Copyright (c) 2010 "Cowboy" Ben Alman,
1469// Dual licensed under the MIT and GPL licenses.
1470// http://benalman.com/about/license/
1471//
1472// About: Examples
1473//
1474// These working examples, complete with fully commented code, illustrate a few
1475// ways in which this plugin can be used.
1476//
1477// Basic AJAX     - http://benalman.com/code/projects/jquery-bbq/examples/fragment-basic/
1478// Advanced AJAX  - http://benalman.com/code/projects/jquery-bbq/examples/fragment-advanced/
1479// jQuery UI Tabs - http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/
1480// Deparam        - http://benalman.com/code/projects/jquery-bbq/examples/deparam/
1481//
1482// About: Support and Testing
1483//
1484// Information about what version or versions of jQuery this plugin has been
1485// tested with, what browsers it has been tested in, and where the unit tests
1486// reside (so you can test it yourself).
1487//
1488// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2
1489// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,
1490//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
1491// Unit Tests      - http://benalman.com/code/projects/jquery-bbq/unit/
1492//
1493// About: Release History
1494//
1495// 1.3pre - (8/26/2010) Integrated <jQuery hashchange event> v1.3, which adds
1496//         document.title and document.domain support in IE6/7, BlackBerry
1497//         support, better Iframe hiding for accessibility reasons, and the new
1498//         <jQuery.fn.hashchange> "shortcut" method. Added the
1499//         <jQuery.param.sorted> method which reduces the possibility of
1500//         extraneous hashchange event triggering. Added the
1501//         <jQuery.param.fragment.ajaxCrawlable> method which can be used to
1502//         enable Google "AJAX Crawlable mode."
1503// 1.2.1 - (2/17/2010) Actually fixed the stale window.location Safari bug from
1504//         <jQuery hashchange event> in BBQ, which was the main reason for the
1505//         previous release!
1506// 1.2   - (2/16/2010) Integrated <jQuery hashchange event> v1.2, which fixes a
1507//         Safari bug, the event can now be bound before DOM ready, and IE6/7
1508//         page should no longer scroll when the event is first bound. Also
1509//         added the <jQuery.param.fragment.noEscape> method, and reworked the
1510//         <hashchange event (BBQ)> internal "add" method to be compatible with
1511//         changes made to the jQuery 1.4.2 special events API.
1512// 1.1.1 - (1/22/2010) Integrated <jQuery hashchange event> v1.1, which fixes an
1513//         obscure IE8 EmulateIE7 meta tag compatibility mode bug.
1514// 1.1   - (1/9/2010) Broke out the jQuery BBQ event.special <hashchange event>
1515//         functionality into a separate plugin for users who want just the
1516//         basic event & back button support, without all the extra awesomeness
1517//         that BBQ provides. This plugin will be included as part of jQuery BBQ,
1518//         but also be available separately. See <jQuery hashchange event>
1519//         plugin for more information. Also added the <jQuery.bbq.removeState>
1520//         method and added additional <jQuery.deparam> examples.
1521// 1.0.3 - (12/2/2009) Fixed an issue in IE 6 where location.search and
1522//         location.hash would report incorrectly if the hash contained the ?
1523//         character. Also <jQuery.param.querystring> and <jQuery.param.fragment>
1524//         will no longer parse params out of a URL that doesn't contain ? or #,
1525//         respectively.
1526// 1.0.2 - (10/10/2009) Fixed an issue in IE 6/7 where the hidden IFRAME caused
1527//         a "This page contains both secure and nonsecure items." warning when
1528//         used on an https:// page.
1529// 1.0.1 - (10/7/2009) Fixed an issue in IE 8. Since both "IE7" and "IE8
1530//         Compatibility View" modes erroneously report that the browser
1531//         supports the native window.onhashchange event, a slightly more
1532//         robust test needed to be added.
1533// 1.0   - (10/2/2009) Initial release
1534
1535(function($,window){
1536  '$:nomunge'; // Used by YUI compressor.
1537
1538  // Some convenient shortcuts.
1539  var undefined,
1540    aps = Array.prototype.slice,
1541    decode = decodeURIComponent,
1542
1543    // Method / object references.
1544    jq_param = $.param,
1545    jq_param_sorted,
1546    jq_param_fragment,
1547    jq_deparam,
1548    jq_deparam_fragment,
1549    jq_bbq = $.bbq = $.bbq || {},
1550    jq_bbq_pushState,
1551    jq_bbq_getState,
1552    jq_elemUrlAttr,
1553    special = $.event.special,
1554
1555    // Reused strings.
1556    str_hashchange = 'hashchange',
1557    str_querystring = 'querystring',
1558    str_fragment = 'fragment',
1559    str_elemUrlAttr = 'elemUrlAttr',
1560    str_href = 'href',
1561    str_src = 'src',
1562
1563    // Reused RegExp.
1564    re_params_querystring = /^.*\?|#.*$/g,
1565    re_params_fragment,
1566    re_fragment,
1567    re_no_escape,
1568
1569    ajax_crawlable,
1570    fragment_prefix,
1571
1572    // Used by jQuery.elemUrlAttr.
1573    elemUrlAttr_cache = {};
1574
1575  // A few commonly used bits, broken out to help reduce minified file size.
1576
1577  function is_string( arg ) {
1578    return typeof arg === 'string';
1579  };
1580
1581  // Why write the same function twice? Let's curry! Mmmm, curry..
1582
1583  function curry( func ) {
1584    var args = aps.call( arguments, 1 );
1585
1586    return function() {
1587      return func.apply( this, args.concat( aps.call( arguments ) ) );
1588    };
1589  };
1590
1591  // Get location.hash (or what you'd expect location.hash to be) sans any
1592  // leading #. Thanks for making this necessary, Firefox!
1593  function get_fragment( url ) {
1594    return url.replace( re_fragment, '$2' );
1595  };
1596
1597  // Get location.search (or what you'd expect location.search to be) sans any
1598  // leading #. Thanks for making this necessary, IE6!
1599  function get_querystring( url ) {
1600    return url.replace( /(?:^[^?#]*\?([^#]*).*$)?.*/, '$1' );
1601  };
1602
1603  // Section: Param (to string)
1604  //
1605  // Method: jQuery.param.querystring
1606  //
1607  // Retrieve the query string from a URL or if no arguments are passed, the
1608  // current window.location.href.
1609  //
1610  // Usage:
1611  //
1612  // > jQuery.param.querystring( [ url ] );
1613  //
1614  // Arguments:
1615  //
1616  //  url - (String) A URL containing query string params to be parsed. If url
1617  //    is not passed, the current window.location.href is used.
1618  //
1619  // Returns:
1620  //
1621  //  (String) The parsed query string, with any leading "?" removed.
1622  //
1623
1624  // Method: jQuery.param.querystring (build url)
1625  //
1626  // Merge a URL, with or without pre-existing query string params, plus any
1627  // object, params string or URL containing query string params into a new URL.
1628  //
1629  // Usage:
1630  //
1631  // > jQuery.param.querystring( url, params [, merge_mode ] );
1632  //
1633  // Arguments:
1634  //
1635  //  url - (String) A valid URL for params to be merged into. This URL may
1636  //    contain a query string and/or fragment (hash).
1637  //  params - (String) A params string or URL containing query string params to
1638  //    be merged into url.
1639  //  params - (Object) A params object to be merged into url.
1640  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
1641  //    specified, and is as-follows:
1642  //
1643  //    * 0: params in the params argument will override any query string
1644  //         params in url.
1645  //    * 1: any query string params in url will override params in the params
1646  //         argument.
1647  //    * 2: params argument will completely replace any query string in url.
1648  //
1649  // Returns:
1650  //
1651  //  (String) A URL with a urlencoded query string in the format '?a=b&c=d&e=f'.
1652
1653  // Method: jQuery.param.fragment
1654  //
1655  // Retrieve the fragment (hash) from a URL or if no arguments are passed, the
1656  // current window.location.href.
1657  //
1658  // Usage:
1659  //
1660  // > jQuery.param.fragment( [ url ] );
1661  //
1662  // Arguments:
1663  //
1664  //  url - (String) A URL containing fragment (hash) params to be parsed. If
1665  //    url is not passed, the current window.location.href is used.
1666  //
1667  // Returns:
1668  //
1669  //  (String) The parsed fragment (hash) string, with any leading "#" removed.
1670
1671  // Method: jQuery.param.fragment (build url)
1672  //
1673  // Merge a URL, with or without pre-existing fragment (hash) params, plus any
1674  // object, params string or URL containing fragment (hash) params into a new
1675  // URL.
1676  //
1677  // Usage:
1678  //
1679  // > jQuery.param.fragment( url, params [, merge_mode ] );
1680  //
1681  // Arguments:
1682  //
1683  //  url - (String) A valid URL for params to be merged into. This URL may
1684  //    contain a query string and/or fragment (hash).
1685  //  params - (String) A params string or URL containing fragment (hash) params
1686  //    to be merged into url.
1687  //  params - (Object) A params object to be merged into url.
1688  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
1689  //    specified, and is as-follows:
1690  //
1691  //    * 0: params in the params argument will override any fragment (hash)
1692  //         params in url.
1693  //    * 1: any fragment (hash) params in url will override params in the
1694  //         params argument.
1695  //    * 2: params argument will completely replace any query string in url.
1696  //
1697  // Returns:
1698  //
1699  //  (String) A URL with a urlencoded fragment (hash) in the format '#a=b&c=d&e=f'.
1700
1701  function jq_param_sub( is_fragment, get_func, url, params, merge_mode ) {
1702    var result,
1703      qs,
1704      matches,
1705      url_params,
1706      hash;
1707
1708    if ( params !== undefined ) {
1709      // Build URL by merging params into url string.
1710
1711      // matches[1] = url part that precedes params, not including trailing ?/#
1712      // matches[2] = params, not including leading ?/#
1713      // matches[3] = if in 'querystring' mode, hash including leading #, otherwise ''
1714      matches = url.match( is_fragment ? re_fragment : /^([^#?]*)\??([^#]*)(#?.*)/ );
1715
1716      // Get the hash if in 'querystring' mode, and it exists.
1717      hash = matches[3] || '';
1718
1719      if ( merge_mode === 2 && is_string( params ) ) {
1720        // If merge_mode is 2 and params is a string, merge the fragment / query
1721        // string into the URL wholesale, without converting it into an object.
1722        qs = params.replace( is_fragment ? re_params_fragment : re_params_querystring, '' );
1723
1724      } else {
1725        // Convert relevant params in url to object.
1726        url_params = jq_deparam( matches[2] );
1727
1728        params = is_string( params )
1729
1730          // Convert passed params string into object.
1731          ? jq_deparam[ is_fragment ? str_fragment : str_querystring ]( params )
1732
1733          // Passed params object.
1734          : params;
1735
1736        qs = merge_mode === 2 ? params                              // passed params replace url params
1737          : merge_mode === 1  ? $.extend( {}, params, url_params )  // url params override passed params
1738          : $.extend( {}, url_params, params );                     // passed params override url params
1739
1740        // Convert params object into a sorted params string.
1741        qs = jq_param_sorted( qs );
1742
1743        // Unescape characters specified via $.param.noEscape. Since only hash-
1744        // history users have requested this feature, it's only enabled for
1745        // fragment-related params strings.
1746        if ( is_fragment ) {
1747          qs = qs.replace( re_no_escape, decode );
1748        }
1749      }
1750
1751      // Build URL from the base url, querystring and hash. In 'querystring'
1752      // mode, ? is only added if a query string exists. In 'fragment' mode, #
1753      // is always added.
1754      result = matches[1] + ( is_fragment ? fragment_prefix : qs || !matches[1] ? '?' : '' ) + qs + hash;
1755
1756    } else {
1757      // If URL was passed in, parse params from URL string, otherwise parse
1758      // params from window.location.href.
1759      result = get_func( url !== undefined ? url : location.href );
1760    }
1761
1762    return result;
1763  };
1764
1765  jq_param[ str_querystring ]                  = curry( jq_param_sub, 0, get_querystring );
1766  jq_param[ str_fragment ] = jq_param_fragment = curry( jq_param_sub, 1, get_fragment );
1767
1768  // Method: jQuery.param.sorted
1769  //
1770  // Returns a params string equivalent to that returned by the internal
1771  // jQuery.param method, but sorted, which makes it suitable for use as a
1772  // cache key.
1773  //
1774  // For example, in most browsers jQuery.param({z:1,a:2}) returns "z=1&a=2"
1775  // and jQuery.param({a:2,z:1}) returns "a=2&z=1". Even though both the
1776  // objects being serialized and the resulting params strings are equivalent,
1777  // if these params strings were set into the location.hash fragment
1778  // sequentially, the hashchange event would be triggered unnecessarily, since
1779  // the strings are different (even though the data described by them is the
1780  // same). By sorting the params string, unecessary hashchange event triggering
1781  // can be avoided.
1782  //
1783  // Usage:
1784  //
1785  // > jQuery.param.sorted( obj [, traditional ] );
1786  //
1787  // Arguments:
1788  //
1789  //  obj - (Object) An object to be serialized.
1790  //  traditional - (Boolean) Params deep/shallow serialization mode. See the
1791  //    documentation at http://api.jquery.com/jQuery.param/ for more detail.
1792  //
1793  // Returns:
1794  //
1795  //  (String) A sorted params string.
1796
1797  jq_param.sorted = jq_param_sorted = function( a, traditional ) {
1798    var arr = [],
1799      obj = {};
1800
1801    $.each( jq_param( a, traditional ).split( '&' ), function(i,v){
1802      var key = v.replace( /(?:%5B|=).*$/, '' ),
1803        key_obj = obj[ key ];
1804
1805      if ( !key_obj ) {
1806        key_obj = obj[ key ] = [];
1807        arr.push( key );
1808      }
1809
1810      key_obj.push( v );
1811    });
1812
1813    return $.map( arr.sort(), function(v){
1814      return obj[ v ];
1815    }).join( '&' );
1816  };
1817
1818  // Method: jQuery.param.fragment.noEscape
1819  //
1820  // Specify characters that will be left unescaped when fragments are created
1821  // or merged using <jQuery.param.fragment>, or when the fragment is modified
1822  // using <jQuery.bbq.pushState>. This option only applies to serialized data
1823  // object fragments, and not set-as-string fragments. Does not affect the
1824  // query string. Defaults to ",/" (comma, forward slash).
1825  //
1826  // Note that this is considered a purely aesthetic option, and will help to
1827  // create URLs that "look pretty" in the address bar or bookmarks, without
1828  // affecting functionality in any way. That being said, be careful to not
1829  // unescape characters that are used as delimiters or serve a special
1830  // purpose, such as the "#?&=+" (octothorpe, question mark, ampersand,
1831  // equals, plus) characters.
1832  //
1833  // Usage:
1834  //
1835  // > jQuery.param.fragment.noEscape( [ chars ] );
1836  //
1837  // Arguments:
1838  //
1839  //  chars - (String) The characters to not escape in the fragment. If
1840  //    unspecified, defaults to empty string (escape all characters).
1841  //
1842  // Returns:
1843  //
1844  //  Nothing.
1845
1846  jq_param_fragment.noEscape = function( chars ) {
1847    chars = chars || '';
1848    var arr = $.map( chars.split(''), encodeURIComponent );
1849    re_no_escape = new RegExp( arr.join('|'), 'g' );
1850  };
1851
1852  // A sensible default. These are the characters people seem to complain about
1853  // "uglifying up the URL" the most.
1854  jq_param_fragment.noEscape( ',/' );
1855
1856  // Method: jQuery.param.fragment.ajaxCrawlable
1857  //
1858  // TODO: DESCRIBE
1859  //
1860  // Usage:
1861  //
1862  // > jQuery.param.fragment.ajaxCrawlable( [ state ] );
1863  //
1864  // Arguments:
1865  //
1866  //  state - (Boolean) TODO: DESCRIBE
1867  //
1868  // Returns:
1869  //
1870  //  (Boolean) The current ajaxCrawlable state.
1871
1872  jq_param_fragment.ajaxCrawlable = function( state ) {
1873    if ( state !== undefined ) {
1874      if ( state ) {
1875        re_params_fragment = /^.*(?:#!|#)/;
1876        re_fragment = /^([^#]*)(?:#!|#)?(.*)$/;
1877        fragment_prefix = '#!';
1878      } else {
1879        re_params_fragment = /^.*#/;
1880        re_fragment = /^([^#]*)#?(.*)$/;
1881        fragment_prefix = '#';
1882      }
1883      ajax_crawlable = !!state;
1884    }
1885
1886    return ajax_crawlable;
1887  };
1888
1889  jq_param_fragment.ajaxCrawlable( 0 );
1890
1891  // Section: Deparam (from string)
1892  //
1893  // Method: jQuery.deparam
1894  //
1895  // Deserialize a params string into an object, optionally coercing numbers,
1896  // booleans, null and undefined values; this method is the counterpart to the
1897  // internal jQuery.param method.
1898  //
1899  // Usage:
1900  //
1901  // > jQuery.deparam( params [, coerce ] );
1902  //
1903  // Arguments:
1904  //
1905  //  params - (String) A params string to be parsed.
1906  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and
1907  //    undefined to their actual value. Defaults to false if omitted.
1908  //
1909  // Returns:
1910  //
1911  //  (Object) An object representing the deserialized params string.
1912
1913  $.deparam = jq_deparam = function( params, coerce ) {
1914    var obj = {},
1915      coerce_types = { 'true': !0, 'false': !1, 'null': null };
1916
1917    // Iterate over all name=value pairs.
1918    $.each( params.replace( /\+/g, ' ' ).split( '&' ), function(j,v){
1919      var param = v.split( '=' ),
1920        key = decode( param[0] ),
1921        val,
1922        cur = obj,
1923        i = 0,
1924
1925        // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
1926        // into its component parts.
1927        keys = key.split( '][' ),
1928        keys_last = keys.length - 1;
1929
1930      // If the first keys part contains [ and the last ends with ], then []
1931      // are correctly balanced.
1932      if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) {
1933        // Remove the trailing ] from the last keys part.
1934        keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' );
1935
1936        // Split first keys part into two parts on the [ and add them back onto
1937        // the beginning of the keys array.
1938        keys = keys.shift().split('[').concat( keys );
1939
1940        keys_last = keys.length - 1;
1941      } else {
1942        // Basic 'foo' style key.
1943        keys_last = 0;
1944      }
1945
1946      // Are we dealing with a name=value pair, or just a name?
1947      if ( param.length === 2 ) {
1948        val = decode( param[1] );
1949
1950        // Coerce values.
1951        if ( coerce ) {
1952          val = val && !isNaN(val)            ? +val              // number
1953            : val === 'undefined'             ? undefined         // undefined
1954            : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
1955            : val;                                                // string
1956        }
1957
1958        if ( keys_last ) {
1959          // Complex key, build deep object structure based on a few rules:
1960          // * The 'cur' pointer starts at the object top-level.
1961          // * [] = array push (n is set to array length), [n] = array if n is
1962          //   numeric, otherwise object.
1963          // * If at the last keys part, set the value.
1964          // * For each keys part, if the current level is undefined create an
1965          //   object or array based on the type of the next keys part.
1966          // * Move the 'cur' pointer to the next level.
1967          // * Rinse & repeat.
1968          for ( ; i <= keys_last; i++ ) {
1969            key = keys[i] === '' ? cur.length : keys[i];
1970            cur = cur[key] = i < keys_last
1971              ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] )
1972              : val;
1973          }
1974
1975        } else {
1976          // Simple key, even simpler rules, since only scalars and shallow
1977          // arrays are allowed.
1978
1979          if ( $.isArray( obj[key] ) ) {
1980            // val is already an array, so push on the next value.
1981            obj[key].push( val );
1982
1983          } else if ( obj[key] !== undefined ) {
1984            // val isn't an array, but since a second value has been specified,
1985            // convert val into an array.
1986            obj[key] = [ obj[key], val ];
1987
1988          } else {
1989            // val is a scalar.
1990            obj[key] = val;
1991          }
1992        }
1993
1994      } else if ( key ) {
1995        // No value was defined, so set something meaningful.
1996        obj[key] = coerce
1997          ? undefined
1998          : '';
1999      }
2000    });
2001
2002    return obj;
2003  };
2004
2005  // Method: jQuery.deparam.querystring
2006  //
2007  // Parse the query string from a URL or the current window.location.href,
2008  // deserializing it into an object, optionally coercing numbers, booleans,
2009  // null and undefined values.
2010  //
2011  // Usage:
2012  //
2013  // > jQuery.deparam.querystring( [ url ] [, coerce ] );
2014  //
2015  // Arguments:
2016  //
2017  //  url - (String) An optional params string or URL containing query string
2018  //    params to be parsed. If url is omitted, the current
2019  //    window.location.href is used.
2020  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and
2021  //    undefined to their actual value. Defaults to false if omitted.
2022  //
2023  // Returns:
2024  //
2025  //  (Object) An object representing the deserialized params string.
2026
2027  // Method: jQuery.deparam.fragment
2028  //
2029  // Parse the fragment (hash) from a URL or the current window.location.href,
2030  // deserializing it into an object, optionally coercing numbers, booleans,
2031  // null and undefined values.
2032  //
2033  // Usage:
2034  //
2035  // > jQuery.deparam.fragment( [ url ] [, coerce ] );
2036  //
2037  // Arguments:
2038  //
2039  //  url - (String) An optional params string or URL containing fragment (hash)
2040  //    params to be parsed. If url is omitted, the current window.location.href
2041  //    is used.
2042  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and
2043  //    undefined to their actual value. Defaults to false if omitted.
2044  //
2045  // Returns:
2046  //
2047  //  (Object) An object representing the deserialized params string.
2048
2049  function jq_deparam_sub( is_fragment, url_or_params, coerce ) {
2050    if ( url_or_params === undefined || typeof url_or_params === 'boolean' ) {
2051      // url_or_params not specified.
2052      coerce = url_or_params;
2053      url_or_params = jq_param[ is_fragment ? str_fragment : str_querystring ]();
2054    } else {
2055      url_or_params = is_string( url_or_params )
2056        ? url_or_params.replace( is_fragment ? re_params_fragment : re_params_querystring, '' )
2057        : url_or_params;
2058    }
2059
2060    return jq_deparam( url_or_params, coerce );
2061  };
2062
2063  jq_deparam[ str_querystring ]                    = curry( jq_deparam_sub, 0 );
2064  jq_deparam[ str_fragment ] = jq_deparam_fragment = curry( jq_deparam_sub, 1 );
2065
2066  // Section: Element manipulation
2067  //
2068  // Method: jQuery.elemUrlAttr
2069  //
2070  // Get the internal "Default URL attribute per tag" list, or augment the list
2071  // with additional tag-attribute pairs, in case the defaults are insufficient.
2072  //
2073  // In the <jQuery.fn.querystring> and <jQuery.fn.fragment> methods, this list
2074  // is used to determine which attribute contains the URL to be modified, if
2075  // an "attr" param is not specified.
2076  //
2077  // Default Tag-Attribute List:
2078  //
2079  //  a      - href
2080  //  base   - href
2081  //  iframe - src
2082  //  img    - src
2083  //  input  - src
2084  //  form   - action
2085  //  link   - href
2086  //  script - src
2087  //
2088  // Usage:
2089  //
2090  // > jQuery.elemUrlAttr( [ tag_attr ] );
2091  //
2092  // Arguments:
2093  //
2094  //  tag_attr - (Object) An object containing a list of tag names and their
2095  //    associated default attribute names in the format { tag: 'attr', ... } to
2096  //    be merged into the internal tag-attribute list.
2097  //
2098  // Returns:
2099  //
2100  //  (Object) An object containing all stored tag-attribute values.
2101
2102  // Only define function and set defaults if function doesn't already exist, as
2103  // the urlInternal plugin will provide this method as well.
2104  $[ str_elemUrlAttr ] || ($[ str_elemUrlAttr ] = function( obj ) {
2105    return $.extend( elemUrlAttr_cache, obj );
2106  })({
2107    a: str_href,
2108    base: str_href,
2109    iframe: str_src,
2110    img: str_src,
2111    input: str_src,
2112    form: 'action',
2113    link: str_href,
2114    script: str_src
2115  });
2116
2117  jq_elemUrlAttr = $[ str_elemUrlAttr ];
2118
2119  // Method: jQuery.fn.querystring
2120  //
2121  // Update URL attribute in one or more elements, merging the current URL (with
2122  // or without pre-existing query string params) plus any params object or
2123  // string into a new URL, which is then set into that attribute. Like
2124  // <jQuery.param.querystring (build url)>, but for all elements in a jQuery
2125  // collection.
2126  //
2127  // Usage:
2128  //
2129  // > jQuery('selector').querystring( [ attr, ] params [, merge_mode ] );
2130  //
2131  // Arguments:
2132  //
2133  //  attr - (String) Optional name of an attribute that will contain a URL to
2134  //    merge params or url into. See <jQuery.elemUrlAttr> for a list of default
2135  //    attributes.
2136  //  params - (Object) A params object to be merged into the URL attribute.
2137  //  params - (String) A URL containing query string params, or params string
2138  //    to be merged into the URL attribute.
2139  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
2140  //    specified, and is as-follows:
2141  //
2142  //    * 0: params in the params argument will override any params in attr URL.
2143  //    * 1: any params in attr URL will override params in the params argument.
2144  //    * 2: params argument will completely replace any query string in attr
2145  //         URL.
2146  //
2147  // Returns:
2148  //
2149  //  (jQuery) The initial jQuery collection of elements, but with modified URL
2150  //  attribute values.
2151
2152  // Method: jQuery.fn.fragment
2153  //
2154  // Update URL attribute in one or more elements, merging the current URL (with
2155  // or without pre-existing fragment/hash params) plus any params object or
2156  // string into a new URL, which is then set into that attribute. Like
2157  // <jQuery.param.fragment (build url)>, but for all elements in a jQuery
2158  // collection.
2159  //
2160  // Usage:
2161  //
2162  // > jQuery('selector').fragment( [ attr, ] params [, merge_mode ] );
2163  //
2164  // Arguments:
2165  //
2166  //  attr - (String) Optional name of an attribute that will contain a URL to
2167  //    merge params into. See <jQuery.elemUrlAttr> for a list of default
2168  //    attributes.
2169  //  params - (Object) A params object to be merged into the URL attribute.
2170  //  params - (String) A URL containing fragment (hash) params, or params
2171  //    string to be merged into the URL attribute.
2172  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
2173  //    specified, and is as-follows:
2174  //
2175  //    * 0: params in the params argument will override any params in attr URL.
2176  //    * 1: any params in attr URL will override params in the params argument.
2177  //    * 2: params argument will completely replace any fragment (hash) in attr
2178  //         URL.
2179  //
2180  // Returns:
2181  //
2182  //  (jQuery) The initial jQuery collection of elements, but with modified URL
2183  //  attribute values.
2184
2185  function jq_fn_sub( mode, force_attr, params, merge_mode ) {
2186    if ( !is_string( params ) && typeof params !== 'object' ) {
2187      // force_attr not specified.
2188      merge_mode = params;
2189      params = force_attr;
2190      force_attr = undefined;
2191    }
2192
2193    return this.each(function(){
2194      var that = $(this),
2195
2196        // Get attribute specified, or default specified via $.elemUrlAttr.
2197        attr = force_attr || jq_elemUrlAttr()[ ( this.nodeName || '' ).toLowerCase() ] || '',
2198
2199        // Get URL value.
2200        url = attr && that.attr( attr ) || '';
2201
2202      // Update attribute with new URL.
2203      that.attr( attr, jq_param[ mode ]( url, params, merge_mode ) );
2204    });
2205
2206  };
2207
2208  $.fn[ str_querystring ] = curry( jq_fn_sub, str_querystring );
2209  $.fn[ str_fragment ]    = curry( jq_fn_sub, str_fragment );
2210
2211  // Section: History, hashchange event
2212  //
2213  // Method: jQuery.bbq.pushState
2214  //
2215  // Adds a 'state' into the browser history at the current position, setting
2216  // location.hash and triggering any bound <hashchange event> callbacks
2217  // (provided the new state is different than the previous state).
2218  //
2219  // If no arguments are passed, an empty state is created, which is just a
2220  // shortcut for jQuery.bbq.pushState( {}, 2 ).
2221  //
2222  // Usage:
2223  //
2224  // > jQuery.bbq.pushState( [ params [, merge_mode ] ] );
2225  //
2226  // Arguments:
2227  //
2228  //  params - (String) A serialized params string or a hash string beginning
2229  //    with # to merge into location.hash.
2230  //  params - (Object) A params object to merge into location.hash.
2231  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
2232  //    specified (unless a hash string beginning with # is specified, in which
2233  //    case merge behavior defaults to 2), and is as-follows:
2234  //
2235  //    * 0: params in the params argument will override any params in the
2236  //         current state.
2237  //    * 1: any params in the current state will override params in the params
2238  //         argument.
2239  //    * 2: params argument will completely replace current state.
2240  //
2241  // Returns:
2242  //
2243  //  Nothing.
2244  //
2245  // Additional Notes:
2246  //
2247  //  * Setting an empty state may cause the browser to scroll.
2248  //  * Unlike the fragment and querystring methods, if a hash string beginning
2249  //    with # is specified as the params agrument, merge_mode defaults to 2.
2250
2251  jq_bbq.pushState = jq_bbq_pushState = function( params, merge_mode ) {
2252    if ( is_string( params ) && /^#/.test( params ) && merge_mode === undefined ) {
2253      // Params string begins with # and merge_mode not specified, so completely
2254      // overwrite window.location.hash.
2255      merge_mode = 2;
2256    }
2257
2258    var has_args = params !== undefined,
2259      // Merge params into window.location using $.param.fragment.
2260      url = jq_param_fragment( location.href,
2261        has_args ? params : {}, has_args ? merge_mode : 2 );
2262
2263    // Set new window.location.href. Note that Safari 3 & Chrome barf on
2264    // location.hash = '#' so the entire URL is set.
2265    location.href = url;
2266  };
2267
2268  // Method: jQuery.bbq.getState
2269  //
2270  // Retrieves the current 'state' from the browser history, parsing
2271  // location.hash for a specific key or returning an object containing the
2272  // entire state, optionally coercing numbers, booleans, null and undefined
2273  // values.
2274  //
2275  // Usage:
2276  //
2277  // > jQuery.bbq.getState( [ key ] [, coerce ] );
2278  //
2279  // Arguments:
2280  //
2281  //  key - (String) An optional state key for which to return a value.
2282  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and
2283  //    undefined to their actual value. Defaults to false.
2284  //
2285  // Returns:
2286  //
2287  //  (Anything) If key is passed, returns the value corresponding with that key
2288  //    in the location.hash 'state', or undefined. If not, an object
2289  //    representing the entire 'state' is returned.
2290
2291  jq_bbq.getState = jq_bbq_getState = function( key, coerce ) {
2292    return key === undefined || typeof key === 'boolean'
2293      ? jq_deparam_fragment( key ) // 'key' really means 'coerce' here
2294      : jq_deparam_fragment( coerce )[ key ];
2295  };
2296
2297  // Method: jQuery.bbq.removeState
2298  //
2299  // Remove one or more keys from the current browser history 'state', creating
2300  // a new state, setting location.hash and triggering any bound
2301  // <hashchange event> callbacks (provided the new state is different than
2302  // the previous state).
2303  //
2304  // If no arguments are passed, an empty state is created, which is just a
2305  // shortcut for jQuery.bbq.pushState( {}, 2 ).
2306  //
2307  // Usage:
2308  //
2309  // > jQuery.bbq.removeState( [ key [, key ... ] ] );
2310  //
2311  // Arguments:
2312  //
2313  //  key - (String) One or more key values to remove from the current state,
2314  //    passed as individual arguments.
2315  //  key - (Array) A single array argument that contains a list of key values
2316  //    to remove from the current state.
2317  //
2318  // Returns:
2319  //
2320  //  Nothing.
2321  //
2322  // Additional Notes:
2323  //
2324  //  * Setting an empty state may cause the browser to scroll.
2325
2326  jq_bbq.removeState = function( arr ) {
2327    var state = {};
2328
2329    // If one or more arguments is passed..
2330    if ( arr !== undefined ) {
2331
2332      // Get the current state.
2333      state = jq_bbq_getState();
2334
2335      // For each passed key, delete the corresponding property from the current
2336      // state.
2337      $.each( $.isArray( arr ) ? arr : arguments, function(i,v){
2338        delete state[ v ];
2339      });
2340    }
2341
2342    // Set the state, completely overriding any existing state.
2343    jq_bbq_pushState( state, 2 );
2344  };
2345
2346  // Event: hashchange event (BBQ)
2347  //
2348  // Usage in jQuery 1.4 and newer:
2349  //
2350  // In jQuery 1.4 and newer, the event object passed into any hashchange event
2351  // callback is augmented with a copy of the location.hash fragment at the time
2352  // the event was triggered as its event.fragment property. In addition, the
2353  // event.getState method operates on this property (instead of location.hash)
2354  // which allows this fragment-as-a-state to be referenced later, even after
2355  // window.location may have changed.
2356  //
2357  // Note that event.fragment and event.getState are not defined according to
2358  // W3C (or any other) specification, but will still be available whether or
2359  // not the hashchange event exists natively in the browser, because of the
2360  // utility they provide.
2361  //
2362  // The event.fragment property contains the output of <jQuery.param.fragment>
2363  // and the event.getState method is equivalent to the <jQuery.bbq.getState>
2364  // method.
2365  //
2366  // > $(window).bind( 'hashchange', function( event ) {
2367  // >   var hash_str = event.fragment,
2368  // >     param_obj = event.getState(),
2369  // >     param_val = event.getState( 'param_name' ),
2370  // >     param_val_coerced = event.getState( 'param_name', true );
2371  // >   ...
2372  // > });
2373  //
2374  // Usage in jQuery 1.3.2:
2375  //
2376  // In jQuery 1.3.2, the event object cannot to be augmented as in jQuery 1.4+,
2377  // so the fragment state isn't bound to the event object and must instead be
2378  // parsed using the <jQuery.param.fragment> and <jQuery.bbq.getState> methods.
2379  //
2380  // > $(window).bind( 'hashchange', function( event ) {
2381  // >   var hash_str = $.param.fragment(),
2382  // >     param_obj = $.bbq.getState(),
2383  // >     param_val = $.bbq.getState( 'param_name' ),
2384  // >     param_val_coerced = $.bbq.getState( 'param_name', true );
2385  // >   ...
2386  // > });
2387  //
2388  // Additional Notes:
2389  //
2390  // * Due to changes in the special events API, jQuery BBQ v1.2 or newer is
2391  //   required to enable the augmented event object in jQuery 1.4.2 and newer.
2392  // * See <jQuery hashchange event> for more detailed information.
2393
2394  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
2395
2396    // Augmenting the event object with the .fragment property and .getState
2397    // method requires jQuery 1.4 or newer. Note: with 1.3.2, everything will
2398    // work, but the event won't be augmented)
2399    add: function( handleObj ) {
2400      var old_handler;
2401
2402      function new_handler(e) {
2403        // e.fragment is set to the value of location.hash (with any leading #
2404        // removed) at the time the event is triggered.
2405        var hash = e[ str_fragment ] = jq_param_fragment();
2406
2407        // e.getState() works just like $.bbq.getState(), but uses the
2408        // e.fragment property stored on the event object.
2409        e.getState = function( key, coerce ) {
2410          return key === undefined || typeof key === 'boolean'
2411            ? jq_deparam( hash, key ) // 'key' really means 'coerce' here
2412            : jq_deparam( hash, coerce )[ key ];
2413        };
2414
2415        old_handler.apply( this, arguments );
2416      };
2417
2418      // This may seem a little complicated, but it normalizes the special event
2419      // .add method between jQuery 1.4/1.4.1 and 1.4.2+
2420      if ( $.isFunction( handleObj ) ) {
2421        // 1.4, 1.4.1
2422        old_handler = handleObj;
2423        return new_handler;
2424      } else {
2425        // 1.4.2+
2426        old_handler = handleObj.handler;
2427        handleObj.handler = new_handler;
2428      }
2429    }
2430
2431  });
2432
2433})(jQuery,this);
2434
2435/*!
2436 * jQuery hashchange event - v1.3 - 7/21/2010
2437 * http://benalman.com/projects/jquery-hashchange-plugin/
2438 *
2439 * Copyright (c) 2010 "Cowboy" Ben Alman
2440 * Dual licensed under the MIT and GPL licenses.
2441 * http://benalman.com/about/license/
2442 */
2443
2444// Script: jQuery hashchange event
2445//
2446// *Version: 1.3, Last updated: 7/21/2010*
2447//
2448// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/
2449// GitHub       - http://github.com/cowboy/jquery-hashchange/
2450// Source       - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js
2451// (Minified)   - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)
2452//
2453// About: License
2454//
2455// Copyright (c) 2010 "Cowboy" Ben Alman,
2456// Dual licensed under the MIT and GPL licenses.
2457// http://benalman.com/about/license/
2458//
2459// About: Examples
2460//
2461// These working examples, complete with fully commented code, illustrate a few
2462// ways in which this plugin can be used.
2463//
2464// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
2465// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/
2466//
2467// About: Support and Testing
2468//
2469// Information about what version or versions of jQuery this plugin has been
2470// tested with, what browsers it has been tested in, and where the unit tests
2471// reside (so you can test it yourself).
2472//
2473// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2
2474// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,
2475//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
2476// Unit Tests      - http://benalman.com/code/projects/jquery-hashchange/unit/
2477//
2478// About: Known issues
2479//
2480// While this jQuery hashchange event implementation is quite stable and
2481// robust, there are a few unfortunate browser bugs surrounding expected
2482// hashchange event-based behaviors, independent of any JavaScript
2483// window.onhashchange abstraction. See the following examples for more
2484// information:
2485//
2486// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/
2487// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/
2488// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/
2489// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/
2490//
2491// Also note that should a browser natively support the window.onhashchange
2492// event, but not report that it does, the fallback polling loop will be used.
2493//
2494// About: Release History
2495//
2496// 1.3   - (7/21/2010) Reorganized IE6/7 Iframe code to make it more
2497//         "removable" for mobile-only development. Added IE6/7 document.title
2498//         support. Attempted to make Iframe as hidden as possible by using
2499//         techniques from http://www.paciellogroup.com/blog/?p=604. Added
2500//         support for the "shortcut" format $(window).hashchange( fn ) and
2501//         $(window).hashchange() like jQuery provides for built-in events.
2502//         Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and
2503//         lowered its default value to 50. Added <jQuery.fn.hashchange.domain>
2504//         and <jQuery.fn.hashchange.src> properties plus document-domain.html
2505//         file to address access denied issues when setting document.domain in
2506//         IE6/7.
2507// 1.2   - (2/11/2010) Fixed a bug where coming back to a page using this plugin
2508//         from a page on another domain would cause an error in Safari 4. Also,
2509//         IE6/7 Iframe is now inserted after the body (this actually works),
2510//         which prevents the page from scrolling when the event is first bound.
2511//         Event can also now be bound before DOM ready, but it won't be usable
2512//         before then in IE6/7.
2513// 1.1   - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug
2514//         where browser version is incorrectly reported as 8.0, despite
2515//         inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.
2516// 1.0   - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special
2517//         window.onhashchange functionality into a separate plugin for users
2518//         who want just the basic event & back button support, without all the
2519//         extra awesomeness that BBQ provides. This plugin will be included as
2520//         part of jQuery BBQ, but also be available separately.
2521
2522(function($,window,undefined){
2523  '$:nomunge'; // Used by YUI compressor.
2524
2525  // Reused string.
2526  var str_hashchange = 'hashchange',
2527
2528    // Method / object references.
2529    doc = document,
2530    fake_onhashchange,
2531    special = $.event.special,
2532
2533    // Does the browser support window.onhashchange? Note that IE8 running in
2534    // IE7 compatibility mode reports true for 'onhashchange' in window, even
2535    // though the event isn't supported, so also test document.documentMode.
2536    doc_mode = doc.documentMode,
2537    supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );
2538
2539  // Get location.hash (or what you'd expect location.hash to be) sans any
2540  // leading #. Thanks for making this necessary, Firefox!
2541  function get_fragment( url ) {
2542    url = url || location.href;
2543    return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
2544  };
2545
2546  // Method: jQuery.fn.hashchange
2547  //
2548  // Bind a handler to the window.onhashchange event or trigger all bound
2549  // window.onhashchange event handlers. This behavior is consistent with
2550  // jQuery's built-in event handlers.
2551  //
2552  // Usage:
2553  //
2554  // > jQuery(window).hashchange( [ handler ] );
2555  //
2556  // Arguments:
2557  //
2558  //  handler - (Function) Optional handler to be bound to the hashchange
2559  //    event. This is a "shortcut" for the more verbose form:
2560  //    jQuery(window).bind( 'hashchange', handler ). If handler is omitted,
2561  //    all bound window.onhashchange event handlers will be triggered. This
2562  //    is a shortcut for the more verbose
2563  //    jQuery(window).trigger( 'hashchange' ). These forms are described in
2564  //    the <hashchange event> section.
2565  //
2566  // Returns:
2567  //
2568  //  (jQuery) The initial jQuery collection of elements.
2569
2570  // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and
2571  // $(elem).hashchange() for triggering, like jQuery does for built-in events.
2572  $.fn[ str_hashchange ] = function( fn ) {
2573    return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
2574  };
2575
2576  // Property: jQuery.fn.hashchange.delay
2577  //
2578  // The numeric interval (in milliseconds) at which the <hashchange event>
2579  // polling loop executes. Defaults to 50.
2580
2581  // Property: jQuery.fn.hashchange.domain
2582  //
2583  // If you're setting document.domain in your JavaScript, and you want hash
2584  // history to work in IE6/7, not only must this property be set, but you must
2585  // also set document.domain BEFORE jQuery is loaded into the page. This
2586  // property is only applicable if you are supporting IE6/7 (or IE8 operating
2587  // in "IE7 compatibility" mode).
2588  //
2589  // In addition, the <jQuery.fn.hashchange.src> property must be set to the
2590  // path of the included "document-domain.html" file, which can be renamed or
2591  // modified if necessary (note that the document.domain specified must be the
2592  // same in both your main JavaScript as well as in this file).
2593  //
2594  // Usage:
2595  //
2596  // jQuery.fn.hashchange.domain = document.domain;
2597
2598  // Property: jQuery.fn.hashchange.src
2599  //
2600  // If, for some reason, you need to specify an Iframe src file (for example,
2601  // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can
2602  // do so using this property. Note that when using this property, history
2603  // won't be recorded in IE6/7 until the Iframe src file loads. This property
2604  // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7
2605  // compatibility" mode).
2606  //
2607  // Usage:
2608  //
2609  // jQuery.fn.hashchange.src = 'path/to/file.html';
2610
2611  $.fn[ str_hashchange ].delay = 50;
2612  /*
2613  $.fn[ str_hashchange ].domain = null;
2614  $.fn[ str_hashchange ].src = null;
2615  */
2616
2617  // Event: hashchange event
2618  //
2619  // Fired when location.hash changes. In browsers that support it, the native
2620  // HTML5 window.onhashchange event is used, otherwise a polling loop is
2621  // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to
2622  // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7
2623  // compatibility" mode), a hidden Iframe is created to allow the back button
2624  // and hash-based history to work.
2625  //
2626  // Usage as described in <jQuery.fn.hashchange>:
2627  //
2628  // > // Bind an event handler.
2629  // > jQuery(window).hashchange( function(e) {
2630  // >   var hash = location.hash;
2631  // >   ...
2632  // > });
2633  // >
2634  // > // Manually trigger the event handler.
2635  // > jQuery(window).hashchange();
2636  //
2637  // A more verbose usage that allows for event namespacing:
2638  //
2639  // > // Bind an event handler.
2640  // > jQuery(window).bind( 'hashchange', function(e) {
2641  // >   var hash = location.hash;
2642  // >   ...
2643  // > });
2644  // >
2645  // > // Manually trigger the event handler.
2646  // > jQuery(window).trigger( 'hashchange' );
2647  //
2648  // Additional Notes:
2649  //
2650  // * The polling loop and Iframe are not created until at least one handler
2651  //   is actually bound to the 'hashchange' event.
2652  // * If you need the bound handler(s) to execute immediately, in cases where
2653  //   a location.hash exists on page load, via bookmark or page refresh for
2654  //   example, use jQuery(window).hashchange() or the more verbose
2655  //   jQuery(window).trigger( 'hashchange' ).
2656  // * The event can be bound before DOM ready, but since it won't be usable
2657  //   before then in IE6/7 (due to the necessary Iframe), recommended usage is
2658  //   to bind it inside a DOM ready handler.
2659
2660  // Override existing $.event.special.hashchange methods (allowing this plugin
2661  // to be defined after jQuery BBQ in BBQ's source code).
2662  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
2663
2664    // Called only when the first 'hashchange' event is bound to window.
2665    setup: function() {
2666      // If window.onhashchange is supported natively, there's nothing to do..
2667      if ( supports_onhashchange ) { return false; }
2668
2669      // Otherwise, we need to create our own. And we don't want to call this
2670      // until the user binds to the event, just in case they never do, since it
2671      // will create a polling loop and possibly even a hidden Iframe.
2672      $( fake_onhashchange.start );
2673    },
2674
2675    // Called only when the last 'hashchange' event is unbound from window.
2676    teardown: function() {
2677      // If window.onhashchange is supported natively, there's nothing to do..
2678      if ( supports_onhashchange ) { return false; }
2679
2680      // Otherwise, we need to stop ours (if possible).
2681      $( fake_onhashchange.stop );
2682    }
2683
2684  });
2685
2686  // fake_onhashchange does all the work of triggering the window.onhashchange
2687  // event for browsers that don't natively support it, including creating a
2688  // polling loop to watch for hash changes and in IE 6/7 creating a hidden
2689  // Iframe to enable back and forward.
2690  fake_onhashchange = (function(){
2691    var self = {},
2692      timeout_id,
2693
2694      // Remember the initial hash so it doesn't get triggered immediately.
2695      last_hash = get_fragment(),
2696
2697      fn_retval = function(val){ return val; },
2698      history_set = fn_retval,
2699      history_get = fn_retval;
2700
2701    // Start the polling loop.
2702    self.start = function() {
2703      timeout_id || poll();
2704    };
2705
2706    // Stop the polling loop.
2707    self.stop = function() {
2708      timeout_id && clearTimeout( timeout_id );
2709      timeout_id = undefined;
2710    };
2711
2712    // This polling loop checks every $.fn.hashchange.delay milliseconds to see
2713    // if location.hash has changed, and triggers the 'hashchange' event on
2714    // window when necessary.
2715    function poll() {
2716      var hash = get_fragment(),
2717        history_hash = history_get( last_hash );
2718
2719      if ( hash !== last_hash ) {
2720        history_set( last_hash = hash, history_hash );
2721
2722        $(window).trigger( str_hashchange );
2723
2724      } else if ( history_hash !== last_hash ) {
2725        location.href = location.href.replace( /#.*/, '' ) + history_hash;
2726      }
2727
2728      timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
2729    };
2730
2731    return self;
2732  })();
2733
2734})(jQuery,this);
2735/*!
2736 * Datepicker for Bootstrap v1.8.0 (https://github.com/uxsolutions/bootstrap-datepicker)
2737 *
2738 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
2739 */
2740
2741!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a,b){function c(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var a=new Date;return c(a.getFullYear(),a.getMonth(),a.getDate())}function e(a,b){return a.getUTCFullYear()===b.getUTCFullYear()&&a.getUTCMonth()===b.getUTCMonth()&&a.getUTCDate()===b.getUTCDate()}function f(c,d){return function(){return d!==b&&a.fn.datepicker.deprecated(d),this[c].apply(this,arguments)}}function g(a){return a&&!isNaN(a.getTime())}function h(b,c){function d(a,b){return b.toLowerCase()}var e,f=a(b).data(),g={},h=new RegExp("^"+c.toLowerCase()+"([A-Z])");c=new RegExp("^"+c.toLowerCase());for(var i in f)c.test(i)&&(e=i.replace(h,d),g[e]=f[i]);return g}function i(b){var c={};if(q[b]||(b=b.split("-")[0],q[b])){var d=q[b];return a.each(p,function(a,b){b in d&&(c[b]=d[b])}),c}}var j=function(){var b={get:function(a){return this.slice(a)[0]},contains:function(a){for(var b=a&&a.valueOf(),c=0,d=this.length;c<d;c++)if(0<=this[c].valueOf()-b&&this[c].valueOf()-b<864e5)return c;return-1},remove:function(a){this.splice(a,1)},replace:function(b){b&&(a.isArray(b)||(b=[b]),this.clear(),this.push.apply(this,b))},clear:function(){this.length=0},copy:function(){var a=new j;return a.replace(this),a}};return function(){var c=[];return c.push.apply(c,arguments),a.extend(c,b),c}}(),k=function(b,c){a.data(b,"datepicker",this),this._process_options(c),this.dates=new j,this.viewDate=this.o.defaultViewDate,this.focusDate=null,this.element=a(b),this.isInput=this.element.is("input"),this.inputField=this.isInput?this.element:this.element.find("input"),this.component=!!this.element.hasClass("date")&&this.element.find(".add-on, .input-group-addon, .btn"),this.component&&0===this.component.length&&(this.component=!1),this.isInline=!this.component&&this.element.is("div"),this.picker=a(r.template),this._check_template(this.o.templates.leftArrow)&&this.picker.find(".prev").html(this.o.templates.leftArrow),this._check_template(this.o.templates.rightArrow)&&this.picker.find(".next").html(this.o.templates.rightArrow),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&this.picker.addClass("datepicker-rtl"),this.o.calendarWeeks&&this.picker.find(".datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear").attr("colspan",function(a,b){return Number(b)+1}
vendor: 13,677 bytes, line 2741
2741),this._process_options({startDate:this._o.startDate,endDate:this._o.endDate,daysOfWeekDisabled:this.o.daysOfWeekDisabled,daysOfWeekHighlighted:this.o.daysOfWeekHighlighted,datesDisabled:this.o.datesDisabled}),this._allow_update=!1,this.setViewMode(this.o.startView),this._allow_update=!0,this.fillDow(),this.fillMonths(),this.update(),this.isInline&&this.show()};k.prototype={constructor:k,_resolveViewName:function(b){return a.each(r.viewModes,function(c,d){if(b===c||a.inArray(b,d.names)!==-1)return b=c,!1}),b},_resolveDaysOfWeek:function(b){return a.isArray(b)||(b=b.split(/[,\s]*/)),a.map(b,Number)},_check_template:function(c){try{if(c===b||""===c)return!1;if((c.match(/[<>]/g)||[]).length<=0)return!0;var d=a(c);return d.length>0}catch(a){return!1}},_process_options:function(b){this._o=a.extend({},this._o,b);var e=this.o=a.extend({},this._o),f=e.language;q[f]||(f=f.split("-")[0],q[f]||(f=o.language)),e.language=f,e.startView=this._resolveViewName(e.startView),e.minViewMode=this._resolveViewName(e.minViewMode),e.maxViewMode=this._resolveViewName(e.maxViewMode),e.startView=Math.max(this.o.minViewMode,Math.min(this.o.maxViewMode,e.startView)),e.multidate!==!0&&(e.multidate=Number(e.multidate)||!1,e.multidate!==!1&&(e.multidate=Math.max(0,e.multidate))),e.multidateSeparator=String(e.multidateSeparator),e.weekStart%=7,e.weekEnd=(e.weekStart+6)%7;var g=r.parseFormat(e.format);e.startDate!==-(1/0)&&(e.startDate?e.startDate instanceof Date?e.startDate=this._local_to_utc(this._zero_time(e.startDate)):e.startDate=r.parseDate(e.startDate,g,e.language,e.assumeNearbyYear):e.startDate=-(1/0)),e.endDate!==1/0&&(e.endDate?e.endDate instanceof Date?e.endDate=this._local_to_utc(this._zero_time(e.endDate)):e.endDate=r.parseDate(e.endDate,g,e.language,e.assumeNearbyYear):e.endDate=1/0),e.daysOfWeekDisabled=this._resolveDaysOfWeek(e.daysOfWeekDisabled||[]),e.daysOfWeekHighlighted=this._resolveDaysOfWeek(e.daysOfWeekHighlighted||[]),e.datesDisabled=e.datesDisabled||[],a.isArray(e.datesDisabled)||(e.datesDisabled=e.datesDisabled.split(",")),e.datesDisabled=a.map(e.datesDisabled,function(a){return r.parseDate(a,g,e.language,e.assumeNearbyYear)});var h=String(e.orientation).toLowerCase().split(/\s+/g),i=e.orientation.toLowerCase();if(h=a.grep(h,function(a){return/^auto|left|right|top|bottom$/.test(a)}),e.orientation={x:"auto",y:"auto"},i&&"auto"!==i)if(1===h.length)switch(h[0]){case"top":case"bottom":e.orientation.y=h[0];break;case"left":case"right":e.orientation.x=h[0]}else i=a.grep(h,function(a){return/^left|right$/.test(a)}),e.orientation.x=i[0]||"auto",i=a.grep(h,function(a){return/^top|bottom$/.test(a)}),e.orientation.y=i[0]||"auto";else;if(e.defaultViewDate instanceof Date||"string"==typeof e.defaultViewDate)e.defaultViewDate=r.parseDate(e.defaultViewDate,g,e.language,e.assumeNearbyYear);else if(e.defaultViewDate){var j=e.defaultViewDate.year||(new Date).getFullYear(),k=e.defaultViewDate.month||0,l=e.defaultViewDate.day||1;e.defaultViewDate=c(j,k,l)}else e.defaultViewDate=d()},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(d=b,e=a[f][1]):3===a[f].length&&(d=a[f][1],e=a[f][2]),c.on(e,d)},_unapplyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(e=b,d=a[f][1]):3===a[f].length&&(e=a[f][1],d=a[f][2]),c.off(d,e)},_buildEvents:function(){var b={keyup:a.proxy(function(b){a.inArray(b.keyCode,[27,37,39,38,40,32,13,9])===-1&&this.update()},this),keydown:a.proxy(this.keydown,this),paste:a.proxy(this.paste,this)};this.o.showOnFocus===!0&&(b.focus=a.proxy(this.show,this)),this.isInput?this._events=[[this.element,b]]:this.component&&this.inputField.length?this._events=[[this.inputField,b],[this.component,{click:a.proxy(this.show,this)}]]:this._events=[[this.element,{click:a.proxy(this.show,this),keydown:a.proxy(this.keydown,this)}]],this._events.push([this.element,"*",{blur:a.proxy(function(a){this._focused_from=a.target},this)}],[this.element,{blur:a.proxy(function(a){this._focused_from=a.target},this)}]),this.o.immediateUpdates&&this._events.push([this.element,{"changeYear changeMonth":a.proxy(function(a){this.update(a.date)},this)}]),this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[this.picker,".prev, .next",{click:a.proxy(this.navArrowsClick,this)}],[this.picker,".day:not(.disabled)",{click:a.proxy(this.dayCellClick,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{"mousedown touchstart":a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).length||this.picker.is(a.target)||this.picker.find(a.target).length||this.isInline||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.dates.get(-1),e=this._utc_to_local(d);this.element.trigger({type:b,date:e,viewMode:this.viewMode,dates:a.map(this.dates,this._utc_to_local),format:a.proxy(function(a,b){0===arguments.length?(a=this.dates.length-1,b=this.o.format):"string"==typeof a&&(b=a,a=this.dates.length-1),b=b||this.o.format;var c=this.dates.get(a);return r.formatDate(c,b,this.o.language)},this)})},show:function(){if(!(this.inputField.prop("disabled")||this.inputField.prop("readonly")&&this.o.enableOnReadonly===!1))return this.isInline||this.picker.appendTo(this.o.container),this.place(),this.picker.show(),this._attachSecondaryEvents(),this._trigger("show"),(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&this.o.disableTouchKeyboard&&a(this.element).blur(),this},hide:function(){return this.isInline||!this.picker.is(":visible")?this:(this.focusDate=null,this.picker.hide().detach(),this._detachSecondaryEvents(),this.setViewMode(this.o.startView),this.o.forceParse&&this.inputField.val()&&this.setValue(),this._trigger("hide"),this)},destroy:function(){return this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date,this},paste:function(b){var c;if(b.originalEvent.clipboardData&&b.originalEvent.clipboardData.types&&a.inArray("text/plain",b.originalEvent.clipboardData.types)!==-1)c=b.originalEvent.clipboardData.getData("text/plain");else{if(!window.clipboardData)return;c=window.clipboardData.getData("Text")}this.setDate(c),this.update(),b.preventDefault()},_utc_to_local:function(a){if(!a)return a;var b=new Date(a.getTime()+6e4*a.getTimezoneOffset());return b.getTimezoneOffset()!==a.getTimezoneOffset()&&(b=new Date(a.getTime()+6e4*b.getTimezoneOffset())),b},_local_to_utc:function(a){return a&&new Date(a.getTime()-6e4*a.getTimezoneOffset())},_zero_time:function(a){return a&&new Date(a.getFullYear(),a.getMonth(),a.getDate())},_zero_utc_time:function(a){return a&&c(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate())},getDates:function(){return a.map(this.dates,this._utc_to_local)},getUTCDates:function(){return a.map(this.dates,function(a){return new Date(a)})},getDate:function(){return this._utc_to_local(this.getUTCDate())},getUTCDate:function(){var a=this.dates.get(-1);return a!==b?new Date(a):null},clearDates:function(){this.inputField.val(""),this.update(),this._trigger("changeDate"),this.o.autoclose&&this.hide()},setDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.update.apply(this,b),this._trigger("changeDate"),this.setValue(),this},setUTCDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.setDates.apply(this,a.map(b,this._utc_to_local)),this},setDate:f("setDates"),setUTCDate:f("setUTCDates"),remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead"),setValue:function(){var a=this.getFormattedDate();return this.inputField.val(a),this},getFormattedDate:function(c){c===b&&(c=this.o.format);var d=this.o.language;return a.map(this.dates,function(a){return r.formatDate(a,c,d)}).join(this.o.multidateSeparator)},getStartDate:function(){return this.o.startDate},setStartDate:function(a){return this._process_options({startDate:a}),this.update(),this.updateNavArrows(),this},getEndDate:function(){return this.o.endDate},setEndDate:function(a){return this._process_options({endDate:a}),this.update(),this.updateNavArrows(),this},setDaysOfWeekDisabled:function(a){return this._process_options({daysOfWeekDisabled:a}),this.update(),this},setDaysOfWeekHighlighted:function(a){return this._process_options({daysOfWeekHighlighted:a}),this.update(),this},setDatesDisabled:function(a){return this._process_options({datesDisabled:a}),this.update(),this},place:function(){if(this.isInline)return this;var b=this.picker.outerWidth(),c=this.picker.outerHeight(),d=10,e=a(this.o.container),f=e.width(),g="body"===this.o.container?a(document).scrollTop():e.scrollTop(),h=e.offset(),i=[0];this.element.parents().each(function(){var b=a(this).css("z-index");"auto"!==b&&0!==Number(b)&&i.push(Number(b))});var j=Math.max.apply(Math,i)+this.o.zIndexOffset,k=this.component?this.component.parent().offset():this.element.offset(),l=this.component?this.component.outerHeight(!0):this.element.outerHeight(!1),m=this.component?this.component.outerWidth(!0):this.element.outerWidth(!1),n=k.left-h.left,o=k.top-h.top;"body"!==this.o.container&&(o+=g),this.picker.removeClass("datepicker-orient-top datepicker-orient-bottom datepicker-orient-right datepicker-orient-left"),"auto"!==this.o.orientation.x?(this.picker.addClass("datepicker-orient-"+this.o.orientation.x),"right"===this.o.orientation.x&&(n-=b-m)):k.left<0?(this.picker.addClass("datepicker-orient-left"),n-=k.left-d):n+b>f?(this.picker.addClass("datepicker-orient-right"),n+=m-b):this.o.rtl?this.picker.addClass("datepicker-orient-right"):this.picker.addClass("datepicker-orient-left");var p,q=this.o.orientation.y;if("auto"===q&&(p=-g+o-c,q=p<0?"bottom":"top"),this.picker.addClass("datepicker-orient-"+q),"top"===q?o-=c+parseInt(this.picker.css("padding-top")):o+=l,this.o.rtl){var r=f-(n+m);this.picker.css({top:o,right:r,zIndex:j})}else this.picker.css({top:o,left:n,zIndex:j});return this},_allow_update:!0,update:function(){if(!this._allow_update)return this;var b=this.dates.copy(),c=[],d=!1;return arguments.length?(a.each(arguments,a.proxy(function(a,b){b instanceof Date&&(b=this._local_to_utc(b)),c.push(b)},this)),d=!0):(c=this.isInput?this.element.val():this.element.data("date")||this.inputField.val(),c=c&&this.o.multidate?c.split(this.o.multidateSeparator):[c],delete this.element.data().date),c=a.map(c,a.proxy(function(a){return r.parseDate(a,this.o.format,this.o.language,this.o.assumeNearbyYear)},this)),c=a.grep(c,a.proxy(function(a){return!this.dateWithinRange(a)||!a},this),!0),this.dates.replace(c),this.o.updateViewDate&&(this.dates.length?this.viewDate=new Date(this.dates.get(-1)):this.viewDate<this.o.startDate?this.viewDate=new Date(this.o.startDate):this.viewDate>this.o.endDate?this.viewDate=new Date(this.o.endDate):this.viewDate=this.o.defaultViewDate),d?(this.setValue(),this.element.change()):this.dates.length&&String(b)!==String(this.dates)&&d&&(this._trigger("changeDate"),this.element.change()),!this.dates.length&&b.length&&(this._trigger("clearDate"),this.element.change()),this.fill(),this},fillDow:function(){if(this.o.showWeekDays){var b=this.o.weekStart,c="<tr>";for(this.o.calendarWeeks&&(c+='<th class="cw">&#160;</th>');b<this.o.weekStart+7;)c+='<th class="dow',a.inArray(b,this.o.daysOfWeekDisabled)!==-1&&(c+=" disabled"),c+='">'+q[this.o.language].daysMin[b++%7]+"</th>";c+="</tr>",this.picker.find(".datepicker-days thead").append(c)}},fillMonths:function(){for(var a,b=this._utc_to_local(this.viewDate),c="",d=0;d<12;d++)a=b&&b.getMonth()===d?" focused":"",c+='<span class="month'+a+'">'+q[this.o.language].monthsShort[d]+"</span>";this.picker.find(".datepicker-months td").html(c)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],f=this.viewDate.getUTCFullYear(),g=this.viewDate.getUTCMonth(),h=d();return b.getUTCFullYear()<f||b.getUTCFullYear()===f&&b.getUTCMonth()<g?c.push("old"):(b.getUTCFullYear()>f||b.getUTCFullYear()===f&&b.getUTCMonth()>g)&&c.push("new"),this.focusDate&&b.valueOf()===this.focusDate.valueOf()&&c.push("focused"),this.o.todayHighlight&&e(b,h)&&c.push("today"),this.dates.contains(b)!==-1&&c.push("active"),this.dateWithinRange(b)||c.push("disabled"),this.dateIsDisabled(b)&&c.push("disabled","disabled-date"),a.inArray(b.getUTCDay(),this.o.daysOfWeekHighlighted)!==-1&&c.push("highlighted"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),a.inArray(b.valueOf(),this.range)!==-1&&c.push("selected"),b.valueOf()===this.range[0]&&c.push("range-start"),b.valueOf()===this.range[this.range.length-1]&&c.push("range-end")),c},_fill_yearsView:function(c,d,e,f,g,h,i){for(var j,k,l,m="",n=e/10,o=this.picker.find(c),p=Math.floor(f/e)*e,q=p+9*n,r=Math.floor(this.viewDate.getFullYear()/n)*n,s=a.map(this.dates,function(a){return Math.floor(a.getUTCFullYear()/n)*n}),t=p-n;t<=q+n;t+=n)j=[d],k=null,t===p-n?j.push("old"):t===q+n&&j.push("new"),a.inArray(t,s)!==-1&&j.push("active"),(t<g||t>h)&&j.push("disabled"),t===r&&j.push("focused"),i!==a.noop&&(l=i(new Date(t,0,1)),l===b?l={}:"boolean"==typeof l?l={enabled:l}:"string"==typeof l&&(l={classes:l}),l.enabled===!1&&j.push("disabled"),l.classes&&(j=j.concat(l.classes.split(/\s+/))),l.tooltip&&(k=l.tooltip)),m+='<sp
2741an class="'+j.join(" ")+'"'+(k?' title="'+k+'"':"")+">"+t+"</span>";o.find(".datepicker-switch").text(p+"-"+q),o.find("td").html(m)},fill:function(){var d,e,f=new Date(this.viewDate),g=f.getUTCFullYear(),h=f.getUTCMonth(),i=this.o.startDate!==-(1/0)?this.o.startDate.getUTCFullYear():-(1/0),j=this.o.startDate!==-(1/0)?this.o.startDate.getUTCMonth():-(1/0),k=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,l=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,m=q[this.o.language].today||q.en.today||"",n=q[this.o.language].clear||q.en.clear||"",o=q[this.o.language].titleFormat||q.en.titleFormat;if(!isNaN(g)&&!isNaN(h)){this.picker.find(".datepicker-days .datepicker-switch").text(r.formatDate(f,o,this.o.language)),this.picker.find("tfoot .today").text(m).css("display",this.o.todayBtn===!0||"linked"===this.o.todayBtn?"table-cell":"none"),this.picker.find("tfoot .clear").text(n).css("display",this.o.clearBtn===!0?"table-cell":"none"),this.picker.find("thead .datepicker-title").text(this.o.title).css("display","string"==typeof this.o.title&&""!==this.o.title?"table-cell":"none"),this.updateNavArrows(),this.fillMonths();var p=c(g,h,0),s=p.getUTCDate();p.setUTCDate(s-(p.getUTCDay()-this.o.weekStart+7)%7);var t=new Date(p);p.getUTCFullYear()<100&&t.setUTCFullYear(p.getUTCFullYear()),t.setUTCDate(t.getUTCDate()+42),t=t.valueOf();for(var u,v,w=[];p.valueOf()<t;){if(u=p.getUTCDay(),u===this.o.weekStart&&(w.push("<tr>"),this.o.calendarWeeks)){var x=new Date(+p+(this.o.weekStart-u-7)%7*864e5),y=new Date(Number(x)+(11-x.getUTCDay())%7*864e5),z=new Date(Number(z=c(y.getUTCFullYear(),0,1))+(11-z.getUTCDay())%7*864e5),A=(y-z)/864e5/7+1;w.push('<td class="cw">'+A+"</td>")}v=this.getClassNames(p),v.push("day");var B=p.getUTCDate();this.o.beforeShowDay!==a.noop&&(e=this.o.beforeShowDay(this._utc_to_local(p)),e===b?e={}:"boolean"==typeof e?e={enabled:e}:"string"==typeof e&&(e={classes:e}),e.enabled===!1&&v.push("disabled"),e.classes&&(v=v.concat(e.classes.split(/\s+/))),e.tooltip&&(d=e.tooltip),e.content&&(B=e.content)),v=a.isFunction(a.uniqueSort)?a.uniqueSort(v):a.unique(v),w.push('<td class="'+v.join(" ")+'"'+(d?' title="'+d+'"':"")+' data-date="'+p.getTime().toString()+'">'+B+"</td>"),d=null,u===this.o.weekEnd&&w.push("</tr>"),p.setUTCDate(p.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").html(w.join(""));var C=q[this.o.language].monthsTitle||q.en.monthsTitle||"Months",D=this.picker.find(".datepicker-months").find(".datepicker-switch").text(this.o.maxViewMode<2?C:g).end().find("tbody span").removeClass("active");if(a.each(this.dates,function(a,b){b.getUTCFullYear()===g&&D.eq(b.getUTCMonth()).addClass("active")}),(g<i||g>k)&&D.addClass("disabled"),g===i&&D.slice(0,j).addClass("disabled"),g===k&&D.slice(l+1).addClass("disabled"),this.o.beforeShowMonth!==a.noop){var E=this;a.each(D,function(c,d){var e=new Date(g,c,1),f=E.o.beforeShowMonth(e);f===b?f={}:"boolean"==typeof f?f={enabled:f}:"string"==typeof f&&(f={classes:f}),f.enabled!==!1||a(d).hasClass("disabled")||a(d).addClass("disabled"),f.classes&&a(d).addClass(f.classes),f.tooltip&&a(d).prop("title",f.tooltip)})}this._fill_yearsView(".datepicker-years","year",10,g,i,k,this.o.beforeShowYear),this._fill_yearsView(".datepicker-decades","decade",100,g,i,k,this.o.beforeShowDecade),this._fill_yearsView(".datepicker-centuries","century",1e3,g,i,k,this.o.beforeShowCentury)}},updateNavArrows:function(){if(this._allow_update){var a,b,c=new Date(this.viewDate),d=c.getUTCFullYear(),e=c.getUTCMonth(),f=this.o.startDate!==-(1/0)?this.o.startDate.getUTCFullYear():-(1/0),g=this.o.startDate!==-(1/0)?this.o.startDate.getUTCMonth():-(1/0),h=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,i=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,j=1;switch(this.viewMode){case 4:j*=10;case 3:j*=10;case 2:j*=10;case 1:a=Math.floor(d/j)*j<f,b=Math.floor(d/j)*j+j>h;break;case 0:a=d<=f&&e<g,b=d>=h&&e>i}this.picker.find(".prev").toggleClass("disabled",a),this.picker.find(".next").toggleClass("disabled",b)}},click:function(b){b.preventDefault(),b.stopPropagation();var e,f,g,h;e=a(b.target),e.hasClass("datepicker-switch")&&this.viewMode!==this.o.maxViewMode&&this.setViewMode(this.viewMode+1),e.hasClass("today")&&!e.hasClass("day")&&(this.setViewMode(0),this._setDate(d(),"linked"===this.o.todayBtn?null:"view")),e.hasClass("clear")&&this.clearDates(),e.hasClass("disabled")||(e.hasClass("month")||e.hasClass("year")||e.hasClass("decade")||e.hasClass("century"))&&(this.viewDate.setUTCDate(1),f=1,1===this.viewMode?(h=e.parent().find("span").index(e),g=this.viewDate.getUTCFullYear(),this.viewDate.setUTCMonth(h)):(h=0,g=Number(e.text()),this.viewDate.setUTCFullYear(g)),this._trigger(r.viewModes[this.viewMode-1].e,this.viewDate),this.viewMode===this.o.minViewMode?this._setDate(c(g,h,f)):(this.setViewMode(this.viewMode-1),this.fill())),this.picker.is(":visible")&&this._focused_from&&this._focused_from.focus(),delete this._focused_from},dayCellClick:function(b){var c=a(b.currentTarget),d=c.data("date"),e=new Date(d);this.o.updateViewDate&&(e.getUTCFullYear()!==this.viewDate.getUTCFullYear()&&this._trigger("changeYear",this.viewDate),e.getUTCMonth()!==this.viewDate.getUTCMonth()&&this._trigger("changeMonth",this.viewDate)),this._setDate(e)},navArrowsClick:function(b){var c=a(b.currentTarget),d=c.hasClass("prev")?-1:1;0!==this.viewMode&&(d*=12*r.viewModes[this.viewMode].navStep),this.viewDate=this.moveMonth(this.viewDate,d),this._trigger(r.viewModes[this.viewMode].e,this.viewDate),this.fill()},_toggle_multidate:function(a){var b=this.dates.contains(a);if(a||this.dates.clear(),b!==-1?(this.o.multidate===!0||this.o.multidate>1||this.o.toggleActive)&&this.dates.remove(b):this.o.multidate===!1?(this.dates.clear(),this.dates.push(a)):this.dates.push(a),"number"==typeof this.o.multidate)for(;this.dates.length>this.o.multidate;)this.dates.remove(0)}
vendor: 6,439 bytes, line 2741
2741,_setDate:function(a,b){b&&"date"!==b||this._toggle_multidate(a&&new Date(a)),(!b&&this.o.updateViewDate||"view"===b)&&(this.viewDate=a&&new Date(a)),this.fill(),this.setValue(),b&&"view"===b||this._trigger("changeDate"),this.inputField.trigger("change"),!this.o.autoclose||b&&"date"!==b||this.hide()},moveDay:function(a,b){var c=new Date(a);return c.setUTCDate(a.getUTCDate()+b),c},moveWeek:function(a,b){return this.moveDay(a,7*b)},moveMonth:function(a,b){if(!g(a))return this.o.defaultViewDate;if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),h=e.getUTCMonth(),i=Math.abs(b);if(b=b>0?1:-1,1===i)d=b===-1?function(){return e.getUTCMonth()===h}:function(){return e.getUTCMonth()!==c},c=h+b,e.setUTCMonth(c),c=(c+12)%12;else{for(var j=0;j<i;j++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!==e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},moveAvailableDate:function(a,b,c){do{if(a=this[c](a,b),!this.dateWithinRange(a))return!1;c="moveDay"}while(this.dateIsDisabled(a));return a},weekOfDateIsDisabled:function(b){return a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled)!==-1},dateIsDisabled:function(b){return this.weekOfDateIsDisabled(b)||a.grep(this.o.datesDisabled,function(a){return e(b,a)}).length>0},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(!this.picker.is(":visible"))return void(40!==a.keyCode&&27!==a.keyCode||(this.show(),a.stopPropagation()));var b,c,d=!1,e=this.focusDate||this.viewDate;switch(a.keyCode){case 27:this.focusDate?(this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill()):this.hide(),a.preventDefault(),a.stopPropagation();break;case 37:case 38:case 39:case 40:if(!this.o.keyboardNavigation||7===this.o.daysOfWeekDisabled.length)break;b=37===a.keyCode||38===a.keyCode?-1:1,0===this.viewMode?a.ctrlKey?(c=this.moveAvailableDate(e,b,"moveYear"),c&&this._trigger("changeYear",this.viewDate)):a.shiftKey?(c=this.moveAvailableDate(e,b,"moveMonth"),c&&this._trigger("changeMonth",this.viewDate)):37===a.keyCode||39===a.keyCode?c=this.moveAvailableDate(e,b,"moveDay"):this.weekOfDateIsDisabled(e)||(c=this.moveAvailableDate(e,b,"moveWeek")):1===this.viewMode?(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveMonth")):2===this.viewMode&&(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveYear")),c&&(this.focusDate=this.viewDate=c,this.setValue(),this.fill(),a.preventDefault());break;case 13:if(!this.o.forceParse)break;e=this.focusDate||this.dates.get(-1)||this.viewDate,this.o.keyboardNavigation&&(this._toggle_multidate(e),d=!0),this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.setValue(),this.fill(),this.picker.is(":visible")&&(a.preventDefault(),a.stopPropagation(),this.o.autoclose&&this.hide());break;case 9:this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill(),this.hide()}d&&(this.dates.length?this._trigger("changeDate"):this._trigger("clearDate"),this.inputField.trigger("change"))},setViewMode:function(a){this.viewMode=a,this.picker.children("div").hide().filter(".datepicker-"+r.viewModes[this.viewMode].clsName).show(),this.updateNavArrows(),this._trigger("changeViewMode",new Date(this.viewDate))}};var l=function(b,c){a.data(b,"datepicker",this),this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,this.keepEmptyValues=c.keepEmptyValues,delete c.keepEmptyValues,n.call(a(this.inputs),c).on("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a.data(b,"datepicker")}),this.updateDates()};l.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.getUTCDate()}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},clearDates:function(){a.each(this.pickers,function(a,b){b.clearDates()})},dateUpdated:function(c){if(!this.updating){this.updating=!0;var d=a.data(c.target,"datepicker");if(d!==b){var e=d.getUTCDate(),f=this.keepEmptyValues,g=a.inArray(c.target,this.inputs),h=g-1,i=g+1,j=this.inputs.length;if(g!==-1){if(a.each(this.pickers,function(a,b){b.getUTCDate()||b!==d&&f||b.setUTCDate(e)}),e<this.dates[h])for(;h>=0&&e<this.dates[h];)this.pickers[h--].setUTCDate(e);else if(e>this.dates[i])for(;i<j&&e>this.dates[i];)this.pickers[i++].setUTCDate(e);this.updateDates(),delete this.updating}}}},destroy:function(){a.map(this.pickers,function(a){a.destroy()}),a(this.inputs).off("changeDate",this.dateUpdated),delete this.element.data().datepicker},remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead")};var m=a.fn.datepicker,n=function(c){var d=Array.apply(null,arguments);d.shift();var e;if(this.each(function(){var b=a(this),f=b.data("datepicker"),g="object"==typeof c&&c;if(!f){var j=h(this,"date"),m=a.extend({},o,j,g),n=i(m.language),p=a.extend({},o,n,j,g);b.hasClass("input-daterange")||p.inputs?(a.extend(p,{inputs:p.inputs||b.find("input").toArray()}),f=new l(this,p)):f=new k(this,p),b.data("datepicker",f)}"string"==typeof c&&"function"==typeof f[c]&&(e=f[c].apply(f,d))}),e===b||e instanceof k||e instanceof l)return this;if(this.length>1)throw new Error("Using only allowed for the collection of a single element ("+c+" function)");return e};a.fn.datepicker=n;var o=a.fn.datepicker.defaults={assumeNearbyYear:!1,autoclose:!1,beforeShowDay:a.noop,beforeShowMonth:a.noop,beforeShowYear:a.noop,beforeShowDecade:a.noop,beforeShowCentury:a.noop,calendarWeeks:!1,clearBtn:!1,toggleActive:!1,daysOfWeekDisabled:[],daysOfWeekHighlighted:[],datesDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keepEmptyValues:!1,keyboardNavigation:!0,language:"en",minViewMode:0,maxViewMode:4,multidate:!1,multidateSeparator:",",orientation:"auto",rtl:!1,startDate:-(1/0),startView:0,todayBtn:!1,todayHighlight:!1,updateViewDate:!0,weekStart:0,disableTouchKeyboard:!1,enableOnReadonly:!0,showOnFocus:!0,zIndexOffset:10,container:"body",immediateUpdates:!1,title:"",templates:{leftArrow:"&#x00AB;",rightArrow:"&#x00BB;"},showWeekDays:!0},p=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=k;var q=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Frid
2741ay","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",titleFormat:"MM yyyy"}},r={viewModes:[{names:["days","month"],clsName:"days",e:"changeMonth"},{names:["months","year"],clsName:"months",e:"changeYear",navStep:1},{names:["years","decade"],clsName:"years",e:"changeDecade",navStep:10},{names:["decades","century"],clsName:"decades",e:"changeCentury",navStep:100},{names:["centuries","millennium"],clsName:"centuries",e:"changeMillennium",navStep:1e3}],validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,parseFormat:function(a){if("function"==typeof a.toValue&&"function"==typeof a.toDisplay)return a;var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,e,f,g){function h(a,b){return b===!0&&(b=10),a<100&&(a+=2e3,a>(new Date).getFullYear()+b&&(a-=100)),a}function i(){var a=this.slice(0,j[n].length),b=j[n].slice(0,a.length);return a.toLowerCase()===b.toLowerCase()}if(!c)return b;if(c instanceof Date)return c;if("string"==typeof e&&(e=r.parseFormat(e)),e.toValue)return e.toValue(c,e,f);var j,l,m,n,o,p={d:"moveDay",m:"moveMonth",w:"moveWeek",y:"moveYear"},s={yesterday:"-1d",today:"+0d",tomorrow:"+1d"};if(c in s&&(c=s[c]),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(c)){for(j=c.match(/([\-+]\d+)([dmwy])/gi),c=new Date,n=0;n<j.length;n++)l=j[n].match(/([\-+]\d+)([dmwy])/i),m=Number(l[1]),o=p[l[2].toLowerCase()],c=k.prototype[o](c,m);return k.prototype._zero_utc_time(c)}j=c&&c.match(this.nonpunctuation)||[];var t,u,v={},w=["yyyy","yy","M","MM","m","mm","d","dd"],x={yyyy:function(a,b){return a.setUTCFullYear(g?h(b,g):b)},m:function(a,b){if(isNaN(a))return a;for(b-=1;b<0;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!==b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};x.yy=x.yyyy,x.M=x.MM=x.mm=x.m,x.dd=x.d,c=d();var y=e.parts.slice();if(j.length!==y.length&&(y=a(y).filter(function(b,c){return a.inArray(c,w)!==-1}).toArray()),j.length===y.length){var z;for(n=0,z=y.length;n<z;n++){if(t=parseInt(j[n],10),l=y[n],isNaN(t))switch(l){case"MM":u=a(q[f].months).filter(i),t=a.inArray(u[0],q[f].months)+1;break;case"M":u=a(q[f].monthsShort).filter(i),t=a.inArray(u[0],q[f].monthsShort)+1}v[l]=t}var A,B;for(n=0;n<w.length;n++)B=w[n],B in v&&!isNaN(v[B])&&(A=new Date(c),x[B](A,v[B]),isNaN(A)||(c=A))}return c},formatDate:function(b,c,d){if(!b)return"";if("string"==typeof c&&(c=r.parseFormat(c)),c.toDisplay)return c.toDisplay(b,c,d);var e={d:b.getUTCDate(),D:q[d].daysShort[b.getUTCDay()],DD:q[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:q[d].monthsShort[b.getUTCMonth()],MM:q[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m,b=[];for(var f=a.extend([],c.separators),g=0,h=c.parts.length;g<=h;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th colspan="7" class="datepicker-title"></th></tr><tr><th class="prev">'+o.templates.leftArrow+'</th><th colspan="5" class="datepicker-switch"></th><th class="next">'+o.templates.rightArrow+"</th></tr></thead>",
2742    contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};r.template='<div class="datepicker"><div class="datepicker-days"><table class="table-condensed">'+r.headTemplate+"<tbody></tbody>"+r.footTemplate+'</table></div><div class="datepicker-months"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-decades"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-centuries"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+"</table></div></div>",a.fn.datepicker.DPGlobal=r,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=m,this},a.fn.datepicker.version="1.8.0",a.fn.datepicker.deprecated=function(a){var b=window.console;b&&b.warn&&b.warn("DEPRECATED: "+a)},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),n.call(c,"show"))}),a(function(){n.call(a('[data-provide="datepicker-inline"]'))})});
2743!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,t;function n(){return e.apply(null,arguments)}function s(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function i(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function r(e){return void 0===e}function a(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function o(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function u(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function l(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function d(e,t){for(var n in t)l(t,n)&&(e[n]=t[n]);return l(t,"toString")&&(e.toString=t.toString),l(t,"valueOf")&&(e.valueOf=t.valueOf),e}function h(e,t,n,s){return Ot(e,t,n,s,!0).utc()}function c(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invali
vendor: 48,702 bytes, line 2743
2743dFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function f(e){if(null==e._isValid){var n=c(e),s=t.call(n.parsedDateParts,function(e){return null!=e}),i=!isNaN(e._d.getTime())&&n.overflow<0&&!n.empty&&!n.invalidMonth&&!n.invalidWeekday&&!n.weekdayMismatch&&!n.nullInput&&!n.invalidFormat&&!n.userInvalidated&&(!n.meridiem||n.meridiem&&s);if(e._strict&&(i=i&&0===n.charsLeftOver&&0===n.unusedTokens.length&&void 0===n.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return i;e._isValid=i}return e._isValid}function m(e){var t=h(NaN);return null!=e?d(c(t),e):c(t).userInvalidated=!0,t}t=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var _=n.momentProperties=[];function y(e,t){var n,s,i;if(r(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),r(t._i)||(e._i=t._i),r(t._f)||(e._f=t._f),r(t._l)||(e._l=t._l),r(t._strict)||(e._strict=t._strict),r(t._tzm)||(e._tzm=t._tzm),r(t._isUTC)||(e._isUTC=t._isUTC),r(t._offset)||(e._offset=t._offset),r(t._pf)||(e._pf=c(t)),r(t._locale)||(e._locale=t._locale),_.length>0)for(n=0;n<_.length;n++)r(i=t[s=_[n]])||(e[s]=i);return e}var g=!1;function p(e){y(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===g&&(g=!0,n.updateOffset(this),g=!1)}function v(e){return e instanceof p||null!=e&&null!=e._isAMomentObject}function w(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function M(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=w(t)),n}function S(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&M(e[s])!==M(t[s]))&&a++;return a+r}function D(e){!1===n.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function k(e,t){var s=!0;return d(function(){if(null!=n.deprecationHandler&&n.deprecationHandler(null,e),s){for(var i,r=[],a=0;a<arguments.length;a++){if(i="","object"==typeof arguments[a]){for(var o in i+="\n["+a+"] ",arguments[0])i+=o+": "+arguments[0][o]+", ";i=i.slice(0,-2)}else i=arguments[a];r.push(i)}D(e+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),s=!1}return t.apply(this,arguments)},t)}var Y,O={};function T(e,t){null!=n.deprecationHandler&&n.deprecationHandler(e,t),O[e]||(D(t),O[e]=!0)}function x(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function b(e,t){var n,s=d({},e);for(n in t)l(t,n)&&(i(e[n])&&i(t[n])?(s[n]={},d(s[n],e[n]),d(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)l(e,n)&&!l(t,n)&&i(e[n])&&(s[n]=d({},s[n]));return s}function P(e){null!=e&&this.set(e)}n.suppressDeprecationWarnings=!1,n.deprecationHandler=null,Y=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)l(e,t)&&n.push(t);return n};var W={};function H(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function R(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function C(e){var t,n,s={};for(n in e)l(e,n)&&(t=R(n))&&(s[t]=e[n]);return s}var F={};function L(e,t){F[e]=t}function U(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(e>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return U(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(e){var t,n,s,i=e.match(N);for(t=0,n=i.length;t<n;t++)E[i[t]]?i[t]=E[i[t]]:i[t]=(s=i[t]).match(/\[[\s\S]/)?s.replace(/^\[|\]$/g,""):s.replace(/\\/g,"");return function(t){var s,r="";for(s=0;s<n;s++)r+=x(i[s])?i[s].call(t,e):i[s];return r}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;n>=0&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,oe={};function ue(e,t,n){oe[e]=x(t)?t:function(e,s){return e&&n?n:t}}function le(e,t){return l(oe,e)?oe[e](t._strict,t._locale):new RegExp(de(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function de(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var he={};function ce(e,t){var n,s=t;for("string"==typeof e&&(e=[e]),a(t)&&(s=function(e,n){n[t]=M(e)}),n=0;n<e.length;n++)he[e[n]]=s}function fe(e,t){ce(e,function(e,n,s,i){s._w=s._w||{},t(e,s._w,s,i)})}var me=0,_e=1,ye=2,ge=3,pe=4,ve=5,we=6,Me=7,Se=8;function De(e){return ke(e)?366:365}function ke(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),H("year","y"),L("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?n.parseTwoDigitYear(e):M(e)}),ce("YY",function(e,t){t[me]=n.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),n.parseTwoDigitYear=function(e){return M(e)+(M(e)>68?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(e,t){return function(s){return null!=s?(be(this,e,s),n.updateOffset(this,t),this):xe(this,e)}}function xe(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function be(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&ke(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?ke(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),H("month","M"),L("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=M(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:c(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,He="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var Re="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Ce(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=M(t);else if(!a(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Fe(e){return null!=e?(Ce(this,e),n.updateOffset(this,!0),this):xe(this,"Month")}var Le=ae;var Ue=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=h([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=de(s[t]),i[t]=de(i[t]);for(t=0;t<24;t++)r[t]=de(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t=new Date(Date.UTC.apply(null,arguments));return e<100&&e>=0&&isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e),t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return o<=0?a=De(r=e-1)+o:o>De(e)?(r=e+1,a=o-De(e)):(r=e,a=o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(De(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),H("week","w"),H("isoWeek","W"),L("week",5),L("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=M(e)});I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),H("day","d"),H("weekday","e"),H("isoWeekday","E"),L("day",11),L("weekday",11),L("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:c(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=M(e)});var je="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var ze="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var $e=ae;var qe=ae;var Je=ae;function Be(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=h([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=de(o[t]),u[t]=de(u[t]),l[t]=de(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Qe(){return this.hours()%12||12}function Xe(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function Ke(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Qe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),Xe("a",!0),Xe("A",!1),H("hour","h"),L("hour",13),ue("a",Ke),ue("A",Ke),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=M(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=M(e),c(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=M(e.substr(0,s)),t[pe]=M(e.substr(s)),c(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=M(e.substr(0,s)),t[pe]=M(e.substr(s,2)),t[ve]=M(e.substr(i)),c(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=M(e.substr(0,s)),t[pe]=M(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=M(e.substr(0,s)),t[pe]=M(e.substr(s,2)),t[ve]=M(e.substr(i))});var et,tt=Te("Hours",!0),nt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:He,monthsShort:Re,week:{dow:0,doy:6},weekdays:je,weekdaysMin:ze,weekdaysShort:Ze,meridiemParse:/[ap]\.?m?\.?/i},st={},it={};function rt(e){return e?e.toLowerCase().replace("_","-"):e}function at(e){var t=null;if(!st[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=et._abbr,require("./locale/"+e),ot(t)}catch(e){}return st[e]}function ot(e,t){var n;return e&&((n=r(t)?lt(e):ut(e,t))?et=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),et._abbr}function ut(e,t){if(null!==t){var n,s=nt;if(t.abbr=e,null!=st[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=st[e]._config;else if(null!=t.parentLocale)if(null!=st[t.parentLocale])s=st[t.parentLocale]._config;else{if(null==(n=at(t.parentLocale)))return it[t.parentLocale]||(it[t.parentLocale]=[]),it[t.parentLocale].push({name:e,config:t}),null;s=n._config}return st[e]=new P(b(s,t)),it[e]&&it[e].forEach(function(e){ut(e.name,e.config)}),ot(e),st[e]}return delete st[e],null}function lt(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return et;if(!s(e)){if(t=at(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=rt(e[r]).split("-")).length,n=(n=rt(e[r+1]))?n.split("-"):null;t>0;){if(s=at(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&S(i,n,!0)>=t-1)break;t--}r++}return et}(e)}function dt(e){var t,n=e._a;return n&&-2===c(e).overflow&&(t=n[_e]<0||n[_e]>11?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||n[ge]>24||24===n[ge]&&(0!==n[pe]||0!==n[ve]||0!==n[we])?ge:n[pe]<0||n[pe]>59?pe:n[ve]<0||n[ve]>59?ve:n[we]<0||n[we]>999?we:-1,c(e)._overflowDayOfYear&&(t<me||t>ye)&&(t=ye),c(e)._overflowWeeks&&-1===t&&(t=Me),c(e)._overflowWeekday&&-1===t&&(t=Se),c(e).overflow=t),e}function ht(e,t,n){return null!=e?e:null!=t?t:n}function ct(e){var t,s,i,r,a,o=[];if(!e._d){var u,l;for(u=e,l=new Date(n.now()),i=u._useUTC?[l.getUTCFullYear(),l.getUTCMonth(),l.getUTCDate()]:[l.getFullYear(),l.getMonth(),l.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ht(t.GG,e._a[me],Ie(Tt(),1,4).year),s=ht(t.W,1),((i=ht(t.E,1))<1||i>7)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(Tt(),r,a);n=ht(t.gg,e._a[me],l.year),s=ht(t.w,l.week),null!=t.d?((i=t.d)<0||i>6)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||t.e>6)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?c(e)._overflowWeeks=!0:null!=u?c(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(a=ht(e._a[me],i[me]),(e._dayOfYear>De(a)||0===e._dayOfYear)&&(c(e)._overflowDayOfYear=!0),s=Ge(a,0,e._dayOfYear),e._a[_e]=s.getUTCMonth(),e._a[ye]=s.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=o[t]=i[t];for(;t<7;t++)e._a[t]=o[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[pe]&&0===e._a[ve]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o=new Date(e,t,n,s,i,r,a);return e<100&&e>=0&&isFinite(o.getFullYear())&&o.setFullYear(e),o}).apply(null,o),r=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==r&&(c(e).weekdayMismatch=!0)}}var ft=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,mt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/Z|[+-]\d\d(?::?\d\d)?/,yt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],gt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function vt(e){var t,n,s,i,r,a,o=e._i,u=ft.exec(o)||mt.exec(o);if(u){for(c(e).iso=!0,t=0,n=yt.length;t<n;t++)if(yt[t][1].exec(u[1])){i=yt[t][0],s=!1!==yt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[3])){r=(u[2]||" ")+gt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!_t.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),kt(e)}else e._isValid=!1}var wt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function Mt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),Re.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=wt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim());if(i){var r=Mt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&Ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(c(s).weekdayMismatch=!0,s._isValid=!1,1))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),c(e).rfc2822=!0}else e._isValid=!1}function kt(e){if(e._f!==n.ISO_8601)if(e._f!==n.RFC_2822){e._a=[],c(e).empty=!0;var t,s,i,r,a,o,u,d,h=""+e._i,f=h.length,m=0;for(i=j(e._f,e._locale).match(N)||[],t=0;t<i.length;t++)r=i[t],(s=(h.match(le(r,e))||[])[0])&&((a=h.substr(0,h.indexOf(s))).length>0&&c(e).unusedInput.push(a),h=h.slice(h.indexOf(s)+s.length),m+=s.length),E[r]?(s?c(e).empty=!1:c(e).unusedTokens.push(r),o=r,d=e,null!=(u=s)&&l(he,o)&&he[o](u,d._a,d,o)):e._strict&&!s&&c(e).unusedTokens.push(r);c(e).charsLeftOver=f-m,h.length>0&&c(e).unusedInput.push(h),e._a[ge]<=12&&!0===c(e).bigHour&&e._a[ge]>0&&(c(e).bigHour=void 0),c(e).parsedDateParts=e._a.slice(0),c(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0),t):t}(e._locale,e._a[ge],e._meridiem),ct(e),dt(e)}else Dt(e);else vt(e)}function Yt(e){var t,l,h,_,g=e._i,w=e._f;return e._locale=e._locale||lt(e._l),null===g||void 0===w&&""===g?m({nullInput:!0}):("string"==typeof g&&(e._i=g=e._locale.preparse(g)),v(g)?new p(dt(g)):(o(g)?e._d=g:s(w)?function(e){var t,n,s,i,r;if(0===e._f.length)return c(e).invalidFormat=!0,void(e._d=new Date(NaN));for(i=0;i<e._f.length;i++)r=0,t=y({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],kt(t),f(t)&&(r+=c(t).charsLeftOver,r+=10*c(t).unusedTokens.length,c(t).score=r,(null==s||r<s)&&(s=r,n=t));d(e,n||t)}(e):w?kt(e):r(l=(t=e)._i)?t._d=new Date(n.now()):o(l)?t._d=new Date(l.valueOf()):"string"==typeof l?(h=t,null===(_=pt.exec(h._i))?(vt(h),!1===h._isValid&&(delete h._isValid,Dt(h),!1===h._isValid&&(delete h._isValid,n.createFromInputFallback(h)))):h._d=new Date(+_[1])):s(l)?(t._a=u(l.slice(0),function(e){return parseInt(e,10)}),ct(t)):i(l)?function(e){if(!e._d){var t=C(e._i);e._a=u([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ct(e)}}(t):a(l)?t._d=new Date(l):n.createFromInputFallback(t),f(e)||(e._d=null),e))}function Ot(e,t,n,r,a){var o,u={};return!0!==n&&!1!==n||(r=n,n=void 0),(i(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||s(e)&&0===e.length)&&(e=void 0),u._isAMomentObject=!0,u._useUTC=u._isUTC=a,u._l=n,u._i=e,u._f=t,u._strict=r,(o=new p(dt(Yt(u))))._nextDay&&(o.add(1,"d"),o._nextDay=void 0),o}function Tt(e,t,n,s){return Ot(e,t,n,s,!1)}n.createFromInputFallback=k("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),n.ISO_8601=function(){},n.RFC_2822=function(){};var xt=k("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=Tt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:m()}),bt=k("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=Tt.apply(null,arguments);return this.isValid()&&e.isValid()?e>this?this:e:m()});function Pt(e,t){var n,i;if(1===t.length&&s(t[0])&&(t=t[0]),!t.length)return Tt();for(n=t[0],i=1;i<t.length;++i)t[i].isValid()&&!t[i][e](n)||(n=t[i]);return n}var Wt=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=C(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,d=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Wt,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Wt.length;++s)if(e[Wt[s]]){if(n)return!1;parseFloat(e[Wt[s]])!==M(e[Wt[s]])&&(n=!0)}return!0}(t),this._milliseconds=+d+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=lt(),this._bubble()}function Rt(e){return e instanceof Ht}function Ct(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,t){I(e,0,0,function(){var e=this.utcOffset(),n="+";return e<0&&(e=-e,n="-"),n+U(~~(e/60),2)+t+U(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Ut(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Ut(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+M(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Nt(e,t){var s,i;return t._isUTC?(s=t.clone(),i=(v(e)||o(e)?e.valueOf():Tt(e).valueOf())-s.valueOf(),s._d.setTime(s._d.valueOf()+i),n.updateOffset(s,!1),s):Tt(e).local()}function Gt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Vt(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}n.updateOffset=function(){};var Et=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,It=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function At(e,t){var n,s,i,r=e,o=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:a(e)?(r={},t?r[t]=e:r.milliseconds=e):(o=Et.exec(e))?(n="-"===o[1]?-1:1,r={y:0,d:M(o[ye])*n,h:M(o[ge])*n,m:M(o[pe])*n,s:M(o[ve])*n,ms:M(Ct(1e3*o[we]))*n}):(o=It.exec(e))?(n="-"===o[1]?-1:(o[1],1),r={y:jt(o[2],n),M:jt(o[3],n),w:jt(o[4],n),d:jt(o[5],n),h:jt(o[6],n),m:jt(o[7],n),s:jt(o[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Nt(t,e),e.isBefore(t)?n=Zt(e,t):((n=Zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(Tt(r.from),Tt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&l(e,"_locale")&&(s._locale=e._locale),s}function jt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Zt(e,t){var n={milliseconds:0,months:0};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function zt(e,t){return function(n,s){var i;return null===s||isNaN(+s)||(T(t,"moment()."+t+"(period, number) is deprecated. Please use moment()."+t+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),i=n,n=s,s=i),$t(this,At(n="string"==typeof n?+n:n,s),e),this}}function $t(e,t,s,i){var r=t._milliseconds,a=Ct(t._days),o=Ct(t._months);e.isValid()&&(i=null==i||i,o&&Ce(e,xe(e,"Month")+o*s),a&&be(e,"Date",xe(e,"Date")+a*s),r&&e._d.setTime(e._d.valueOf()+r*s),i&&n.updateOffset(e,a||o))}At.fn=Ht.prototype,At.invalid=function(){return At(NaN)};var qt=zt(1,"add"),Jt=zt(-1,"subtract");function Bt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Qt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=lt(e))&&(this._locale=t),this)}n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xt=k("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function Kt(){return this._locale}function en(e,t){I(0,[e,e.length],0,t)}function tn(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:(t>(r=Ae(e,s,i))&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),en("gggg","weekYear"),en("ggggg","weekYear"),en("GGGG","isoWeekYear"),en("GGGGG","isoWeekYear"),H("weekYear","gg"),H("isoWeekYear","GG"),L("weekYear",1),L("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=M(e)}),fe(["gg","GG"],function(e,t,s,i){t[i]=n.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),H("quarter","Q"),L("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(M(e)-1)}),I("D",["DD",2],"Do","date"),H("date","D"),L("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=M(e.match(B)[0])});var nn=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),H("dayOfYear","DDD"),L("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=M(e)}),I("m",["mm",2],0,"minute"),H("minute","m"),L("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],pe);var sn=Te("Minutes",!1);I("s",["ss",2],0,"second"),H("second","s"),L("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],ve);var rn,an=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),H("millisecond","ms"),L("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),rn="SSSS";rn.length<=9;rn+="S")ue(rn,ne);function on(e,t){t[we]=M(1e3*("0."+e))}for(rn="S";rn.length<=9;rn+="S")ce(rn,on);var un=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var ln=p.prototype;function dn(e){return e}ln.add=qt,ln.calendar=function(e,t){var s=e||Tt(),i=Nt(s,this).startOf("day"),r=n.calendarFormat(this,i)||"sameElse",a=t&&(x(t[r])?t[r].call(this,s):t[r]);return this.format(a||this.localeData().calendar(r,this,Tt(s)))},ln.clone=function(){return new p(this)},ln.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Nt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=R(t)){case"year":r=Bt(this,s)/12;break;case"month":r=Bt(this,s);break;case"quarter":r=Bt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:w(r)},ln.endOf=function(e){return void 0===(e=R(e))||"millisecond"===e?this:("date"===e&&(e="day"),this.startOf(e).add(1,"isoWeek"===e?"week":e).subtract(1,"ms"))},ln.format=function(e){e||(e=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},ln.from=function(e,t){return this.isValid()&&(v(e)&&e.isValid()||Tt(e).isValid())?At({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},ln.fromNow=function(e){return this.from(Tt(),e)},ln.to=function(e,t){return this.isValid()&&(v(e)&&e.isValid()||Tt(e).isValid())?At({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},ln.toNow=function(e){return this.to(Tt(),e)},ln.get=function(e){return x(this[e=R(e)])?this[e]():this},ln.invalidAt=function(){return c(this).overflow},ln.isAfter=function(e,t){var n=v(e)?e:Tt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=R(r(t)?"millisecond":t))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},ln.isBefore=function(e,t){var n=v(e)?e:Tt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=R(r(t)?"millisecond":t))?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},ln.isBetween=function(e,t,n,s){return("("===(s=s||"()")[0]?this.isAfter(e,n):!this.isBefore(e,n))&&(")"===s[1]?this.isBefore(t,n):!this.isAfter(t,n))},ln.isSame=function(e,t){var n,s=v(e)?e:Tt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=R(t||"millisecond"))?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},ln.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},ln.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},ln.isValid=function(){return f(this)},ln.lang=Xt,ln.locale=Qt,ln.localeData=Kt,ln.max=bt,ln.min=xt,ln.parsingFlags=function(){return d({},c(this))},ln.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:F[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=C(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(x(this[e=R(e)]))return this[e](t);return this},ln.startOf=function(e){switch(e=R(e)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===e&&this.weekday(0),"isoWeek"===e&&this.isoWeekday(1),"quarter"===e&&this.month(3*Math.floor(this.month()/3)),this},ln.subtract=Jt,ln.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},ln.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},ln.toDate=function(){return new Date(this.valueOf())},ln.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||n.year()>9999?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):x(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},ln.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},ln.toJSON=function(){return this.isValid()?this.toISOString():null},ln.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},ln.unix=function(){return Math.floor(this.valueOf()/1e3)},ln.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},ln.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},ln.year=Oe,ln.isLeapYear=function(){return ke(this.year())},ln.weekYear=function(e){return tn.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},ln.isoWeekYear=function(e){return tn.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},ln.quarter=ln.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},ln.month=Fe,ln.daysInMonth=function(){return Pe(this.year(),this.month())},ln.week=ln.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},ln.isoWeek=ln.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},ln.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},ln.isoWeeksInYear=function(){return Ae(this.year(),1,4)},ln.date=nn,ln.day=ln.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},ln.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},ln.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=(n=e,s=this.localeData(),"string"==typeof n?s.weekdaysParse(n)%7||7:isNaN(n)?null:n);return this.day(this.day()%7?t:t-7)}return this.day()||7;var n,s},ln.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},ln.hour=ln.hours=tt,ln.minute=ln.minutes=sn,ln.second=ln.seconds=an,ln.millisecond=ln.milliseconds=un,ln.utcOffset=function(e,t,s){var i,r=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null!=e){if("string"==typeof e){if(null===(e=Ut(re,e)))return this}else Math.abs(e)<16&&!s&&(e*=60);return!this._isUTC&&t&&(i=Gt(this)),this._offset=e,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==e&&(!t||this._changeInProgress?$t(this,At(e-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,n.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Gt(this)},ln.utc=function(e){return this.utcOffset(0,e)},ln.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Gt(this),"m")),this},ln.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Ut(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},ln.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?Tt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},ln.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ln.isLocal=function(){return!!this.isValid()&&!this._isUTC},ln.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ln.isUtc=Vt,ln.isUTC=Vt,ln.zoneAbbr=function(){return this._isUTC?"UTC":""},ln.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ln.dates=k("dates accessor is deprecated. Use date instead.",nn),ln.months=k("months accessor is deprecated. Use month instead",Fe),ln.years=k("years accessor is deprecated. Use year instead",Oe),ln.zone=k("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),ln.isDSTShifted=k("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!r(this._isDSTShifted))return this._isDSTShifted;var e={};if(y(e,this),(e=Yt(e))._a){var t=e._isUTC?h(e._a):Tt(e._a);this._isDSTShifted=this.isValid()&&S(e._a,t.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var hn=P.prototype;function cn(e,t,n,s){var i=lt(),r=h().set(s,t);return i[n](r,e)}function fn(e,t,n){if(a(e)&&(t=e,e=void 0),e=e||"",null!=t)return cn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=cn(e,s,n,"month");return i}function mn(e,t,n,s){"boolean"==typeof e?(a(t)&&(n=t,t=void 0),t=t||""):(n=t=e,e=!1,a(t)&&(n=t,t=void 0),t=t||"");var i,r=lt(),o=e?r._week.dow:0;if(null!=n)return cn(t,(n+o)%7,s,"day");var u=[];for(i=0;i<7;i++)u[i]=cn(t,(i+o)%7,s,"day");return u}hn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return x(s)?s.call(t,n):s},hn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},hn.invalidDate=function(){return this._invalidDate},hn.ordinal=function(e){return this._ordinal.replace("%d",e)},hn.preparse=dn,hn.postformat=dn,hn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return x(i)?i(e,t,n,s):i.replace(/%d/i,e)},hn.pastFuture=function(e,t){var n=this._relativeTime[e>0?"future":"past"];return x(n)?n(t):n.replace(/%s/i,t)},hn.set=function(e){var t,n;for(n in e)x(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},hn.months=function(e,t){return e?s(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:s(this._months)?this._months:this._months.standalone},hn.monthsShort=function(e,t){return e?s(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:s(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},hn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=h([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=h([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},hn.monthsRegex=function(e){return this._monthsParseExact?(l(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(l(this,"_monthsRegex")||(this._monthsRegex=Ue),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},hn.monthsShortRegex=function(e){return this._monthsParseExact?(l(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(l(this,"_monthsShortRegex")||(this._monthsShortRegex=Le),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},hn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},hn.firstDayOfYear=function(){return this._week.doy},hn.firstDayOfWeek=function(){return this._week.dow},hn.weekdays=function(e,t){return e?s(this._weekdays)?this._weekdays[e.day()]:this._weekdays[this._weekdays.isFormat.test(t)?"format":"standalone"][e.day()]:s(this._weekdays)?this._weekdays:this._weekdays.standalone},hn.weekdaysMin=function(e){return e?this._weekdaysMin[e.day()]:this._weekdaysMin},hn.weekdaysShort=function(e){return e?this._weekdaysShort[e.day()]:this._weekdaysShort},hn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=h([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=h([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".",".?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},hn.weekdaysRegex=function(e){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(l(this,"_weekdaysRegex")||(this._weekdaysRegex=$e),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},hn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(l(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qe),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},hn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(l(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Je),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},hn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},hn.meridiem=function(e,t,n){return e>11?n?"pm":"PM":n?"am":"AM"},ot("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===M(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),n.lang=k("moment.lang is deprecated. Use moment.locale instead.",ot),n.langData=k("moment.langData is deprecated. Use moment.localeData instead.",lt);var _n=Math.abs;function yn(e,t,n,s){var i=At(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function gn(e){return e<0?Math.floor(e):Math.ceil(e)}function pn(e){return 4800*e/146097}function vn(e){return 146097*e/4800}function wn(e){return function(){return this.as(e)}}var Mn=wn("ms"),Sn=wn("s"),Dn=wn("m"),kn=wn("h"),Yn=wn("d"),On=wn("w"),Tn=wn("M"),xn=wn("y");function bn(e){return function(){return this.isValid()?this._data[e]:NaN}}var Pn=bn("milliseconds"),Wn=bn("seconds"),Hn=bn("minutes"),Rn=bn("hours"),Cn=bn("days"),Fn=bn("months"),Ln=bn("years");var Un=Math.round,Nn={ss:44,s:45,m:45,h:22,d:26,M:11};var Gn=Math.abs;function Vn(e){return(e>0)-(e<0)||+e}function En(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Gn(this._milliseconds)/1e3,s=Gn(this._days),i=Gn(this._months);t=w((e=w(n/60))/60),n%=60,e%=60;var r=w(i/12),a=i%=12,o=s,u=t,l=e,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=Vn(this._months)!==Vn(h)?"-":"",m=Vn(this._days)!==Vn(h)?"-":"",_=Vn(this._milliseconds)!==Vn(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||d?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(d?_+d+"S":"")}var In=Ht.prototype;return In.isValid=function(){return this._isValid},In.abs=function(){var e=this._data;return this._milliseconds=_n(this._milliseconds),this._days=_n(this._days),this._months=_n(this._months),e.milliseconds=_n(e.milliseconds),e.seconds=_n(e.seconds),e.minutes=_n(e.minutes),e.hours=_n(e.hours),e.months=_n(e.months),e.years=_n(e.years),this},In.add=function(e,t){return yn(this,e,t,1)},In.subtract=function(e,t){return yn(this,e,t,-1)},In.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=R(e))||"year"===e)return t=this._days+s/864e5,n=this._months+pn(t),"month"===e?n:n/12;switch(t=this._days+Math.round(vn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},In.asMilliseconds=Mn,In.asSeconds=Sn,In.asMinutes=Dn,In.asHours=kn,In.asDays=Yn,In.asWeeks=On,In.asMonths=Tn,In.asYears=xn,In.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*M(this._months/12):NaN},In._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return r>=0&&a>=0&&o>=0||r<=0&&a<=0&&o<=0||(r+=864e5*gn(vn(o)+a),a=0,o=0),u.milliseconds=r%1e3,e=w(r/1e3),u.seconds=e%60,t=w(e/60),u.minutes=t%60,n=w(t/60),u.hours=n%24,o+=i=w(pn(a+=w(n/24))),a-=gn(vn(i)),s=w(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},In.clone=function(){return At(this)},In.get=function(e){return e=R(e),this.isValid()?this[e+"s"]():NaN},In.milliseconds=Pn,In.seconds=Wn,In.minutes=Hn,In.hours=Rn,In.days=Cn,In.weeks=function(){return w(this.days()/7)},In.months=Fn,In.years=Ln,In.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,d,h,c=this.localeData(),f=(n=!e,s=c,i=At(t=this).abs(),r=Un(i.as("s")),a=Un(i.as("m")),o=Un(i.as("h")),u=Un(i.as("d")),l=Un(i.as("M")),d=Un(i.as("y")),(h=r<=Nn.ss&&["s",r]||r<Nn.s&&["ss",r]||a<=1&&["m"]||a<Nn.m&&["mm",a]||o<=1&&["h"]||o<Nn.h&&["hh",o]||u<=1&&["d"]||u<Nn.d&&["dd",u]||l<=1&&["M"]||l<Nn.M&&["MM",l]||d<=1&&["y"]||["yy",d])[2]=n,h[3]=+t>0,h[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,h));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},In.toISOString=En,In.toString=En,In.toJSON=En,In.locale=Qt,In.localeData=Kt,In.toIsoString=k("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",En),In.lang=Xt,I("X",0,0,"
2743unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(M(e))}),n.version="2.21.0",e=Tt,n.fn=ln,n.min=function(){return Pt("isBefore",[].slice.call(arguments,0))},n.max=function(){return Pt("isAfter",[].slice.call(arguments,0))},n.now=function(){return Date.now?Date.now():+new Date},n.utc=h,n.unix=function(e){return Tt(1e3*e)},n.months=function(e,t){return fn(e,t,"months")},n.isDate=o,n.locale=ot,n.invalid=m,n.duration=At,n.isMoment=v,n.weekdays=function(e,t,n){return mn(e,t,n,"weekdays")},n.parseZone=function(){return Tt.apply(null,arguments).parseZone()},n.localeData=lt,n.isDuration=Rt,n.monthsShort=function(e,t){return fn(e,t,"monthsShort")},n.weekdaysMin=function(e,t,n){return mn(e,t,n,"weekdaysMin")},n.defineLocale=ut,n.updateLocale=function(e,t){if(null!=t){var n,s,i=nt;null!=(s=at(e))&&(i=s._config),(n=new P(t=b(i,t))).parentLocale=st[e],st[e]=n,ot(e)}else null!=st[e]&&(null!=st[e].parentLocale?st[e]=st[e].parentLocale:null!=st[e]&&delete st[e]);return st[e]},n.locales=function(){return Y(st)},n.weekdaysShort=function(e,t,n){return mn(e,t,n,"weekdaysShort")},n.normalizeUnits=R,n.relativeTimeRounding=function(e){return void 0===e?Un:"function"==typeof e&&(Un=e,!0)},n.relativeTimeThreshold=function(e,t){return void 0!==Nn[e]&&(void 0===t?Nn[e]:(Nn[e]=t,"s"===e&&(Nn.ss=t-1),!0))},n.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},n.prototype=ln,n.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"YYYY-[W]WW",MONTH:"YYYY-MM"},n});
2744/*!
2745 * FullCalendar v3.9.0
2746 * Docs & License: https://fullcalendar.io/
2747 * (c) 2018 Adam Shaw
2748 */
2749!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("moment"),require("jquery")):"function"==typeof define&&define.amd?define(["moment","jquery"],e):"object"==typeof exports?exports.FullCalendar=e(require("moment"),require("jquery")):t.FullCalendar=e(t.moment,t.jQuery)}("undefined"!=typeof self?self:this,function(t,e){return function(t){function e(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=236)}([function(e,n){e.exports=t},,function(t,e){var n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])};e.__extends=function(t,e){function i(){this.constructor=t}n(t,e),t.prototype=null===e?Object.create(e):(i.prototype=e.prototype,new i)}},function(t,n){t.exports=e},function(t,e,n){function i(t,e){e.left&&t.css({"border-left-width":1,"margin-left":e.left-1}),e.right&&t.css({"border-right-width":1,"margin-right":e.right-1})}function r(t){t.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function o(){ht("body").addClass("fc-not-allowed")}function s(){ht("body").removeClass("fc-not-allowed")}function a(t,e,n){var i=Math.floor(e/t.length),r=Math.floor(e-i*(t.length-1)),o=[],s=[],a=[],u=0;l(t),t.each(function(e,n){var l=e===t.length-1?r:i,d=ht(n).outerHeight(!0);d<l?(o.push(n),s.push(d),a.push(ht(n).height())):u+=d}),n&&(e-=u,i=Math.floor(e/o.length),r=Math.floor(e-i*(o.length-1))),ht(o).each(function(t,e){var n=t===o.length-1?r:i,l=s[t],u=a[t],d=n-(l-u);l<n&&ht(e).height(d)})}function l(t){t.height("")}function u(t){var e=0;return t.find("> *").each(function(t,n){var i=ht(n).outerWidth();i>e&&(e=i)}),e++,t.width(e),e}function d(t,e){var n,i=t.add(e);return i.css({position:"relative",left:-1}),n=t.outerHeight()-e.outerHeight(),i.css({position:"",left:""}),n}function c(t){var e=t.css("position"),n=t.parents().filter(function(){var t=ht(this);return/(auto|scroll)/.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==e&&n.length?n:ht(t[0].ownerDocument||document)}function p(t,e){var n=t.offset(),i=n.left-(e?e.left:0),r=n.top-(e?e.top:0);return{left:i,right:i+t.outerWidth(),top:r,bottom:r+t.outerHeight()}}function h(t,e){var n=t.offset(),i=g(t),r=n.left+b(t,"border-left-width")+i.left-(e?e.left:0),o=n.top+b(t,"border-top-width")+i.top-(e?e.top:0);return{left:r,right:r+t[0].clientWidth,top:o,bottom:o+t[0].clientHeight}}function f(t,e){var n=t.offset(),i=n.left+b(t,"border-left-width")+b(t,"padding-left")-(e?e.left:0),r=n.top+b(t,"border-top-width")+b(t,"padding-top")-(e?e.top:0);return{left:i,right:i+t.width(),top:r,bottom:r+t.height()}}function g(t){var e,n=t[0].offsetWidth-t[0].clientWidth,i=t[0].offsetHeight-t[0].clientHeight;return n=v(n),i=v(i),e={left:0,right:0,top:0,bottom:i},y()&&"rtl"===t.css("direction")?e.left=n:e.right=n,e}function v(t){return t=Math.max(0,t),t=Math.round(t)}function y(){return null===ft&&(ft=m()),ft}function m(){var t=ht("<div><div/></div>").css({position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}).appendTo("body"),e=t.children(),n=e.offset().left>t.offset().left;return t.remove(),n}function b(t,e){return parseFloat(t.css(e))||0}function w(t){return 1===t.which&&!t.ctrlKey}function D(t){var e=t.originalEvent.touches;return e&&e.length?e[0].pageX:t.pageX}function E(t){var e=t.originalEvent.touches;return e&&e.length?e[0].pageY:t.pageY}function S(t){return/^touch/.test(t.type)}function C(t){t.addClass("fc-unselectable").on("selectstart",T)}function R(t){t.removeClass("fc-unselectable").off("selectstart",T)}function T(t){t.preventDefault()}function M(t,e){var n={left:Math.max(t.left,e.left),right:Math.min(t.right,e.right),top:Math.max(t.top,e.top),bottom:Math.min(t.bottom,e.bottom)};return n.left<n.right&&n.top<n.bottom&&n}function I(t,e){return{left:Math.min(Math.max(t.left,e.left),e.right),top:Math.min(Math.max(t.top,e.top),e.bottom)}}function H(t){return{left:(t.left+t.right)/2,top:(t.top+t.bottom)/2}}function P(t,e){return{left:t.left-e.left,top:t.top-e.top}}function _(t){var e,n,i=[],r=[];for("string"==typeof t?r=t.split(/\s*,\s*/):"function"==typeof t?r=[t]:ht.isArray(t)&&(r=t),e=0;e<r.length;e++)n=r[e],"string"==typeof n?i.push("-"===n.charAt(0)?{field:n.substring(1),order:-1}:{field:n,order:1}):"function"==typeof n&&i.push({func:n});return i}function x(t,e,n,i,r){var o,s;for(o=0;o<n.length;o++)if(s=O(t,e,n[o],i,r))return s;return 0}function O(t,e,n,i,r){if(n.func)return n.func(t,e);var o=t[n.field],s=e[n.field];return null==o&&i&&(o=i[n.field]),null==s&&r&&(s=r[n.field]),F(o,s)*(n.order||1)}function F(t,e){return t||e?null==e?-1:null==t?1:"string"===ht.type(t)||"string"===ht.type(e)?String(t).localeCompare(String(e)):t-e:0}function z(t,e){return pt.duration({days:t.clone().stripTime().diff(e.clone().stripTime(),"days"),ms:t.time()-e.time()})}function B(t,e){return pt.duration({days:t.clone().stripTime().diff(e.clone().stripTime(),"days")})}function A(t,e,n){return pt.duration(Math.round(t.diff(e,n,!0)),n)}function k(t,n){var i,r,o;for(i=0;i<e.unitsDesc.length&&(r=e.unitsDesc[i],!((o=V(r,t,n))>=1&&ut(o)));i++);return r}function L(t,e){var n=k(t);return"week"===n&&"object"==typeof e&&e.days&&(n="day"),n}function V(t,e,n){return null!=n?n.diff(e,t,!0):pt.isDuration(e)?e.as(t):e.end.diff(e.start,t,!0)}function G(t,e,n){var i;return U(n)?(e-t)/n:(i=n.asMonths(),Math.abs(i)>=1&&ut(i)?e.diff(t,"months",!0)/i:e.diff(t,"days",!0)/n.asDays())}function N(t,e){var n,i;return U(t)||U(e)?t/e:(n=t.asMonths(),i=e.asMonths(),Math.abs(n)>=1&&ut(n)&&Math.abs(i)>=1&&ut(i)?n/i:t.asDays()/e.asDays())}function j(t,e){var n;return U(t)?pt.duration(t*e):(n=t.asMonths(),Math.abs(n)>=1&&ut(n)?pt.duration({months:n*e}):pt.duration({days:t.asDays()*e}))}function U(t){return Boolean(t.hours()||t.minutes()||t.seconds()||t.milliseconds())}function W(t){return"[object Date]"===Object.prototype.toString.call(t)||t instanceof Date}function q(t){return"string"==typeof t&&/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(t)}function Y(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=window.console;if(n&&n.log)return n.log.apply(n,t)}function Z(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=window.console;return n&&n.warn?n.warn.apply(n,t):Y.apply(null,t)}function Q(t,e){var n,i,r,o,s,a,l={};if(e)for(n=0;n<e.length;n++){for(i=e[n],r=[],o=t.length-1;o>=0;o--)if("object"==typeof(s=t[o][i]))r.unshift(s);else if(void 0!==s){l[i]=s;break}r.length&&(l[i]=Q(r))}for(n=t.length-1;n>=0;n--){a=t[n];for(i in a)i in l||(l[i]=a[i])}return l}function X(t,e){for(var n in t)$(t,n)&&(e[n]=t[n])}function $(t,e){return gt.call(t,e)}function K(t,e,n){if(ht.isFunction(t)&&(t=[t]),t){var i=void 0,r=void 0;for(i=0;i<t.length;i++)r=t[i].apply(e,n)||r;return r}}function J(t,e){for(var n=0,i=0;i<t.length;)e(t[i])?(t.splice(i,1),n++):i++;return n}function tt(t,e){for(var n=0,i=0;i<t.length;)t[i]===e?(t.splice(i,1),n++):i++;return n}function et(t,e){var n,i=t.length;if(null==i||i!==e.length)return!1;for(n=0;n<i;n++)if(t[n]!==e[n])return!1;return!0}function nt(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];for(var n=0;n<t.length;n++)if(void 0!==t[n])return t[n]}function it(t){return(t+"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/'/g,"&#039;").replace(/"/g,"&quot;").replace(/\n/g,"<br />")}function rt(t){return t.replace(/&.*?;/g,"")}function ot(t){var e=[];return ht.each(t,function(t,n){null!=n&&e.push(t+":"+n)}),e.join(";")}function st(t){var e=[];return ht.each(t,function(t,n){null!=n&&e.push(t+'="'+it(n)+'"')}),e.join(" ")}function at(t){return t.charAt(0).toUpperCase()+t.slice(1)}function lt(t,e){return t-e}function ut(t){return t%1==0}function dt(t,e){var n=t[e];return function(){return n.apply(t,arguments)}}function ct(t,e,n){void 0===n&&(n=!1);var i,r,o,s,a,l=function(){var u=+new Date-s;u<e?i=setTimeout(l,e-u):(i=null,n||(a=t.apply(o,r),o=r=null))};return function(){o=this,r=arguments,s=+new Date;var u=n&&!i;
2749return i||(i=setTimeout(l,e)),u&&(a=t.apply(o,r),o=r=null),a}}Object.defineProperty(e,"__esModule",{value:!0});var pt=n(0),ht=n(3);e.compensateScroll=i,e.uncompensateScroll=r,e.disableCursor=o,e.enableCursor=s,e.distributeHeight=a,e.undistributeHeight=l,e.matchCellWidths=u,e.subtractInnerElHeight=d,e.getScrollParent=c,e.getOuterRect=p,e.getClientRect=h,e.getContentRect=f,e.getScrollbarWidths=g;var ft=null;e.isPrimaryMouseButton=w,e.getEvX=D,e.getEvY=E,e.getEvIsTouch=S,e.preventSelection=C,e.allowSelection=R,e.preventDefault=T,e.intersectRects=M,e.constrainPoint=I,e.getRectCenter=H,e.diffPoints=P,e.parseFieldSpecs=_,e.compareByFieldSpecs=x,e.compareByFieldSpec=O,e.flexibleCompare=F,e.dayIDs=["sun","mon","tue","wed","thu","fri","sat"],e.unitsDesc=["year","month","week","day","hour","minute","second","millisecond"],e.diffDayTime=z,e.diffDay=B,e.diffByUnit=A,e.computeGreatestUnit=k,e.computeDurationGreatestUnit=L,e.divideRangeByDuration=G,e.divideDurationByDuration=N,e.multiplyDuration=j,e.durationHasTime=U,e.isNativeDate=W,e.isTimeString=q,e.log=Y,e.warn=Z;var gt={}.hasOwnProperty;e.mergeProps=Q,e.copyOwnProps=X,e.hasOwnProp=$,e.applyAll=K,e.removeMatching=J,e.removeExact=tt,e.isArraysEqual=et,e.firstDefined=nt,e.htmlEscape=it,e.stripHtmlEntities=rt,e.cssToStr=ot,e.attrsToStr=st,e.capitaliseFirstLetter=at,e.compareNumbers=lt,e.isInt=ut,e.proxy=dt,e.debounce=ct},function(t,e,n){function i(t,e){return t.startMs-e.startMs}Object.defineProperty(e,"__esModule",{value:!0});var r=n(0),o=n(10),s=function(){function t(t,e){this.isStart=!0,this.isEnd=!0,r.isMoment(t)&&(t=t.clone().stripZone()),r.isMoment(e)&&(e=e.clone().stripZone()),t&&(this.startMs=t.valueOf()),e&&(this.endMs=e.valueOf())}return t.invertRanges=function(e,n){var r,o,s=[],a=n.startMs;for(e.sort(i),r=0;r<e.length;r++)o=e[r],o.startMs>a&&s.push(new t(a,o.startMs)),o.endMs>a&&(a=o.endMs);return a<n.endMs&&s.push(new t(a,n.endMs)),s},t.prototype.intersect=function(e){var n=this.startMs,i=this.endMs,r=null;return null!=e.startMs&&(n=null==n?e.startMs:Math.max(n,e.startMs)),null!=e.endMs&&(i=null==i?e.endMs:Math.min(i,e.endMs)),(null==n||null==i||n<i)&&(r=new t(n,i),r.isStart=this.isStart&&n===this.startMs,r.isEnd=this.isEnd&&i===this.endMs),r},t.prototype.intersectsWith=function(t){return(null==this.endMs||null==t.startMs||this.endMs>t.startMs)&&(null==this.startMs||null==t.endMs||this.startMs<t.endMs)},t.prototype.containsRange=function(t){return(null==this.startMs||null!=t.startMs&&t.startMs>=this.startMs)&&(null==this.endMs||null!=t.endMs&&t.endMs<=this.endMs)},t.prototype.containsDate=function(t){var e=t.valueOf();return(null==this.startMs||e>=this.startMs)&&(null==this.endMs||e<this.endMs)},t.prototype.constrainDate=function(t){var e=t.valueOf();return null!=this.startMs&&e<this.startMs&&(e=this.startMs),null!=this.endMs&&e>=this.endMs&&(e=this.endMs-1),e},t.prototype.equals=function(t){return this.startMs===t.startMs&&this.endMs===t.endMs},t.prototype.clone=function(){var e=new t(this.startMs,this.endMs);return e.isStart=this.isStart,e.isEnd=this.isEnd,e},t.prototype.getStart=function(){return null!=this.startMs?o.default.utc(this.startMs).stripZone():null},t.prototype.getEnd=function(){return null!=this.endMs?o.default.utc(this.endMs).stripZone():null},t.prototype.as=function(t){return r.utc(this.endMs).diff(r.utc(this.startMs),t,!0)},t}();e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(208),s=n(33),a=n(49),l=function(t){function e(n){var i=t.call(this)||this;return i.calendar=n,i.className=[],i.uid=String(e.uuid++),i}return i.__extends(e,t),e.parse=function(t,e){var n=new this(e);return!("object"!=typeof t||!n.applyProps(t))&&n},e.normalizeId=function(t){return t?String(t):null},e.prototype.fetch=function(t,e,n){},e.prototype.removeEventDefsById=function(t){},e.prototype.removeAllEventDefs=function(){},e.prototype.getPrimitive=function(t){},e.prototype.parseEventDefs=function(t){var e,n,i=[];for(e=0;e<t.length;e++)(n=this.parseEventDef(t[e]))&&i.push(n);return i},e.prototype.parseEventDef=function(t){var e=this.calendar.opt("eventDataTransform"),n=this.eventDataTransform;return e&&(t=e(t,this.calendar)),n&&(t=n(t,this.calendar)),a.default.parse(t,this)}
2749,e.prototype.applyManualStandardProps=function(t){return null!=t.id&&(this.id=e.normalizeId(t.id)),r.isArray(t.className)?this.className=t.className:"string"==typeof t.className&&(this.className=t.className.split(/\s+/)),!0},e.uuid=0,e.defineStandardProps=o.default.defineStandardProps,e.copyVerbatimStandardProps=o.default.copyVerbatimStandardProps,e}(s.default);e.default=l,o.default.mixInto(l),l.defineStandardProps({id:!1,className:!1,color:!0,backgroundColor:!0,borderColor:!0,textColor:!0,editable:!0,startEditable:!0,durationEditable:!0,rendering:!0,overlap:!0,constraint:!0,allDayDefault:!0,eventDataTransform:!0})},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(14),s=0,a=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.listenTo=function(t,e,n){if("object"==typeof e)for(var i in e)e.hasOwnProperty(i)&&this.listenTo(t,i,e[i]);else"string"==typeof e&&t.on(e+"."+this.getListenerNamespace(),r.proxy(n,this))},e.prototype.stopListeningTo=function(t,e){t.off((e||"")+"."+this.getListenerNamespace())},e.prototype.getListenerNamespace=function(){return null==this.listenerId&&(this.listenerId=s++),"_listener"+this.listenerId},e}(o.default);e.default=a},,,function(t,e,n){function i(t,e){return c.format.call(t,e)}function r(t,e,n){void 0===e&&(e=!1),void 0===n&&(n=!1);var i,r,d,c,p=t[0],h=1===t.length&&"string"==typeof p;return o.isMoment(p)||a.isNativeDate(p)||void 0===p?c=o.apply(null,t):(i=!1,r=!1,h?l.test(p)?(p+="-01",t=[p],i=!0,r=!0):(d=u.exec(p))&&(i=!d[5],r=!0):s.isArray(p)&&(r=!0),c=e||i?o.utc.apply(o,t):o.apply(null,t),i?(c._ambigTime=!0,c._ambigZone=!0):n&&(r?c._ambigZone=!0:h&&c.utcOffset(p))),c._fullCalendar=!0,c}Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),s=n(3),a=n(4),l=/^\s*\d{4}-\d\d$/,u=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/,d=o.fn;e.newMomentProto=d;var c=s.extend({},d);e.oldMomentProto=c;var p=o.momentProperties;p.push("_fullCalendar"),p.push("_ambigTime"),p.push("_ambigZone"),e.oldMomentFormat=i;var h=function(){return r(arguments)};e.default=h,h.utc=function(){var t=r(arguments,!0);return t.hasTime()&&t.utc(),t},h.parseZone=function(){return r(arguments,!0,!0)},d.week=d.weeks=function(t){var e=this._locale._fullCalendar_weekCalc;return null==t&&"function"==typeof e?e(this):"ISO"===e?c.isoWeek.apply(this,arguments):c.week.apply(this,arguments)},d.time=function(t){if(!this._fullCalendar)return c.time.apply(this,arguments);if(null==t)return o.duration({hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()});this._ambigTime=!1,o.isDuration(t)||o.isMoment(t)||(t=o.duration(t));var e=0;return o.isDuration(t)&&(e=24*Math.floor(t.asDays())),this.hours(e+t.hours()).minutes(t.minutes()).seconds(t.seconds()).milliseconds(t.milliseconds())},d.stripTime=function(){return this._ambigTime||(this.utc(!0),this.set({hours:0,minutes:0,seconds:0,ms:0}),this._ambigTime=!0,this._ambigZone=!0),this},d.hasTime=function(){return!this._ambigTime},d.stripZone=function(){var t;return this._ambigZone||(t=this._ambigTime,this.utc(!0),this._ambigTime=t||!1,this._ambigZone=!0),this},d.hasZone=function(){return!this._ambigZone},d.local=function(t){return c.local.call(this,this._ambigZone||t),this._ambigTime=!1,this._ambigZone=!1,this},d.utc=function(t){return c.utc.call(this,t),this._ambigTime=!1,this._ambigZone=!1,this},d.utcOffset=function(t){return null!=t&&(this._ambigTime=!1,this._ambigZone=!1),c.utcOffset.apply(this,arguments)}},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(14),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.on=function(t,e){return r(this).on(t,this._prepareIntercept(e)),this},e.prototype.one=function(t,e){return r(this).one(t,this._prepareIntercept(e)),this},e.prototype._prepareIntercept=function(t){var e=function(e,n){return t.apply(n.context||this,n.args||[])};return t.guid||(t.guid=r.guid++),e.guid=t.guid,e},e.prototype.off=function(t,e){return r(this).off(t,e),this},e.prototype.trigger=function(t){for(var e=[],n=1;n<arguments.length;n++)e[n-1]=arguments[n];return r(this).triggerHandler(t,{args:e}),this},e.prototype.triggerWith=function(t,e,n){return r(this).triggerHandler(t,{context:e,args:n}),this},e.prototype.hasHandlers=function(t){var e=r._data(this,"events");return e&&e[t]&&e[t].length>0},e}(o.default);e.default=s}
2749,function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t,e){this.isAllDay=!1,this.unzonedRange=t,this.isAllDay=e}return t.prototype.toLegacy=function(t){return{start:t.msToMoment(this.unzonedRange.startMs,this.isAllDay),end:t.msToMoment(this.unzonedRange.endMs,this.isAllDay)}},t}();e.default=n},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(34),o=n(209),s=n(17),a=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.buildInstances=function(){return[this.buildInstance()]},e.prototype.buildInstance=function(){return new o.default(this,this.dateProfile)},e.prototype.isAllDay=function(){return this.dateProfile.isAllDay()},e.prototype.clone=function(){var e=t.prototype.clone.call(this);return e.dateProfile=this.dateProfile,e},e.prototype.rezone=function(){var t=this.source.calendar,e=this.dateProfile;this.dateProfile=new s.default(t.moment(e.start),e.end?t.moment(e.end):null,t)},e.prototype.applyManualStandardProps=function(e){var n=t.prototype.applyManualStandardProps.call(this,e),i=s.default.parse(e,this.source);return!!i&&(this.dateProfile=i,null!=e.date&&(this.miscProps.date=e.date),n)},e}(r.default);e.default=a,a.defineStandardProps({start:!1,date:!1,end:!1,allDay:!1})},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(){}return t.mixInto=function(t){var e=this;Object.getOwnPropertyNames(this.prototype).forEach(function(n){t.prototype[n]||(t.prototype[n]=e.prototype[n])})},t.mixOver=function(t){var e=this;Object.getOwnPropertyNames(this.prototype).forEach(function(n){t.prototype[n]=e.prototype[n]})},t}();e.default=n},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t){this.view=t._getView(),this.component=t}return t.prototype.opt=function(t){return this.view.opt(t)},t.prototype.end=function(){},t}();e.default=n},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0}),e.version="3.9.0",e.internalApiVersion=12;var i=n(4);e.applyAll=i.applyAll,e.debounce=i.debounce,e.isInt=i.isInt,e.htmlEscape=i.htmlEscape,e.cssToStr=i.cssToStr,e.proxy=i.proxy,e.capitaliseFirstLetter=i.capitaliseFirstLetter,e.getOuterRect=i.getOuterRect,e.getClientRect=i.getClientRect,e.getContentRect=i.getContentRect,e.getScrollbarWidths=i.getScrollbarWidths,e.preventDefault=i.preventDefault,e.parseFieldSpecs=i.parseFieldSpecs,e.compareByFieldSpecs=i.compareByFieldSpecs,e.compareByFieldSpec=i.compareByFieldSpec,e.flexibleCompare=i.flexibleCompare,e.computeGreatestUnit=i.computeGreatestUnit,e.divideRangeByDuration=i.divideRangeByDuration,e.divideDurationByDuration=i.divideDurationByDuration,e.multiplyDuration=i.multiplyDuration,e.durationHasTime=i.durationHasTime,e.log=i.log,e.warn=i.warn,e.removeExact=i.removeExact,e.intersectRects=i.intersectRects;var r=n(47);e.formatDate=r.formatDate,e.formatRange=r.formatRange,e.queryMostGranularFormatUnit=r.queryMostGranularFormatUnit;var o=n(31);e.datepickerLocale=o.datepickerLocale,e.locale=o.locale;var s=n(10);e.moment=s.default;var a=n(11);e.EmitterMixin=a.default;var l=n(7);e.ListenerMixin=l.default;var u=n(48);e.Model=u.default;var d=n(207);e.Constraints=d.default;var c=n(5);e.UnzonedRange=c.default;var p=n(12);e.ComponentFootprint=p.default;var h=n(212);e.BusinessHourGenerator=h.default;var f=n(34);e.EventDef=f.default;var g=n(37);e.EventDefMutation=g.default;var v=n(38);e.EventSourceParser=v.default;var y=n(6);e.EventSource=y.default;var m=n(51);e.defineThemeSystem=m.defineThemeSystem;var b=n(18);e.EventInstanceGroup=b.default;var w=n(52);e.ArrayEventSource=w.default;var D=n(215);e.FuncEventSource=D.default;var E=n(216);e.JsonFeedEventSource=E.default;var S=n(36);e.EventFootprint=S.default;var C=n(33);e.Class=C.default;var R=n(14);e.Mixin=R.default;var T=n(53);e.CoordCache=T.default;var M=n(54);e.DragListener=M.default;var I=n(20);e.Promise=I.default;var H=n(217);e.TaskQueue=H.default;var P=n(218);e.RenderQueue=P.default;var _=n(39);e.Scroller=_.default;var x=n(19);e.Theme=x.default;var O=n(219);e.DateComponent=O.default;var F=n(40);e.InteractiveDateComponent=F.default;var z=n(220);e.Calendar=z.default;var B=n(41);e.View=B.default;var A=n(22);e.defineView=A.defineView,e.getViewConfig=A.getViewConfig;var k=n(55);e.DayTableMixin=k.default;var L=n(56);e.BusinessHourRenderer=L.default;var V=n(42);e.EventRenderer=V.default;var G=n(57);e.FillRenderer=G.default;var N=n(58);e.HelperRenderer=N.default;var j=n(222);e.ExternalDropping=j.default;var U=n(223);e.EventResizing=U.default;var W=n(59);e.EventPointing=W.default;var q=n(224);e.EventDragging=q.default;var Y=n(225);e.DateSelecting=Y.default;var Z=n(60);e.StandardInteractionsMixin=Z.default;var Q=n(226);e.AgendaView=Q.default;var X=n(227);e.TimeGrid=X.default;var $=n(61);e.DayGrid=$.default;var K=n(62);e.BasicView=K.default;var J=n(229);e.MonthView=J.default;var tt=n(230);e.ListView=tt.default}
2749,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),r=function(){function t(t,e,n){this.start=t,this.end=e||null,this.unzonedRange=this.buildUnzonedRange(n)}return t.parse=function(e,n){var i=e.start||e.date,r=e.end;if(!i)return!1;var o=n.calendar,s=o.moment(i),a=r?o.moment(r):null,l=e.allDay,u=o.opt("forceEventDuration");return!!s.isValid()&&(!a||a.isValid()&&a.isAfter(s)||(a=null),null==l&&null==(l=n.allDayDefault)&&(l=o.opt("allDayDefault")),!0===l?(s.stripTime(),a&&a.stripTime()):!1===l&&(s.hasTime()||s.time(0),a&&!a.hasTime()&&a.time(0)),!a&&u&&(a=o.getDefaultEventEnd(!s.hasTime(),s)),new t(s,a,o))},t.isStandardProp=function(t){return"start"===t||"date"===t||"end"===t||"allDay"===t},t.prototype.isAllDay=function(){return!(this.start.hasTime()||this.end&&this.end.hasTime())},t.prototype.buildUnzonedRange=function(t){var e=this.start.clone().stripZone().valueOf(),n=this.getEnd(t).stripZone().valueOf();return new i.default(e,n)},t.prototype.getEnd=function(t){return this.end?this.end.clone():t.getDefaultEventEnd(this.isAllDay(),this.start)},t}();e.default=r},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),r=n(35),o=n(211),s=function(){function t(t){this.eventInstances=t||[]}return t.prototype.getAllEventRanges=function(t){return t?this.sliceNormalRenderRanges(t):this.eventInstances.map(r.eventInstanceToEventRange)},t.prototype.sliceRenderRanges=function(t){return this.isInverse()?this.sliceInverseRenderRanges(t):this.sliceNormalRenderRanges(t)},t.prototype.sliceNormalRenderRanges=function(t){var e,n,i,r=this.eventInstances,s=[];for(e=0;e<r.length;e++)n=r[e],(i=n.dateProfile.unzonedRange.intersect(t))&&s.push(new o.default(i,n.def,n));return s},t.prototype.sliceInverseRenderRanges=function(t){var e=this.eventInstances.map(r.eventInstanceToUnzonedRange),n=this.getEventDef();return e=i.default.invertRanges(e,t),e.map(function(t){return new o.default(t,n)})},t.prototype.isInverse=function(){return this.getEventDef().hasInverseRendering()},t.prototype.getEventDef=function(){return this.explicitEventDef||this.eventInstances[0].def},t}();e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=function(){function t(t){this.optionsManager=t,this.processIconOverride()}return t.prototype.processIconOverride=function(){this.iconOverrideOption&&this.setIconOverride(this.optionsManager.get(this.iconOverrideOption))},t.prototype.setIconOverride=function(t){var e,n;if(i.isPlainObject(t)){e=i.extend({},this.iconClasses);for(n in t)e[n]=this.applyIconOverridePrefix(t[n]);this.iconClasses=e}else!1===t&&(this.iconClasses={})},t.prototype.applyIconOverridePrefix=function(t){var e=this.iconOverridePrefix;return e&&0!==t.indexOf(e)&&(t=e+t),t},t.prototype.getClass=function(t){return this.classes[t]||""},t.prototype.getIconClass=function(t){var e=this.iconClasses[t];return e?this.baseIconClass+" "+e:""},t.prototype.getCustomButtonIconClass=function(t){var e;return this.iconOverrideCustomButtonOption&&(e=t[this.iconOverrideCustomButtonOption])?this.baseIconClass+" "+this.applyIconOverridePrefix(e):""},t}();e.default=r,r.prototype.classes={},r.prototype.iconClasses={},r.prototype.baseIconClass="",r.prototype.iconOverridePrefix=""},function(t,e,n){function i(t,e){t.then=function(n){return"function"==typeof n?s.resolve(n(e)):t}}function r(t){t.then=function(e,n){return"function"==typeof n&&n(),t}}Object.defineProperty(e,"__esModule",{value:!0});var o=n(3),s={construct:function(t){var e=o.Deferred(),n=e.promise();return"function"==typeof t&&t(function(t){e.resolve(t),i(n,t)},function(){e.reject(),r(n)}),n},resolve:function(t){var e=o.Deferred().resolve(t),n=e.promise();return i(n,t),n},reject:function(){var t=o.Deferred().reject(),e=t.promise();return r(e),e}};e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(16),o=n(11),s=n(7);r.touchMouseIgnoreWait=500;var a=null,l=0,u=function(){function t(){this.isTouching=!1,this.mouseIgnoreDepth=0}return t.get=function(){return a||(a=new t,a.bind()),a},t.needed=function(){t.get(),l++},t.unneeded=function(){--l||(a.unbind(),a=null)},t.prototype.bind=function(){var t=this;this.listenTo(i(document),{touchstart:this.handleTouchStart,touchcancel:this.handleTouchCancel,touchend:this.handleTouchEnd,mousedown:this.handleMouseDown,mousemove:this.handleMouseMove,mouseup:this.handleMouseUp,click:this.handleClick,selectstart:this.handleSelectStart,contextmenu:this.handleContextMenu}),window.addEventListener("touchmove",this.handleTouchMoveProxy=function(e){t.handleTouchMove(i.Event(e))},{passive:!1}),window.addEventListener("scroll",this.handleScrollProxy=function(e){t.handleScroll(i.Event(e))},!0)},t.prototype.unbind=function(){this.stopListeningTo(i(document)),window.removeEventListener("touchmove",this.handleTouchMoveProxy),window.removeEventListener("scroll",this.handleScrollProxy,!0)},t.prototype.handleTouchStart=function(t){this.stopTouch(t,!0),this.isTouching=!0,this.trigger("touchstart",t)},t.prototype.handleTouchMove=function(t){this.isTouching&&this.trigger("touchmove",t)},t.prototype.handleTouchCancel=function(t){this.isTouching&&(this.trigger("touchcancel",t),this.stopTouch(t))},t.prototype.handleTouchEnd=function(t){this.stopTouch(t)},t.prototype.handleMouseDown=function(t){this.shouldIgnoreMouse()||this.trigger("mousedown",t)},t.prototype.handleMouseMove=function(t){this.shouldIgnoreMouse()||this.trigger("mousemove",t)},t.prototype.handleMouseUp=function(t){this.shouldIgnoreMouse()||this.trigger("mouseup",t)},t.prototype.handleClick=function(t){this.shouldIgnoreMouse()||this.trigger("click",t)},t.prototype.handleSelectStart=function(t){this.trigger("selectstart",t)},t.prototype.handleContextMenu=function(t){this.trigger("contextmenu",t)},t.prototype.handleScroll=function(t){this.trigger("scroll",t)},t.prototype.stopTouch=function(t,e){void 0===e&&(e=!1),this.isTouching&&(this.isTouching=!1,this.trigger("touchend",t),e||this.startTouchMouseIgnore())},t.prototype.startTouchMouseIgnore=function(){var t=this,e=r.touchMouseIgnoreWait;e&&(this.mouseIgnoreDepth++,setTimeout(function(){t.mouseIgnoreDepth--},e))},t.prototype.shouldIgnoreMouse=function(){return this.isTouching||Boolean(this.mouseIgnoreDepth)},t}();e.default=u,s.default.mixInto(u),o.default.mixInto(u)},function(t,e,n){function i(t,n){e.viewHash[t]=n}function r(t){return e.viewHash[t]}
2749Object.defineProperty(e,"__esModule",{value:!0});var o=n(16);e.viewHash={},o.views=e.viewHash,e.defineView=i,e.getViewConfig=r},function(t,e,n){function i(t,e){return!t&&!e||!(!t||!e)&&(t.component===e.component&&r(t,e)&&r(e,t))}function r(t,e){for(var n in t)if(!/^(component|left|right|top|bottom)$/.test(n)&&t[n]!==e[n])return!1;return!0}Object.defineProperty(e,"__esModule",{value:!0});var o=n(2),s=n(4),a=n(54),l=function(t){function e(e,n){var i=t.call(this,n)||this;return i.component=e,i}return o.__extends(e,t),e.prototype.handleInteractionStart=function(e){var n,i,r,o=this.subjectEl;this.component.hitsNeeded(),this.computeScrollBounds(),e?(i={left:s.getEvX(e),top:s.getEvY(e)},r=i,o&&(n=s.getOuterRect(o),r=s.constrainPoint(r,n)),this.origHit=this.queryHit(r.left,r.top),o&&this.options.subjectCenter&&(this.origHit&&(n=s.intersectRects(this.origHit,n)||n),r=s.getRectCenter(n)),this.coordAdjust=s.diffPoints(r,i)):(this.origHit=null,this.coordAdjust=null),t.prototype.handleInteractionStart.call(this,e)},e.prototype.handleDragStart=function(e){var n;t.prototype.handleDragStart.call(this,e),(n=this.queryHit(s.getEvX(e),s.getEvY(e)))&&this.handleHitOver(n)},e.prototype.handleDrag=function(e,n,r){var o;t.prototype.handleDrag.call(this,e,n,r),o=this.queryHit(s.getEvX(r),s.getEvY(r)),i(o,this.hit)||(this.hit&&this.handleHitOut(),o&&this.handleHitOver(o))},e.prototype.handleDragEnd=function(e){this.handleHitDone(),t.prototype.handleDragEnd.call(this,e)},e.prototype.handleHitOver=function(t){var e=i(t,this.origHit);this.hit=t,this.trigger("hitOver",this.hit,e,this.origHit)},e.prototype.handleHitOut=function(){this.hit&&(this.trigger("hitOut",this.hit),this.handleHitDone(),this.hit=null)},e.prototype.handleHitDone=function(){this.hit&&this.trigger("hitDone",this.hit)},e.prototype.handleInteractionEnd=function(e,n){t.prototype.handleInteractionEnd.call(this,e,n),this.origHit=null,this.hit=null,this.component.hitsNotNeeded()},e.prototype.handleScrollEnd=function(){t.prototype.handleScrollEnd.call(this),this.isDragging&&(this.component.releaseHits(),this.component.prepareHits())},e.prototype.queryHit=function(t,e){return this.coordAdjust&&(t+=this.coordAdjust.left,e+=this.coordAdjust.top),this.component.queryHit(t,e)},e}(a.default);e.default=l}
2749,,,,,,,,function(t,e,n){function i(t){a.each(f,function(e,n){null==t[e]&&(t[e]=n(t))})}function r(t,n,i){var r=e.localeOptionHash[t]||(e.localeOptionHash[t]={});r.isRTL=i.isRTL,r.weekNumberTitle=i.weekHeader,a.each(p,function(t,e){r[t]=e(i)});var o=a.datepicker;o&&(o.regional[n]=o.regional[t]=i,o.regional.en=o.regional[""],o.setDefaults(i))}function o(t,n){var i,r;i=e.localeOptionHash[t]||(e.localeOptionHash[t]={}),n&&(i=e.localeOptionHash[t]=d.mergeOptions([i,n])),r=s(t),a.each(h,function(t,e){null==i[t]&&(i[t]=e(r,i))}),d.globalDefaults.locale=t}function s(t){return l.localeData(t)||l.localeData("en")}Object.defineProperty(e,"__esModule",{value:!0});var a=n(3),l=n(0),u=n(16),d=n(32),c=n(4);e.localeOptionHash={},u.locales=e.localeOptionHash;var p={buttonText:function(t){return{prev:c.stripHtmlEntities(t.prevText),next:c.stripHtmlEntities(t.nextText),today:c.stripHtmlEntities(t.currentText)}},monthYearFormat:function(t){return t.showMonthAfterYear?"YYYY["+t.yearSuffix+"] MMMM":"MMMM YYYY["+t.yearSuffix+"]"}},h={dayOfMonthFormat:function(t,e){var n=t.longDateFormat("l");return n=n.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g,""),e.isRTL?n+=" ddd":n="ddd "+n,n},
2750mediumTimeFormat:function(t){return t.longDateFormat("LT").replace(/\s*a$/i,"a")},smallTimeFormat:function(t){return t.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"a")},extraSmallTimeFormat:function(t){return t.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"t")},hourFormat:function(t){return t.longDateFormat("LT").replace(":mm","").replace(/(\Wmm)$/,"").replace(/\s*a$/i,"a")},noMeridiemTimeFormat:function(t){return t.longDateFormat("LT").replace(/\s*a$/i,"")}},f={smallDayDateFormat:function(t){return t.isRTL?"D dd":"dd D"},weekFormat:function(t){return t.isRTL?"w[ "+t.weekNumberTitle+"]":"["+t.weekNumberTitle+" ]w"},smallWeekFormat:function(t){return t.isRTL?"w["+t.weekNumberTitle+"]":"["+t.weekNumberTitle+"]w"}};e.populateInstanceComputableOptions=i,e.datepickerLocale=r,e.locale=o,e.getMomentLocaleData=s,o("en",d.englishDefaults)},function(t,e,n){function i(t){return r.mergeProps(t,o)}Object.defineProperty(e,"__esModule",{value:!0});var r=n(4);e.globalDefaults={titleRangeSeparator:" – ",monthYearFormat:"MMMM YYYY",defaultTimedEventDuration:"02:00:00",defaultAllDayEventDuration:{days:1},forceEventDuration:!1,nextDayThreshold:"09:00:00",columnHeader:!0,defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberTitle:"W",weekNumberCalculation:"local",scrollTime:"06:00:00",minTime:"00:00:00",maxTime:"24:00:00",showNonCurrentDates:!0,lazyFetching:!0,startParam:"start",endParam:"end",timezoneParam:"timezone",timezone:!1,locale:null,isRTL:!1,buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day"},allDayText:"all-day",agendaEventMinHeight:0,theme:!1,dragOpacity:.75,dragRevertDuration:500,dragScroll:!0,unselectAuto:!0,dropAccept:"*",eventOrder:"title",eventLimit:!1,eventLimitText:"more",eventLimitClick:"popover",dayPopoverFormat:"LL",handleWindowResize:!0,windowResizeDelay:100,longPressDelay:1e3},e.englishDefaults={dayPopoverFormat:"dddd, MMMM D"},e.rtlDefaults={header:{left:"next,prev today",center:"",right:"title"},buttonIcons:{prev:"right-single-arrow",next:"left-single-arrow",prevYear:"right-double-arrow",nextYear:"left-double-arrow"},themeButtonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w",nextYear:"seek-prev",prevYear:"seek-next"}};var o=["header","footer","buttonText","buttonIcons","themeButtonIcons"];e.mergeOptions=i},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(4),o=function(){function t(){}return t.extend=function(t){var e=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e}(this);return r.copyOwnProps(t,e.prototype),e},t.mixin=function(t){r.copyOwnProps(t,this.prototype)},t}();e.default=o},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(208),o=function(){function t(t){this.source=t,this.className=[],this.miscProps={}}return t.parse=function(t,e){var n=new this(e);return!!n.applyProps(t)&&n},t.normalizeId=function(t){return String(t)},t.generateId=function(){return"_fc"+t.uuid++},t.prototype.clone=function(){var e=new this.constructor(this.source);return e.id=this.id,e.rawId=this.rawId,e.uid=this.uid,t.copyVerbatimStandardProps(this,e),e.className=this.className.slice(),e.miscProps=i.extend({},this.miscProps),e},t.prototype.hasInverseRendering=function(){return"inverse-background"===this.getRendering()},t.prototype.hasBgRendering=function(){var t=this.getRendering();return"inverse-background"===t||"background"===t},t.prototype.getRendering=function(){return null!=this.rendering?this.rendering:this.source.rendering},t.prototype.getConstraint=function(){return null!=this.constraint?this.constraint:null!=this.source.constraint?this.source.constraint:this.source.calendar.opt("eventConstraint")},t.prototype.getOverlap=function(){return null!=this.overlap?this.overlap:null!=this.source.overlap?this.source.overlap:this.source.calendar.opt("eventOverlap")},t.prototype.isStartExplicitlyEditable=function(){return null!=this.startEditable?this.startEditable:this.source.startEditable},t.prototype.isDurationExplicitlyEditable=function(){return null!=this.durationEditable?this.durationEditable:this.source.durationEditable},t.prototype.isExplicitlyEditable=function(){return null!=this.editable?this.editable:this.source.editable},t.prototype.toLegacy=function(){var e=i.extend({},this.miscProps);return e._id=this.uid,e.source=this.source,e.className=this.className.slice(),e.allDay=this.isAllDay(),null!=this.rawId&&(e.id=this.rawId
2750),t.copyVerbatimStandardProps(this,e),e},t.prototype.applyManualStandardProps=function(e){return null!=e.id?this.id=t.normalizeId(this.rawId=e.id):this.id=t.generateId(),null!=e._id?this.uid=String(e._id):this.uid=t.generateId(),i.isArray(e.className)&&(this.className=e.className),"string"==typeof e.className&&(this.className=e.className.split(/\s+/)),!0},t.prototype.applyMiscProps=function(t){i.extend(this.miscProps,t)},t.uuid=0,t.defineStandardProps=r.default.defineStandardProps,t.copyVerbatimStandardProps=r.default.copyVerbatimStandardProps,t}();e.default=o,r.default.mixInto(o),o.defineStandardProps({_id:!1,id:!1,className:!1,source:!1,title:!0,url:!0,rendering:!0,constraint:!0,overlap:!0,editable:!0,startEditable:!0,durationEditable:!0,color:!0,backgroundColor:!0,borderColor:!0,textColor:!0})},function(t,e,n){function i(t,e){var n,i=[];for(n=0;n<t.length;n++)i.push.apply(i,t[n].buildInstances(e));return i}function r(t){return new l.default(t.dateProfile.unzonedRange,t.def,t)}function o(t){return new u.default(new d.default(t.unzonedRange,t.eventDef.isAllDay()),t.eventDef,t.eventInstance)}function s(t){return t.dateProfile.unzonedRange}function a(t){return t.componentFootprint}Object.defineProperty(e,"__esModule",{value:!0});var l=n(211),u=n(36),d=n(12);e.eventDefsToEventInstances=i,e.eventInstanceToEventRange=r,e.eventRangeToEventFootprint=o,e.eventInstanceToUnzonedRange=s,e.eventFootprintToComponentFootprint=a},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t,e,n){this.componentFootprint=t,this.eventDef=e,n&&(this.eventInstance=n)}return t.prototype.getEventLegacy=function(){return(this.eventInstance||this.eventDef).toLegacy()},t}();e.default=n},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(4),r=n(17),o=n(34),s=n(50),a=n(13),l=function(){function t(){}return t.createFromRawProps=function(e,n,a){var l,u,d,c,p=e.def,h={},f={},g={},v={},y=null,m=null;for(l in n)r.default.isStandardProp(l)?h[l]=n[l]:p.isStandardProp(l)?f[l]=n[l]:p.miscProps[l]!==n[l]&&(g[l]=n[l]);return u=r.default.parse(h,p.source),u&&(d=s.default.createFromDiff(e.dateProfile,u,a)),f.id!==p.id&&(y=f.id),i.isArraysEqual(f.className,p.className)||(m=f.className),o.default.copyVerbatimStandardProps(f,v),c=new t,c.eventDefId=y,c.className=m,c.verbatimStandardProps=v,c.miscProps=g,d&&(c.dateMutation=d),c},t.prototype.mutateSingle=function(t){var e;return this.dateMutation&&(e=t.dateProfile,t.dateProfile=this.dateMutation.buildNewDateProfile(e,t.source.calendar)),null!=this.eventDefId&&(t.id=o.default.normalizeId(t.rawId=this.eventDefId)),this.className&&(t.className=this.className),this.verbatimStandardProps&&a.default.copyVerbatimStandardProps(this.verbatimStandardProps,t),this.miscProps&&t.applyMiscProps(this.miscProps),e?function(){t.dateProfile=e}:function(){}},t.prototype.setDateMutation=function(t){t&&!t.isEmpty()?this.dateMutation=t:this.dateMutation=null},t.prototype.isEmpty=function(){return!this.dateMutation},t}();e.default=l},function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.default={sourceClasses:[],registerClass:function(t){this.sourceClasses.unshift(t)},parse:function(t,e){var n,i,r=this.sourceClasses;for(n=0;n<r.length;n++)if(i=r[n].parse(t,e))return i}}},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(33),a=function(t){function e(e){var n=t.call(this)||this;return e=e||{},n.overflowX=e.overflowX||e.overflow||"auto",n.overflowY=e.overflowY||e.overflow||"auto",n}return i.__extends(e,t),e.prototype.render=function(){this.el=this.renderEl(),this.applyOverflow()},e.prototype.renderEl=function(){return this.scrollEl=r('<div class="fc-scroller"></div>')},e.prototype.clear=function(){this.setHeight("auto"),this.applyOverflow()},e.prototype.destroy=function(){this.el.remove()},e.prototype.applyOverflow=function(){this.scrollEl.css({"overflow-x":this.overflowX,"overflow-y":this.overflowY})},e.prototype.lockOverflow=function(t){var e=this.overflowX,n=this.overflowY;t=t||this.getScrollbarWidths(),"auto"===e&&(e=t.top||t.bottom||this.scrollEl[0].scrollWidth-1>this.scrollEl[0].clientWidth?"scroll":"hidden"),"auto"===n&&(n=t.left||t.right||this.scrollEl[0].scrollHeight-1>this.scrollEl[0].clientHeight?"scroll":"hidden"),this.scrollEl.css({"overflow-x":e,"overflow-y":n})},e.prototype.setHeight=function(t){this.scrollEl.height(t)},e.prototype.getScrollTop=function(){return this.scrollEl.scrollTop()},e.prototype.setScrollTop=function(t){this.scrollEl.scrollTop(t)},e.prototype.getClientWidth=function(){return this.scrollEl[0].clientWidth},e.prototype.getClientHeight=function(){return this.scrollEl[0].clientHeight},e.prototype.getScrollbarWidths=function(){return o.getScrollbarWidths(this.scrollEl)},e}(s.default);e.default=a}
2750,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(219),a=n(21),l=function(t){function e(e,n){var i=t.call(this,e,n)||this;return i.segSelector=".fc-event-container > *",i.dateSelectingClass&&(i.dateClicking=new i.dateClickingClass(i)),i.dateSelectingClass&&(i.dateSelecting=new i.dateSelectingClass(i)),i.eventPointingClass&&(i.eventPointing=new i.eventPointingClass(i)),i.eventDraggingClass&&i.eventPointing&&(i.eventDragging=new i.eventDraggingClass(i,i.eventPointing)),i.eventResizingClass&&i.eventPointing&&(i.eventResizing=new i.eventResizingClass(i,i.eventPointing)),i.externalDroppingClass&&(i.externalDropping=new i.externalDroppingClass(i)),i}return i.__extends(e,t),e.prototype.setElement=function(e){t.prototype.setElement.call(this,e),this.dateClicking&&this.dateClicking.bindToEl(e),this.dateSelecting&&this.dateSelecting.bindToEl(e),this.bindAllSegHandlersToEl(e)},e.prototype.removeElement=function(){this.endInteractions(),t.prototype.removeElement.call(this)},e.prototype.executeEventUnrender=function(){this.endInteractions(),t.prototype.executeEventUnrender.call(this)},e.prototype.bindGlobalHandlers=function(){t.prototype.bindGlobalHandlers.call(this),this.externalDropping&&this.externalDropping.bindToDocument()},e.prototype.unbindGlobalHandlers=function(){t.prototype.unbindGlobalHandlers.call(this),this.externalDropping&&this.externalDropping.unbindFromDocument()},e.prototype.bindDateHandlerToEl=function(t,e,n){var i=this;this.el.on(e,function(t){if(!r(t.target).is(i.segSelector+":not(.fc-helper),"+i.segSelector+":not(.fc-helper) *,.fc-more,a[data-goto]"))return n.call(i,t)})},e.prototype.bindAllSegHandlersToEl=function(t){[this.eventPointing,this.eventDragging,this.eventResizing].forEach(function(e){e&&e.bindToEl(t)})},e.prototype.bindSegHandlerToEl=function(t,e,n){var i=this;t.on(e,this.segSelector,function(t){var e=r(t.currentTarget);if(!e.is(".fc-helper")){var o=e.data("fc-seg");if(o&&!i.shouldIgnoreEventPointing())return n.call(i,o,t)}})},e.prototype.shouldIgnoreMouse=function(){return a.default.get().shouldIgnoreMouse()},e.prototype.shouldIgnoreTouch=function(){var t=this._getView();return t.isSelected||t.selectedEvent},e.prototype.shouldIgnoreEventPointing=function(){return this.eventDragging&&this.eventDragging.isDragging||this.eventResizing&&this.eventResizing.isResizing},e.prototype.canStartSelection=function(t,e){return o.getEvIsTouch(e)&&!this.canStartResize(t,e)&&(this.isEventDefDraggable(t.footprint.eventDef)||this.isEventDefResizable(t.footprint.eventDef))},e.prototype.canStartDrag=function(t,e){return!this.canStartResize(t,e)&&this.isEventDefDraggable(t.footprint.eventDef)},e.prototype.canStartResize=function(t,e){var n=this._getView(),i=t.footprint.eventDef;return(!o.getEvIsTouch(e)||n.isEventDefSelected(i))&&this.isEventDefResizable(i)&&r(e.target).is(".fc-resizer")},e.prototype.endInteractions=function(){[this.dateClicking,this.dateSelecting,this.eventPointing,this.eventDragging,this.eventResizing].forEach(function(t){t&&t.end()})},e.prototype.isEventDefDraggable=function(t){return this.isEventDefStartEditable(t)},e.prototype.isEventDefStartEditable=function(t){var e=t.isStartExplicitlyEditable();return null==e&&null==(e=this.opt("eventStartEditable"))&&(e=this.isEventDefGenerallyEditable(t)),e},e.prototype.isEventDefGenerallyEditable=function(t){var e=t.isExplicitlyEditable();return null==e&&(e=this.opt("editable")),e},e.prototype.isEventDefResizableFromStart=function(t){return this.opt("eventResizableFromStart")&&this.isEventDefResizable(t)},e.prototype.isEventDefResizableFromEnd=function(t){return this.isEventDefResizable(t)},e.prototype.isEventDefResizable=function(t){var e=t.isDurationExplicitlyEditable();return null==e&&null==(e=this.opt("eventDurationEditable"))&&(e=this.isEventDefGenerallyEditable(t)),e},e.prototype.diffDates=function(t,e){return this.largeUnit?o.diffByUnit(t,e,this.largeUnit):o.diffDayTime(t,e)},e.prototype.isEventInstanceGroupAllowed=function(t){var e,n=this._getView(),i=this.dateProfile,r=this.eventRangesToEventFootprints(t.getAllEventRanges());for(e=0;e<r.length;e++)if(!i.validUnzonedRange.containsRange(r[e].componentFootprint.unzonedRange))return!1;return n.calendar.constraints.isEventInstanceGroupAllowed(t)},e.prototype.isExternalInstanceGroupAllowed=function(t){var e,n=this._getView(),i=this.dateProfile,r=this.eventRangesToEventFootprints(t.getAllEventRanges());for(e=0;e<r.length;e++)if(!i.validUnzonedRange.containsRange(r[e].componentFootprint.unzonedRange))return!1;for(e=0;e<r.length;e++)if(!n.calendar.constraints.isSelectionFootprintAllowed(r[e].componentFootprint))return!1;return!0},e}(s.default);e.default=l}
2750,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(0),s=n(4),a=n(218),l=n(221),u=n(40),d=n(21),c=n(5),p=function(t){function e(e,n){var i=t.call(this,null,n.options)||this;return i.batchRenderDepth=0,i.isSelected=!1,i.calendar=e,i.viewSpec=n,i.type=n.type,i.name=i.type,i.initRenderQueue(),i.initHiddenDays(),i.dateProfileGenerator=new i.dateProfileGeneratorClass(i),i.bindBaseRenderHandlers(),i.eventOrderSpecs=s.parseFieldSpecs(i.opt("eventOrder")),i.initialize&&i.initialize(),i}return i.__extends(e,t),e.prototype._getView=function(){return this},e.prototype.opt=function(t){return this.options[t]},e.prototype.initRenderQueue=function(){this.renderQueue=new a.default({event:this.opt("eventRenderWait")}),this.renderQueue.on("start",this.onRenderQueueStart.bind(this)),this.renderQueue.on("stop",this.onRenderQueueStop.bind(this)),this.on("before:change",this.startBatchRender),this.on("change",this.stopBatchRender)},e.prototype.onRenderQueueStart=function(){this.calendar.freezeContentHeight(),this.addScroll(this.queryScroll())},e.prototype.onRenderQueueStop=function(){this.calendar.updateViewSize()&&this.popScroll(),this.calendar.thawContentHeight()},e.prototype.startBatchRender=function(){this.batchRenderDepth++||this.renderQueue.pause()},e.prototype.stopBatchRender=function(){--this.batchRenderDepth||this.renderQueue.resume()},e.prototype.requestRender=function(t,e,n){this.renderQueue.queue(t,e,n)},e.prototype.whenSizeUpdated=function(t){this.renderQueue.isRunning?this.renderQueue.one("stop",t.bind(this)):t.call(this)},e.prototype.computeTitle=function(t){var e;return e=/^(year|month)$/.test(t.currentRangeUnit)?t.currentUnzonedRange:t.activeUnzonedRange,this.formatRange({start:this.calendar.msToMoment(e.startMs,t.isRangeAllDay),end:this.calendar.msToMoment(e.endMs,t.isRangeAllDay)},t.isRangeAllDay,this.opt("titleFormat")||this.computeTitleFormat(t),this.opt("titleRangeSeparator"))},e.prototype.computeTitleFormat=function(t){var e=t.currentRangeUnit;return"year"===e?"YYYY":"month"===e?this.opt("monthYearFormat"):t.currentUnzonedRange.as("days")>1?"ll":"LL"},e.prototype.setDate=function(t){var e=this.get("dateProfile"),n=this.dateProfileGenerator.build(t,void 0,!0);e&&e.activeUnzonedRange.equals(n.activeUnzonedRange)||this.set("dateProfile",n)},e.prototype.unsetDate=function(){this.unset("dateProfile")},e.prototype.fetchInitialEvents=function(t){var e=this.calendar,n=t.isRangeAllDay&&!this.usesMinMaxTime;return e.requestEvents(e.msToMoment(t.activeUnzonedRange.startMs,n),e.msToMoment(t.activeUnzonedRange.endMs,n))},e.prototype.bindEventChanges=function(){this.listenTo(this.calendar,"eventsReset",this.resetEvents)},e.prototype.unbindEventChanges=function(){this.stopListeningTo(this.calendar,"eventsReset")},e.prototype.setEvents=function(t){this.set("currentEvents",t),this.set("hasEvents",!0)},e.prototype.unsetEvents=function(){this.unset("currentEvents"),this.unset("hasEvents")},e.prototype.resetEvents=function(t){this.startBatchRender(),this.unsetEvents(),this.setEvents(t),this.stopBatchRender()},e.prototype.requestDateRender=function(t){var e=this;this.requestRender(function(){e.executeDateRender(t)},"date","init")},e.prototype.requestDateUnrender=function(){var t=this;this.requestRender(function(){t.executeDateUnrender()},"date","destroy")},e.prototype.executeDateRender=function(e){t.prototype.executeDateRender.call(this,e),this.render&&this.render(),this.trigger("datesRendered"),this.addScroll({isDateInit:!0}),this.startNowIndicator()},e.prototype.executeDateUnrender=function(){this.unselect(),this.stopNowIndicator(),this.trigger("before:datesUnrendered"),this.destroy&&this.destroy(),t.prototype.executeDateUnrender.call(this)},e.prototype.bindBaseRenderHandlers=function(){var t=this;this.on("datesRendered",function(){t.whenSizeUpdated(t.triggerViewRender)}),this.on("before:datesUnrendered",function(){t.triggerViewDestroy()})},e.prototype.triggerViewRender=function(){this.publiclyTrigger("viewRender",{context:this,args:[this,this.el]})},e.prototype.triggerViewDestroy=function(){this.publiclyTrigger("viewDestroy",{context:this,args:[this,this.el]})},e.prototype.requestEventsRender=function(t){var e=this;this.requestRender(function(){e.executeEventRender(t),e.whenSizeUpdated(e.triggerAfterEventsRendered)},"event","init")},e.prototype.requestEventsUnrender=function(){var t=this;this.requestRender(function(){t.triggerBeforeEventsDestroyed(),t.executeEventUnrender()},"event","destroy")},e.prototype.requestBusinessHoursRender=function(t){var e=this;this.requestRender(function(){e.renderBusinessHours(t)},"businessHours","init")},e.prototype.requestBusinessHoursUnrender=function(){var t=this;this.requestRender(function(){t.unrenderBusinessHours()},"businessHours","destroy")},e.prototype.bindGlobalHandlers=function(){t.prototype.bindGlobalHandlers.call(this),this.listenTo(d.default.get(),{touchstart:this.processUnselect,mousedown:this.handleDocumentMousedown})},e.prototype.unbindGlobalHandlers=function(){t.prototype.unbindGlobalHandlers.call(this),this.stopListeningTo(d.default.get())},e.prototype.startNowIndicator=function(){var t,e,n,i=this;
2750this.opt("nowIndicator")&&(t=this.getNowIndicatorUnit())&&(e=s.proxy(this,"updateNowIndicator"),this.initialNowDate=this.calendar.getNow(),this.initialNowQueriedMs=(new Date).valueOf(),n=this.initialNowDate.clone().startOf(t).add(1,t).valueOf()-this.initialNowDate.valueOf(),this.nowIndicatorTimeoutID=setTimeout(function(){i.nowIndicatorTimeoutID=null,e(),n=+o.duration(1,t),n=Math.max(100,n),i.nowIndicatorIntervalID=setInterval(e,n)},n))},e.prototype.updateNowIndicator=function(){this.isDatesRendered&&this.initialNowDate&&(this.unrenderNowIndicator(),this.renderNowIndicator(this.initialNowDate.clone().add((new Date).valueOf()-this.initialNowQueriedMs)),this.isNowIndicatorRendered=!0)},e.prototype.stopNowIndicator=function(){this.isNowIndicatorRendered&&(this.nowIndicatorTimeoutID&&(clearTimeout(this.nowIndicatorTimeoutID),this.nowIndicatorTimeoutID=null),this.nowIndicatorIntervalID&&(clearInterval(this.nowIndicatorIntervalID),this.nowIndicatorIntervalID=null),this.unrenderNowIndicator(),this.isNowIndicatorRendered=!1)},e.prototype.updateSize=function(e,n,i){this.setHeight?this.setHeight(e,n):t.prototype.updateSize.call(this,e,n,i),this.updateNowIndicator()},e.prototype.addScroll=function(t){var e=this.queuedScroll||(this.queuedScroll={});r.extend(e,t)},e.prototype.popScroll=function(){this.applyQueuedScroll(),this.queuedScroll=null},e.prototype.applyQueuedScroll=function(){this.queuedScroll&&this.applyScroll(this.queuedScroll)},e.prototype.queryScroll=function(){var t={};return this.isDatesRendered&&r.extend(t,this.queryDateScroll()),t},e.prototype.applyScroll=function(t){t.isDateInit&&this.isDatesRendered&&r.extend(t,this.computeInitialDateScroll()),this.isDatesRendered&&this.applyDateScroll(t)},e.prototype.computeInitialDateScroll=function(){return{}},e.prototype.queryDateScroll=function(){return{}},e.prototype.applyDateScroll=function(t){},e.prototype.reportEventDrop=function(t,e,n,i){var r=this.calendar.eventManager,s=r.mutateEventsWithId(t.def.id,e),a=e.dateMutation;a&&(t.dateProfile=a.buildNewDateProfile(t.dateProfile,this.calendar)),this.triggerEventDrop(t,a&&a.dateDelta||o.duration(),s,n,i)},e.prototype.triggerEventDrop=function(t,e,n,i,r){this.publiclyTrigger("eventDrop",{context:i[0],args:[t.toLegacy(),e,n,r,{},this]})},e.prototype.reportExternalDrop=function(t,e,n,i,r,o){e&&this.calendar.eventManager.addEventDef(t,n),this.triggerExternalDrop(t,e,i,r,o)},e.prototype.triggerExternalDrop=function(t,e,n,i,r){this.publiclyTrigger("drop",{context:n[0],args:[t.dateProfile.start.clone(),i,r,this]}),e&&this.publiclyTrigger("eventReceive",{context:this,args:[t.buildInstance().toLegacy(),this]})},e.prototype.reportEventResize=function(t,e,n,i){var r=this.calendar.eventManager,o=r.mutateEventsWithId(t.def.id,e);t.dateProfile=e.dateMutation.buildNewDateProfile(t.dateProfile,this.calendar),this.triggerEventResize(t,e.dateMutation.endDelta,o,n,i)},e.prototype.triggerEventResize=function(t,e,n,i,r){this.publiclyTrigger("eventResize",{context:i[0],args:[t.toLegacy(),e,n,r,{},this]})},e.prototype.select=function(t,e){this.unselect(e),this.renderSelectionFootprint(t),this.reportSelection(t,e)},e.prototype.renderSelectionFootprint=function(e){this.renderSelection?this.renderSelection(e.toLegacy(this.calendar)):t.prototype.renderSelectionFootprint.call(this,e)},e.prototype.reportSelection=function(t,e){this.isSelected=!0,this.triggerSelect(t,e)},e.prototype.triggerSelect=function(t,e){var n=this.calendar.footprintToDateProfile(t);this.publiclyTrigger("select",{context:this,args:[n.start,n.end,e,this]})},e.prototype.unselect=function(t){this.isSelected&&(this.isSelected=!1,this.destroySelection&&this.destroySelection(),this.unrenderSelection(),this.publiclyTrigger("unselect",{context:this,args:[t,this]}))},e.prototype.selectEventInstance=function(t){this.selectedEventInstance&&this.selectedEventInstance===t||(this.unselectEventInstance(),this.getEventSegs().forEach(function(e){e.footprint.eventInstance===t&&e.el&&e.el.addClass("fc-selected")}),this.selectedEventInstance=t)},e.prototype.unselectEventInstance=function(){this.selectedEventInstance&&(this.getEventSegs().forEac
2750h(function(t){t.el&&t.el.removeClass("fc-selected")}),this.selectedEventInstance=null)},e.prototype.isEventDefSelected=function(t){return this.selectedEventInstance&&this.selectedEventInstance.def.id===t.id},e.prototype.handleDocumentMousedown=function(t){s.isPrimaryMouseButton(t)&&this.processUnselect(t)},e.prototype.processUnselect=function(t){this.processRangeUnselect(t),this.processEventUnselect(t)},e.prototype.processRangeUnselect=function(t){var e;this.isSelected&&this.opt("unselectAuto")&&((e=this.opt("unselectCancel"))&&r(t.target).closest(e).length||this.unselect(t))},e.prototype.processEventUnselect=function(t){this.selectedEventInstance&&(r(t.target).closest(".fc-selected").length||this.unselectEventInstance())},e.prototype.triggerBaseRendered=function(){this.publiclyTrigger("viewRender",{context:this,args:[this,this.el]})},e.prototype.triggerBaseUnrendered=function(){this.publiclyTrigger("viewDestroy",{context:this,args:[this,this.el]})},e.prototype.triggerDayClick=function(t,e,n){var i=this.calendar.footprintToDateProfile(t);this.publiclyTrigger("dayClick",{context:e,args:[i.start,n,this]})},e.prototype.isDateInOtherMonth=function(t,e){return!1},e.prototype.getUnzonedRangeOption=function(t){var e=this.opt(t);if("function"==typeof e&&(e=e.apply(null,Array.prototype.slice.call(arguments,1))),e)return this.calendar.parseUnzonedRange(e)},e.prototype.initHiddenDays=function(){var t,e=this.opt("hiddenDays")||[],n=[],i=0;for(!1===this.opt("weekends")&&e.push(0,6),t=0;t<7;t++)(n[t]=-1!==r.inArray(t,e))||i++;if(!i)throw new Error("invalid hiddenDays");this.isHiddenDayHash=n},e.prototype.trimHiddenDays=function(t){var e=t.getStart(),n=t.getEnd();return e&&(e=this.skipHiddenDays(e)),n&&(n=this.skipHiddenDays(n,-1,!0)),null===e||null===n||e<n?new c.default(e,n):null},e.prototype.isHiddenDay=function(t){return o.isMoment(t)&&(t=t.day()),this.isHiddenDayHash[t]},e.prototype.skipHiddenDays=function(t,e,n){void 0===e&&(e=1),void 0===n&&(n=!1);for(var i=t.clone();this.isHiddenDayHash[(i.day()+(n?e:0)+7)%7];)i.add(e,"days");return i},e}(u.default);e.default=p,p.prototype.usesMinMaxTime=!1,p.prototype.dateProfileGeneratorClass=l.default,p.watch("displayingDates",["isInDom","dateProfile"],function(t){this.requestDateRender(t.dateProfile)},function(){this.requestDateUnrender()}),p.watch("displayingBusinessHours",["displayingDates","businessHourGenerator"],function(t){this.requestBusinessHoursRender(t.businessHourGenerator)},function(){this.requestBusinessHoursUnrender()}),p.watch("initialEvents",["dateProfile"],function(t){return this.fetchInitialEvents(t.dateProfile)}),p.watch("bindingEvents",["initialEvents"],function(t){this.setEvents(t.initialEvents),this.bindEventChanges()},function(){this.unbindEventChanges(),this.unsetEvents()}),p.watch("displayingEvents",["displayingDates","hasEvents"],function(){this.requestEventsRender(this.get("currentEvents"))},function(){this.requestEventsUnrender()}),p.watch("title",["dateProfile"],function(t){return this.title=this.computeTitle(t.dateProfile)}),p.watch("legacyDateProps",["dateProfile"],function(t){var e=this.calendar,n=t.dateProfile;this.start=e.msToMoment(n.activeUnzonedRange.startMs,n.isRangeAllDay),this.end=e.msToMoment(n.activeUnzonedRange.endMs,n.isRangeAllDay),this.intervalStart=e.msToMoment(n.currentUnzonedRange.startMs,n.isRangeAllDay),this.intervalEnd=e.msToMoment(n.currentUnzonedRange.endMs,n.isRangeAllDay)})},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=function(){function t(t,e){this.view=t._getView(),this.component=t,this.fillRenderer=e}return t.prototype.opt=function(t){return this.view.opt(t)},t.prototype.rangeUpdated=function(){var t,e;this.eventTimeFormat=this.opt("eventTimeFormat")||this.opt("timeFormat")||this.computeEventTimeFormat(),t=this.opt("displayEventTime"),null==t&&(t=this.computeDisplayEventTime()),e=this.opt("displayEventEnd"),null==e&&(e=this.computeDisplayEventEnd()),this.displayEventTime=t,this.displayEventEnd=e},t.prototype.render=function(t){var e,n,i,r=this.component._getDateProfile(),o=[],s=[];for(e in t)n=t[e],i=n.sliceRenderRanges(r.activeUnzonedRange),n.getEventDef().hasBgRendering()?o.push.apply(o,i):s.push.apply(s,i);this.renderBgRanges(o),this.renderFgRanges(s)},t.prototype.unrender=function(){this.unrenderBgRanges(),this.unrenderFgRanges()},t.prototype.renderFgRanges=function(t){var e=this.component.eventRangesToEventFootprints(t),n=this.component.eventFootprintsToSegs(e);n=this.renderFgSegEls(n),!1!==this.renderFgSegs(n)&&(this.fgSegs=n)},t.prototype.unrenderFgRanges=function(){this.unrenderFgSegs(this.fgSegs||[]),this.fgSegs=null},t.prototype.renderBgRanges=function(t){var e=this.component.eventRangesToEventFootprints(t),n=this.component.eventFootprintsToSegs(e);!1!==this.renderBgSegs(n)&&(this.bgSegs=n)},t.prototype.unrenderBgRanges=function(){this.unrenderBgSegs(),this.bgSegs=null},t.prototype.getSegs=function(){return(this.bgSegs||[]).concat(this.fgSegs||[])},t.prototype.renderFgSegs=function(t){return!1},t.prototype.unrenderFgSegs=function(t){},t.prototype.renderBgSegs=function(t){var e=this;if(!this.fillRenderer)return!1;this.fillRenderer.renderSegs("bgEvent",t,{getClasses:function(t){return e.getBgClasses(t.footprint.eventDef)},getCss:function(t){return{"background-color":e.getBgColor(t.footprint.eventDef)}},filterEl:function(t,n){return e.filterEventRenderEl(t.footprint,n)}})},t.prototype.unrenderBgSegs=function(){this.fillRenderer&&this.fillRenderer.unrender("bgEvent")},t.prototype.renderFgSegEls=function(t,e){var n=this;void 0===e&&(e=!1);var r,o=this.view.hasPublicHandlers("eventRender"),s="",a=[];if(t.length){for(r=0;r<t.length;r++)this.beforeFgSegHtml(t[r]),s+=this.fgSegHtml(t[r],e);i(s).each(function(e,r){var s=t[e],l=i(r);o&&(l=n.filterEventRenderEl(s.footprint,l)),l&&(l.data("fc-seg",s
2750),s.el=l,a.push(s))})}return a},t.prototype.beforeFgSegHtml=function(t){},t.prototype.fgSegHtml=function(t,e){},t.prototype.getSegClasses=function(t,e,n){var i=["fc-event",t.isStart?"fc-start":"fc-not-start",t.isEnd?"fc-end":"fc-not-end"].concat(this.getClasses(t.footprint.eventDef));return e&&i.push("fc-draggable"),n&&i.push("fc-resizable"),this.view.isEventDefSelected(t.footprint.eventDef)&&i.push("fc-selected"),i},t.prototype.filterEventRenderEl=function(t,e){var n=t.getEventLegacy(),r=this.view.publiclyTrigger("eventRender",{context:n,args:[n,e,this.view]});return!1===r?e=null:r&&!0!==r&&(e=i(r)),e},t.prototype.getTimeText=function(t,e,n){return this._getTimeText(t.eventInstance.dateProfile.start,t.eventInstance.dateProfile.end,t.componentFootprint.isAllDay,e,n)},t.prototype._getTimeText=function(t,e,n,i,r){return null==i&&(i=this.eventTimeFormat),null==r&&(r=this.displayEventEnd),this.displayEventTime&&!n?r&&e?this.view.formatRange({start:t,end:e},!1,i):t.format(i):""},t.prototype.computeEventTimeFormat=function(){return this.opt("smallTimeFormat")},t.prototype.computeDisplayEventTime=function(){return!0},t.prototype.computeDisplayEventEnd=function(){return!0},t.prototype.getBgClasses=function(t){var e=this.getClasses(t);return e.push("fc-bgevent"),e},t.prototype.getClasses=function(t){var e,n=this.getStylingObjs(t),i=[];for(e=0;e<n.length;e++)i.push.apply(i,n[e].eventClassName||n[e].className||[]);return i},t.prototype.getSkinCss=function(t){return{"background-color":this.getBgColor(t),"border-color":this.getBorderColor(t),color:this.getTextColor(t)}},t.prototype.getBgColor=function(t){var e,n,i=this.getStylingObjs(t);for(e=0;e<i.length&&!n;e++)n=i[e].eventBackgroundColor||i[e].eventColor||i[e].backgroundColor||i[e].color;return n||(n=this.opt("eventBackgroundColor")||this.opt("eventColor")),n},t.prototype.getBorderColor=function(t){var e,n,i=this.getStylingObjs(t);for(e=0;e<i.length&&!n;e++)n=i[e].eventBorderColor||i[e].eventColor||i[e].borderColor||i[e].color;return n||(n=this.opt("eventBorderColor")||this.opt("eventColor")),n},t.prototype.getTextColor=function(t){var e,n,i=this.getStylingObjs(t);for(e=0;e<i.length&&!n;e++)n=i[e].eventTextColor||i[e].textColor;return n||(n=this.opt("eventTextColor")),n},t.prototype.getStylingObjs=function(t){var e=this.getFallbackStylingObjs(t);return e.unshift(t),e},t.prototype.getFallbackStylingObjs=function(t){return[t.source]},t.prototype.sortEventSegs=function(t){t.sort(r.proxy(this,"compareEventSegs"))},t.prototype.compareEventSegs=function(t,e){var n=t.footprint,i=e.footprint,o=n.componentFootprint,s=i.componentFootprint,a=o.unzonedRange,l=s.unzonedRange
2751;return a.startMs-l.startMs||l.endMs-l.startMs-(a.endMs-a.startMs)||s.isAllDay-o.isAllDay||r.compareByFieldSpecs(n.eventDef,i.eventDef,this.view.eventOrderSpecs,n.eventDef.miscProps,i.eventDef.miscProps)},t}();e.default=o},,,,,function(t,e,n){function i(t){return"en"!==t.locale()?t.clone().locale("en"):t}function r(t,e){return h(a(e).fakeFormatString,t)}function o(t,e,n,i,r){var o;return t=y.default.parseZone(t),e=y.default.parseZone(e),o=t.localeData(),n=o.longDateFormat(n)||n,s(a(n),t,e,i||" - ",r)}function s(t,e,n,i,r){var o,s,a,l=t.sameUnits,u=e.clone().stripZone(),d=n.clone().stripZone(),c=f(t.fakeFormatString,e),p=f(t.fakeFormatString,n),h="",v="",y="",m="",b="";for(o=0;o<l.length&&(!l[o]||u.isSame(d,l[o]));o++)h+=c[o];for(s=l.length-1;s>o&&(!l[s]||u.isSame(d,l[s]))&&(s-1!==o||"."!==c[s]);s--)v=c[s]+v;for(a=o;a<=s;a++)y+=c[a],m+=p[a];return(y||m)&&(b=r?m+i+y:y+i+m),g(h+b+v)}function a(t){return C[t]||(C[t]=l(t))}function l(t){var e=u(t);return{fakeFormatString:c(e),sameUnits:p(e)}}function u(t){for(var e,n=[],i=/\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;e=i.exec(t);)e[1]?n.push.apply(n,d(e[1])):e[2]?n.push({maybe:u(e[2])}):e[3]?n.push({token:e[3]}):e[5]&&n.push.apply(n,d(e[5]));return n}function d(t){return". "===t?["."," "]:[t]}function c(t){var e,n,i=[];for(e=0;e<t.length;e++)n=t[e],"string"==typeof n?i.push("["+n+"]"):n.token?n.token in E?i.push(b+"["+n.token+"]"):i.push(n.token):n.maybe&&i.push(w+c(n.maybe)+w);return i.join(m)}function p(t){var e,n,i,r=[];for(e=0;e<t.length;e++)n=t[e],n.token?(i=S[n.token.charAt(0)],r.push(i?i.unit:"second")):n.maybe?r.push.apply(r,p(n.maybe)):r.push(null);return r}function h(t,e){return g(f(t,e).join(""))}function f(t,e){var n,i,r=[],o=y.oldMomentFormat(e,t),s=o.split(m);for(n=0;n<s.length;n++)i=s[n],i.charAt(0)===b?r.push(E[i.substring(1)](e)):r.push(i);return r}function g(t){return t.replace(D,function(t,e){return e.match(/[1-9]/)?e:""})}function v(t){var e,n,i,r,o=u(t);for(e=0;e<o.length;e++)n=o[e],n.token&&(i=S[n.token.charAt(0)])&&(!r||i.value>r.value)&&(r=i);return r?r.unit:null}
2751Object.defineProperty(e,"__esModule",{value:!0});var y=n(10);y.newMomentProto.format=function(){return this._fullCalendar&&arguments[0]?r(this,arguments[0]):this._ambigTime?y.oldMomentFormat(i(this),"YYYY-MM-DD"):this._ambigZone?y.oldMomentFormat(i(this),"YYYY-MM-DD[T]HH:mm:ss"):this._fullCalendar?y.oldMomentFormat(i(this)):y.oldMomentProto.format.apply(this,arguments)},y.newMomentProto.toISOString=function(){return this._ambigTime?y.oldMomentFormat(i(this),"YYYY-MM-DD"):this._ambigZone?y.oldMomentFormat(i(this),"YYYY-MM-DD[T]HH:mm:ss"):this._fullCalendar?y.oldMomentProto.toISOString.apply(i(this),arguments):y.oldMomentProto.toISOString.apply(this,arguments)};var m="\v",b="�",w="�",D=new RegExp(w+"([^"+w+"]*)"+w,"g"),E={t:function(t){return y.oldMomentFormat(t,"a").charAt(0)},T:function(t){return y.oldMomentFormat(t,"A").charAt(0)}},S={Y:{value:1,unit:"year"},M:{value:2,unit:"month"},W:{value:3,unit:"week"},w:{value:3,unit:"week"},D:{value:4,unit:"day"},d:{value:4,unit:"day"}};e.formatDate=r,e.formatRange=o;var C={};e.queryMostGranularFormatUnit=v},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(33),o=n(11),s=n(7),a=function(t){function e(){var e=t.call(this)||this;return e._watchers={},e._props={},e.applyGlobalWatchers(),e.constructed(),e}return i.__extends(e,t),e.watch=function(t){for(var e=[],n=1;n<arguments.length;n++)e[n-1]=arguments[n];this.prototype.hasOwnProperty("_globalWatchArgs")||(this.prototype._globalWatchArgs=Object.create(this.prototype._globalWatchArgs)),this.prototype._globalWatchArgs[t]=e},e.prototype.constructed=function(){},e.prototype.applyGlobalWatchers=function(){var t,e=this._globalWatchArgs;for(t in e)this.watch.apply(this,[t].concat(e[t]))},e.prototype.has=function(t){return t in this._props},e.prototype.get=function(t){return void 0===t?this._props:this._props[t]},e.prototype.set=function(t,e){var n;"string"==typeof t?(n={},n[t]=void 0===e?null:e):n=t,this.setProps(n)},e.prototype.reset=function(t){var e,n=this._props,i={};for(e in n)i[e]=void 0;for(e in t)i[e]=t[e];this.setProps(i)},e.prototype.unset=function(t){var e,n,i={};for(e="string"==typeof t?[t]:t,n=0;n<e.length;n++)i[e[n]]=void 0;this.setProps(i)},e.prototype.setProps=function(t){var e,n,i={},r=0;for(e in t)"object"!=typeof(n=t[e])&&n===this._props[e]||(i[e]=n,r++);if(r){this.trigger("before:batchChange",i);for(e in i)n=i[e],this.trigger("before:change",e,n),this.trigger("before:change:"+e,n);for(e in i)n=i[e],void 0===n?delete this._props[e]:this._props[e]=n,this.trigger("change:"+e,n),this.trigger("change",e,n);this.trigger("batchChange",i)}},e.prototype.watch=function(t,e,n,i){var r=this;this.unwatch(t),this._watchers[t]=this._watchDeps(e,function(e){var i=n.call(r,e);i&&i.then?(r.unset(t),i.then(function(e){r.set(t,e)})):r.set(t,i)},function(e){r.unset(t),i&&i.call(r,e)})},e.prototype.unwatch=function(t){var e=this._watchers[t];e&&(delete this._watchers[t],e.teardown())},e.prototype._watchDeps=function(t,e,n){var i=this,r=0,o=t.length,s=0,a={},l=[],u=!1,d=function(t,e,i){1===++r&&s===o&&(u=!0,n(a),u=!1)},c=function(t,n,i){void 0===n?(i||void 0===a[t]||s--,delete a[t]):(i||void 0!==a[t]||s++,a[t]=n),--r||s===o&&(u||e(a))},p=function(t,e){i.on(t,e),l.push([t,e])};return t.forEach(function(t){var e=!1;"?"===t.charAt(0)&&(t=t.substring(1),e=!0),p("before:change:"+t,function(t){d()}),p("change:"+t,function(n){c(t,n,e)})}),t.forEach(function(t){var e=!1;"?"===t.charAt(0)&&(t=t.substring(1),e=!0),i.has(t)?(a[t]=i.get(t),s++):e&&s++}),s===o&&e(a),{teardown:function(){for(var t=0;t<l.length;t++)i.off(l[t][0],l[t][1]);l=null,s===o&&n()},flash:function(){s===o&&(n(),e(a))}}},e.prototype.flash=function(t){var e=this._watchers[t];e&&e.flash()},e}(r.default);e.default=a,a.prototype._globalWatchArgs={},o.default.mixInto(a),s.default.mixInto(a)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(0),r=n(4),o=n(13),s=n(210);e.default={parse:function(t,e){return r.isTimeString(t.start)||i.isDuration(t.start)||r.isTimeString(t.end)||i.isDuration(t.end)?s.default.parse(t,e):o.default.parse(t,e)}}}
2751,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(4),r=n(17),o=function(){function t(){this.clearEnd=!1,this.forceTimed=!1,this.forceAllDay=!1}return t.createFromDiff=function(e,n,r){function o(t,e){return r?i.diffByUnit(t,e,r):n.isAllDay()?i.diffDay(t,e):i.diffDayTime(t,e)}var s,a,l,u,d=e.end&&!n.end,c=e.isAllDay()&&!n.isAllDay(),p=!e.isAllDay()&&n.isAllDay();return s=o(n.start,e.start),n.end&&(a=o(n.unzonedRange.getEnd(),e.unzonedRange.getEnd()),l=a.subtract(s)),u=new t,u.clearEnd=d,u.forceTimed=c,u.forceAllDay=p,u.setDateDelta(s),u.setEndDelta(l),u},t.prototype.buildNewDateProfile=function(t,e){var n=t.start.clone(),i=null,o=!1;return t.end&&!this.clearEnd?i=t.end.clone():this.endDelta&&!i&&(i=e.getDefaultEventEnd(t.isAllDay(),n)),this.forceTimed?(o=!0,n.hasTime()||n.time(0),i&&!i.hasTime()&&i.time(0)):this.forceAllDay&&(n.hasTime()&&n.stripTime(),i&&i.hasTime()&&i.stripTime()),this.dateDelta&&(o=!0,n.add(this.dateDelta),i&&i.add(this.dateDelta)),this.endDelta&&(o=!0,i.add(this.endDelta)),this.startDelta&&(o=!0,n.add(this.startDelta)),o&&(n=e.applyTimezone(n),i&&(i=e.applyTimezone(i))),!i&&e.opt("forceEventDuration")&&(i=e.getDefaultEventEnd(t.isAllDay(),n)),new r.default(n,i,e)},t.prototype.setDateDelta=function(t){t&&t.valueOf()?this.dateDelta=t:this.dateDelta=null},t.prototype.setStartDelta=function(t){t&&t.valueOf()?this.startDelta=t:this.startDelta=null},t.prototype.setEndDelta=function(t){t&&t.valueOf()?this.endDelta=t:this.endDelta=null},t.prototype.isEmpty=function(){return!(this.clearEnd||this.forceTimed||this.forceAllDay||this.dateDelta||this.startDelta||this.endDelta)},t}();e.default=o},function(t,e,n){function i(t,e){a[t]=e}function r(t){return t?!0===t?s.default:a[t]:o.default}Object.defineProperty(e,"__esModule",{value:!0});var o=n(213),s=n(214),a={};e.defineThemeSystem=i,e.getThemeSystemClass=r},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(20),a=n(6),l=n(13),u=function(t){function e(e){var n=t.call(this,e)||this;return n.eventDefs=[],n}return i.__extends(e,t),e.parse=function(t,e){var n;return r.isArray(t.events)?n=t:r.isArray(t)&&(n={events:t}),!!n&&a.default.parse.call(this,n,e)},e.prototype.setRawEventDefs=function(t){this.rawEventDefs=t,this.eventDefs=this.parseEventDefs(t)},e.prototype.fetch=function(t,e,n){var i,r=this.eventDefs;if(null!=this.currentTimezone&&this.currentTimezone!==n)for(i=0;i<r.length;i++)r[i]instanceof l.default&&r[i].rezone();return this.currentTimezone=n,s.default.resolve(r)},e.prototype.addEventDef=function(t){this.eventDefs.push(t)},e.prototype.removeEventDefsById=function(t){return o.removeMatching(this.eventDefs,function(e){return e.id===t})},e.prototype.removeAllEventDefs=function(){this.eventDefs=[]},e.prototype.getPrimitive=function(){return this.rawEventDefs},e.prototype.applyManualStandardProps=function(e){var n=t.prototype.applyManualStandardProps.call(this,e);return this.setRawEventDefs(e.events),n},e}(a.default);e.default=u,u.defineStandardProps({events:!1})},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=function(){function t(t){this.isHorizontal=!1,this.isVertical=!1,this.els=i(t.els),this.isHorizontal=t.isHorizontal,this.isVertical=t.isVertical,this.forcedOffsetParentEl=t.offsetParent?i(t.offsetParent):null}return t.prototype.build=function(){var t=this.forcedOffsetParentEl;!t&&this.els.length>0&&(t=this.els.eq(0).offsetParent()),this.origin=t?t.offset():null,this.boundingRect=this.queryBoundingRect
2751(),this.isHorizontal&&this.buildElHorizontals(),this.isVertical&&this.buildElVerticals()},t.prototype.clear=function(){this.origin=null,this.boundingRect=null,this.lefts=null,this.rights=null,this.tops=null,this.bottoms=null},t.prototype.ensureBuilt=function(){this.origin||this.build()},t.prototype.buildElHorizontals=function(){var t=[],e=[];this.els.each(function(n,r){var o=i(r),s=o.offset().left,a=o.outerWidth();t.push(s),e.push(s+a)}),this.lefts=t,this.rights=e},t.prototype.buildElVerticals=function(){var t=[],e=[];this.els.each(function(n,r){var o=i(r),s=o.offset().top,a=o.outerHeight();t.push(s),e.push(s+a)}),this.tops=t,this.bottoms=e},t.prototype.getHorizontalIndex=function(t){this.ensureBuilt();var e,n=this.lefts,i=this.rights,r=n.length;for(e=0;e<r;e++)if(t>=n[e]&&t<i[e])return e},t.prototype.getVerticalIndex=function(t){this.ensureBuilt();var e,n=this.tops,i=this.bottoms,r=n.length;for(e=0;e<r;e++)if(t>=n[e]&&t<i[e])return e},t.prototype.getLeftOffset=function(t){return this.ensureBuilt(),this.lefts[t]},t.prototype.getLeftPosition=function(t){return this.ensureBuilt(),this.lefts[t]-this.origin.left},t.prototype.getRightOffset=function(t){return this.ensureBuilt(),this.rights[t]},t.prototype.getRightPosition=function(t){return this.ensureBuilt(),this.rights[t]-this.origin.left},t.prototype.getWidth=function(t){return this.ensureBuilt(),this.rights[t]-this.lefts[t]},t.prototype.getTopOffset=function(t){return this.ensureBuilt(),this.tops[t]},t.prototype.getTopPosition=function(t){return this.ensureBuilt(),this.tops[t]-this.origin.top},t.prototype.getBottomOffset=function(t){return this.ensureBuilt(),this.bottoms[t]},t.prototype.getBottomPosition=function(t){return this.ensureBuilt(),this.bottoms[t]-this.origin.top},t.prototype.getHeight=function(t){return this.ensureBuilt(),this.bottoms[t]-this.tops[t]},t.prototype.queryBoundingRect=function(){var t;return this.els.length>0&&(t=r.getScrollParent(this.els.eq(0)),!t.is(document))?r.getClientRect(t):null},t.prototype.isPointInBounds=function(t,e){return this.isLeftInBounds(t)&&this.isTopInBounds(e)},t.prototype.isLeftInBounds=function(t){return!this.boundingRect||t>=this.boundingRect.left&&t<this.boundingRect.right},t.prototype.isTopInBounds=function(t){return!this.boundingRect||t>=this.boundingRect.top&&t<this.boundingRect.bottom},t}();e.default=o},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=n(7),s=n(21),a=function(){function t(t){this.isInteracting=!1,this.isDistanceSurpassed=!1,this.isDelayEnded=!1,this.isDragging=!1,this.isTouch=!1,this.isGeneric=!1,this.shouldCancelTouchScroll=!0,this.scrollAlwaysKills=!1,this.isAutoScroll=!1,this.scrollSensitivity=30,this.scrollSpeed=200,this.scrollIntervalMs=50,this.options=t||{}}return t.prototype.startInteraction=function(t,e){if(void 0===e&&(e={}),"mousedown"===t.type){if(s.default.get().shouldIgnoreMouse())return;if(!r.isPrimaryMouseButton(t))return;t.preventDefault()}this.isInteracting||(this.delay=r.firstDefined(e.delay,this.options.delay,0),this.minDistance=r.firstDefined(e.distance,this.options.distance,0),this.subjectEl=this.options.subjectEl,r.preventSelection(i("body")),this.isInteracting=!0,this.isTouch=r.getEvIsTouch(t),this.isGeneric="dragstart"===t.type,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,this.originX=r.getEvX(t),this.originY=r.getEvY(t),this.scrollEl=r.getScrollParent(i(t.target)),this.bindHandlers(),this.initAutoScroll(),this.handleInteractionStart(t),this.startDelay(t),this.minDistance||this.handleDistanceSurpassed(t))},t.prototype.handleInteractionStart=function(t){this.trigger("interactionStart",t)},t.prototype.endInteraction=function(t,e){this.isInteracting&&(this.endDrag(t),this.delayTimeoutId&&(clearTimeout(this.delayTimeoutId),this.delayTimeoutId=null),this.destroyAutoScroll(),this.unbindHandlers(),this.isInteracting=!1,this.handleInteractionEnd(t,e),r.allowSelection(i("body")))},t.prototype.handleInteractionEnd=function(t,e){this.trigger("interactionEnd",t,e||!1)},t.prototype.bindHandlers=function(){var t=s.default.get();this.isGeneric?this.listenTo(i(document),{drag:this.handleMove,dragstop:this.endInteraction}):this.isTouch?this.listenTo(t,{touchmove:this.handleTouchMove,touchend:this.endInteraction,scroll:this.handleTouchScroll}):this.listenTo(t,{mousemove:this.handleMouseMove,mouseup:this.endInteraction}),this.listenTo(t,{selectstart:r.preventDefault,contextmenu:r.preventDefault})},t.prototype.unbindHandlers=function(){this.stopListeningTo(s.default.get()),this.stopListeningTo(i(document))},t.prototype.startDrag=function(t,e){this.startInteraction(t,e),this.isDragging||(this.isDragging=!0,this.handleDragStart(t))},t.prototype.handleDragStart=function(t){this.trigger("dragStart",t)},t.prototype.handleMove=function(t){var e=r.getEvX(t)-this.originX,n=r.getEvY(t)-this.originY,i=this.minDistance;this.isDistanceSurpassed||e*e+n*n>=i*i&&this.handleDistanceSurpassed(t),this.isDragging&&this.handleDrag(e,n,t)},t.prototype.handleDrag=function(t,e,n){this.trigger("drag",t,e,n),this.updateAutoScroll(n)},t.prototype.endDrag=function(t){this.isDragging&&(this.isDragging=!1,this.handleDragEnd(t))},t.prototype.handleDragEnd=function(t){this.trigger("dragEnd",t)},t.prototype.startDelay=function(t){var e=this;this.delay?this.delayTimeoutId=setTimeout(function(){e.handleDelayEnd(t)},this.delay):this.handleDelayEnd(t)},t.prototype.handleDelayEnd=function(t){this.isDelayEnded=!0,this.isDistanceSurpassed&&this.startDrag(t)},t.prototype.handleDistanceSurpassed=function(t){this.isDistanceSurpassed=!0,this.isDelayEnded&&this.startDrag(t)},t.prototype.handleTouchMove=function(t){this.isDragging&&this.shouldCancelTouchScroll&&t.preventDefault(),this.handleMove(t)},t.prototype.handleMouseMove=function(t){this.handleMove(t)},t.prototype.handleTouchScroll=function(t){this.isDragging&&!this.scrollAlwaysKills||this.endInteraction(t,!0)},t.prototype.trigger=function(t){for(var e=[],n=1;n<arguments.length;n++)e[n-1]=arguments[n];this.options[t]&&this.options[t].apply(this,e),this["_"+t]&&this["_"+t].apply(this,e)},t.prototype.initAutoScroll=function(){var t=this.scrollEl;
2751this.isAutoScroll=this.options.scroll&&t&&!t.is(window)&&!t.is(document),this.isAutoScroll&&this.listenTo(t,"scroll",r.debounce(this.handleDebouncedScroll,100))},t.prototype.destroyAutoScroll=function(){this.endAutoScroll(),this.isAutoScroll&&this.stopListeningTo(this.scrollEl,"scroll")},t.prototype.computeScrollBounds=function(){this.isAutoScroll&&(this.scrollBounds=r.getOuterRect(this.scrollEl))},t.prototype.updateAutoScroll=function(t){var e,n,i,o,s=this.scrollSensitivity,a=this.scrollBounds,l=0,u=0;a&&(e=(s-(r.getEvY(t)-a.top))/s,n=(s-(a.bottom-r.getEvY(t)))/s,i=(s-(r.getEvX(t)-a.left))/s,o=(s-(a.right-r.getEvX(t)))/s,e>=0&&e<=1?l=e*this.scrollSpeed*-1:n>=0&&n<=1&&(l=n*this.scrollSpeed),i>=0&&i<=1?u=i*this.scrollSpeed*-1:o>=0&&o<=1&&(u=o*this.scrollSpeed)),this.setScrollVel(l,u)},t.prototype.setScrollVel=function(t,e){this.scrollTopVel=t,this.scrollLeftVel=e,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(r.proxy(this,"scrollIntervalFunc"),this.scrollIntervalMs))},t.prototype.constrainScrollVel=function(){var t=this.scrollEl;this.scrollTopVel<0?t.scrollTop()<=0&&(this.scrollTopVel=0):this.scrollTopVel>0&&t.scrollTop()+t[0].clientHeight>=t[0].scrollHeight&&(this.scrollTopVel=0),this.scrollLeftVel<0?t.scrollLeft()<=0&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&t.scrollLeft()+t[0].clientWidth>=t[0].scrollWidth&&(this.scrollLeftVel=0)},t.prototype.scrollIntervalFunc=function(){var t=this.scrollEl,e=this.scrollIntervalMs/1e3;this.scrollTopVel&&t.scrollTop(t.scrollTop()+this.scrollTopVel*e),this.scrollLeftVel&&t.scrollLeft(t.scrollLeft()+this.scrollLeftVel*e),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.endAutoScroll()},t.prototype.endAutoScroll=function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.handleScrollEnd())},t.prototype.handleDebouncedScroll=function(){this.scrollIntervalId||this.handleScrollEnd()},t.prototype.handleScrollEnd=function(){},t}();e.default=a,o.default.mixInto(a)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(4),o=n(14),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.updateDayTable=function(){for(var t,e,n,i=this,r=i.view,o=r.calendar,s=o.msToUtcMoment(i.dateProfile.renderUnzonedRange.startMs,!0),a=o.msToUtcMoment(i.dateProfile.renderUnzonedRange.endMs,!0),l=-1,u=[],d=[];s.isBefore(a);)r.isHiddenDay(s)?u.push(l+.5):(l++,u.push(l),d.push(s.clone())),s.add(1,"days");if(this.breakOnWeeks){for(e=d[0].day(),t=1;t<d.length&&d[t].day()!==e;t++);n=Math.ceil(d.length/t)}else n=1,t=d.length;this.dayDates=d,this.dayIndices=u,this.daysPerRow=t,this.rowCnt=n,this.updateDayTableCols()},e.prototype.updateDayTableCols=function(){this.colCnt=this.computeColCnt(),this.colHeadFormat=this.opt("columnHeaderFormat")||this.opt("columnFormat")||this.computeColHeadFormat()},e.prototype.computeColCnt=function(){return this.daysPerRow},e.prototype.getCellDate=function(t,e){return this.dayDates[this.getCellDayIndex(t,e)].clone()},e.prototype.getCellRange=function(t,e){var n=this.getCellDate(t,e);return{start:n,end:n.clone().add(1,"days")}},e.prototype.getCellDayIndex=function(t,e){return t*this.daysPerRow+this.getColDayIndex(e)},e.prototype.getColDayIndex=function(t){return this.isRTL?this.colCnt-1-t:t},e.prototype.getDateDayIndex=function(t){var e=this.dayIndices,n=t.diff(this.dayDates[0],"days");return n<0?e[0]-1:n>=e.length?e[e.length-1]+1:e[n]},e.prototype.computeColHeadFormat=function(){return this.rowCnt>1||this.colCnt>10?"ddd":this.colCnt>1?this.opt("dayOfMonthFormat"):"dddd"},e.prototype.sliceRangeByRow=function(t){var e,n,i,r,o,s=this.daysPerRow,a=this.view.computeDayRange(t),l=this.getDateDayIndex(a.start),u=this.getDateDayIndex(a.end.clone().subtract(1,"days")),d=[];for(e=0;e<this.rowCnt;e++)n=e*s,i=n+s-1,r=Math.max(l,n),o=Math.min(u,i),r=Math.ceil(r),o=Math.floor(o),r<=o&&d.push({row:e,firstRowDayIndex:r-n,lastRowDayIndex:o-n,isStart:r===l,isEnd:o===u});return d},e.prototype.sliceRangeByDay=function(t){var e,n,i,r,o,s,a=this.daysPerRow,l=this.view.computeDayRange(t),u=this.getDateDayIndex(l.start),d=this.getDateDayIndex(l.end.clone().subtract(1,"days")),c=[];for(e=0;e<this.rowCnt;e++)for(n=e*a,i=n+a-1,r=n;r<=i;r++)o=Math.max(u,r),s=Math.min(d,r),o=Math.ceil(o),s=Math.floor(s),o<=s&&c.push({row:e,firstRowDayIndex:o-n,lastRowDayIndex:s-n,isStart:o===u,isEnd:s===d});return c},e.prototype.renderHeadHtml=function(){var t=this.view.calendar.theme;return'<div class="fc-row '+t.getClass("headerRow")+'"><table class="'+t.getClass("tableGrid")+'"><thead>'+this.renderHeadTrHtml()+"</thead></table></div>"},e.prototype.renderHeadIntroHtml=function(){return this.renderIntroHtml()},e.prototype.renderHeadTrHtml=function(){return"<tr>"+(this.isRTL?"":this.renderHeadIntroHtml())+this.renderHeadDateCellsHtml()+(this.isRTL?this.renderHeadIntroHtml():"")+"</tr>"},e.prototype.renderHeadDateCellsHtml=function(){var t,e,n=[];for(t=0;t<this.colCnt;t++)e=this.getCellDate(0,t),n.push(this.renderHeadDateCellHtml(e));return n.join("")},e.prototype.renderHeadDateCellHtml=function(t,e,n){var i,o=this,s=o.view,a=o.dateProfile.activeUnzonedRange.containsDate(t),l=["fc-day-header",s.calendar.theme.getClass("widgetHeader")];return i="function"==typeof o.opt("columnHeaderHtml")?o.opt("columnHeaderHtml")(t):"function"==typeof o.opt("columnHeaderText")?r.htmlEscape(o.opt("columnHeaderText")(t)):r.htmlEscape(t.format(o.colHeadFormat)),1===o.rowCnt?l=l.concat(o.getDayClasses(t,!0)):l.push("fc-"+r.dayIDs[t.day()]),'<th class="'+l.join(" ")+'"'+(1===(a&&o.rowCnt)?' data-date="'+t.format("YYYY-MM-DD")+'"':"")+(e>1?' colspan="'+e+'"':"")+(n?" "+n:"")+">"+(a?s.buildGotoAnchorHtml({date:t,forceOff:o.rowCnt>1||1===o.colCnt},i):i)+"</th>"},e.prototype.renderBgTrHtml=function(t){return"<tr>"+(this.isRTL?"":this.renderBgIntroHtml(t))+this.renderBgCellsHtml(t)+(this.isRTL?this.renderBgIntroHtml(t):"")+"</tr>"},e.prototype.renderBgIntroHtml=function(t){return this.renderIntroHtml()},e.prototype.renderBgCellsHtml=function(t){var e,n,i=[];for(e=0;e<this.colCnt;e++)n=this.getCellDate(t,e),i.push(this.renderBgCellHtml(n));return i.join("")},e.prototype.renderBgCellHtml=function(t,e){var n=this,i=n.view,r=n.dateProfile.activeUnzonedRange.containsDate(t),o=n.getDayClasses(t);return o.unshift("fc-day",i.calendar.theme.getClass("widgetContent")),'<td class="'+o.join(" ")+'"'+(r?' data-date="'+t.format("YYYY-MM-DD")+'"':"")+(e?" "+e:"")+"></td>"},e.prototype.renderIntroHtml=function(){},e.prototype.bookendCells=function(t){var e=this.renderIntroHtml();e&&(this.isRTL?t.append(e):t.prepend(e))},e}(o.default);e.default=s}
2751,function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t,e){this.component=t,this.fillRenderer=e}return t.prototype.render=function(t){var e=this.component,n=e._getDateProfile().activeUnzonedRange,i=t.buildEventInstanceGroup(e.hasAllDayBusinessHours,n),r=i?e.eventRangesToEventFootprints(i.sliceRenderRanges(n)):[];this.renderEventFootprints(r)},t.prototype.renderEventFootprints=function(t){var e=this.component.eventFootprintsToSegs(t);this.renderSegs(e),this.segs=e},t.prototype.renderSegs=function(t){this.fillRenderer&&this.fillRenderer.renderSegs("businessHours",t,{getClasses:function(t){return["fc-nonbusiness","fc-bgevent"]}})},t.prototype.unrender=function(){this.fillRenderer&&this.fillRenderer.unrender("businessHours"),this.segs=null},t.prototype.getSegs=function(){return this.segs||[]},t}();e.default=n},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=function(){function t(t){this.fillSegTag="div",this.component=t,this.elsByFill={}}return t.prototype.renderFootprint=function(t,e,n){this.renderSegs(t,this.component.componentFootprintToSegs(e),n)},t.prototype.renderSegs=function(t,e,n){var i;return e=this.buildSegEls(t,e,n),i=this.attachSegEls(t,e),i&&this.reportEls(t,i),e},t.prototype.unrender=function(t){var e=this.elsByFill[t];e&&(e.remove(),delete this.elsByFill[t])},t.prototype.buildSegEls=function(t,e,n){var r,o=this,s="",a=[];if(e.length){for(r=0;r<e.length;r++)s+=this.buildSegHtml(t,e[r],n);i(s).each(function(t,r){var s=e[t],l=i(r);n.filterEl&&(l=n.filterEl(s,l)),l&&(l=i(l),l.is(o.fillSegTag)&&(s.el=l,a.push(s)))})}return a},t.prototype.buildSegHtml=function(t,e,n){var i=n.getClasses?n.getClasses(e):[],o=r.cssToStr(n.getCss?n.getCss(e):{});return"<"+this.fillSegTag+(i.length?' class="'+i.join(" ")+'"':"")+(o?' style="'+o+'"':"")+" />"},t.prototype.attachSegEls=function(t,e){},t.prototype.reportEls=function(t,e){this.elsByFill[t]?this.elsByFill[t]=this.elsByFill[t].add(e):this.elsByFill[t]=i(e)},t}();e.default=o},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(13),r=n(36),o=n(6),s=function(){function t(t,e){this.view=t._getView(),this.component=t,this.eventRenderer=e}return t.prototype.renderComponentFootprint=function(t){this.renderEventFootprints([this.fabricateEventFootprint(t)])},t.prototype.renderEventDraggingFootprints=function(t,e,n){this.renderEventFootprints(t,e,"fc-dragging",n?null:this.view.opt("dragOpacity"))},t.prototype.renderEventResizingFootprints=function(t,e,n){this.renderEventFootprints(t,e,"fc-resizing")},t.prototype.renderEventFootprints=function(t,e,n,i){var r,o=this.component.eventFootprintsToSegs(t),s="fc-helper "+(n||"");for(o=this.eventRenderer.renderFgSegEls(o),r=0;r<o.length;r++)o[r].el.addClass(s);if(null!=i)for(r=0;r<o.length;r++)o[r].el.css("opacity",i);this.helperEls=this.renderSegs(o,e)},t.prototype.renderSegs=function(t,e){},t.prototype.unrender=function(){this.helperEls&&(this.helperEls.remove(),this.helperEls=null)},t.prototype.fabricateEventFootprint=function(t){var e,n=this.view.calendar,s=n.footprintToDateProfile(t),a=new i.default(new o.default(n));return a.dateProfile=s,e=a.buildInstance(),new r.default(t,a,e)},t}();e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(21),o=n(15),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.bindToEl=function(t){var e=this.component;e.bindSegHandlerToEl(t,"click",this.handleClick.bind(this)),e.bindSegHandlerToEl(t,"mouseenter",this.handleMouseover.bind(this)),e.bindSegHandlerToEl(t,"mouseleave",this.handleMouseout.bind(this))},e.prototype.handleClick=function(t,e){!1===this.component.publiclyTrigger("eventClick",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,this.view]})&&e.preventDefault()},e.prototype.handleMouseover=function(t,e){r.default.get().shouldIgnoreMouse()||this.mousedOverSeg||(this.mousedOverSeg=t,this.view.isEventDefResizable(t.footprint.eventDef)&&t.el.addClass("fc-allow-mouse-resize"),this.component.publiclyTrigger("eventMouseover",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,this.view]}))},e.prototype.handleMouseout=function(t,e){this.mousedOverSeg&&(this.mousedOverSeg=null,this.view.isEventDefResizable(t.footprint.eventDef)&&t.el.removeClass("fc-allow-mouse-resize"),this.component.publiclyTrigger("eventMouseout",{context:t.el[0],args:[t.footprint.getEventLegacy(),e||{},this.view]}))},e.prototype.end=function(){this.mousedOverSeg&&this.handleMouseout(this.mousedOverSeg)},e}(o.default);e.default=s}
2751,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(14),o=n(245),s=n(225),a=n(59),l=n(224),u=n(223),d=n(222),c=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e}(r.default);e.default=c,c.prototype.dateClickingClass=o.default,c.prototype.dateSelectingClass=s.default,c.prototype.eventPointingClass=a.default,c.prototype.eventDraggingClass=l.default,c.prototype.eventResizingClass=u.default,c.prototype.externalDroppingClass=d.default},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(53),a=n(249),l=n(5),u=n(12),d=n(36),c=n(56),p=n(60),h=n(40),f=n(55),g=n(250),v=n(251),y=n(252),m=function(t){function e(e){var n=t.call(this,e)||this;return n.cellWeekNumbersVisible=!1,n.bottomCoordPadding=0,n.isRigid=!1,n.hasAllDayBusinessHours=!0,n}return i.__extends(e,t),e.prototype.componentFootprintToSegs=function(t){var e,n,i=this.sliceRangeByRow(t.unzonedRange);for(e=0;e<i.length;e++)n=i[e],this.isRTL?(n.leftCol=this.daysPerRow-1-n.lastRowDayIndex,n.rightCol=this.daysPerRow-1-n.firstRowDayIndex):(n.leftCol=n.firstRowDayIndex,n.rightCol=n.lastRowDayIndex);return i},e.prototype.renderDates=function(t){this.dateProfile=t,this.updateDayTable(),this.renderGrid()},e.prototype.unrenderDates=function(){this.removeSegPopover()},e.prototype.renderGrid=function(){var t,e,n=this.view,i=this.rowCnt,r=this.colCnt,o="";for(this.headContainerEl&&this.headContainerEl.html(this.renderHeadHtml()),t=0;t<i;t++)o+=this.renderDayRowHtml(t,this.isRigid);for(this.el.html(o),this.rowEls=this.el.find(".fc-row"),this.cellEls=this.el.find(".fc-day, .fc-disabled-day"),this.rowCoordCache=new s.default({els:this.rowEls,isVertical:!0}),this.colCoordCache=new s.default({els:this.cellEls.slice(0,this.colCnt),isHorizontal:!0}),t=0;t<i;t++)for(e=0;e<r;e++)this.publiclyTrigger("dayRender",{context:n,args:[this.getCellDate(t,e),this.getCellEl(t,e),n]})},e.prototype.renderDayRowHtml=function(t,e){var n=this.view.calendar.theme,i=["fc-row","fc-week",n.getClass("dayRow")];return e&&i.push("fc-rigid"),'<div class="'+i.join(" ")+'"><div class="fc-bg"><table class="'+n.getClass("tableGrid")+'">'+this.renderBgTrHtml(t)+'</table></div><div class="fc-content-skeleton"><table>'+(this.getIsNumbersVisible()?"<thead>"+this.renderNumberTrHtml(t)+"</thead>":"")+"</table></div></div>"},e.prototype.getIsNumbersVisible=function(){return this.getIsDayNumbersVisible()||this.cellWeekNumbersVisible},e.prototype.getIsDayNumbersVisible=function(){return this.rowCnt>1},e.prototype.renderNumberTrHtml=function(t){return"<tr>"+(this.isRTL?"":this.renderNumberIntroHtml(t))+this.renderNumberCellsHtml(t)+(this.isRTL?this.renderNumberIntroHtml(t):"")+"</tr>"},e.prototype.renderNumberIntroHtml=function(t){return this.renderIntroHtml()},e.prototype.renderNumberCellsHtml=function(t){var e,n,i=[];for(e=0;e<this.colCnt;e++)n=this.getCellDate(t,e),i.push(this.renderNumberCellHtml(n));return i.join("")},e.prototype.renderNumberCellHtml=function(t){var e,n,i=this.view,r="",o=this.dateProfile.activeUnzonedRange.containsDate(t),s=this.getIsDayNumbersVisible()&&o;return s||this.cellWeekNumbersVisible?(e=this.getDayClasses(t),e.unshift("fc-day-top"),this.cellWeekNumbersVisible&&(n="ISO"===t._locale._fullCalendar_weekCalc?1:t._locale.firstDayOfWeek()),r+='<td class="'+e.join(" ")+'"'+(o?' data-date="'+t.format()+'"':"")+">",this.cellWeekNumbersVisible&&t.day()===n&&(r+=i.buildGotoAnchorHtml({date:t,type:"week"},{class:"fc-week-number"},t.format("w"))),s&&(r+=i.buildGotoAnchorHtml(t,{class:"fc-day-number"},t.format("D"))),r+="</td>"):"<td/>"},e.prototype.prepareHits=function(){this.colCoordCache.build(),this.rowCoordCache.build(),this.rowCoordCache.bottoms[this.rowCnt-1]+=this.bottomCoordPadding},e.prototype.releaseHits=function(){this.colCoordCache.clear(),this.rowCoordCache.clear()},e.prototype.queryHit=function(t,e){if(this.colCoordCache.isLeftInBounds(t)&&this.rowCoordCache.isTopInBounds(e)){var n=this.colCoordCache.getHorizontalIndex(t),i=this.rowCoordCache.getVerticalIndex(e);if(null!=i&&null!=n)return this.getCellHit(i,n)}},e.prototype.getHitFootprint=function(t){var e=this.getCellRange(t.row,t.col);return new u.default(new l.default(e.start,e.end),!0)},e.prototype.getHitEl=function(t){return this.getCellEl(t.row,t.col)},e.prototype.getCellHit=function(t,e){return{row:t,col:e,component:this,left:this.colCoordCache.getLeftOffset(e),right:this.colCoordCache.getRightOffset(e),top:this.rowCoordCache.getTopOffset(t),bottom:this.rowCoordCache.getBottomOffset(t)}},e.prototype.getCellEl=function(t,e){return this.cellEls.eq(t*this.colCnt+e)},e.prototype.executeEventUnrender=function(){this.removeSegPopover(),t.prototype.executeEventUnrender.call(this)},e.prototype.getOwnEventSegs=function(){
2752return t.prototype.getOwnEventSegs.call(this).concat(this.popoverSegs||[])},e.prototype.renderDrag=function(t,e,n){var i;for(i=0;i<t.length;i++)this.renderHighlight(t[i].componentFootprint);if(t.length&&e&&e.component!==this)return this.helperRenderer.renderEventDraggingFootprints(t,e,n),!0},e.prototype.unrenderDrag=function(){this.unrenderHighlight(),this.helperRenderer.unrender()},e.prototype.renderEventResize=function(t,e,n){var i;for(i=0;i<t.length;i++)this.renderHighlight(t[i].componentFootprint);this.helperRenderer.renderEventResizingFootprints(t,e,n)},e.prototype.unrenderEventResize=function(){this.unrenderHighlight(),this.helperRenderer.unrender()},e.prototype.removeSegPopover=function(){this.segPopover&&this.segPopover.hide()},e.prototype.limitRows=function(t){var e,n,i=this.eventRenderer.rowStructs||[];for(e=0;e<i.length;e++)this.unlimitRow(e),!1!==(n=!!t&&("number"==typeof t?t:this.computeRowLevelLimit(e)))&&this.limitRow(e,n)},e.prototype.computeRowLevelLimit=function(t){function e(t,e){o=Math.max(o,r(e).outerHeight())}var n,i,o,s=this.rowEls.eq(t),a=s.height(),l=this.eventRenderer.rowStructs[t].tbodyEl.children();for(n=0;n<l.length;n++)if(i=l.eq(n).removeClass("fc-limited"),o=0,i.find("> td > :first-child").each(e),i.position().top+o>a)return n;return!1},e.prototype.limitRow=function(t,e){var n,i,o,s,a,l,u,d,c,p,h,f,g,v,y,m=this,b=this.eventRenderer.rowStructs[t],w=[],D=0,E=function(n){for(;D<n;)l=m.getCellSegs(t,D,e),l.length&&(c=i[e-1][D],y=m.renderMoreLink(t,D,l),v=r("<div/>").append(y),c.append(v),w.push(v[0])),D++};if(e&&e<b.segLevels.length){for(n=b.segLevels[e-1],i=b.cellMatrix,o=b.tbodyEl.children().slice(e).addClass("fc-limited").get(),s=0;s<n.length;s++){for(a=n[s],E(a.leftCol),d=[],u=0;D<=a.rightCol;)l=this.getCellSegs(t,D,e),d.push(l),u+=l.length,D++;if(u){for(c=i[e-1][a.leftCol],p=c.attr("rowspan")||1,h=[],f=0;f<d.length;f++)g=r('<td class="fc-more-cell"/>').attr("rowspan",p),l=d[f],y=this.renderMoreLink(t,a.leftCol+f,[a].concat(l)),v=r("<div/>").append(y),g.append(v),h.push(g[0]),w.push(g[0]);c.addClass("fc-limited").after(r(h)),o.push(c[0])}}E(this.colCnt),b.moreEls=r(w),b.limitedEls=r(o)}},e.prototype.unlimitRow=function(t){var e=this.eventRenderer.rowStructs[t];e.moreEls&&(e.moreEls.remove(),e.moreEls=null),e.limitedEls&&(e.limitedEls.removeClass("fc-limited"),e.limitedEls=null)},e.prototype.renderMoreLink=function(t,e,n){var i=this,o=this.view;return r('<a class="fc-more"/>').text(this.getMoreLinkText(n.length)).on("click",function(s){var a=i.opt("eventLimitClick"),l=i.getCellDate(t,e),u=r(s.currentTarget),d=i.getCellEl(t,e),c=i.getCellSegs(t,e),p=i.resliceDaySeg
2752s(c,l),h=i.resliceDaySegs(n,l);"function"==typeof a&&(a=i.publiclyTrigger("eventLimitClick",{context:o,args:[{date:l.clone(),dayEl:d,moreEl:u,segs:p,hiddenSegs:h},s,o]})),"popover"===a?i.showSegPopover(t,e,u,p):"string"==typeof a&&o.calendar.zoomTo(l,a)})},e.prototype.showSegPopover=function(t,e,n,i){var r,o,s=this,l=this.view,u=n.parent();r=1===this.rowCnt?l.el:this.rowEls.eq(t),o={className:"fc-more-popover "+l.calendar.theme.getClass("popover"),content:this.renderSegPopoverContent(t,e,i),parentEl:l.el,top:r.offset().top,autoHide:!0,viewportConstrain:this.opt("popoverViewportConstrain"),hide:function(){s.popoverSegs&&s.triggerBeforeEventSegsDestroyed(s.popoverSegs),s.segPopover.removeElement(),s.segPopover=null,s.popoverSegs=null}},this.isRTL?o.right=u.offset().left+u.outerWidth()+1:o.left=u.offset().left-1,this.segPopover=new a.default(o),this.segPopover.show(),this.bindAllSegHandlersToEl(this.segPopover.el),this.triggerAfterEventSegsRendered(i)},e.prototype.renderSegPopoverContent=function(t,e,n){var i,s=this.view,a=s.calendar.theme,l=this.getCellDate(t,e).format(this.opt("dayPopoverFormat")),u=r('<div class="fc-header '+a.getClass("popoverHeader")+'"><span class="fc-close '+a.getIconClass("close")+'"></span><span class="fc-title">'+o.htmlEscape(l)+'</span><div class="fc-clear"/></div><div class="fc-body '+a.getClass("popoverContent")+'"><div class="fc-event-container"></div></div>'),d=u.find(".fc-event-container");for(n=this.eventRenderer.renderFgSegEls(n,!0),this.popoverSegs=n,i=0;i<n.length;i++)this.hitsNeeded(),n[i].hit=this.getCellHit(t,e),this.hitsNotNeeded(),d.append(n[i].el);return u},e.prototype.resliceDaySegs=function(t,e){var n,i,o,s=e.clone(),a=s.clone().add(1,"days"),c=new l.default(s,a),p=[];for(n=0;n<t.length;n++)i=t[n],(o=i.footprint.componentFootprint.unzonedRange.intersect(c))&&p.push(r.extend({},i,{footprint:new d.default(new u.default(o,i.footprint.componentFootprint.isAllDay),i.footprint.eventDef,i.footprint.eventInstance),isStart:i.isStart&&o.isStart,isEnd:i.isEnd&&o.isEnd}));return this.eventRenderer.sortEventSegs(p),p},e.prototype.getMoreLinkText=function(t){var e=this.opt("eventLimitText");return"function"==typeof e?e(t):"+"+t+" "+e},e.prototype.getCellSegs=function(t,e,n){for(var i,r=this.eventRenderer.rowStructs[t].segMatrix,o=n||0,s=[];o<r.length;)i=r[o][e],i&&s.push(i),o++;return s},e}(h.default);e.default=m,m.prototype.eventRendererClass=g.default,m.prototype.businessHourRendererClass=c.default,m.prototype.helperRendererClass=v.default,m.prototype.fillRendererClass=y.default,p.default.mixInto(m),f.default.mixInto(m)},function(t,e,n){function i(t){return function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.colWeekNumbersVisible=!1,e}return r.__extends(e,t),e.prototype.renderHeadIntroHtml=function(){var t=this.view;return this.colWeekNumbersVisible?'<th class="fc-week-number '+t.calendar.theme.getClass("widgetHeader")+'" '+t.weekNumberStyleAttr()+"><span>"+s.htmlEscape(this.opt("weekNumberTitle"))+"</span></th>":""},e.prototype.renderNumberIntroHtml=function(t){var e=this.view,n=this.getCellDate(t,0);return this.colWeekNumbersVisible?'<td class="fc-week-number" '+e.weekNumberStyleAttr()+">"+e.buildGotoAnchorHtml({date:n,type:"week",forceOff:1===this.colCnt},n.format("w"))+"</td>":""},e.prototype.renderBgIntroHtml=function(){var t=this.view;return this.colWeekNumbersVisible?'<td class="fc-week-number '+t.calendar.theme.getClass("widgetContent")+'" '+t.weekNumberStyleAttr()+"></td>":""},e.prototype.renderIntroHtml=function(){var t=this.view;return this.colWeekNumbersVisible?'<td class="fc-week-number" '+t.weekNumberStyleAttr()+"></td>":""},e.prototype.getIsNumbersVisible=function(){return d.default.prototype.getIsNumbersVisible.apply(this,arguments)||this.colWeekNumbersVisible},e}(t)}Object.defineProperty(e,"__esModule",{value:!0});var r=n(2),o=n(3),s=n(4),a=n(39),l=n(41),u=n(228),d=n(61),c=function(t){function e(e,n){var i=t.call(this,e,n)||this;return i.dayGrid=i.instantiateDayGrid(),i.dayGrid.isRigid=i.hasRigidRows(),i.opt("weekNumbers")&&(i.opt("weekNumbersWithinDays")?(i.dayGrid.cellWeekNumbersVisible=!0,i.dayGrid.colWeekNumbersVisible=!1):(i.dayGrid.cellWeekNumbersVisible=!1,i.dayGrid.colWeekNumbersVisible=!0)),i.addChild(i.dayGrid),i.scroller=new a.default({overflowX:"hidden",overflowY:"auto"}),i}return r.__extends(e,t),e.prototype.instantiateDayGrid=function(){return new(i(this.dayGridClass))(this)},e.prototype.executeDateRender=function(e){this.dayGrid.breakOnWeeks=/year|month|week/.test(e.currentRangeUnit),t.prototype.executeDateRender.call(this,e)},e.prototype.renderSkeleton=function(){var t,e;this.el.addClass("fc-basic-view").html(this.renderSkeletonHtml()),this.scroller.render(),t=this.scroller.el.addClass("fc-day-grid-container"),e=o('<div class="fc-day-grid" />').appendTo(t),this.el.find(".fc-body > tr > td").append(t),this.dayGrid.headContainerEl=this.el.find(".fc-head-container"),this.dayGrid.setElement(e)},e.prototype.unrenderSkeleton=function(){this.dayGrid.removeElement(),this.scroller.destroy()},e.prototype.renderSkeletonHtml=function(){var t=this.calendar.theme;return'<table class="'+t.getClass("tableGrid")+'">'+(this.opt("columnHeader")?'<thead class="fc-head"><tr><td class="fc-head-container '+t.getClass("widgetHeader")+'">&nbsp;</td></tr></thead>':"")+'<tbody class="fc-body"><tr><td class="'+t.getClass("widgetContent")+'"></td></tr></tbody></table>'},e.prototype.weekNumberStyleAttr=function(){return null!=this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},e.prototype.hasRigidRows=function(){var t=this.opt("eventLimit");return t&&"number"!=typeof t},e.prototype.updateSize=function(e,n,i){var r,o,a=this.opt("eventLimit"),l=this.dayGrid.headContainerEl.find(".fc-row");if(!this.dayGrid.rowEls)return void(n||(r=this.computeScrollerHeight(e),this.scroller.setHeight(r)));t.prototype.updateSize.call(this,e,n,i),this.dayGrid.colWeekNumbersVisible&&(this.weekNumberWidth=s.matchCellWidths(this.el.find(".fc-week-number"))),this.scroller.clear(),s.uncompensateScroll(l),this.dayGrid.removeSegPopover(),a&&"number"==typeof a&&this.dayGrid.limitRows(a),r=this.computeScrollerHeight(e),this.setGridHeight(r,n),a&&"number"!=typeof a&&this.dayGrid.limitRows(a),n||(this.scroller.setHeight(r),o=this.scroller.getScrollbarWidths(),(o.left||o.right)&&(s.compensateScroll(l,o),r=this.computeScrollerHeight(e),this.scroller.setHeight(r)),this.scroller.lockOverflow(o))},e.prototype.computeScrollerHeight=function(t){return t-s.subtractInnerElHe
2752ight(this.el,this.scroller.el)},e.prototype.setGridHeight=function(t,e){e?s.undistributeHeight(this.dayGrid.rowEls):s.distributeHeight(this.dayGrid.rowEls,t,!0)},e.prototype.computeInitialDateScroll=function(){return{top:0}},e.prototype.queryDateScroll=function(){return{top:this.scroller.getScrollTop()}},e.prototype.applyDateScroll=function(t){void 0!==t.top&&this.scroller.setScrollTop(t.top)},e}(l.default);e.default=c,c.prototype.dateProfileGeneratorClass=u.default,c.prototype.dayGridClass=d.default},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(t,e,n){function i(t,e,n){var i;for(i=0;i<t.length;i++)if(!e(t[i].eventInstance.toLegacy(),n?n.toLegacy():null))return!1;return!0}function r(t,e){var n,i,r,o,s=e.toLegacy();for(n=0;n<t.length;n++){if(i=t[n].eventInstance,r=i.def,!1===(o=r.getOverlap()))return!1;if("function"==typeof o&&!o(i.toLegacy(),s))return!1}return!0}Object.defineProperty(e,"__esModule",{value:!0});var o=n(5),s=n(12),a=n(49),l=n(6),u=n(35),d=function(){function t(t,e){this.eventManager=t,this._calendar=e}return t.prototype.opt=function(t){return this._calendar.opt(t)},t.prototype.isEventInstanceGroupAllowed=function(t){var e,n=t.getEventDef(),i=this.eventRangesToEventFootprints(t.getAllEventRanges()),r=this.getPeerEventInstances(n),o=r.map(u.eventInstanceToEventRange),s=this.eventRangesToEventFootprints(o),a=n.getConstraint(),l=n.getOverlap(),d=this.opt("eventAllow");for(e=0;e<i.length;e++)if(!this.isFootprintAllowed(i[e].componentFootprint,s,a,l,i[e].eventInstance))return!1;if(d)for(e=0;e<i.length;e++)if(!1===d(i[e].componentFootprint.toLegacy(this._calendar),i[e].getEventLegacy()))return!1;return!0},t.prototype.getPeerEventInstances=function(t){return this.eventManager.getEventInstancesWithoutId(t.id)},t.prototype.isSelectionFootprintAllowed=function(t){var e,n=this.eventManager.getEventInstances(),i=n.map(u.eventInstanceToEventRange),r=this.eventRangesToEventFootprints(i);return!!this.isFootprintAllowed(t,r,this.opt("selectConstraint"),this.opt("selectOverlap"))&&(!(e=this.opt("selectAllow"))||!1!==e(t.toLegacy(this._calendar)))},t.prototype.isFootprintAllowed=function(t,e,n,o,s){var a,l;if(null!=n&&(a=this.constraintValToFootprints(n,t.isAllDay),!this.isFootprintWithinConstraints(t,a)))return!1;if(l=this.collectOverlapEventFootprints(e,t),!1===o){if(l.length)return!1}else if("function"==typeof o&&!i(l,o,s))return!1;return!(s&&!r(l,s))},t.prototype.isFootprintWithinConstraints=function(t,e){var n;for(n=0;n<e.length;n++)if(this.footprintContainsFootprint(e[n],t))return!0;return!1},t.prototype.constraintValToFootprints=function(t,e){var n;return"businessHours"===t?this.buildCurrentBusinessFootprints(e):"object"==typeof t?(n=this.parseEventDefToInstances(t),n?this.eventInstancesToFootprints(n):this.parseFootprints(t)):null!=t?(n=this.eventManager.getEventInstancesWithId(t),this.eventInstancesToFootprints(n)):void 0},t.prototype.buildCurrentBusinessFootprints=function(t){var e=this._calendar.view,n=e.get("businessHourGenerator"),i=e.dateProfile.activeUnzonedRange,r=n.buildEventInstanceGroup(t,i);return r?this.eventInstancesToFootprints(r.eventInstances):[]},t.prototype.eventInstancesToFootprints=function(t){var e=t.map(u.eventInstanceToEventRange);return this.eventRangesToEventFootprints(e).map(u.eventFootprintToComponentFootprint)},t.prototype.collectOverlapEventFootprints=function(t,e){var n,i=[];for(n=0;n<t.length;n++)this.footprintsIntersect(e,t[n].componentFootprint)&&i.push(t[n]);return i},t.prototype.parseEventDefToInstances=function(t){var e=this.eventManager,n=a.default.parse(t,new l.default(this._calendar));return!!n&&n.buildInstances(e.currentPeriod.unzonedRange)},t.prototype.eventRangesToEventFootprints=function(t){var e,n=[];for(e=0;e<t.length;e++)n.push.apply(n,this.eventRangeToEventFootprints(t[e]));return n},t.prototype.eventRangeToEventFootprints=function(t){return[u.eventRangeToEventFootprint(t)]},t.prototype.parseFootprints=function(t){var e,n;return t.start&&(e=this._calendar.moment(t.start),e.isValid()||(e=null)),t.end&&(n=this._calendar.moment(t.end),n.isValid()||(n=null)),[new s.default(new o.default(e,n),e&&!e.hasTime()||n&&!n.hasTime())]},t.prototype.footprintContainsFootprint=function(t,e){return t.unzonedRange.containsRange(e.unzonedRange)},t.prototype.footprintsIntersect=function(t,e){return t.unzonedRange.intersectsWith(e.unzonedRange)},t}();e.default=d}
2752,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(4),o=n(14),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.defineStandardProps=function(t){var e=this.prototype;e.hasOwnProperty("standardPropMap")||(e.standardPropMap=Object.create(e.standardPropMap)),r.copyOwnProps(t,e.standardPropMap)},e.copyVerbatimStandardProps=function(t,e){var n,i=this.prototype.standardPropMap;for(n in i)null!=t[n]&&!0===i[n]&&(e[n]=t[n])},e.prototype.applyProps=function(t){var e,n=this.standardPropMap,i={},r={};for(e in t)!0===n[e]?this[e]=t[e]:!1===n[e]?i[e]=t[e]:r[e]=t[e];return this.applyMiscProps(r),this.applyManualStandardProps(i)},e.prototype.applyManualStandardProps=function(t){return!0},e.prototype.applyMiscProps=function(t){},e.prototype.isStandardProp=function(t){return t in this.standardPropMap},e}(o.default);e.default=s,s.prototype.standardPropMap={}},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t,e){this.def=t,this.dateProfile=e}return t.prototype.toLegacy=function(){var t=this.dateProfile,e=this.def.toLegacy();return e.start=t.start.clone(),e.end=t.end?t.end.clone():null,e},t}();e.default=n},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(0),s=n(34),a=n(209),l=n(17),u=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.isAllDay=function(){return!this.startTime&&!this.endTime},e.prototype.buildInstances=function(t){for(var e,n,i,r=this.source.calendar,o=t.getStart(),s=t.getEnd(),u=[];o.isBefore(s);)this.dowHash&&!this.dowHash[o.day()]||(e=r.applyTimezone(o),n=e.clone(),i=null,this.startTime?n.time(this.startTime):n.stripTime(),this.endTime&&(i=e.clone().time(this.endTime)),u.push(new a.default(this,new l.default(n,i,r)))),o.add(1,"days");return u},e.prototype.setDow=function(t){this.dowHash||(this.dowHash={});for(var e=0;e<t.length;e++)this.dowHash[t[e]]=!0},e.prototype.clone=function(){var e=t.prototype.clone.call(this);return e.startTime&&(e.startTime=o.duration(this.startTime)),e.endTime&&(e.endTime=o.duration(this.endTime)),this.dowHash&&(e.dowHash=r.extend({},this.dowHash)),e},e}(s.default);e.default=u,u.prototype.applyProps=function(t){var e=s.default.prototype.applyProps.call(this,t);return t.start&&(this.startTime=o.duration(t.start)),t.end&&(this.endTime=o.duration(t.end)),t.dow&&this.setDow(t.dow),e},u.defineStandardProps({start:!1,end:!1,dow:!1})},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t,e,n){this.unzonedRange=t,this.eventDef=e,n&&(this.eventInstance=n)}return t}();e.default=n},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(35),o=n(18),s=n(210),a=n(6),l={start:"09:00",end:"17:00",dow:[1,2,3,4,5],rendering:"inverse-background"},u=function(){function t(t,e){this.rawComplexDef=t,this.calendar=e}return t.prototype.buildEventInstanceGroup=function(t,e){var n,i=this.buildEventDefs(t);if(i.length)return n=new o.default(r.eventDefsToEventInstances(i,e)),n.explicitEventDef=i[0],n},t.prototype.buildEventDefs=function(t){var e,n=this.rawComplexDef,r=[],o=!1,s=[];for(!0===n?r=[{}]:i.isPlainObject(n)?r=[n]:i.isArray(n)&&(r=n,o=!0),e=0;e<r.length;e++)o&&!r[e].dow||s.push(this.buildEventDef(t,r[e]));return s},t.prototype.buildEventDef=function(t,e){var n=i.extend({},l,e);return t&&(n.start=null,n.end=null),s.default.parse(n,new a.default(this.calendar))},t}();e.default=u},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(19),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e}(r.default);e.default=o,o.prototype.classes={widget:"fc-unthemed",widgetHeader:"fc-widget-header",widgetContent:"fc-widget-content",buttonGroup:"fc-button-group",button:"fc-button",cornerLeft:"fc-corner-left",cornerRight:"fc-corner-right",stateDefault:"fc-state-default",stateActive:"fc-state-active",stateDisabled:"fc-state-disabled",stateHover:"fc-state-hover",stateDown:"fc-state-down",popoverHeader:"fc-widget-header",popoverContent:"fc-widget-content",headerRow:"fc-widget-header",dayRow:"fc-widget-content",listView:"fc-widget-content"},o.prototype.baseIconClass="fc-icon",o.prototype.iconClasses={close:"fc-icon-x",prev:"fc-icon-left-single-arrow",next:"fc-icon-right-single-arrow",prevYear:"fc-icon-left-double-arrow",nextYear:"fc-icon-right-double-arrow"},o.prototype.iconOverrideOption="buttonIcons",o.prototype.iconOverrideCustomButtonOption="icon",o.prototype.iconOverridePrefix="fc-icon-"}
2752,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(19),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e}(r.default);e.default=o,o.prototype.classes={widget:"ui-widget",widgetHeader:"ui-widget-header",widgetContent:"ui-widget-content",buttonGroup:"fc-button-group",button:"ui-button",cornerLeft:"ui-corner-left",cornerRight:"ui-corner-right",stateDefault:"ui-state-default",stateActive:"ui-state-active",stateDisabled:"ui-state-disabled",stateHover:"ui-state-hover",stateDown:"ui-state-down",today:"ui-state-highlight",popoverHeader:"ui-widget-header",popoverContent:"ui-widget-content",headerRow:"ui-widget-header",dayRow:"ui-widget-content",listView:"ui-widget-content"},o.prototype.baseIconClass="ui-icon",o.prototype.iconClasses={close:"ui-icon-closethick",prev:"ui-icon-circle-triangle-w",next:"ui-icon-circle-triangle-e",prevYear:"ui-icon-seek-prev",nextYear:"ui-icon-seek-next"},o.prototype.iconOverrideOption="themeButtonIcons",o.prototype.iconOverrideCustomButtonOption="themeIcon",o.prototype.iconOverridePrefix="ui-icon-"},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(20),s=n(6),a=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.parse=function(t,e){var n;return r.isFunction(t.events)?n=t:r.isFunction(t)&&(n={events:t}),!!n&&s.default.parse.call(this,n,e)},e.prototype.fetch=function(t,e,n){var i=this;return this.calendar.pushLoading(),o.default.construct(function(r){i.func.call(i.calendar,t.clone(),e.clone(),n,function(t){i.calendar.popLoading(),r(i.parseEventDefs(t))})})},e.prototype.getPrimitive=function(){return this.func},e.prototype.applyManualStandardProps=function(e){var n=t.prototype.applyManualStandardProps.call(this,e);return this.func=e.events,n},e}(s.default);e.default=a,a.defineStandardProps({events:!1})},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(20),a=n(6),l=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.parse=function(t,e){var n;return"string"==typeof t.url?n=t:"string"==typeof t&&(n={url:t}),!!n&&a.default.parse.call(this,n,e)},e.prototype.fetch=function(t,n,i){var a=this,l=this.ajaxSettings,u=l.success,d=l.error,c=this.buildRequestParams(t,n,i);return this.calendar.pushLoading(),s.default.construct(function(t,n){r.ajax(r.extend({},e.AJAX_DEFAULTS,l,{url:a.url,data:c,success:function(e,i,s){var l;a.calendar.popLoading(),e?(l=o.applyAll(u,a,[e,i,s]),r.isArray(l)&&(e=l),t(a.parseEventDefs(e))):n()},error:function(t,e,i){a.calendar.popLoading(),o.applyAll(d,a,[t,e,i]),n()}}))})},e.prototype.buildRequestParams=function(t,e,n){var i,o,s,a,l=this.calendar,u=this.ajaxSettings,d={};return i=this.startParam,null==i&&(i=l.opt("startParam")),o=this.endParam,null==o&&(o=l.opt("endParam")),s=this.timezoneParam,null==s&&(s=l.opt("timezoneParam")),a=r.isFunction(u.data)?u.data():u.data||{},r.extend(d,a),d[i]=t.format(),d[o]=e.format(),n&&"local"!==n&&(d[s]=n),d},e.prototype.getPrimitive=function(){return this.url},e.prototype.applyMiscProps=function(t){this.ajaxSettings=t},e.AJAX_DEFAULTS={dataType:"json",cache:!1},e}(a.default);e.default=l,l.defineStandardProps({url:!0,startParam:!0,endParam:!0,timezoneParam:!0})},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(11),r=function(){function t(){this.q=[],this.isPaused=!1,this.isRunning=!1}return t.prototype.queue=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];this.q.push.apply(this.q,t),this.tryStart()},t.prototype.pause=function(){this.isPaused=!0},t.prototype.resume=function(){this.isPaused=!1,this.tryStart()},t.prototype.getIsIdle=function(){return!this.isRunning&&!this.isPaused},t.prototype.tryStart=function(){!this.isRunning&&this.canRunNext()&&(this.isRunning=!0,this.trigger("start"),this.runRemaining())},t.prototype.canRunNext=function(){return!this.isPaused&&this.q.length},t.prototype.runRemaining=function(){var t,e,n=this;do{if(t=this.q.shift(),(e=this.runTask(t))&&e.then)return void e.then(function(){n.canRunNext()&&n.runRemaining()})}while(this.canRunNext());this.trigger("stop"),this.isRunning=!1,this.tryStart()},t.prototype.runTask=function(t){return t()},t}();e.default=r,i.default.mixInto(r)}
2752,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(217),o=function(t){function e(e){var n=t.call(this)||this;return n.waitsByNamespace=e||{},n}return i.__extends(e,t),e.prototype.queue=function(t,e,n){var i,r={func:t,namespace:e,type:n};e&&(i=this.waitsByNamespace[e]),this.waitNamespace&&(e===this.waitNamespace&&null!=i?this.delayWait(i):(this.clearWait(),this.tryStart())),this.compoundTask(r)&&(this.waitNamespace||null==i?this.tryStart():this.startWait(e,i))},e.prototype.startWait=function(t,e){this.waitNamespace=t,this.spawnWait(e)},e.prototype.delayWait=function(t){clearTimeout(this.waitId),this.spawnWait(t)},e.prototype.spawnWait=function(t){var e=this;this.waitId=setTimeout(function(){e.waitNamespace=null,e.tryStart()},t)},e.prototype.clearWait=function(){this.waitNamespace&&(clearTimeout(this.waitId),this.waitId=null,this.waitNamespace=null)},e.prototype.canRunNext=function(){if(!t.prototype.canRunNext.call(this))return!1;if(this.waitNamespace){for(var e=this.q,n=0;n<e.length;n++)if(e[n].namespace!==this.waitNamespace)return!0;return!1}return!0},e.prototype.runTask=function(t){t.func()},e.prototype.compoundTask=function(t){var e,n,i=this.q,r=!0;if(t.namespace&&"destroy"===t.type)for(e=i.length-1;e>=0;e--)switch(n=i[e],n.type){case"init":r=!1;case"add":case"remove":i.splice(e,1)}return r&&i.push(t),r},e}(r.default);e.default=o},function(t,e,n){function i(t){var e,n,i,r=[];for(e in t)for(n=t[e].eventInstances,i=0;i<n.length;i++)r.push(n[i].toLegacy());return r}Object.defineProperty(e,"__esModule",{value:!0});var r=n(2),o=n(3),s=n(0),a=n(4),l=n(10),u=n(47),d=n(237),c=n(35),p=function(t){function e(n,i){var r=t.call(this)||this;return r.isRTL=!1,r.hitsNeededDepth=0,r.hasAllDayBusinessHours=!1,r.isDatesRendered=!1,n&&(r.view=n),i&&(r.options=i),r.uid=String(e.guid++),r.childrenByUid={},r.nextDayThreshold=s.duration(r.opt("nextDayThreshold")),r.isRTL=r.opt("isRTL"),r.fillRendererClass&&(r.fillRenderer=new r.fillRendererClass(r)),r.eventRendererClass&&(r.eventRenderer=new r.eventRendererClass(r,r.fillRenderer)),r.helperRendererClass&&r.eventRenderer&&(r.helperRenderer=new r.helperRendererClass(r,r.eventRenderer)),r.businessHourRendererClass&&r.fillRenderer&&(r.businessHourRenderer=new r.businessHourRendererClass(r,r.fillRenderer)),r}return r.__extends(e,t),e.prototype.addChild=function(t){return!this.childrenByUid[t.uid]&&(this.childrenByUid[t.uid]=t,!0)},e.prototype.removeChild=function(t){return!!this.childrenByUid[t.uid]&&(delete this.childrenByUid[t.uid],!0)},e.prototype.updateSize=function(t,e,n){this.callChildren("updateSize",arguments)},e.prototype.opt=function(t){return this._getView().opt(t)},e.prototype.publiclyTrigger=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=this._getCalendar();return n.publiclyTrigger.apply(n,t)},e.prototype.hasPublicHandlers=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=this._getCalendar();return n.hasPublicHandlers.apply(n,t)},e.prototype.executeDateRender=function(t){this.dateProfile=t,this.renderDates(t),this.isDatesRendered=!0,this.callChildren("executeDateRender",arguments)},e.prototype.executeDateUnrender=function(){this.callChildren("executeDateUnrender",arguments),this.dateProfile=null,this.unrenderDates(),this.isDatesRendered=!1},e.prototype.renderDates=function(t){},e.prototype.unrenderDates=function(){},e.prototype.getNowIndicatorUnit=function(){},e.prototype.renderNowIndicator=function(t){this.callChildren("renderNowIndicator",arguments)},e.prototype.unrenderNowIndicator=function(){this.callChildren("unrenderNowIndicator",arguments)},e.prototype.renderBusinessHours=function(t){this.businessHourRenderer&&this.businessHourRenderer.render(t),this.callChildren("renderBusinessHours",arguments)},e.prototype.unrenderBusinessHours=function(){this.callChildren("unrenderBusinessHours",arguments),this.businessHourRenderer&&this.businessHourRenderer.unrender()},e.prototype.executeEventRender=function(t){this.eventRenderer?(this.eventRenderer.rangeUpdated(),this.eventRenderer.render(t)):this.renderEvents&&this.renderEvents(i(t)),this.callChildren("executeEventRender",arguments)},e.prototype.executeEventUnrender=function(){this.callChildren("executeEventUnrender",arguments),this.eventRenderer?this.eventRenderer.unrender():this.destroyEvents&&this.destroyEvents()},e.prototype.getBusinessHourSegs=function(){var t=this.getOwnBusinessHourSegs();return this.iterChildren(function(e){t.push.apply(t,e.getBusinessHourSegs())}),t},e.prototype.getOwnBusinessHourSegs=function(){return this.businessHourRenderer?this.businessHourRenderer.getSegs():[]},e.prototype.getEventSegs=function(){var t=this.getOwnEventSegs();return this.iterChildren(function(e){t.push.apply(t,e.getEventSegs())}),t},e.prototype.getOwnEventSegs=function(){return this.eventRenderer?this.eventRenderer.getSegs():[]},e.prototype.triggerAfterEventsRendered=function(){this.triggerAfterEventSegsRendered(this.getEventSegs()),this.publiclyTrigger("eventAfterAllRender",{context:this,args:[this]})},e.prototype.triggerAfterEventSegsRendered=function(t){var e=this;this.hasPublicHandlers("eventAfterRender")&&t.forEach(function(t){var n;t.el&&(n=t.footprint.getEventLegacy(),e.publiclyTrigger("eventAfterRender",{context:n,args:[n,t.el,e]}))})},e.prototype.triggerBeforeEventsDestroyed=function(){this.triggerBeforeEventSegsDestroyed(this.getEventSegs())},e.prototype.triggerBeforeEventSegsDestroyed=function(t){var e=this;this.hasPublicHandlers("eventDestroy")&&t.forEach(function(t){var n;t.el&&(n=t.footprint.getEventLegacy(),e.publiclyTrigger("eventDestroy",{context:n,args:[n,t.el,e]}))})},e.prototype.showEventsWithId=function(t){this.getEventSegs().forEac
2752h(function(e){e.footprint.eventDef.id===t&&e.el&&e.el.css("visibility","")}),this.callChildren("showEventsWithId",arguments)},e.prototype.hideEventsWithId=function(t){this.getEventSegs().forEach(function(e){e.footprint.eventDef.id===t&&e.el&&e.el.css("visibility","hidden")}),this.callChildren("hideEventsWithId",arguments)},e.prototype.renderDrag=function(t,e,n){var i=!1;return this.iterChildren(function(r){r.renderDrag(t,e,n)&&(i=!0)}),i},e.prototype.unrenderDrag=function(){this.callChildren("unrenderDrag",arguments)},e.prototype.renderEventResize=function(t,e,n){this.callChildren("renderEventResize",arguments)},e.prototype.unrenderEventResize=function(){this.callChildren("unrenderEventResize",arguments)},e.prototype.renderSelectionFootprint=function(t){this.renderHighlight(t),this.callChildren("renderSelectionFootprint",arguments)},e.prototype.unrenderSelection=function(){this.unrenderHighlight(),this.callChildren("unrenderSelection",arguments)},e.prototype.renderHighlight=function(t){this.fillRenderer&&this.fillRenderer.renderFootprint("highlight",t,{getClasses:function(){return["fc-highlight"]}}),this.callChildren("renderHighlight",arguments)},e.prototype.unrenderHighlight=function(){this.fillRenderer&&this.fillRenderer.unrender("highlight"),this.callChildren("unrenderHighlight",arguments)},e.prototype.hitsNeeded=function(){this.hitsNeededDepth++||this.prepareHits(),this.callChildren("hitsNeeded",arguments)},e.prototype.hitsNotNeeded=function(){this.hitsNeededDepth&&!--this.hitsNeededDepth&&this.releaseHits(),this.callChildren("hitsNotNeeded",arguments)},e.prototype.prepareHits=function(){},e.prototype.releaseHits=function(){},e.prototype.queryHit=function(t,e){var n,i,r=this.childrenByUid;for(n in r)if(i=r[n].queryHit(t,e))break;return i},e.prototype.getSafeHitFootprint=function(t){var e=this.getHitFootprint(t);return this.dateProfile.activeUnzonedRange.containsRange(e.unzonedRange)?e:null},e.prototype.getHitFootprint=function(t){},e.prototype.getHitEl=function(t){},e.prototype.eventRangesToEventFootprints=function(t){var e,n=[];for(e=0;e<t.length;e++)n.push.apply(n,this.eventRangeToEventFootprints(t[e]));return n},e.prototype.eventRangeToEventFootprints=function(t){return[c.eventRangeToEventFootprint(t)]},e.prototype.eventFootprintsToSegs=function(t){var e,n=[];for(e=0;e<t.length;e++)n.push.apply(n,this.eventFootprintToSegs(t[e]));return n},e.prototype.eventFootprintToSegs=function(t){var e,n,i,r=t.componentFootprint.unzonedRange;for(e=this.componentFootprintToSegs(t.componentFootprint),n=0;n<e.length;n++)i=e[n],r.isStart||(i.isStart=!1),r.isEnd||(i.isEnd=!1),i.footprint=t;return e},e.prototype.componentFootprintToSegs=function(t){return[]},e.prototype.callChildren=function(t,e){this.iterChildren(function(n){n[t].apply(n,e)})},e.prototype.iterChildren=function(t){var e,n=this.childrenByUid;for(e in n)t(n[e])},e.prototype._getCalendar=function(){var t=this;return t.calendar||t.view.calendar},e.prototype._getView=function(){return this.view},e.prototype._getDateProfile=function(){return this._getView().get("dateProfile")},e.prototype.buildGotoAnchorHtml=function(t,e,n){var i,r,s,u;return o.isPlainObject(t)?(i=t.date,r=t.type,s=t.forceOff):i=t,i=l.default(i),u={date:i.format("YYYY-MM-DD"),type:r||"day"},"string"==typeof e&&(n=e,e=null),e=e?" "+a.attrsToStr(e):"",n=n||"",!s&&this.opt("navLinks")?"<a"+e+' data-goto="'+a.htmlEscape(JSON.stringify(u))+'">'+n+"</a>":"<span"+e+">"+n+"</span>"},e.prototype.getAllDayHtml=function(){return this.opt("allDayHtml")||a.htmlEscape(this.opt("allDayText"))},e.prototype.getDayClasses=function(t,e){var n,i=this._getView(),r=[]
2753;return this.dateProfile.activeUnzonedRange.containsDate(t)?(r.push("fc-"+a.dayIDs[t.day()]),i.isDateInOtherMonth(t,this.dateProfile)&&r.push("fc-other-month"),n=i.calendar.getNow(),t.isSame(n,"day")?(r.push("fc-today"),!0!==e&&r.push(i.calendar.theme.getClass("today"))):t<n?r.push("fc-past"):r.push("fc-future")):r.push("fc-disabled-day"),r},e.prototype.formatRange=function(t,e,n,i){var r=t.end;return e&&(r=r.clone().subtract(1)),u.formatRange(t.start,r,n,i,this.isRTL)},e.prototype.currentRangeAs=function(t){return this._getDateProfile().currentUnzonedRange.as(t)},e.prototype.computeDayRange=function(t){var e=this._getCalendar(
2753),n=e.msToUtcMoment(t.startMs,!0),i=e.msToUtcMoment(t.endMs),r=+i.time(),o=i.clone().stripTime();return r&&r>=this.nextDayThreshold&&o.add(1,"days"),o<=n&&(o=n.clone().add(1,"days")),{start:n,end:o}},e.prototype.isMultiDayRange=function(t){var e=this.computeDayRange(t);return e.end.diff(e.start,"days")>1},e.guid=0,e}(d.default);e.default=p},function(t,e,n){function i(t,e){return null==e?t:r.isFunction(e)?t.filter(e):(e+="",t.filter(function(t){return t.id==e||t._id===e}))}Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),o=n(0),s=n(4),a=n(32),l=n(238),u=n(21),d=n(11),c=n(7),p=n(239),h=n(240),f=n(241),g=n(207),v=n(31),y=n(10),m=n(5),b=n(12),w=n(17),D=n(242),E=n(212),S=n(38),C=n(49),R=n(13),T=n(37),M=n(6),I=n(51),H=function(){function t(t,e){this.loadingLevel=0,this.ignoreUpdateViewSize=0,this.freezeContentHeightDepth=0,u.default.needed(),this.el=t,this.viewsByType={},this.optionsManager=new h.default(this,e),this.viewSpecManager=new f.default(this.optionsManager,this),this.initMomentInternals(),this.initCurrentDate(),this.initEventManager(),this.constraints=new g.default(this.eventManager,this),this.constructed()}return t.prototype.constructed=function(){},t.prototype.getView=function(){return this.view},t.prototype.publiclyTrigger=function(t,e){var n,i,o=this.opt(t);if(r.isPlainObject(e)?(n=e.context,i=e.args):r.isArray(e)&&(i=e),null==n&&(n=this.el[0]),i||(i=[]),this.triggerWith(t,n,i),o)return o.apply(n,i)},t.prototype.hasPublicHandlers=function(t){return this.hasHandlers(t)||this.opt(t)},t.prototype.option=function(t,e){var n;if("string"==typeof t){if(void 0===e)return this.optionsManager.get(t);n={},n[t]=e,this.optionsManager.add(n)}else"object"==typeof t&&this.optionsManager.add(t)},t.prototype.opt=function(t){return this.optionsManager.get(t)},t.prototype.instantiateView=function(t){var e=this.viewSpecManager.getViewSpec(t);if(!e)throw new Error('View type "'+t+'" is not valid');return new e.class(this,e)},t.prototype.isValidViewType=function(t){return Boolean(this.viewSpecManager.getViewSpec(t))},t.prototype.changeView=function(t,e){e&&(e.start&&e.end?this.optionsManager.recordOverrides({visibleRange:e}):this.currentDate=this.moment(e).stripZone()),this.renderView(t)},t.prototype.zoomTo=function(t,e){var n;e=e||"day",n=this.viewSpecManager.getViewSpec(e)||this.viewSpecManager.getUnitViewSpec(e),this.currentDate=t.clone(),this.renderView(n?n.type:null)},t.prototype.initCurrentDate=function(){var t=this.opt("defaultDate");this.currentDate=null!=t?this.moment(t).stripZone():this.getNow()},t.prototype.prev=function(){var t=this.view,e=t.dateProfileGenerator.buildPrev(t.get("dateProfile"));e.isValid&&(this.currentDate=e.date,this.renderView())},t.prototype.next=function(){var t=this.view,e=t.dateProfileGenerator.buildNext(t.get("dateProfile"));e.isValid&&(this.currentDate=e.date,this.renderView())},t.prototype.prevYear=function(){this.currentDate.add(-1,"years"),this.renderView()},t.prototype.nextYear=function(){this.currentDate.add(1,"years"),this.renderView()},t.prototype.today=function(){this.currentDate=this.getNow(),this.renderView()},t.prototype.gotoDate=function(t){this.currentDate=this.moment(t).stripZone(),this.renderView()},t.prototype.incrementDate=function(t){this.currentDate.add(o.duration(t)),this.renderView()},t.prototype.getDate=function(){return this.applyTimezone(this.currentDate)},t.prototype.pushLoading=function(){this.loadingLevel++||this.publiclyTrigger("loading",[!0,this.view])},t.prototype.popLoading=function(){--this.loadingLevel||this.publiclyTrigger("loading",[!1,this.view])},t.prototype.render=function(){this.contentEl?this.elementVisible()&&(this.calcSize(),this.updateViewSize()):this.initialRender()},t.prototype.initialRender=function(){var t=this,e=this.el;e.addClass("fc"),e.on("click.fc","a[data-goto]",function(e){var n=r(e.currentTarget),i=n.data("goto"),o=t.moment(i.date),a=i.type,l=t.view.opt("navLink"+s.capitaliseFirstLetter(a)+"Click");"function"==typeof l?l(o,e):("string"==typeof l&&(a=l),t.zoomTo(o,a))}),this.optionsManager.watch("settingTheme",["?theme","?themeSystem"],function(n){var i=I.getThemeSystemClass(n.themeSystem||n.theme),r=new i(t.optionsManager),o=r.getClass("widget");t.theme=r,o&&e.addClass(o)},function(){var n=t.theme.getClass("widget");t.theme=null,n&&e.removeClass(n)}),this.optionsManager.watch("settingBusinessHourGenerator",["?businessHours"],function(e){t.businessHourGenerator=new E.default(e.businessHours,t),t.view&&t.view.set("businessHourGenerator",t.businessHourGenerator)},function(){t.businessHourGenerator=null}),this.optionsManager.watch("applyingDirClasses",["?isRTL","?locale"],function(t){e.toggleClass("fc-ltr",!t.isRTL),e.toggleClass("fc-rtl",t.isRTL)}),this.contentEl=r("<div class='fc-view-container'/>").prependTo(e),this.initToolbars(),this.renderHeader(),this.renderFooter(),this.renderView(this.opt("defaultView")),this.opt("handleWindowResize")&&r(window).resize(this.windowResizeProxy=s.debounce(this.windowResize.bind(this),this.opt("windowResizeDelay")))},t.prototype.destroy=function(){this.view&&this.clearView(),this.toolbarsManager.proxyCall("removeElement"),this.contentEl.remove(),this.el.removeClass("fc fc-ltr fc-rtl"),this.optionsManager.unwatch("settingTheme"),this.optionsManager.unwatch("settingBusinessHourGenerator"),this.el.off(".fc"),this.windowResizeProxy&&(r(window).unbind("resize",this.windowResizeProxy),this.windowResizeProxy=null),u.default.unneeded()},t.prototype.elementVisible=function(){return this.el.is(":visible")},t.prototype.bindViewHandlers=function(t){var e=this;
2753t.watch("titleForCalendar",["title"],function(n){t===e.view&&e.setToolbarsTitle(n.title)}),t.watch("dateProfileForCalendar",["dateProfile"],function(n){t===e.view&&(e.currentDate=n.dateProfile.date,e.updateToolbarButtons(n.dateProfile))})},t.prototype.unbindViewHandlers=function(t){t.unwatch("titleForCalendar"),t.unwatch("dateProfileForCalendar")},t.prototype.renderView=function(t){var e,n=this.view;this.freezeContentHeight(),n&&t&&n.type!==t&&this.clearView(),!this.view&&t&&(e=this.view=this.viewsByType[t]||(this.viewsByType[t]=this.instantiateView(t)),this.bindViewHandlers(e),e.startBatchRender(),e.setElement(r("<div class='fc-view fc-"+t+"-view' />").appendTo(this.contentEl)),this.toolbarsManager.proxyCall("activateButton",t)),this.view&&(this.view.get("businessHourGenerator")!==this.businessHourGenerator&&this.view.set("businessHourGenerator",this.businessHourGenerator),this.view.setDate(this.currentDate),e&&e.stopBatchRender()),this.thawContentHeight()},t.prototype.clearView=function(){var t=this.view;this.toolbarsManager.proxyCall("deactivateButton",t.type),this.unbindViewHandlers(t),t.removeElement(),t.unsetDate(),this.view=null},t.prototype.reinitView=function(){var t=this.view,e=t.queryScroll();this.freezeContentHeight(),this.clearView(),this.calcSize(),this.renderView(t.type),this.view.applyScroll(e),this.thawContentHeight()},t.prototype.getSuggestedViewHeight=function(){return null==this.suggestedViewHeight&&this.calcSize(),this.suggestedViewHeight},t.prototype.isHeightAuto=function(){return"auto"===this.opt("contentHeight")||"auto"===this.opt("height")},t.prototype.updateViewSize=function(t){void 0===t&&(t=!1);var e,n=this.view;if(!this.ignoreUpdateViewSize&&n)return t&&(this.calcSize(),e=n.queryScroll()),this.ignoreUpdateViewSize++,n.updateSize(this.getSuggestedViewHeight(),this.isHeightAuto(),t),this.ignoreUpdateViewSize--,t&&n.applyScroll(e),!0},t.prototype.calcSize=function(){this.elementVisible()&&this._calcSize()},t.prototype._calcSize=function(){var t=this.opt("contentHeight"),e=this.opt("height");this.suggestedViewHeight="number"==typeof t?t:"function"==typeof t?t():"number"==typeof e?e-this.queryToolbarsHeight():"function"==typeof e?e()-this.queryToolbarsHeight():"parent"===e?this.el.parent().height()-this.queryToolbarsHeight():Math.round(this.contentEl.width()/Math.max(this.opt("aspectRatio"),.5))},t.prototype.windowResize=function(t){t.target===window&&this.view&&this.view.isDatesRendered&&this.updateViewSize(!0)&&this.publiclyTrigger("windowResize",[this.view])},t.prototype.freezeContentHeight=function(){this.freezeContentHeightDepth++||this.forceFreezeContentHeight()},t.prototype.forceFreezeContentHeight=function(){this.contentEl.css({width:"100%",height:this.contentEl.height(),overflow:"hidden"})},t.prototype.thawContentHeight=function(){this.freezeContentHeightDepth--,this.contentEl.css({width:"",height:"",overflow:""}),this.freezeContentHeightDepth&&this.forceFreezeContentHeight()},t.prototype.initToolbars=function(){this.header=new p.default(this,this.computeHeaderOptions()),this.footer=new p.default(this,this.computeFooterOptions()),this.toolbarsManager=new l.default([this.header,this.footer])},t.prototype.computeHeaderOptions=function(){return{extraClasses:"fc-header-toolbar",layout:this.opt("header")}},t.prototype.computeFooterOptions=function(){return{extraClasses:"fc-footer-toolbar",layout:this.opt("footer")}},t.prototype.renderHeader=function(){var t=this.header;t.setToolbarOptions(this.computeHeaderOptions()),t.render(),t.el&&this.el.prepend(t.el)},t.prototype.renderFooter=function(){var t=this.footer;t.setToolbarOptions(this.computeFooterOptions()),t.render(),t.el&&this.el.append(t.el)},t.prototype.setToolbarsTitle=function(t){this.toolbarsManager.proxyCall("updateTitle",t)},t.prototype.updateToolbarButtons=function(t){var e=this.getNow(),n=this.view,i=n.dateProfileGenerator.build(e),r=n.dateProfileGenerator.buildPrev(n.get("dateProfile")),o=n.dateProfileGenerator.buildNext(n.get("dateProfile"));this.toolbarsManager.proxyCall(i.isValid&&!t.currentUnzonedRange.containsDate(e)?"enableButton":"disableButton","today"),this.toolbarsManager.proxyCall(r.isValid?"enableButton":"disableButton","prev"),this.toolbarsManager.proxyCall(o.isValid?"enableButton":"disableButton","
2753next")},t.prototype.queryToolbarsHeight=function(){return this.toolbarsManager.items.reduce(function(t,e){return t+(e.el?e.el.outerHeight(!0):0)},0)},t.prototype.select=function(t,e){this.view.select(this.buildSelectFootprint.apply(this,arguments))},t.prototype.unselect=function(){this.view&&this.view.unselect()},t.prototype.buildSelectFootprint=function(t,e){var n,i=this.moment(t).stripZone();return n=e?this.moment(e).stripZone():i.hasTime()?i.clone().add(this.defaultTimedEventDuration):i.clone().add(this.defaultAllDayEventDuration),new b.default(new m.default(i,n),!i.hasTime())},t.prototype.initMomentInternals=function(){var t=this;this.defaultAllDayEventDuration=o.duration(this.opt("defaultAllDayEventDuration")),this.defaultTimedEventDuration=o.duration(this.opt("defaultTimedEventDuration")),this.optionsManager.watch("buildingMomentLocale",["?locale","?monthNames","?monthNamesShort","?dayNames","?dayNamesShort","?firstDay","?weekNumberCalculation"],function(e){var n,i=e.weekNumberCalculation,r=e.firstDay;"iso"===i&&(i="ISO");var o=Object.create(v.getMomentLocaleData(e.locale));e.monthNames&&(o._months=e.monthNames),e.monthNamesShort&&(o._monthsShort=e.monthNamesShort),e.dayNames&&(o._weekdays=e.dayNames),e.dayNamesShort&&(o._weekdaysShort=e.dayNamesShort),null==r&&"ISO"===i&&(r=1),null!=r&&(n=Object.create(o._week),n.dow=r,o._week=n),"ISO"!==i&&"local"!==i&&"function"!=typeof i||(o._fullCalendar_weekCalc=i),t.localeData=o,t.currentDate&&t.localizeMoment(t.currentDate)})},t.prototype.moment=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n;return"local"===this.opt("timezone")?(n=y.default.apply(null,t),n.hasTime()&&n.local()):n="UTC"===this.opt("timezone")?y.default.utc.apply(null,t):y.default.parseZone.apply(null,t),this.localizeMoment(n),n},t.prototype.msToMoment=function(t,e){var n=y.default.utc(t);return e?n.stripTime():n=this.applyTimezone(n),this.localizeMoment(n),n},t.prototype.msToUtcMoment=function(t,e){var n=y.default.utc(t);return e&&n.stripTime(),this.localizeMoment(n),n},t.prototype.localizeMoment=function(t){t._locale=this.localeData},t.prototype.getIsAmbigTimezone=function(){return"local"!==this.opt("timezone")&&"UTC"!==this.opt("timezone")},t.prototype.applyTimezone=function(t){if(!t.hasTime())return t.clone();var e,n=this.moment(t.toArray()),i=t.time().asMilliseconds()-n.time().asMilliseconds();return i&&(e=n.clone().add(i),t.time().asMilliseconds()-e.time().asMilliseconds()==0&&(n=e)),n},t.prototype.footprintToDateProfile=function(t,e){void 0===e&&(e=!1);var n,i=y.default.utc(t.unzonedRange.startMs);return e||(n=y.default.utc(t.unzonedRange.endMs)),t.isAllDay?(i.stripTime(),n&&n.stripTime()):(i=this.applyTimezone(i),n&&(n=this.applyTimezone(n))),new w.default(i,n,this)},t.prototype.getNow=function(){var t=this.opt("now");return"function"==typeof t&&(t=t()),this.moment(t).stripZone()},t.prototype.humanizeDuration=function(t){return t.locale(this.opt("locale")).humanize()},t.prototype.parseUnzonedRange=function(t){var e=null,n=null;return t.start&&(e=this.moment(t.start).stripZone()),t.end&&(n=this.moment(t.end).stripZone()),e||n?e&&n&&n.isBefore(e)?null:new m.default(e,n):null},t.prototype.initEventManager=function(){var t=this,e=new D.default(this),n=this.opt("eventSources")||[],i=this.opt("events");this.eventManager=e,i&&n.unshift(i),e.on("release",function(e){t.trigger("eventsReset",e)}),e.freeze(),n.forEach(function(n){var i=S.default.parse(n,t);i&&e.addSource(i)}),e.thaw()},t.prototype.requestEvents=function(t,e){return this.eventManager.requestEvents(t,e,this.opt("timezone"),!this.opt("lazyFetching"))},t.prototype.getEventEnd=function(t){return t.end?t.end.clone():this.getDefaultEventEnd(t.allDay,t.start)},t.prototype.getDefaultEventEnd=function(t,e){var n=e.clone();return t?n.stripTime().add(this.defaultAllDayEventDuration):n.add(this.defaultTimedEventDuration),this.getIsAmbigTimezone()&&n.stripZone(),n},t.prototype.rerenderEvents=function(){this.view.flash("displayingEvents")},t.prototype.refetchEvents=function(){this.eventManager.refetchAllSources()},t.prototype.renderEvents=function(t,e){this.eventManager.freeze();for(var n=0;n<t.length;n++)this.renderEvent(t[n],e);this.eventManager.thaw()},t.prototype.renderEvent=function(t,e){void 0===e&&(e=!1);var n=this.eventManager,i=C.default.parse(t,t.source||n.stickySource);i&&n.addEventDef(i,e)},t.prototype.removeEvents=function(t){var e,n,r=this.eventManager,o=[],s={};if(null==t)r.removeAllEventDefs();
2753else{for(r.getEventInstances().forEach(function(t){o.push(t.toLegacy())}),o=i(o,t),n=0;n<o.length;n++)e=this.eventManager.getEventDefByUid(o[n]._id),s[e.id]=!0;r.freeze();for(n in s)r.removeEventDefsById(n);r.thaw()}},t.prototype.clientEvents=function(t){var e=[];return this.eventManager.getEventInstances().forEach(function(t){e.push(t.toLegacy())}),i(e,t)},t.prototype.updateEvents=function(t){this.eventManager.freeze();for(var e=0;e<t.length;e++)this.updateEvent(t[e]);this.eventManager.thaw()},t.prototype.updateEvent=function(t){var e,n,i=this.eventManager.getEventDefByUid(t._id);i instanceof R.default&&(e=i.buildInstance(),n=T.default.createFromRawProps(e,t,null),this.eventManager.mutateEventsWithId(i.id,n))},t.prototype.getEventSources=function(){return this.eventManager.otherSources.slice()},t.prototype.getEventSourceById=function(t){return this.eventManager.getSourceById(M.default.normalizeId(t))},t.prototype.addEventSource=function(t){var e=S.default.parse(t,this);e&&this.eventManager.addSource(e)},t.prototype.removeEventSources=function(t){var e,n,i=this.eventManager;if(null==t)this.eventManager.removeAllSources();else{for(e=i.multiQuerySources(t),i.freeze(),n=0;n<e.length;n++)i.removeSource(e[n]);i.thaw()}},t.prototype.removeEventSource=function(t){var e,n=this.eventManager,i=n.querySources(t);for(n.freeze(),e=0;e<i.length;e++)n.removeSource(i[e]);n.thaw()},t.prototype.refetchEventSources=function(t){var e,n=this.eventManager,i=n.multiQuerySources(t);for(n.freeze(),e=0;e<i.length;e++)n.refetchSource(i[e]);n.thaw()},t.defaults=a.globalDefaults,t.englishDefaults=a.englishDefaults,t.rtlDefaults=a.rtlDefaults,t}();e.default=H,d.default.mixInto(H),c.default.mixInto(H)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(0),r=n(4),o=n(5),s=function(){function t(t){this._view=t}return t.prototype.opt=function(t){return this._view.opt(t)},t.prototype.trimHiddenDays=function(t){return this._view.trimHiddenDays(t)},t.prototype.msToUtcMoment=function(t,e){return this._view.calendar.msToUtcMoment(t,e)},t.prototype.buildPrev=function(t){var e=t.date.clone().startOf(t.currentRangeUnit).subtract(t.dateIncrement);return this.build(e,-1)},t.prototype.buildNext=function(t){var e=t.date.clone().startOf(t.currentRangeUnit).add(t.dateIncrement);return this.build(e,1)},t.prototype.build=function(t,e,n){void 0===n&&(n=!1);var r,o,s,a,l,u,d=!t.hasTime(),c=null,p=null;return r=this.buildValidRange(),r=this.trimHiddenDays(r),n&&(t=this.msToUtcMoment(r.constrainDate(t),d)),o=this.buildCurrentRangeInfo(t,e),s=/^(year|month|week|day)$/.test(o.unit),a=this.buildRenderRange(this.trimHiddenDays(o.unzonedRange),o.unit,s),a=this.trimHiddenDays(a),l=a.clone(),this.opt("showNonCurrentDates")||(l=l.intersect(o.unzonedRange)),c=i.duration(this.opt("minTime")),p=i.duration(this.opt("maxTime")),l=this.adjustActiveRange(l,c,p),l=l.intersect(r),l&&(t=this.msToUtcMoment(l.constrainDate(t),d)),u=o.unzonedRange.intersectsWith(r),{validUnzonedRange:r,currentUnzonedRange:o.unzonedRange,currentRangeUnit:o.unit,isRangeAllDay:s,activeUnzonedRange:l,renderUnzonedRange:a,minTime:c,maxTime:p,isValid:u,date:t,dateIncrement:this.buildDateIncrement(o.duration)}},t.prototype.buildValidRange=function(){return this._view.getUnzonedRangeOption("validRange",this._view.calendar.getNow())||new o.default},t.prototype.buildCurrentRangeInfo=function(t,e){var n,i=this._view.viewSpec,o=null,s=null,a=null;return i.duration?(o=i.duration,s=i.durationUnit,a=this.buildRangeFromDuration(t,e,o,s)):(n=this.opt("dayCount"))?(s="day",a=this.buildRangeFromDayCount(t,e,n)):(a=this.buildCustomVisibleRange(t))?s=r.computeGreatestUnit(a.getStart(),a.getEnd()):(o=this.getFallbackDuration(),s=r.computeGreatestUnit(o),a=this.buildRangeFromDuration(t,e,o,s)),{duration:o,unit:s,unzonedRange:a}},t.prototype.getFallbackDuration=function(){return i.duration({days:1})},t.prototype.adjustActiveRange=function(t,e,n){var i=t.getStart(),r=t.getEnd();return this._view.usesMinMaxTime&&(e<0&&i.time(0).add(e),n>864e5&&r.time(n-864e5)),new o.default(i,r)},t.prototype.buildRangeFromDuration=function(t,e,n,s){function a(){d=t.clone().startOf(h),c=d.clone().add(n),p=new o.default(d,c)}var l,u,d,c,p,h=this.opt("dateAlignment");return h||(l=this.opt("dateIncrement"),l?(u=i.duration(l),h=u<n?r.computeDurationGreatestUnit(u,l):s):h=s),n.as("days")<=1&&this._view.isHiddenD
2753ay(d)&&(d=this._view.skipHiddenDays(d,e),d.startOf("day")),a(),this.trimHiddenDays(p)||(t=this._view.skipHiddenDays(t,e),a()),p},t.prototype.buildRangeFromDayCount=function(t,e,n){var i,r=this.opt("dateAlignment"),s=0,a=t.clone();r&&a.startOf(r),a.startOf("day"),a=this._view.skipHiddenDays(a,e),i=a.clone();do{i.add(1,"day"),this._view.isHiddenDay(i)||s++}while(s<n);return new o.default(a,i)},t.prototype.buildCustomVisibleRange=function(t){var e=this._view.getUnzonedRangeOption("visibleRange",this._view.calendar.applyTimezone(t));return!e||null!=e.startMs&&null!=e.endMs?e:null},t.prototype.buildRenderRange=function(t,e,n){return t.clone()},t.prototype.buildDateIncrement=function(t){var e,n=this.opt("dateIncrement");return n?i.duration(n):(e=this.opt("dateAlignment"))?i.duration(1,e):t||i.duration({days:1})},t}();e.default=s},function(t,e,n){function i(t){var e,n,i,r,l=a.dataAttrPrefix;return l&&(l+="-"),e=t.data(l+"event")||null,e&&(e="object"==typeof e?o.extend({},e):{},n=e.start,null==n&&(n=e.time),i=e.duration,r=e.stick,delete e.start,delete e.time,delete e.duration,delete e.stick),null==n&&(n=t.data(l+"start")),null==n&&(n=t.data(l+"time")),null==i&&(i=t.data(l+"duration")),null==r&&(r=t.data(l+"stick")),n=null!=n?s.duration(n):null,i=null!=i?s.duration(i):null,r=Boolean(r),{eventProps:e,startTime:n,duration:i,stick:r}}Object.defineProperty(e,"__esModule",{value:!0});var r=n(2),o=n(3),s=n(0),a=n(16),l=n(4),u=n(10),d=n(7),c=n(23),p=n(13),h=n(18),f=n(6),g=n(15),v=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.isDragging=!1,e}return r.__extends(e,t),e.prototype.end=function(){this.dragListener&&this.dragListener.endInteraction()},e.prototype.bindToDocument=function(){this.listenTo(o(document),{dragstart:this.handleDragStart,sortstart:this.handleDragStart})},e.prototype.unbindFromDocument=function(){this.stopListeningTo(o(document))},e.prototype.handleDragStart=function(t,e){var n,i;this.opt("droppable")&&(n=o((e?e.item:null)||t.target),i=this.opt("dropAccept"),(o.isFunction(i)?i.call(n[0],n):n.is(i))&&(this.isDragging||this.listenToExternalDrag(n,t,e)))},e.prototype.listenToExternalDrag=function(t,e,n){var r,o=this,s=this.component,a=this.view,u=i(t);(this.dragListener=new c.default(s,{interactionStart:function(){o.isDragging=!0},hitOver:function(t){var e,n=!0,i=t.component.getSafeHitFootprint(t);i?(r=o.computeExternalDrop(i,u),r?(e=new h.default(r.buildInstances()),n=u.eventProps?s.isEventInstanceGroupAllowed(e):s.isExternalInstanceGroupAllowed(e)):n=!1):n=!1,n||(r=null,l.disableCursor()),r&&s.renderDrag(s.eventRangesToEventFootprints(e.sliceRenderRanges(s.dateProfile.renderUnzonedRange,a.calendar)))},hitOut:function(){r=null},hitDone:function(){l.enableCursor(),s.unrenderDrag()},interactionEnd:function(e){r&&a.reportExternalDrop(r,Boolean(u.eventProps),Boolean(u.stick),t,e,n),o.isDragging=!1,o.dragListener=null}})).startDrag(e)},e.prototype.computeExternalDrop=function(t,e){var n,i=this.view.calendar,r=u.default.utc(t.unzonedRange.startMs).stripZone();return t.isAllDay&&(e.startTime?r.time(e.startTime):r.stripTime()),e.duration&&(n=r.clone().add(e.duration)),r=i.applyTimezone(r),n&&(n=i.applyTimezone(n)),p.default.parse(o.extend({},e.eventProps,{start:r,end:n}),new f.default(i))},e}(g.default);e.default=v,d.default.mixInto(v),a.dataAttrPrefix=""},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(37),a=n(50),l=n(23),u=n(15),d=function(t){function e(e,n){var i=t.call(this,e)||this;return i.isResizing=!1,i.eventPointing=n,i}return i.__extends(e,t),e.prototype.end=function(){this.dragListener&&this.dragListener.endInteraction()},e.prototype.bindToEl=function(t){var e=this.component;e.bindSegHandlerToEl(t,"mousedown",this.handleMouseDown.bind(this)),e.bindSegHandlerToEl(t,"touchstart",this.handleTouchStart.bind(this))},e.prototype.handleMouseDown=function(t,e){this.component.canStartResize(t,e)&&this.buildDragListener(t,r(e.target).is(".fc-start-resizer")).startInteraction(e,{distance:5})},e.prototype.handleTouchStart=function(t,e){this.component.canStartResize(t,e)&&this.buildDragListener(t,r(e.target).is(".fc-start-resizer")).startInteraction(e)},e.prototype.buildDragListener=function(t,e){var n,i,r=this,s=this.component,a=this.view,u=a.calendar,d=u.eventManager,c=t.el,p=t.footprint.eventDef,h=t.footprint.eventInstance;return this.dragListener=new l.default(s,{scroll:this.opt("dragScroll"),subjectEl:c,interactionStart:function(){n=!1},dragStart:function(e){n=!0,r.eventPointing.handleMouseout(t,e),r.segResizeStart(t,e)},hitOver:function(n,l,c){var h,f=!0,g=s.getSafeHitFootprint(c),v=s.getSafeHitFootprint(n);g&&v?(i=e?r.computeEventStartResizeMutation(g,v,t.footprint):r.computeEventEndResizeMutation(g,v,t.footprint),i?(h=d.buildMutatedEventInstanceGroup(p.id,i),f=s.isEventInstanceGroupAllowed(h)):f=!1):f=!1,f?i.isEmpty()&&(i=null):(i=null,o.disableCursor(
2753)),i&&(a.hideEventsWithId(t.footprint.eventDef.id),a.renderEventResize(s.eventRangesToEventFootprints(h.sliceRenderRanges(s.dateProfile.renderUnzonedRange,u)),t))},hitOut:function(){i=null},hitDone:function(){a.unrenderEventResize(t),a.showEventsWithId(t.footprint.eventDef.id),o.enableCursor()},interactionEnd:function(e){n&&r.segResizeStop(t,e),i&&a.reportEventResize(h,i,c,e),r.dragListener=null}})},e.prototype.segResizeStart=function(t,e){this.isResizing=!0,this.component.publiclyTrigger("eventResizeStart",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},e.prototype.segResizeStop=function(t,e){this.isResizing=!1,this.component.publiclyTrigger("eventResizeStop",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},e.prototype.computeEventStartResizeMutation=function(t,e,n){var i,r,o=n.componentFootprint.unzonedRange,l=this.component.diffDates(e.unzonedRange.getStart(),t.unzonedRange.getStart());return o.getStart().add(l)<o.getEnd()&&(i=new a.default,i.setStartDelta(l),r=new s.default,r.setDateMutation(i),r)},e.prototype.computeEventEndResizeMutation=function(t,e,n){var i,r,o=n.componentFootprint.unzonedRange,l=this.component.diffDates(e.unzonedRange.getEnd(),t.unzonedRange.getEnd());return o.getEnd().add(l)>o.getStart()&&(i=new a.default,i.setEndDelta(l),r=new s.default,r.setDateMutation(i),r)},e}(u.default);e.default=d},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(4),o=n(37),s=n(50),a=n(54),l=n(23),u=n(244),d=n(15),c=function(t){function e(e,n){var i=t.call(this,e)||this;return i.isDragging=!1,i.eventPointing=n,i}return i.__extends(e,t),e.prototype.end=function(){this.dragListener&&this.dragListener.endInteraction()},e.prototype.getSelectionDelay=function(){var t=this.opt("eventLongPressDelay");return null==t&&(t=this.opt("longPressDelay")),t},e.prototype.bindToEl=function(t){var e=this.component;e.bindSegHandlerToEl(t,"mousedown",this.handleMousedown.bind(this)),e.bindSegHandlerToEl(t,"touchstart",this.handleTouchStart.bind(this))},e.prototype.handleMousedown=function(t,e){!this.component.shouldIgnoreMouse()&&this.component.canStartDrag(t,e)&&this.buildDragListener(t).startInteraction(e,{distance:5})},e.prototype.handleTouchStart=function(t,e){var n=this.component,i={delay:this.view.isEventDefSelected(t.footprint.eventDef)?0:this.getSelectionDelay()};n.canStartDrag(t,e)?this.buildDragListener(t).startInteraction(e,i):n.canStartSelection(t,e)&&this.buildSelectListener(t).startInteraction(e,i)},e.prototype.buildSelectListener=function(t){var e=this,n=this.view,i=t.footprint.eventDef,r=t.footprint.eventInstance;if(this.dragListener)return this.dragListener;var o=this.dragListener=new a.default({dragStart:function(t){o.isTouch&&!n.isEventDefSelected(i)&&r&&n.selectEventInstance(r)},interactionEnd:function(t){e.dragListener=null}});return o},e.prototype.buildDragListener=function(t){var e,n,i,o=this,s=this.component,a=this.view,d=a.calendar,c=d.eventManager,p=t.el,h=t.footprint.eventDef,f=t.footprint.eventInstance;if(this.dragListener)return this.dragListener;var g=this.dragListener=new l.default(a,{scroll:this.opt("dragScroll"),subjectEl:p,subjectCenter:!0,interactionStart:function(i){t.component=s,e=!1,n=new u.default(t.el,{additionalClass:"fc-dragging",parentEl:a.el,opacity:g.isTouch?null:o.opt("dragOpacity"),revertDuration:o.opt("dragRevertDuration"),zIndex:2}),n.hide(),n.start(i)},dragStart:function(n){g.isTouch&&!a.isEventDefSelected(h)&&f&&a.selectEventInstance(f),e=!0,o.eventPointing.handleMouseout(t,n),o.segDragStart(t,n),a.hideEventsWithId(t.footprint.eventDef.id)},hitOver:function(e,l,u){var p,f,v,y=!0;t.hit&&(u=t.hit),p=u.component.getSafeHitFootprint(u),f=e.component.getSafeHitFootprint(e),p&&f?(i=o.computeEventDropMutation(p,f,h),i?(v=c.buildMutatedEventInstanceGroup(h.id,i),y=s.isEventInstanceGroupAllowed(v)):y=!1):y=!1,y||(i=null,r.disableCursor()),i&&a.renderDrag(s.eventRangesToEventFootprints(v.sliceRenderRanges(s.dateProfile.renderUnzonedRange,d)),t,g.isTouch)?n.hide():n.show(),l&&(i=null)},hitOut:function(){a.unrenderDrag(t),n.show(),i=null}
2753,hitDone:function(){r.enableCursor()},interactionEnd:function(r){delete t.component,n.stop(!i,function(){e&&(a.unrenderDrag(t),o.segDragStop(t,r)),a.showEventsWithId(t.footprint.eventDef.id),i&&a.reportEventDrop(f,i,p,r)}),o.dragListener=null}});return g},e.prototype.segDragStart=function(t,e){this.isDragging=!0,this.component.publiclyTrigger("eventDragStart",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},e.prototype.segDragStop=function(t,e){this.isDragging=!1,this.component.publiclyTrigger("eventDragStop",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},e.prototype.computeEventDropMutation=function(t,e,n){var i=new o.default;return i.setDateMutation(this.computeEventDateMutation(t,e)),i},e.prototype.computeEventDateMutation=function(t,e){var n,i,r=t.unzonedRange.getStart(),o=e.unzonedRange.getStart(),a=!1,l=!1,u=!1;return t.isAllDay!==e.isAllDay&&(a=!0,e.isAllDay?(u=!0,r.stripTime()):l=!0),n=this.component.diffDates(o,r),i=new s.default,i.clearEnd=a,i.forceTimed=l,i.forceAllDay=u,i.setDateDelta(n),i},e}(d.default);e.default=c},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(4),o=n(23),s=n(12),a=n(5),l=n(15),u=function(t){function e(e){var n=t.call(this,e)||this;return n.dragListener=n.buildDragListener(),n}return i.__extends(e,t),e.prototype.end=function(){this.dragListener.endInteraction()},e.prototype.getDelay=function(){var t=this.opt("selectLongPressDelay");return null==t&&(t=this.opt("longPressDelay")),t},e.prototype.bindToEl=function(t){var e=this,n=this.component,i=this.dragListener;n.bindDateHandlerToEl(t,"mousedown",function(t){e.opt("selectable")&&!n.shouldIgnoreMouse()&&i.startInteraction(t,{distance:e.opt("selectMinDistance")})}),n.bindDateHandlerToEl(t,"touchstart",function(t){e.opt("selectable")&&!n.shouldIgnoreTouch()&&i.startInteraction(t,{delay:e.getDelay()})}),r.preventSelection(t)},e.prototype.buildDragListener=function(){var t,e=this,n=this.component;return new o.default(n,{scroll:this.opt("dragScroll"),interactionStart:function(){t=null},dragStart:function(t){e.view.unselect(t)},hitOver:function(i,o,s){var a,l;s&&(a=n.getSafeHitFootprint(s),l=n.getSafeHitFootprint(i),t=a&&l?e.computeSelection(a,l):null,t?n.renderSelectionFootprint(t):!1===t&&r.disableCursor())},hitOut:function(){t=null,n.unrenderSelection()},hitDone:function(){r.enableCursor()},interactionEnd:function(n,i){!i&&t&&e.view.reportSelection(t,n)}})},e.prototype.computeSelection=function(t,e){var n=this.computeSelectionFootprint(t,e);return!(n&&!this.isSelectionFootprintAllowed(n))&&n},e.prototype.computeSelectionFootprint=function(t,e){var n=[t.unzonedRange.startMs,t.unzonedRange.endMs,e.unzonedRange.startMs,e.unzonedRange.endMs];return n.sort(r.compareNumbers),new s.default(new a.default(n[0],n[3]),t.isAllDay)},e.prototype.isSelectionFootprintAllowed=function(t){return this.component.dateProfile.validUnzonedRange.containsRange(t.unzonedRange)&&this.view.calendar.constraints.isSelectionFootprintAllowed(t)},e}(l.default);e.default=u},function(t,e,n){function i(t){var e,n=[],i=[];for(e=0;e<t.length;e++)t[e].componentFootprint.isAllDay?n.push(t[e]):i.push(t[e]);return{allDay:n,timed:i}}Object.defineProperty(e,"__esModule",{value:!0});var r,o,s=n(2),a=n(0),l=n(3),u=n(4),d=n(39),c=n(41),p=n(227),h=n(61),f=function(t){function e(e,n){var i=t.call(this,e,n)||this;return i.usesMinMaxTime=!0,i.timeGrid=i.instantiateTimeGrid(),i.addChild(i.timeGrid),i.opt("allDaySlot")&&(i.dayGrid=i.instantiateDayGrid(),i.addChild(i.dayGrid)),i.scroller=new d.default({overflowX:"hidden",overflowY:"auto"}),i}
2754return s.__extends(e,t),e.prototype.instantiateTimeGrid=function(){var t=new this.timeGridClass(this);return u.copyOwnProps(r,t),t},e.prototype.instantiateDayGrid=function(){var t=new this.dayGridClass(this);return u.copyOwnProps(o,t),t},e.prototype.renderSkeleton=function(){var t,e;this.el.addClass("fc-agenda-view").html(this.renderSkeletonHtml()),this.scroller.render(),t=this.scroller.el.addClass("fc-time-grid-container"),e=l('<div class="fc-time-grid" />').appendTo(t),this.el.find(".fc-body > tr > td").append(t),this.timeGrid.headContainerEl=this.el.find(".fc-head-container"),this.timeGrid.setElement(e),this.dayGrid&&(this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight())},e.prototype.unrenderSkeleton=function(){this.timeGrid.removeElement(),this.dayGrid&&this.dayGrid.removeElement(),this.scroller.destroy()},e.prototype.renderSkeletonHtml=function(){var t=this.calendar.theme;return'<table class="'+t.getClass("tableGrid")+'">'+(this.opt("columnHeader")?'<thead class="fc-head"><tr><td class="fc-head-container '+t.getClass("widgetHeader")+'">&nbsp;</td></tr></thead>':"")+'<tbody class="fc-body"><tr><td class="'+t.getClass("widgetContent")+'">'+(this.dayGrid?'<div class="fc-day-grid"/><hr class="fc-divider '+t.getClass("widgetHeader")+'"/>':"")+"</td></tr></tbody></table>"},e.prototype.axisStyleAttr=function(){return null!=this.axisWidth?'style="width:'+this.axisWidth+'px"':""},e.prototype.getNowIndicatorUnit=function(){return this.timeGrid.getNowIndicatorUnit()},e.prototype.updateSize=function(e,n,i){var r,o,s;if(t.prototype.updateSize.call(this,e,n,i),this.axisWidth=u.matchCellWidths(this.el.find(".fc-axis")),!this.timeGrid.colEls)return void(n||(o=this.computeScrollerHeight(e),this.scroller.setHeight(o)));var a=this.el.find(".fc-row:not(.fc-scroller *)");this.timeGrid.bottomRuleEl.hide(),this.scroller.clear(),u.uncompensateScroll(a),this.dayGrid&&(this.dayGrid.removeSegPopover(),r=this.opt("eventLimit"),r&&"number"!=typeof r&&(r=5),r&&this.dayGrid.limitRows(r)),n||(o=this.computeScrollerHeight(e),this.scroller.setHeight(o),s=this.scroller.getScrollbarWidths(),(s.left||s.right)&&(u.compensateScroll(a,s),o=this.computeScrollerHeight(e),this.scroller.setHeight(o)),this.scroller.lockOverflow(s),this.timeGrid.getTotalSlatHeight()<o&&this.timeGrid.bottomRuleEl.show())},e.prototype.computeScrollerHeight=function(t){return t-u.subtractInnerElHe
2754ight(this.el,this.scroller.el)},e.prototype.computeInitialDateScroll=function(){var t=a.duration(this.opt("scrollTime")),e=this.timeGrid.computeTimeTop(t);return e=Math.ceil(e),e&&e++,{top:e}},e.prototype.queryDateScroll=function(){return{top:this.scroller.getScrollTop()}},e.prototype.applyDateScroll=function(t){void 0!==t.top&&this.scroller.setScrollTop(t.top)},e.prototype.getHitFootprint=function(t){return t.component.getHitFootprint(t)},e.prototype.getHitEl=function(t){return t.component.getHitEl(t)},e.prototype.executeEventRender=function(t){var e,n,i={},r={};for(e in t)n=t[e],n.getEventDef().isAllDay()?i[e]=n:r[e]=n;this.timeGrid.executeEventRender(r),this.dayGrid&&this.dayGrid.executeEventRender(i)},e.prototype.renderDrag=function(t,e,n){var r=i(t),o=!1;return o=this.timeGrid.renderDrag(r.timed,e,n),this.dayGrid&&(o=this.dayGrid.renderDrag(r.allDay,e,n)||o),o},e.prototype.renderEventResize=function(t,e,n){var r=i(t);this.timeGrid.renderEventResize(r.timed,e,n),this.dayGrid&&this.dayGrid.renderEventResize(r.allDay,e,n)},e.prototype.renderSelectionFootprint=function(t){t.isAllDay?this.dayGrid&&this.dayGrid.renderSelectionFootprint(t):this.timeGrid.renderSelectionFootprint(t)},e}(c.default);e.default=f,f.prototype.timeGridClass=p.default,f.prototype.dayGridClass=h.default,r={renderHeadIntroHtml:function(){var t,e=this.view,n=e.calendar,i=n.msToUtcMoment(this.dateProfile.renderUnzonedRange.startMs,!0);return this.opt("weekNumbers")?(t=i.format(this.opt("smallWeekFormat")),'<th class="fc-axis fc-week-number '+n.theme.getClass("widgetHeader")+'" '+e.axisStyleAttr()+">"+e.buildGotoAnchorHtml({date:i,type:"week",forceOff:this.colCnt>1},u.htmlEscape(t))+"</th>"):'<th class="fc-axis '+n.theme.getClass("widgetHeader")+'" '+e.axisStyleAttr()+"></th>"},renderBgIntroHtml:function(){var t=this.view;return'<td class="fc-axis '+t.calendar.theme.getClass("widgetContent")+'" '+t.axisStyleAttr()+"></td>"},renderIntroHtml:function(){return'<td class="fc-axis" '+this.view.axisStyleAttr()+"></td>"}},o={renderBgIntroHtml:function(){var t=this.view;return'<td class="fc-axis '+t.calendar.theme.getClass("widgetContent")+'" '+t.axisStyleAttr()+"><span>"+t.getAllDayHtml()+"</span></td>"},renderIntroHtml:function(){return'<td class="fc-axis" '+this.view.axisStyleAttr()+"></td>"}}},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(0),s=n(4),a=n(40),l=n(56),u=n(60),d=n(55),c=n(53),p=n(5),h=n(12),f=n(246),g=n(247),v=n(248),y=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}],m=function(t){function e(e){var n=t.call(this,e)||this;return n.processOptions(),n}return i.__extends(e,t),e.prototype.componentFootprintToSegs=function(t){var e,n=this.sliceRangeByTimes(t.unzonedRange);for(e=0;e<n.length;e++)this.isRTL?n[e].col=this.daysPerRow-1-n[e].dayIndex:n[e].col=n[e].dayIndex;return n},e.prototype.sliceRangeByTimes=function(t){var e,n,i=[];for(n=0;n<this.daysPerRow;n++)(e=t.intersect(this.dayRanges[n]))&&i.push({startMs:e.startMs,endMs:e.endMs,isStart:e.isStart,isEnd:e.isEnd,dayIndex:n});return i},e.prototype.processOptions=function(){var t,e=this.opt("slotDuration"),n=this.opt("snapDuration");e=o.duration(e),n=n?o.duration(n):e,this.slotDuration=e,this.snapDuration=n,this.snapsPerSlot=e/n,t=this.opt("slotLabelFormat"),r.isArray(t)&&(t=t[t.length-1]),this.labelFormat=t||this.opt("smallTimeFormat"),t=this.opt("slotLabelInterval"),this.labelInterval=t?o.duration(t):this.computeLabelInterval(e)},e.prototype.computeLabelInterval=function(t){var e,n,i;for(e=y.length-1;e>=0;e--)if(n=o.duration(y[e]),i=s.divideDurationByDuration(n,t),s.isInt(i)&&i>1)return n;return o.duration(t)},e.prototype.renderDates=function(t){this.dateProfile=t,this.updateDayTable(),this.renderSlats(),this.renderColumns()},e.prototype.unrenderDates=function(){this.unrenderColumns()},e.prototype.renderSkeleton=function(){var t=this.view.calendar.theme;this.el.html('<div class="fc-bg"></div><div class="fc-slats"></div><hr class="fc-divider '+t.getClass("widgetHeader")+'" style="display:none" />'),this.bottomRuleEl=this.el.find("hr")},e.prototype.renderSlats=function(){var t=this.view.calendar.theme;
2754this.slatContainerEl=this.el.find("> .fc-slats").html('<table class="'+t.getClass("tableGrid")+'">'+this.renderSlatRowHtml()+"</table>"),this.slatEls=this.slatContainerEl.find("tr"),this.slatCoordCache=new c.default({els:this.slatEls,isVertical:!0})},e.prototype.renderSlatRowHtml=function(){for(var t,e,n,i=this.view,r=i.calendar,a=r.theme,l=this.isRTL,u=this.dateProfile,d="",c=o.duration(+u.minTime),p=o.duration(0);c<u.maxTime;)t=r.msToUtcMoment(u.renderUnzonedRange.startMs).time(c),e=s.isInt(s.divideDurationByDuration(p,this.labelInterval)),n='<td class="fc-axis fc-time '+a.getClass("widgetContent")+'" '+i.axisStyleAttr()+">"+(e?"<span>"+s.htmlEscape(t.format(this.labelFormat))+"</span>":"")+"</td>",d+='<tr data-time="'+t.format("HH:mm:ss")+'"'+(e?"":' class="fc-minor"')+">"+(l?"":n)+'<td class="'+a.getClass("widgetContent")+'"/>'+(l?n:"")+"</tr>",c.add(this.slotDuration),p.add(this.slotDuration);return d},e.prototype.renderColumns=function(){var t=this.dateProfile,e=this.view.calendar.theme;this.dayRanges=this.dayDates.map(function(e){return new p.default(e.clone().add(t.minTime),e.clone().add(t.maxTime))}),this.headContainerEl&&this.headContainerEl.html(this.renderHeadHtml()),this.el.find("> .fc-bg").html('<table class="'+e.getClass("tableGrid")+'">'+this.renderBgTrHtml(0)+"</table>"),this.colEls=this.el.find(".fc-day, .fc-disabled-day"),this.colCoordCache=new c.default({els:this.colEls,isHorizontal:!0}),this.renderContentSkeleton()},e.prototype.unrenderColumns=function(){this.unrenderContentSkeleton()},e.prototype.renderContentSkeleton=function(){var t,e,n="";for(t=0;t<this.colCnt;t++)n+='<td><div class="fc-content-col"><div class="fc-event-container fc-helper-container"></div><div class="fc-event-container"></div><div class="fc-highlight-container"></div><div class="fc-bgevent-container"></div><div class="fc-business-container"></div></div></td>';e=this.contentSkeletonEl=r('<div class="fc-content-skeleton"><table><tr>'+n+"</tr></table></div>"),this.colContainerEls=e.find(".fc-content-col"),this.helperContainerEls=e.find(".fc-helper-container"),this.fgContainerEls=e.find(".fc-event-container:not(.fc-helper-container)"),this.bgContainerEls=e.find(".fc-bgevent-container"),this.highlightContainerEls=e.find(".fc-highlight-container"),this.businessContainerEls=e.find(".fc-business-container"),this.bookendCells(e.find("tr")),this.el.append(e)},e.prototype.unrenderContentSkeleton=function(){this.contentSkeletonEl&&(this.contentSkeletonEl.remove(),this.contentSkeletonEl=null,this.colContainerEls=null,this.helperContainerEls=null,this.fgContainerEls=null,this.bgContainerEls=null,this.highlightContainerEls=null,this.businessContainerEls=null)},e.prototype.groupSegsByCol=function(t){var e,n=[];for(e=0;e<this.colCnt;e++)n.push([]);for(e=0;e<t.length;e++)n[t[e].col].push(t[e]);return n},e.prototype.attachSegsByCol=function(t,e){var n,i,r;for(n=0;n<this.colCnt;n++)for(i=t[n],r=0;r<i.length;r++)e.eq(n).append(i[r].el)},e.prototype.getNowIndicatorUnit=function(){return"minute"},e.prototype.renderNowIndicator=function(t){if(this.colContainerEls){var e,n=this.componentFootprintToSegs(new h.default(new p.default(t,t.valueOf()+1),!1)),i=this.computeDateTop(t,t),o=[];for(e=0;e<n.length;e++)o.push(r('<div class="fc-now-indicator fc-now-indicator-line"></div>').css("top",i).appendTo(this.colContainerEls.eq(n[e].col))[0]);n.length>0&&o.push(r('<div class="fc-now-indicator fc-now-indicator-arrow"></div>').css("top",i).appendTo(this.el.find(".fc-content-skeleton"))[0]),this.nowIndicatorEls=r(o)}},e.prototype.unrenderNowIndicator=function(){this.nowIndicatorEls&&(this.nowIndicatorEls.remove(),this.nowIndicatorEls=null)},e.prototype.updateSize=function(e,n,i){t.prototype.updateSize.call(this,e,n,i),this.slatCoordCache.build(),i&&this.updateSegVerticals([].concat(this.eventRenderer.getSegs(),this.businessSegs||[]))}
2754,e.prototype.getTotalSlatHeight=function(){return this.slatContainerEl.outerHeight()},e.prototype.computeDateTop=function(t,e){return this.computeTimeTop(o.duration(t-e.clone().stripTime()))},e.prototype.computeTimeTop=function(t){var e,n,i=this.slatEls.length,r=this.dateProfile,o=(t-r.minTime)/this.slotDuration;return o=Math.max(0,o),o=Math.min(i,o),e=Math.floor(o),e=Math.min(e,i-1),n=o-e,this.slatCoordCache.getTopPosition(e)+this.slatCoordCache.getHeight(e)*n},e.prototype.updateSegVerticals=function(t){this.computeSegVerticals(t),this.assignSegVerticals(t)},e.prototype.computeSegVerticals=function(t){var e,n,i,r=this.opt("agendaEventMinHeight");for(e=0;e<t.length;e++)n=t[e],i=this.dayDates[n.dayIndex],n.top=this.computeDateTop(n.startMs,i),n.bottom=Math.max(n.top+r,this.computeDateTop(n.endMs,i))},e.prototype.assignSegVerticals=function(t){var e,n;for(e=0;e<t.length;e++)n=t[e],n.el.css(this.generateSegVerticalCss(n))},e.prototype.generateSegVerticalCss=function(t){return{top:t.top,bottom:-t.bottom}},e.prototype.prepareHits=function(){this.colCoordCache.build(),this.slatCoordCache.build()},e.prototype.releaseHits=function(){this.colCoordCache.clear()},e.prototype.queryHit=function(t,e){var n=this.snapsPerSlot,i=this.colCoordCache,r=this.slatCoordCache;if(i.isLeftInBounds(t)&&r.isTopInBounds(e)){var o=i.getHorizontalIndex(t),s=r.getVerticalIndex(e);if(null!=o&&null!=s){var a=r.getTopOffset(s),l=r.getHeight(s),u=(e-a)/l,d=Math.floor(u*n),c=s*n+d,p=a+d/n*l,h=a+(d+1)/n*l;return{col:o,snap:c,component:this,left:i.getLeftOffset(o),right:i.getRightOffset(o),top:p,bottom:h}}}},e.prototype.getHitFootprint=function(t){var e,n=this.getCellDate(0,t.col),i=this.computeSnapTime(t.snap);return n.time(i),e=n.clone().add(this.snapDuration),new h.default(new p.default(n,e),!1)},e.prototype.computeSnapTime=function(t){return o.duration(this.dateProfile.minTime+this.snapDuration*t)},e.prototype.getHitEl=function(t){return this.colEls.eq(t.col)},e.prototype.renderDrag=function(t,e,n){var i;if(e){if(t.length)return this.helperRenderer.renderEventDraggingFootprints(t,e,n),!0}else for(i=0;i<t.length;i++)this.renderHighlight(t[i].componentFootprint)},e.prototype.unrenderDrag=function(){this.unrenderHighlight(),this.helperRenderer.unrender()},e.prototype.renderEventResize=function(t,e,n){this.helperRenderer.renderEventResizingFootprints(t,e,n)},e.prototype.unrenderEventResize=function(){this.helperRenderer.unrender()},e.prototype.renderSelectionFootprint=function(t){this.opt("selectHelper")?this.helperRenderer.renderComponentFootprint(t):this.renderHighlight(t)},e.prototype.unrenderSelection=function(){this.helperRenderer.unrender(),this.unrenderHighlight()},e}(a.default);e.default=m,m.prototype.eventRendererClass=f.default,m.prototype.businessHourRendererClass=l.default,m.prototype.helperRendererClass=g.default,m.prototype.fillRendererClass=v.default,u.default.mixInto(m),d.default.mixInto(m)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(5),o=n(221),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.buildRenderRange=function(e,n,i){var o=t.prototype.buildRenderRange.call(this,e,n,i),s=this.msToUtcMoment(o.startMs,i),a=this.msToUtcMoment(o.endMs,i);return/^(year|month)$/.test(n)&&(s.startOf("week"),a.weekday()&&a.add(1,"week").startOf("week")),new r.default(s,a)},e}(o.default);e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(0),o=n(4),s=n(62),a=n(253),l=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.setGridHeight=function(t,e){e&&(t*=this.dayGrid.rowCnt/6),o.distributeHeight(this.dayGrid.rowEls,t,!e)},e.prototype.isDateInOtherMonth=function(t,e){return t.month()!==r.utc(e.currentUnzonedRange.startMs).month()},e}(s.default);e.default=l,l.prototype.dateProfileGeneratorClass=a.default},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(5),a=n(41),l=n(39),u=n(254),d=n(255),c=function(t){function e(e,n){var i=t.call(this,e,n)||this;return i.segSelector=".fc-list-item",i.scroller=new l.default({overflowX:"hidden",overflowY:"auto"}),i}return i.__extends(e,t),e.prototype.renderSkeleton=function(){this.el.addClass("fc-list-view "+this.calendar.theme.getClass("listView")),this.scroller.render(),this.scroller.el.appendTo(this.el),this.contentEl=this.scroller.scrollEl},e.prototype.unrenderSkeleton=function(){this.scroller.destroy()},e.prototype.updateSize=function(e,n,i){t.prototype.updateSize.call(this,e,n,i),this.scroller.clear(),n||this.scroller.setHeight(this.computeScrollerHeight(e))},e.prototype.computeScrollerHeight=function(t){return t-o.subtractInnerElHe
2754ight(this.el,this.scroller.el)},e.prototype.renderDates=function(t){for(var e=this.calendar,n=e.msToUtcMoment(t.renderUnzonedRange.startMs,!0),i=e.msToUtcMoment(t.renderUnzonedRange.endMs,!0),r=[],o=[];n<i;)r.push(n.clone()),o.push(new s.default(n,n.clone().add(1,"day"))),n.add(1,"day");this.dayDates=r,this.dayRanges=o},e.prototype.componentFootprintToSegs=function(t){var e,n,i,r=this.dayRanges,o=[];for(e=0;e<r.length;e++)if((n=t.unzonedRange.intersect(r[e]))&&(i={startMs:n.startMs,endMs:n.endMs,isStart:n.isStart,isEnd:n.isEnd,dayIndex:e},o.push(i),!i.isEnd&&!t.isAllDay&&e+1<r.length&&t.unzonedRange.endMs<r[e+1].startMs+this.nextDayThreshold)){i.endMs=t.unzonedRange.endMs,i.isEnd=!0;break}return o},e.prototype.renderEmptyMessage=function(){this.contentEl.html('<div class="fc-list-empty-wrap2"><div class="fc-list-empty-wrap1"><div class="fc-list-empty">'+o.htmlEscape(this.opt("noEventsMessage"))+"</div></div></div>")},e.prototype.renderSegList=function(t){var e,n,i,o=this.groupSegsByDay(t),s=r('<table class="fc-list-table '+this.calendar.theme.getClass("tableList")+'"><tbody/></table>'),a=s.find("tbody");for(e=0;e<o.length;e++)if(n=o[e])for(a.append(this.dayHeaderHtml(this.dayDates[e])),this.eventRenderer.sortEventSegs(n),i=0;i<n.length;i++)a.append(n[i].el);this.contentEl.empty().append(s)},e.prototype.groupSegsByDay=function(t){var e,n,i=[];for(e=0;e<t.length;e++)n=t[e],(i[n.dayIndex]||(i[n.dayIndex]=[])).push(n);return i},e.prototype.dayHeaderHtml=function(t){var e=this.opt("listDayFormat"),n=this.opt("listDayAltFormat");return'<tr class="fc-list-heading" data-date="'+t.format("YYYY-MM-DD")+'"><td class="'+(this.calendar.theme.getClass("tableListHeading")||this.calendar.theme.getClass("widgetHeader"))+'" colspan="3">'+(e?this.buildGotoAnchorHtml(t,{class:"fc-list-heading-main"},o.htmlEscape(t.format(e))):"")+(n?this.buildGotoAnchorHtml(t,{class:"fc-list-heading-alt"},o.htmlEscape(t.format(n))):"")+"</td></tr>"},e}(a.default);e.default=c,c.prototype.eventRendererClass=u.default,c.prototype.eventPointingClass=d.default},,,,,,function(t,e,n){var i=n(3),r=n(16),o=n(4),s=n(220);n(10),n(47),n(256),n(257),n(260),n(261),n(262),n(263),i.fullCalendar=r,i.fn.fullCalendar=function(t){var e=Array.prototype.slice.call(arguments,1),n=this;return this.each(function(r,a){var l,u=i(a),d=u.data("fullCalendar");"string"==typeof t?"getCalendar"===t?r||(n=d):"destroy"===t?d&&(d.destroy(),u.removeData("fullCalendar")):d?i.isFunction(d[t])?(l=d[t].apply(d,e),r||(n=l),"destroy"===t&&u.removeData("fullCalendar")):o.warn("'"+t+"' is an unknown FullCalendar method."):o.warn("Attempting to call a FullCalendar method on an element with no calendar."):d||(d=new s.default(u,t),u.data("fullCalendar",d),d.render())}),n},t.exports=r},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(48),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.setElement=function(t){this.el=t,this.bindGlobalHandlers(),this.renderSkeleton(),this.set("isInDom",!0)},e.prototype.removeElement=function(){this.unset("isInDom"),this.unrenderSkeleton(),this.unbindGlobalHandlers(),this.el.remove()},e.prototype.bindGlobalHandlers=function(){},e.prototype.unbindGlobalHandlers=function(){},e.prototype.renderSkeleton=function(){},e.prototype.unrenderSkeleton=function(){},e}(r.default);e.default=o},function(t,e){Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t){this.items=t||[]}return t.prototype.proxyCall=function(t){for(var e=[],n=1;n<arguments.length;n++)e[n-1]=arguments[n];var i=[];return this.items.forEach(function(n){i.push(n[t].apply(n,e))}),i},t}();e.default=n},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=function(){function t(t,e){this.el=null,this.viewsWithButtons=[],this.calendar=t,this.toolbarOptions=e}return t.prototype.setToolbarOptions=function(t){this.toolbarOptions=t},t.prototype.render=function(){var t=this.toolbarOptions.layout,e=this.el;t?(e?e.empty():e=this.el=i("<div class='fc-toolbar "+this.toolbarOptions.extraClasse
2754s+"'/>"),e.append(this.renderSection("left")).append(this.renderSection("right")).append(this.renderSection("center")).append('<div class="fc-clear"/>')):this.removeElement()},t.prototype.removeElement=function(){this.el&&(this.el.remove(),this.el=null)},t.prototype.renderSection=function(t){var e=this,n=this.calendar,o=n.theme,s=n.optionsManager,a=n.viewSpecManager,l=i('<div class="fc-'+t+'"/>'),u=this.toolbarOptions.layout[t],d=s.get("customButtons")||{},c=s.overrides.buttonText||{},p=s.get("buttonText")||{};return u&&i.each(u.split(" "),function(t,s){var u,h=i(),f=!0;i.each(s.split(","),function(t,s){var l,u,g,v,y,m,b,w,D;"title"===s?(h=h.add(i("<h2>&nbsp;</h2>")),f=!1):((l=d[s])?(g=function(t){l.click&&l.click.call(w[0],t)},(v=o.getCustomButtonIconClass(l))||(v=o.getIconClass(s))||(y=l.text)):(u=a.getViewSpec(s))?(e.viewsWithButtons.push(s),g=function(){n.changeView(s)},(y=u.buttonTextOverride)||(v=o.getIconClass(s))||(y=u.buttonTextDefault)):n[s]&&(g=function(){n[s]()},(y=c[s])||(v=o.getIconClass(s))||(y=p[s])),g&&(b=["fc-"+s+"-button",o.getClass("button"),o.getClass("stateDefault")],y?(m=r.htmlEscape(y),D=""):v&&(m="<span class='"+v+"'></span>",D=' aria-label="'+s+'"'),w=i('<button type="button" class="'+b.join(" ")+'"'+D+">"+m+"</button>").click(function(t){w.hasClass(o.getClass("stateDisabled"))||(g(t),(w.hasClass(o.getClass("stateActive"))||w.hasClass(o.getClass("stateDisabled")))&&w.removeClass(o.getClass("stateHover")))}).mousedown(function(){w.not("."+o.getClass("stateActive")).not("."+o.getClass("stateDisabled")).addClass(o.getClass("stateDown"))}).mouseup(function(){w.removeClass(o.getClass("stateDown"))}).hover(function(){w.not("."+o.getClass("stateActive")).not("."+o.getClass("stateDisabled")).addClass(o.getClass("stateHover"))},function(){w.removeClass(o.getClass("stateHover")).removeClass(o.getClass("stateDown"))}),h=h.add(w)))}),f&&h.first().addClass(o.getClass("cornerLeft")).end().last().addClass(o.getClass("cornerRight")).end(),h.length>1?(u=i("<div/>"),f&&u.addClass(o.getClass("buttonGroup")),u.append(h),l.append(u)):l.append(h)}),l},t.prototype.updateTitle=function(t){this.el&&this.el.find("h2").text(t)},t.prototype.activateButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").addClass(this.calendar.theme.getClass("stateActive"))},t.prototype.deactivateButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").removeClass(this.calendar.theme.getClass("stateActive"))},t.prototype.disableButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").prop("disabled",!0).addClass(this.calendar.theme.getClass("stateDisabled"))},t.prototype.enableButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").prop("disabled",!1).removeClass(this.calendar.theme.getClass("stateDisabled"))},t.prototype.getViewsWithButtons=function(){return this.viewsWithButtons},t}();e.default=o},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(4),s=n(32),a=n(31),l=n(48),u=function(t){function e(e,n){var i=t.call(this)||this;return i._calendar=e,i.overrides=r.extend({},n),i.dynamicOverrides={},i.compute(),i}return i.__extends(e,t),e.prototype.add=function(t){var e,n=0;this.recordOverrides(t);for(e in t)n++;if(1===n){if("height"===e||"contentHeight"===e||"aspectRatio"===e)return void this._calendar.updateViewSize(!0);if("defaultDate"===e)return;if("businessHours"===e)return;if(/^(event|select)(Overlap|Constraint|Allow)$/.test(e))return;if("timezone"===e)return void this._calendar.view.flash("initialEvents")}this._calendar.renderHeader(),this._calendar.renderFooter(),this._calendar.viewsByType={},this._calendar.reinitView()},e.prototype.compute=function(){var t,e,n,i,r;t=o.firstDefined(this.dynamicOverrides.locale,this.overrides.locale),e=a.localeOptionHash[t],e||(t=s.globalDefaults.locale,e=a.localeOptionHash[t]||{}),n=o.firstDefined(this.dynamicOverrides.isRTL,this.overrides.isRTL,e.isRTL,s.globalDefaults.isRTL),i=n?s.rtlDefaults:{},this.dirDefaults=i,this.localeDefaults=e,r=s.mergeOptions([s.globalDefaults,i,e,this.overrides,this.dynamicOverrides]),a.populateInstanceComputableOptions(r),this.reset(r)},e.prototype.recordOverrides=function(t){var e;
2754for(e in t)this.dynamicOverrides[e]=t[e];this._calendar.viewSpecManager.clearCache(),this.compute()},e}(l.default);e.default=u},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(0),r=n(3),o=n(22),s=n(4),a=n(32),l=n(31),u=function(){function t(t,e){this.optionsManager=t,this._calendar=e,this.clearCache()}return t.prototype.clearCache=function(){this.viewSpecCache={}},t.prototype.getViewSpec=function(t){var e=this.viewSpecCache;return e[t]||(e[t]=this.buildViewSpec(t))},t.prototype.getUnitViewSpec=function(t){var e,n,i;if(-1!==r.inArray(t,s.unitsDesc))for(e=this._calendar.header.getViewsWithButtons(),r.each(o.viewHash,function(t){e.push(t)}),n=0;n<e.length;n++)if((i=this.getViewSpec(e[n]))&&i.singleUnit===t)return i},t.prototype.buildViewSpec=function(t){for(var e,n,r,l,u,d=this.optionsManager.overrides.views||{},c=[],p=[],h=[],f=t;f;)e=o.viewHash[f],n=d[f],f=null,"function"==typeof e&&(e={class:e}),e&&(c.unshift(e),p.unshift(e.defaults||{}),r=r||e.duration,f=f||e.type),n&&(h.unshift(n),r=r||n.duration,f=f||n.type);return e=s.mergeProps(c),e.type=t,!!e.class&&(r=r||this.optionsManager.dynamicOverrides.duration||this.optionsManager.overrides.duration,r&&(l=i.duration(r),l.valueOf()&&(u=s.computeDurationGreatestUnit(l,r),e.duration=l,e.durationUnit=u,1===l.as(u)&&(e.singleUnit=u,h.unshift(d[u]||{})))),e.defaults=a.mergeOptions(p),e.overrides=a.mergeOptions(h),this.buildViewSpecOptions(e),this.buildViewSpecButtonText(e,t),e)},t.prototype.buildViewSpecOptions=function(t){var e=this.optionsManager;t.options=a.mergeOptions([a.globalDefaults,t.defaults,e.dirDefaults,e.localeDefaults,e.overrides,t.overrides,e.dynamicOverrides]),l.populateInstanceComputableOptions(t.options)},t.prototype.buildViewSpecButtonText=function(t,e){function n(n){var i=n.buttonText||{};return i[e]||(t.buttonTextKey?i[t.buttonTextKey]:null)||(t.singleUnit?i[t.singleUnit]:null)}var i=this.optionsManager;t.buttonTextOverride=n(i.dynamicOverrides)||n(i.overrides)||t.overrides.buttonText,t.buttonTextDefault=n(i.localeDefaults)||n(i.dirDefaults)||t.defaults.buttonText||n(a.globalDefaults)||(t.duration?this._calendar.humanizeDuration(t.duration):null)||e},t}();e.default=u},function(t,e,n){function i(t,e){return t.getPrimitive()===e.getPrimitive()}Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),o=n(4),s=n(243),a=n(52),l=n(6),u=n(38),d=n(13),c=n(18),p=n(11),h=n(7),f=function(){function t(t){this.calendar=t,this.stickySource=new a.default(t),this.otherSources=[]}return t.prototype.requestEvents=function(t,e,n,i){return!i&&this.currentPeriod&&this.currentPeriod.isWithinRange(t,e)&&n===this.currentPeriod.timezone||this.setPeriod(new s.default(t,e,n)),this.currentPeriod.whenReleased()},t.prototype.addSource=function(t){this.otherSources.push(t),this.currentPeriod&&this.currentPeriod.requestSource(t)},t.prototype.removeSource=function(t){o.removeExact(this.otherSources,t),this.currentPeriod&&this.currentPeriod.purgeSource(t)},t.prototype.removeAllSources=function(){this.otherSources=[],this.currentPeriod&&this.currentPeriod.purgeAllSources()},t.prototype.refetchSource=function(t){var e=this.currentPeriod;e&&(e.freeze(),e.purgeSource(t),e.requestSource(t),e.thaw())},t.prototype.refetchAllSources=function(){var t=this.currentPeriod;t&&(t.freeze(),t.purgeAllSources(),t.requestSources(this.getSources()),t.thaw())},t.prototype.getSources=function(){return[this.stickySource].concat(this.otherSources)},t.prototype.multiQuerySources=function(t){t?r.isArray(t)||(t=[t]):t=[];var e,n=[];for(e=0;e<t.length;e++)n.push.apply(n,this.querySources(t[e]));return n},t.prototype.querySources=function(t){var e,n,o=this.otherSources;for(e=0;e<o.length;e++)if((n=o[e])===t)return[n];return(n=this.getSourceById(l.default.normalizeId(t)))?[n]:(t=u.default.parse(t,this.calendar),t?r.grep(o,function(e){return i(t,e)}):void 0)},t.prototype.getSourceById=function(t){return r.grep(this.otherSources,function(e){return e.id&&e.id===t})[0]},t.prototype.setPeriod=function(t){this.currentPeriod&&(this.unbindPeriod(this.currentPeriod),this.currentPeriod=null),this.currentPeriod=t,this.bindPeriod(t),t.requestSources(this.getSources())},t.prototype.bindPeriod=function(t){this.listenTo(t,"release",function(t){this.trigger("release",t)})},t.prototype.unbindPeriod=function(t){this.stopListeningTo(t)},t.prototype.getEventDefByUid=function(t){if(this.currentPeriod)return this.currentPeriod.getEventDefByUid(t)},t.prototype.addEventDef=function(t,e){e&&this.stickySource.addEventDef(t),this.currentPeriod&&this.currentPeriod.addEventDef(t)}
2754,t.prototype.removeEventDefsById=function(t){this.getSources().forEach(function(e){e.removeEventDefsById(t)}),this.currentPeriod&&this.currentPeriod.removeEventDefsById(t)},t.prototype.removeAllEventDefs=function(){this.getSources().forEach(function(t){t.removeAllEventDefs()}),this.currentPeriod&&this.currentPeriod.removeAllEventDefs()},t.prototype.mutateEventsWithId=function(t,e){var n,i=this.currentPeriod,r=[];return i?(i.freeze(),n=i.getEventDefsById(t),n.forEach(function(t){i.removeEventDef(t),r.push(e.mutateSingle(t)),i.addEventDef(t)}),i.thaw(),function(){i.freeze();for(var t=0;t<n.length;t++)i.removeEventDef(n[t]),r[t](),i.addEventDef(n[t]);i.thaw()}):function(){}},t.prototype.buildMutatedEventInstanceGroup=function(t,e){var n,i,r=this.getEventDefsById(t),o=[];for(n=0;n<r.length;n++)(i=r[n].clone())instanceof d.default&&(e.mutateSingle(i),o.push.apply(o,i.buildInstances()));return new c.default(o)},t.prototype.freeze=function(){this.currentPeriod&&this.currentPeriod.freeze()},t.prototype.thaw=function(){this.currentPeriod&&this.currentPeriod.thaw()},t.prototype.getEventDefsById=function(t){return this.currentPeriod.getEventDefsById(t)},t.prototype.getEventInstances=function(){return this.currentPeriod.getEventInstances()},t.prototype.getEventInstancesWithId=function(t){return this.currentPeriod.getEventInstancesWithId(t)},t.prototype.getEventInstancesWithoutId=function(t){return this.currentPeriod.getEventInstancesWithoutId(t)},t}();e.default=f,p.default.mixInto(f),h.default.mixInto(f)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=n(20),s=n(11),a=n(5),l=n(18),u=function(){function t(t,e,n){this.pendingCnt=0,this.freezeDepth=0,this.stuntedReleaseCnt=0,this.releaseCnt=0,this.start=t,this.end=e,this.timezone=n,this.unzonedRange=new a.default(t.clone().stripZone(),e.clone().stripZone()),this.requestsByUid={},this.eventDefsByUid={},this.eventDefsById={},this.eventInstanceGroupsById={}}return t.prototype.isWithinRange=function(t,e){return!t.isBefore(this.start)&&!e.isAfter(this.end)},t.prototype.requestSources=function(t){this.freeze();for(var e=0;e<t.length;e++)this.requestSource(t[e]);this.thaw()},t.prototype.requestSource=function(t){var e=this,n={source:t,status:"pending",eventDefs:null};this.requestsByUid[t.uid]=n,this.pendingCnt+=1,t.fetch(this.start,this.end,this.timezone).then(function(t){"cancelled"!==n.status&&(n.status="completed",n.eventDefs=t,e.addEventDefs(t),e.pendingCnt--,e.tryRelease())},function(){"cancelled"!==n.status&&(n.status="failed",e.pendingCnt--,e.tryRelease())})},t.prototype.purgeSource=function(t){var e=this.requestsByUid[t.uid];e&&(delete this.requestsByUid[t.uid],"pending"===e.status?(e.status="cancelled",this.pendingCnt--,this.tryRelease()):"completed"===e.status&&e.eventDefs.forEach(this.removeEventDef.bind(this)))},t.prototype.purgeAllSources=function(){var t,e,n=this.requestsByUid,i=0;for(t in n)e=n[t],"pending"===e.status?e.status="cancelled":"completed"===e.status&&i++;this.requestsByUid={},this.pendingCnt=0,i&&this.removeAllEventDefs()},t.prototype.getEventDefByUid=function(t){return this.eventDefsByUid[t]},t.prototype.getEventDefsById=function(t){var e=this.eventDefsById[t];return e?e.slice():[]},t.prototype.addEventDefs=function(t){for(var e=0;e<t.length;e++)this.addEventDef(t[e])},t.prototype.addEventDef=function(t){var e,n=this.eventDefsById,i=t.id,r=n[i]||(n[i]=[]),o=t.buildInstances(this.unzonedRange);for(r.push(t),this.eventDefsByUid[t.uid]=t,e=0;e<o.length;e++)this.addEventInstance(o[e],i)},t.prototype.removeEventDefsById=function(t){var e=this;this.getEventDefsById(t).forEach(function(t){e.removeEventDef(t)})},t.prototype.removeAllEventDefs=function(){var t=i.isEmptyObject(this.eventDefsByUid);this.eventDefsByUid={},this.eventDefsById={},this.eventInstanceGroupsById={},t||this.tryRelease()},t.prototype.removeEventDef=function(t){var e=this.eventDefsById,n=e[t.id]
2755;delete this.eventDefsByUid[t.uid],n&&(r.removeExact(n,t),n.length||delete e[t.id],this.removeEventInstancesForDef(t))},t.prototype.getEventInstances=function(){var t,e=this.eventInstanceGroupsById,n=[];for(t in e)n.push.apply(n,e[t].eventInstances);return n},t.prototype.getEventInstancesWithId=function(t){var e=this.eventInstanceGroupsById[t];return e?e.eventInstances.slice():[]},t.prototype.getEventInstancesWithoutId=function(t){var e,n=this.eventInstanceGroupsById,i=[];for(e in n)e!==t&&i.push.apply(i,n[e].eventInstances);return i},t.prototype.addEventInstance=function(t,e){var n=this.eventInstanceGroupsById;(n[e]||(n[e]=new l.default)).eventInstances.push(t),this.tryRelease()},t.prototype.removeEventInstancesForDef=function(t){var e,n=this.eventInstanceGroupsById,i=n[t.id];i&&(e=r.removeMatching(i.eventInstances,function(e){return e.def===t}),i.eventInstances.length||delete n[t.id],e&&this.tryRelease())},t.prototype.tryRelease=function(){this.pendingCnt||(this.freezeDepth?this.stuntedReleaseCnt++:this.release()
2755)},t.prototype.release=function(){this.releaseCnt++,this.trigger("release",this.eventInstanceGroupsById)},t.prototype.whenReleased=function(){var t=this;return this.releaseCnt?o.default.resolve(this.eventInstanceGroupsById):o.default.construct(function(e){t.one("release",e)})},t.prototype.freeze=function(){this.freezeDepth++||(this.stuntedReleaseCnt=0)},t.prototype.thaw=function(){--this.freezeDepth||!this.stuntedReleaseCnt||this.pendingCnt||this.release()},t}();e.default=u,s.default.mixInto(u)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=n(7),s=function(){function t(t,e){this.isFollowing=!1,this.isHidden=!1,this.isAnimating=!1,this.options=e=e||{},this.sourceEl=t,this.parentEl=e.parentEl?i(e.parentEl):t.parent()}return t.prototype.start=function(t){this.isFollowing||(this.isFollowing=!0,this.y0=r.getEvY(t),this.x0=r.getEvX(t),this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),r.getEvIsTouch(t)?this.listenTo(i(document),"touchmove",this.handleMove):this.listenTo(i(document),"mousemove",this.handleMove))},t.prototype.stop=function(t,e){var n=this,r=this.options.revertDuration,o=function(){n.isAnimating=!1,n.removeElement(),n.top0=n.left0=null,e&&e()};this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,this.stopListeningTo(i(document)),t&&r&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:r,complete:o})):o())},t.prototype.getEl=function(){var t=this.el;return t||(t=this.el=this.sourceEl.clone().addClass(this.options.additionalClass||"").css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}),t.addClass("fc-unselectable"),t.appendTo(this.parentEl)),t},t.prototype.removeElement=function(){this.el&&(this.el.remove(),this.el=null)},t.prototype.updatePosition=function(){var t,e;this.getEl(),null==this.top0&&(t=this.sourceEl.offset(),e=this.el.offsetParent().offset(),this.top0=t.top-e.top,this.left0=t.left-e.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},t.prototype.handleMove=function(t){this.topDelta=r.getEvY(t)-this.y0,this.leftDelta=r.getEvX(t)-this.x0,this.isHidden||this.updatePosition()},t.prototype.hide=function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},t.prototype.show=function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())},t}();e.default=s,o.default.mixInto(s)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(23),o=n(15),s=function(t){function e(e){var n=t.call(this,e)||this;return n.dragListener=n.buildDragListener(),n}return i.__extends(e,t),e.prototype.end=function(){this.dragListener.endInteraction()},e.prototype.bindToEl=function(t){var e=this.component,n=this.dragListener;e.bindDateHandlerToEl(t,"mousedown",function(t){e.shouldIgnoreMouse()||n.startInteraction(t)}),e.bindDateHandlerToEl(t,"touchstart",function(t){e.shouldIgnoreTouch()||n.startInteraction(t)})},e.prototype.buildDragListener=function(){var t,e=this,n=this.component,i=new r.default(n,{scroll:this.opt("dragScroll"),interactionStart:function(){t=i.origHit},hitOver:function(e,n,i){n||(t=null)},hitOut:function(){t=null},interactionEnd:function(i,r){var o;!r&&t&&(o=n.getSafeHitFootprint(t))&&e.view.triggerDayClick(o,n.getHitEl(t),i)}});return i.shouldCancelTouchScroll=!1,i.scrollAlwaysKills=!0,i},e}(o.default);e.default=s},function(t,e,n){function i(t){var e,n,i,r=[];for(e=0;e<t.length;e++){for(n=t[e],i=0;i<r.length&&s(n,r[i]).length;i++);n.level=i,(r[i]||(r[i]=[])).push(n)}return r}function r(t){var e,n,i,r,o;for(e=0;e<t.length;e++)for(n=t[e],i=0;i<n.length;i++)for(r=n[i],r.forwardSegs=[],o=e+1;o<t.length;o++)s(r,t[o],r.forwardSegs)}function o(t){var e,n,i=t.forwardSegs,r=0;if(void 0===t.forwardPressure){for(e=0;e<i.length;e++)n=i[e],o(n),r=Math.max(r,1+n.forwardPressure);t.forwardPressure=r}}function s(t,e,n){void 0===n&&(n=[]);for(var i=0;i<e.length;i++)a(t,e[i])&&n.push(e[i]);return n}function a(t,e){return t.bottom>e.top&&t.top<e.bottom}
2755Object.defineProperty(e,"__esModule",{value:!0});var l=n(2),u=n(4),d=n(42),c=function(t){function e(e,n){var i=t.call(this,e,n)||this;return i.timeGrid=e,i}return l.__extends(e,t),e.prototype.renderFgSegs=function(t){this.renderFgSegsIntoContainers(t,this.timeGrid.fgContainerEls)},e.prototype.renderFgSegsIntoContainers=function(t,e){var n,i;for(n=this.timeGrid.groupSegsByCol(t),i=0;i<this.timeGrid.colCnt;i++)this.updateFgSegCoords(n[i]);this.timeGrid.attachSegsByCol(n,e)},e.prototype.unrenderFgSegs=function(){this.fgSegs&&this.fgSegs.forEach(function(t){t.el.remove()})},e.prototype.computeEventTimeFormat=function(){return this.opt("noMeridiemTimeFormat")},e.prototype.computeDisplayEventEnd=function(){return!0},e.prototype.fgSegHtml=function(t,e){var n,i,r,o=this.view,s=o.calendar,a=t.footprint.componentFootprint,l=a.isAllDay,d=t.footprint.eventDef,c=o.isEventDefDraggable(d),p=!e&&t.isStart&&o.isEventDefResizableFromStart(d),h=!e&&t.isEnd&&o.isEventDefResizableFromEnd(d),f=this.getSegClasses(t,c,p||h),g=u.cssToStr(this.getSkinCss(d));if(f.unshift("fc-time-grid-event","fc-v-event"),o.isMultiDayRange(a.unzonedRange)){if(t.isStart||t.isEnd){var v=s.msToMoment(t.startMs),y=s.msToMoment(t.endMs);n=this._getTimeText(v,y,l),i=this._getTimeText(v,y,l,"LT"),r=this._getTimeText(v,y,l,null,!1)}}else n=this.getTimeText(t.footprint),i=this.getTimeText(t.footprint,"LT"),r=this.getTimeText(t.footprint,null,!1);return'<a class="'+f.join(" ")+'"'+(d.url?' href="'+u.htmlEscape(d.url)+'"':"")+(g?' style="'+g+'"':"")+'><div class="fc-content">'+(n?'<div class="fc-time" data-start="'+u.htmlEscape(r)+'" data-full="'+u.htmlEscape(i)+'"><span>'+u.htmlEscape(n)+"</span></div>":"")+(d.title?'<div class="fc-title">'+u.htmlEscape(d.title)+"</div>":"")+'</div><div class="fc-bg"/>'+(h?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},e.prototype.updateFgSegCoords=function(t){this.timeGrid.computeSegVerticals(t),this.computeFgSegHorizontals(t),this.timeGrid.assignSegVerticals(t),this.assignFgSegHorizontals(t)},e.prototype.computeFgSegHorizontals=function(t){var e,n,s;if(this.sortEventSegs(t),e=i(t),r(e),n=e[0]){for(s=0;s<n.length;s++)o(n[s]);for(s=0;s<n.length;s++)this.computeFgSegForwardBack(n[s],0,0)}},e.prototype.computeFgSegForwardBack=function(t,e,n){var i,r=t.forwardSegs;if(void 0===t.forwardCoord)for(r.length?(this.sortForwardSegs(r),this.computeFgSegForwardBack(r[0],e+1,n),t.forwardCoord=r[0].backwardCoord):t.forwardCoord=1,t.backwardCoord=t.forwardCoord-(t.forwardCoord-n)/(e+1),i=0;i<r.length;i++)this.computeFgSegForwardBack(r[i],0,t.forwardCoord)},e.prototype.sortForwardSegs=function(t){t.sort(u.proxy(this,"compareForwardSegs"))},e.prototype.compareForwardSegs=function(t,e){return e.forwardPressure-t.forwardPressure||(t.backwardCoord||0)-(e.backwardCoord||0)||this.compareEventSegs(t,e)},e.prototype.assignFgSegHorizontals=function(t){var e,n;for(e=0;e<t.length;e++)n=t[e],n.el.css(this.generateFgSegHorizontalCss(n)),n.bottom-n.top<30&&n.el.addClass("fc-short")},e.prototype.generateFgSegHorizontalCss=function(t){var e,n,i=this.opt("slotEventOverlap"),r=t.backwardCoord,o=t.forwardCoord,s=this.timeGrid.generateSegVerticalCss(t),a=this.timeGrid.isRTL;return i&&(o=Math.min(1,r+2*(o-r))),a?(e=1-o,n=r):(e=r,n=1-o),s.zIndex=t.level+1,s.left=100*e+"%",s.right=100*n+"%",i&&t.forwardPressure&&(s[a?"marginLeft":"marginRight"]=20),s},e}(d.default);e.default=c},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(58),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.renderSegs=function(t,e){var n,i,o,s=[];for(this.eventRenderer.renderFgSegsIntoContainers(t,this.component.helperContainerEls),n=0;n<t.length;n++)i=t[n],e&&e.col===i.col&&(o=e.el,i.el.css({left:o.css("left"),right:o.css("right"),"margin-left":o.css("margin-left"),"margin-right":o.css("margin-right")})),s.push(i.el[0]);return r(s)},e}(o.default);e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(57),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.attachSegEls=function(t,e){var n,i=this.component;return"bgEvent"===t?n=i.bgContainerEls:"businessHours"===t?n=i.businessContainerEls:"highlight"===t&&(n=i.highlightContainerEls),i.updateSegVerticals(e),i.attachSegsByCol(i.groupSegsByCol(e),n),e.map(function(t){return t.el[0]})},e}(r.default);e.default=o}
2755,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(3),r=n(4),o=n(7),s=function(){function t(t){this.isHidden=!0,this.margin=10,this.options=t||{}}return t.prototype.show=function(){this.isHidden&&(this.el||this.render(),this.el.show(),this.position(),this.isHidden=!1,this.trigger("show"))},t.prototype.hide=function(){this.isHidden||(this.el.hide(),this.isHidden=!0,this.trigger("hide"))},t.prototype.render=function(){var t=this,e=this.options;this.el=i('<div class="fc-popover"/>').addClass(e.className||"").css({top:0,left:0}).append(e.content).appendTo(e.parentEl),this.el.on("click",".fc-close",function(){t.hide()}),e.autoHide&&this.listenTo(i(document),"mousedown",this.documentMousedown)},t.prototype.documentMousedown=function(t){this.el&&!i(t.target).closest(this.el).length&&this.hide()},t.prototype.removeElement=function(){this.hide(),this.el&&(this.el.remove(),this.el=null),this.stopListeningTo(i(document),"mousedown")},t.prototype.position=function(){var t,e,n,o,s,a=this.options,l=this.el.offsetParent().offset(),u=this.el.outerWidth(),d=this.el.outerHeight(),c=i(window),p=r.getScrollParent(this.el);o=a.top||0,s=void 0!==a.left?a.left:void 0!==a.right?a.right-u:0,p.is(window)||p.is(document)?(p=c,t=0,e=0):(n=p.offset(),t=n.top,e=n.left),t+=c.scrollTop(),e+=c.scrollLeft(),!1!==a.viewportConstrain&&(o=Math.min(o,t+p.outerHeight()-d-this.margin),o=Math.max(o,t+this.margin),s=Math.min(s,e+p.outerWidth()-u-this.margin),s=Math.max(s,e+this.margin)),this.el.css({top:o-l.top,left:s-l.left})},t.prototype.trigger=function(t){this.options[t]&&this.options[t].apply(this,Array.prototype.slice.call(arguments,1))},t}();e.default=s,o.default.mixInto(s)},function(t,e,n){function i(t,e){var n,i;for(n=0;n<e.length;n++)if(i=e[n],i.leftCol<=t.rightCol&&i.rightCol>=t.leftCol)return!0;return!1}function r(t,e){return t.leftCol-e.leftCol}Object.defineProperty(e,"__esModule",{value:!0});var o=n(2),s=n(3),a=n(4),l=n(42),u=function(t){function e(e,n){var i=t.call(this,e,n)||this;return i.dayGrid=e,i}return o.__extends(e,t),e.prototype.renderBgRanges=function(e){e=s.grep(e,function(t){return t.eventDef.isAllDay()}),t.prototype.renderBgRanges.call(this,e)},e.prototype.renderFgSegs=function(t){var e=this.rowStructs=this.renderSegRows(t);this.dayGrid.rowEls.each(function(t,n){s(n).find(".fc-content-skeleton > table").append(e[t].tbodyEl)})},e.prototype.unrenderFgSegs=function(){for(var t,e=this.rowStructs||[];t=e.pop();)t.tbodyEl.remove();this.rowStructs=null},e.prototype.renderSegRows=function(t){var e,n,i=[];for(e=this.groupSegRows(t),n=0;n<e.length;n++)i.push(this.renderSegRow(n,e[n]));return i},e.prototype.renderSegRow=function(t,e){function n(t){for(;o<t;)d=(y[i-1]||[])[o],d?d.attr("rowspan",parseInt(d.attr("rowspan")||1,10)+1):(d=s("<td/>"),a.append(d)),v[i][o]=d,y[i][o]=d,o++}var i,r,o,a,l,u,d,c=this.dayGrid.colCnt,p=this.buildSegLevels(e),h=Math.max(1,p.length),f=s("<tbody/>"),g=[],v=[],y=[];for(i=0;i<h;i++){if(r=p[i],o=0,a=s("<tr/>"),g.push([]),v.push([]),y.push([]),r)for(l=0;l<r.length;l++){for(u=r[l],n(u.leftCol),d=s('<td class="fc-event-container"/>').append(u.el),u.leftCol!==u.rightCol?d.attr("colspan",u.rightCol-u.leftCol+1):y[i][o]=d;o<=u.rightCol;)v[i][o]=d,g[i][o]=u,o++;a.append(d)}n(c),this.dayGrid.bookendCells(a),f.append(a)}return{row:t,tbodyEl:f,cellMatrix:v,segMatrix:g,segLevels:p,segs:e}},e.prototype.buildSegLevels=function(t){var e,n,o,s=[];for(this.sortEventSegs(t),e=0;e<t.length;e++){for(n=t[e],o=0;o<s.length&&i(n,s[o]);o++);n.level=o,(s[o]||(s[o]=[])).push(n)}for(o=0;o<s.length;o++)s[o].sort(r);return s},e.prototype.groupSegRows=function(t){var e,n=[];for(e=0;e<this.dayGrid.rowCnt;e++)n.push([]);for(e=0;e<t.length;e++)n[t[e].row].push(t[e]);return n},e.prototype.computeEventTimeFormat=function(){return this.opt("extraSmallTimeFormat")},e.prototype.computeDisplayEventEnd=function(){return 1===this.dayGrid.colCnt},e.prototype.fgSegHtml=function(t,e){var n,i,r=this.view,o=t.footprint.eventDef,s=t.footprint.componentFootprint.isAllDay,l=r.isEventDefDraggable(o),u=!e&&s&&t.isStart&&r.isEventDefResizableFromStart(o),d=!e&&s&&t.isEnd&&r.isEventDefResizableFromEnd(o),c=this.getSegClasses(t,l,u||d),p=a.cssToStr(this.getSkinCss(o)),h="";return c.unshift("fc-day-grid-event","fc-h-event"),t.isStart&&(n=this.getTimeText(t.footprint))&&(h='<span class="fc-time">'+a.htmlEscape(n)+"</span>"),i='<span class="fc-title">'+(a.htmlEscape(o.title||"")||"&nbsp;")+"</span>",'<a class="'+c.join(" ")+'"'+(o.url?' href="'+a.htmlEscape(o.url)+'"':"")+(p?' style="'+p+'"':"")+'><div class="fc-content">'+(this.dayGrid.isRTL?i+" "+h:h+" "+i)+"</div>"+(u?'<div class="fc-resizer fc-start-resizer" />':"")+(d?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},e}(l.default);e.default=u}
2755,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(58),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.renderSegs=function(t,e){var n,i=[];return n=this.eventRenderer.renderSegRows(t),this.component.rowEls.each(function(t,o){var s,a,l=r(o),u=r('<div class="fc-helper-skeleton"><table/></div>');e&&e.row===t?a=e.el.position().top:(s=l.find(".fc-content-skeleton tbody"),s.length||(s=l.find(".fc-content-skeleton table")),a=s.position().top),u.css("top",a).find("table").append(n[t].tbodyEl),l.append(u),i.push(u[0])}),r(i)},e}(o.default);e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(57),s=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.fillSegTag="td",e}return i.__extends(e,t),e.prototype.attachSegEls=function(t,e){var n,i,r,o=[];for(n=0;n<e.length;n++)i=e[n],r=this.renderFillRow(t,i),this.component.rowEls.eq(i.row).append(r),o.push(r[0]);return o},e.prototype.renderFillRow=function(t,e){var n,i,o,s=this.component.colCnt,a=e.leftCol,l=e.rightCol+1;return n="businessHours"===t?"bgevent":t.toLowerCase(),i=r('<div class="fc-'+n+'-skeleton"><table><tr/></table></div>'),o=i.find("tr"),a>0&&o.append('<td colspan="'+a+'"/>'),o.append(e.el.attr("colspan",l-a)),l<s&&o.append('<td colspan="'+(s-l)+'"/>'),this.component.bookendCells(o),i},e}(o.default);e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(228),o=n(5),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.buildRenderRange=function(e,n,i){var r,s=t.prototype.buildRenderRange.call(this,e,n,i),a=this.msToUtcMoment(s.startMs,i),l=this.msToUtcMoment(s.endMs,i);return this.opt("fixedWeekCount")&&(r=Math.ceil(l.diff(a,"weeks",!0)),l.add(6-r,"weeks")),new o.default(a,l)},e}(r.default);e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(4),o=n(42),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.renderFgSegs=function(t){t.length?this.component.renderSegList(t):this.component.renderEmptyMessage()},e.prototype.fgSegHtml=function(t){var e,n=this.view,i=n.calendar,o=i.theme,s=t.footprint,a=s.eventDef,l=s.componentFootprint,u=a.url,d=["fc-list-item"].concat(this.getClasses(a)),c=this.getBgColor(a);return e=l.isAllDay?n.getAllDayHtml():n.isMultiDayRange(l.unzonedRange)?t.isStart||t.isEnd?r.htmlEscape(this._getTimeText(i.msToMoment(t.startMs),i.msToMoment(t.endMs),l.isAllDay)):n.getAllDayHtml():r.htmlEscape(this.getTimeText(s)),u&&d.push("fc-has-url"),'<tr class="'+d.join(" ")+'">'+(this.displayEventTime?'<td class="fc-list-item-time '+o.getClass("widgetContent")+'">'+(e||"")+"</td>":"")+'<td class="fc-list-item-marker '+o.getClass("widgetContent")+'"><span class="fc-event-dot"'+(c?' style="background-color:'+c+'"':"")+'></span></td><td class="fc-list-item-title '+o.getClass("widgetContent")+'"><a'+(u?' href="'+r.htmlEscape(u)+'"':"")+">"+r.htmlEscape(a.title||"")+"</a></td></tr>"},e.prototype.computeEventTimeFormat=function(){return this.opt("mediumTimeFormat")},e}(o.default);e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(3),o=n(59),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e.prototype.handleClick=function(e,n){var i;t.prototype.handleClick.call(this,e,n),r(n.target).closest("a[href]").length||(i=e.footprint.eventDef.url)&&!n.isDefaultPrevented()&&(window.location.href=i)},e}(o.default);e.default=s},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(38),r=n(52),o=n(215),s=n(216);i.default.registerClass(r.default),i.default.registerClass(o.default),i.default.registerClass(s.default)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(51),r=n(213),o=n(214),s=n(258),a=n(259);i.defineThemeSystem("standard",r.default),i.defineThemeSystem("jquery-ui",o.default),i.defineThemeSystem("bootstrap3",s.default),i.defineThemeSystem("bootstrap4",a.default)}
2755,function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(19),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e}(r.default);e.default=o,o.prototype.classes={widget:"fc-bootstrap3",tableGrid:"table-bordered",tableList:"table",tableListHeading:"active",buttonGroup:"btn-group",button:"btn btn-default",stateActive:"active",stateDisabled:"disabled",today:"alert alert-info",popover:"panel panel-default",popoverHeader:"panel-heading",popoverContent:"panel-body",headerRow:"panel-default",dayRow:"panel-default",listView:"panel panel-default"},o.prototype.baseIconClass="glyphicon",o.prototype.iconClasses={close:"glyphicon-remove",prev:"glyphicon-chevron-left",next:"glyphicon-chevron-right",prevYear:"glyphicon-backward",nextYear:"glyphicon-forward"},o.prototype.iconOverrideOption="bootstrapGlyphicons",o.prototype.iconOverrideCustomButtonOption="bootstrapGlyphicon",o.prototype.iconOverridePrefix="glyphicon-"},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),r=n(19),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i.__extends(e,t),e}(r.default);e.default=o,o.prototype.classes={widget:"fc-bootstrap4",tableGrid:"table-bordered",tableList:"table",tableListHeading:"table-active",buttonGroup:"btn-group",button:"btn btn-primary",stateActive:"active",stateDisabled:"disabled",today:"alert alert-info",popover:"card card-primary",popoverHeader:"card-header",popoverContent:"card-body",headerRow:"table-bordered",dayRow:"table-bordered",listView:"card card-primary"},o.prototype.baseIconClass="fa",o.prototype.iconClasses={close:"fa-times",prev:"fa-chevron-left",next:"fa-chevron-right",prevYear:"fa-angle-double-left",nextYear:"fa-angle-double-right"},o.prototype.iconOverrideOption="bootstrapFontAwesome",o.prototype.iconOverrideCustomButtonOption="bootstrapFontAwesome",o.prototype.iconOverridePrefix="fa-"},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(22),r=n(62),o=n(229);i.defineView("basic",{class:r.default}),i.defineView("basicDay",{type:"basic",duration:{days:1}}),i.defineView("basicWeek",{type:"basic",duration:{weeks:1}}),i.defineView("month",{class:o.default,duration:{months:1},defaults:{fixedWeekCount:!0}})},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(22),r=n(226);i.defineView("agenda",{class:r.default,defaults:{allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0}}),i.defineView("agendaDay",{type:"agenda",duration:{days:1}}),i.defineView("agendaWeek",{type:"agenda",duration:{weeks:1}})},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var i=n(22),r=n(230);i.defineView("list",{class:r.default,buttonTextKey:"list",defaults:{buttonText:"list",listDayFormat:"LL",noEventsMessage:"No events to display"}}),i.defineView("listDay",{type:"list",duration:{days:1},defaults:{listDayFormat:"dddd"}}),i.defineView("listWeek",{type:"list",duration:{weeks:1},defaults:{listDayFormat:"dddd",listDayAltFormat:"LL"}}),i.defineView("listMonth",{type:"list",duration:{month:1},defaults:{listDayAltFormat:"dddd"}}),i.defineView("listYear",{type:"list",duration:{year:1},defaults:{listDayAltFormat:"dddd"}})},function(t,e){Object.defineProperty(e,"__esModule",{value:!0})}])});
2756/*! iFrame Resizer (iframeSizer.min.js ) - v4.1.1 - 2019-04-10
2757 *  Desc: Force cross domain iframes to size to content.
2758 *  Requires: iframeResizer.contentWindow.min.js to be loaded into the target frame.
2759 *  Copyright: (c) 2019 David J. Bradshaw - [email protected]
2760 *  License: MIT
2761 */
2762
2763!function(f){if("undefined"!=typeof window){var e,l=0,m=!1,n=!1,p="message".length,b="[iFrameSizer]",y=b.length,v=null,r=window.requestAnimationFrame,g={max:1,scroll:1,bodyScroll:1,documentElementScroll:1},F={},i=null,h={autoResize:!0,bodyBackground:null,bodyMargin:null,bodyMarginV1:8,bodyPadding:null,checkOrigin:!0,inPageLinks:!1,enablePublicMethods:!0,heightCalculationMethod:"bodyOffset",id:"iFrameResizer",interval:32,log:!1,maxHeight:1/0,maxWidth:1/0,minHeight:0,minWidth:0,resizeFrom:"parent",scrolling:!1,sizeHeight:!0,sizeWidth:!1,warningTimeout:5e3,tolerance:0,widthCalculationMethod:"scroll",onClosed:function(){},onInit:function(){},onMessage:function(){O("onMessage function not defined")},onResized:function(){},onScroll:function(){return!0}},I={};window.jQuery&&((e=window.jQuery).fn?e.fn.iFrameResize||(e.fn.iFrameResize=function(i){return this.filter("iframe").each(function(e,n){d(n,i)}).end()}):z("","Unable to bind to jQuery, it is not fully loaded.")),"function"==typeof define&&define.amd?define([],B):"object"==typeof module&&"object"==typeof module.exports&&(module.exports=B()),window.iFrameResize=window.iFrameResize||B()}function w(){return window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver}function M(e,n,i){e.addEventListener(n,i,!1)}function x(e,n,i){e.removeEventListener(n,i,!1)}function o(e){return b+"["+(i="Host page: "+(n=e),window.top!==window.self&&(i=window.parentIFrame&&window.parentIFrame.getId?window.parentIFrame.getId()+": "+n:"Nested host page: "+n),i)+"]";var n,i}function t(e){return F[e]?F[e].log:m}function k(e,n){a("log",e,n,t(e))}function z(e,n){a("info",e,n,t(e))}function O(e,n){a("warn",e,n,!0)}function a(e,n,i,t){!0===t&&"object"==typeof window.console&&console[e](o(n),i)}function s(n){function a(){e("Height"),e("Width"),j(function(){S(h),N(w),l("onResized",h)},h,"init")}function e(e){var n=Number(F[w]["max"+e]),i=Number(F[w]["min"+e]),t=e.toLowerCase(),o=Number(h[t]);k(w,"Checking "+t+" is in range "+i+"-"+n),o<i&&(o=i,k(w,"Set "+t+" to min value")),n<o&&(o=n,k(w,"Set "+t+" to max value")),h[t]=""+o}function s(e){return g.substr(g.indexOf(":")+p+e)}function d(i,t){var e,n,o;e=function(){var e,n;P("Send Page Info","pageInfo:"+(e=document.body.getBoundingClientRect(),n=h.iframe.getBoundingClientRect(),JSON.stringify({iframeHeight:n.height,iframeWidth:n.width,clientHeight:Math.max(document.documentElement.clientHeight,window.innerHeight||0),clientWidth:Math.max(document.documentElement.clientWidth,window.innerWidth||0),offsetTop:parseInt(n.top-e.top,10),offsetLeft:parseInt(n.left-e.left,10),scrollTop:window.pageYOffset,scrollLeft:window.pageXOffset,documentHeight:document.documentElement.clientHeight,documentWidth:document.documentElement.clientWidth,windowHeight:window.innerHeight,windowWidth:window.innerWidth})),i,t)},n=32,I[o=t]||(I[o]=setTimeout(function(){I[o]=null,e()},n))}function c(e){var n=e.getBoundingClientRect();return W(w),{x:Math.floor(Number(n.left)+Number(v.x)),y:Math.floor(Number(n.top)+Number(v.y))}}function u(e){var n=e?c(h.iframe):{x:0,y:0},i={x:Number(h.width)+n.x,y:Number(h.height)+n.y};k(w,"Reposition requested from iFrame (offset x:"+n.x+" y:"+n.y+")"),window.top!==window.self?window.parentIFrame?window.parentIFrame["scrollTo"+(e?"Offset":"")](i.x,i.y):O(w,"Unable to scroll to requested position, window.parentIFrame not found"):(v=i,f(),k(w,"--"))}function f(){!1!==l("onScroll",v)?N(w):C()}function l(e,n){return R(w,e,n)}var i,t,o,r,m,g=n.data,h={},w=null;"[iFrameResizerChild]Ready"===g?function(){for(var e in F)P("iFrame requested init",A
vendor: 5,018 bytes, line 2763
2763(e),document.getElementById(e),e)}():b===(""+g).substr(0,y)&&g.substr(y).split(":")[0]in F?(m=g.substr(y).split(":"),h={iframe:F[m[0]]&&F[m[0]].iframe,id:m[0],height:m[1],width:m[2],type:m[3]},w=h.id,F[w]&&(F[w].loaded=!0),(r=h.type in{true:1,false:1,undefined:1})&&k(w,"Ignoring init message from meta parent page"),!r&&(o=!0,F[t=w]||(o=!1,O(h.type+" No settings for "+t+". Message was: "+g)),o)&&(k(w,"Received: "+g),i=!0,null===h.iframe&&(O(w,"IFrame ("+h.id+") not found"),i=!1),i&&function(){var e,i=n.origin,t=F[w]&&F[w].checkOrigin;if(t&&""+i!="null"&&!(t.constructor===Array?function(){var e=0,n=!1;for(k(w,"Checking connection is from allowed list of origins: "+t);e<t.length;e++)if(t[e]===i){n=!0;break}return n}():(e=F[w]&&F[w].remoteHost,k(w,"Checking connection is from: "+e),i===e)))throw new Error("Unexpected message received from: "+i+" for "+h.iframe.id+". Message was: "+n.data+". This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains.");return!0}()&&function(){switch(F[w]&&F[w].firstRun&&F[w]&&(F[w].firstRun=!1),h.type){case"close":F[w].closeRequeston?R(w,"onCloseRequest",F[w].iframe):T(h.iframe);break;case"message":r=s(6),k(w,"onMessage passed: {iframe: "+h.iframe.id+", message: "+r+"}"),l("onMessage",{iframe:h.iframe,message:JSON.parse(r)}),k(w,"--");break;case"scrollTo":u(!1);break;case"scrollToOffset":u(!0);break;case"pageInfo":d(F[w]&&F[w].iframe,w),function(){function e(n,i){function t(){F[r]?d(F[r].iframe,r):o()}["scroll","resize"].forEach(function(e){k(r,n+e+" listener for sendPageInfo"),i(window,e,t)})}function o(){e("Remove ",x)}var r=w;e("Add ",M),F[r]&&(F[r].stopPageInfo=o)}();break;case"pageInfoStop":F[w]&&F[w].stopPageInfo&&(F[w].stopPageInfo(),delete F[w].stopPageInfo);break;case"inPageLink":e=s(9),i=e.split("#")[1]||"",t=decodeURIComponent(i),(o=document.getElementById(t)||document.getElementsByName(t)[0])?(n=c(o),k(w,"Moving to in page link (#"+i+") at x: "+n.x+" y: "+n.y),v={x:n.x,y:n.y},f(),k(w,"--")):window.top!==window.self?window.parentIFrame?window.parentIFrame.moveToAnchor(i):k(w,"In page link #"+i+" not found and window.parentIFrame not found"):k(w,"In page link #"+i+" not found");break;case"reset":H(h);break;case"init":a(),l("onInit",h.iframe);break;default:a()}var e,n,i,t,o,r}())):z(w,"Ignored: "+g)}function R(e,n,i){var t=null,o=null;if(F[e]){if("function"!=typeof(t=F[e][n]))throw new TypeError(n+" on iFrame["+e+"] is not a function");o=t(i)}return o}function E(e){var n=e.id;delete F[n]}function T(e){var n=e.id;k(n,"Removing iFrame: "+n);try{e.parentNode&&e.parentNode.removeChild(e)}catch(e){O(e)}R(n,"onClosed",n),k(n,"--"),E(e)}function W(e){null===v&&k(e,"Get page position: "+(v={x:window.pageXOffset!==f?window.pageXOffset:document.documentElement.scrollLeft,y:window.pageYOffset!==f?window.pageYOffset:document.documentElement.scrollTop}).x+","+v.y)}function N(e){null!==v&&(window.scrollTo(v.x,v.y),k(e,"Set page position: "+v.x+","+v.y),C())}function C(){v=null}function H(e){k(e.id,"Size reset requested by "+("init"===e.type?"host page":"iFrame")),W(e.id),j(function(){S(e),P("reset","reset",e.iframe,e.id)},e,"reset")}function S(i){function t(e){n||"0"!==i[e]||(n=!0,k(o,"Hidden iFrame detected, creating visibility listener"),function(){function n(){Object.keys(F).forEach(function(e){!function(n){function e(e){return"0px"===(F[n]&&F[n].iframe.style[e])}F[n]&&(i=F[n].iframe,null!==i.offsetParent)&&(e("height")||e("width"))&&P("Visibility change","resize",F[n].iframe,n);var i}(F[e])})}function e(e){k("window","Mutation observed: "+e[0].target+" "+e[0].type),c(n,16)}var i=w();i&&(t=document.querySelector("body"),o={attributes:!0,attributeOldValue:!1,characterData:!0,characterDataOldValue:!1,childList:!0,subtree:!0},new i(e).observe(t,o));var t,o}())}function e(e){var n;n=e,i.id?(i.iframe.style[n]=i[n]+"px",k(i.id,"IFrame ("+o+") "+n+" set to "+i[n]+"px")):k("undefined","messageData id not set"),t(e)}var o=i.iframe.id;F[o]&&(F[o].sizeHeight&&e("height"),F[o].sizeWidth&&e("width"))}function j(e,n,i){i!==n.type&&r?(k(n.id,"Requesting animation frame"),r(e)):e()}function P(e,n,i,t,o){var r,a=!1;t=t||i.id,F[t]&&(i&&"contentWindow"in i&&null!==i.contentWindow?(r=F[t]&&F[t].targetOrigin,k(t,"["+e+"] Sending msg to iframe["+t+"] ("+n+") targetOrigin: "+r),i.contentWindow.postMessage(b+n,r)):O(t,"["+e+"] IFrame("+t+") not found"),o&&F[t]&&F[t].warningTimeout&&(F[t].msgTimeout=setTimeout(function(){!F[t]||F[t].loaded||a||(a=!0,O(t,"IFrame has not responded within "+F[t].warningTimeout/1e3+" seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ignored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning."))},F[t].warningTimeout)))}function A(e){return e+":"+F[e].bodyMarginV1+":"+F[e].sizeWidth+":"+F[e].log+":"+F[e].interval+":"+F[e].enablePublicMethods+":"+F[e].autoResize+":"+F[e].bodyMargin+":"+F[e].heightCalculationMethod+":"+F[e].bodyBackgroun
2763d+":"+F[e].bodyPadding+":"+F[e].tolerance+":"+F[e].inPageLinks+":"+F[e].resizeFrom+":"+F[e].widthCalculationMethod}function d(i,e){function n(e){var n=e.split("Callback");if(2===n.length){var i="on"+n[0].charAt(0).toUpperCase()+n[0].slice(1);this[i]=this[e],delete this[e],O(u,"Deprecated: '"+e+"' has been renamed '"+i+"'. The old method will be removed in the next major version.")}}var t,o,r,a,s,d,c,u=(""===(t=i.id)&&(i.id=(o=e&&e.id||h.id+l++,null!==document.getElementById(o)&&(o+=l++),t=o),m=(e||{}).log,k(t,"Added missing iframe ID: "+t+" ("+i.src+")")),t);u in F&&"iFrameResizer"in i?O(u,"Ignored iFrame, already setup."):(d=(d=e)||{},F[u]={firstRun:!0,iframe:i,remoteHost:i.src.split("/").slice(0,3).join("/")},function(e){if("object"!=typeof e)throw new TypeError("Options is not an object")}(d),Object.keys(d).forEach(n,d),function(e){for(var n in h)Object.prototype.hasOwnProperty.call(h,n)&&(F[u][n]=Object.prototype.hasOwnProperty.call(e,n)?e[n]:h[n])}(d),F[u]&&(F[u].targetOrigin=!0===F[u].checkOrigin?""===(c=F[u].remoteHost)||"file://"===c?"*":c:"*"),function(){switch(k(u,"IFrame scrolling "+(F[u]&&F[u].scrolling?"enabled":"disabled")+" for "+u),i.style.overflow=!1===(F[u]&&F[u].scrolling)?"hidden":"auto",F[u]&&F[u].scrolling){case"omit":break;case!0:i.scrolling="yes";break;case!1:i.scrolling="no";break;default:i.scrolling=F[u]?F[u].scrolling:"no"}}(),function(){function e(e){1/0!==F[u][e]&&0!==F[u][e]&&(i.style[e]=F[u][e]+"px",k(u,"Set "+e+" = "+F[u][e]+"px"))}function n(e){if(F[u]["min"+e]>F[u]["max"+e])throw new Error("Value for min"+e+" can not be greater than max"+e)}n("Height"),n("Width"),e("maxHeight"),e("minHeight"),e("maxWidth"),e("minWidth")}(),"number"!=typeof(F[u]&&F[u].bodyMargin)&&"0"!==(F[u]&&F[u].bodyMargin)||(F[u].bodyMarginV1=F[u].bodyMargin,F[u].bodyMargin=F[u].bodyMargin+"px"),r=A(u),(s=w())&&(a=s,i.parentNode&&new a(function(e){e.forEach(function(e){Array.prototype.slice.call(e.removedNodes).forEach(function(e){e===i&&T(i)})})}).observe(i.parentNode,{childList:!0})),M(i,"load",function(){var e,n;P("iFrame.onload",r,i,f,!0),e=F[u]&&F[u].firstRun,n=F[u]&&F[u].heightCalculationMethod in g,!e&&n&&H({iframe:i,height:0,width:0,type:"init"})}),P("init",r,i,f,!0),F[u]&&(F[u].iframe.iFrameResizer={close:T.bind(null,F[u].iframe),removeListeners:E.bind(null,F[u].iframe),resize:P.bind(null,"Window resize","resize",F[u].iframe),moveToAnchor:function(e){P("Move to anchor","moveToAnchor:"+e,F[u].iframe,u)},sendMessage:function(e){P("Send Message","message:"+(e=JSON.stringify(e)),F[u].iframe,u)}}))}function c(e,n){null===i&&(i=setTimeout(function(){i=null,e()},n))}function u(){"hidden"!==document.visibilityState&&(k("document","Trigger event: Visiblity change"),c(function(){q("Tab Visable","resize")},16))}function q(i,t){Object.keys(F).forEach(function(e){var n;F[n=e]&&"parent"===F[n].resizeFrom&&F[n].autoResize&&!F[n].firstRun&&P(i,t,document.getElementById(e),e)})}function L(){M(window,"message",s),M(window,"resize",function(){var e;k("window","Trigger event: "+(e="resize")),c(function(){q("Window "+e,"resize")},16)}),M(document,"visibilitychange",u),M(document,"-webkit-visibilitychange",u)}function B(){function t(e,n){n&&(!function(){if(!n.tagName)throw new TypeError("Object is not a valid DOM element");if("IFRAME"!==n.tagName.toUpperCase())throw new TypeError("Expected <IFRAME> tag, found <"+n.tagName+">")}(),d(n,e),o.push(n))}var o;return function(){var e,n=["moz","webkit","o","ms"];for(e=0;e<n.length&&!r;e+=1)r=window[n[e]+"RequestAnimationFrame"];r||k("setup","RequestAnimationFrame not supported")}(),L(),function(e,n){var i;switch(o=[],(i=e)&&i.enablePublicMethods&&O("enablePublicMethods option has been removed, public methods are now always available in the iFrame"),typeof n){case"undefined":case"string":Array.prototype.forEach.call(document.querySelectorAll(n||"iframe"),t.bind(f,e));break;case"object":t(e,n);break;default:throw new TypeError("Unexpected data type ("+typeof n+")")}return o}}}();
2764//# sourceMappingURL=iframeResizer.map
2765/**
2766 * Paginator viewmodel, creates an array for pagination. Also keeps track of pagination variables.
2767 * @param {String} totalResults    Total number of items.
2768 * @param {String} itemsPerPage    How many items are on each page.
2769 * @param {String} paginationItems How many pagination buttons to display.
2770 */
2771
2772var PaginationViewModel = function(totalResults, itemsPerPage, paginationItems) {
2773	var self = this;
2774    self.itemsPerPage = ko.observable(itemsPerPage || 6); 					// How many results to display per page.
2775    self.totalResults = ko.observable(totalResults || -1);
2776    self.currentPage = ko.observable(1);
2777    self.paginationItems = ko.observable(paginationItems || 3); 			// Max number pagination buttons to display at the bottom of the page. (Must be set to odd numbers)
2778    
2779    self.firstVisibleItem = ko.computed(function(){
2780    	if(self.currentPage() === 1){
2781    		return 1;
2782    	}
2783    	return parseInt(self.itemsPerPage()) * (parseInt(self.currentPage()) - 1) + 1;
2784    });
2785
2786    self.totalPages = ko.computed(function(){
2787    	return Math.ceil(self.totalResults() / self.itemsPerPage());
2788    });
2789
2790    self.lastVisibleItem = ko.computed(function(){
2791    	if(self.currentPage() < self.totalPages()){
2792    		return parseInt(self.firstVisibleItem()) - 1 + parseInt(self.itemsPerPage());
2793    	} else {
2794    		return parseInt(self.totalResults());
2795    	}
2796    });
2797
2798    self.nextPageExists = ko.computed(function() {
2799        return self.currentPage() < self.totalPages();
2800    });
2801
2802    self.showPageDetails = ko.computed(function() {
2803        return self.totalResults() > 0;
2804    });
2805
2806    self.showPageButtons = ko.computed(function() {
2807        return self.totalPages() > 1;
2808    });
2809
2810    self.showPagination = ko.computed(function() {
2811        return self.showPageDetails() || self.showPageButtons();
2812    });
2813
2814    self.previousPageExists = ko.computed(function() {
2815        return self.currentPage() > 1;
2816    });
2817
2818    self.getTabIndex = ko.computed(function(page) {
2819        return (self.currentPage() === page) ? -1 : 0;
2820    });
2821
2822    self.prevDisabled = ko.computed(function(){
2823    	return self.previousPageExists() ? '' : 'disabled';
2824    });
2825
2826    self.nextDisabled = ko.computed(function(){
2827    	return self.nextPageExists() ? '' : 'disabled';
2828    });
2829
2830    self.activeClass = function(data){
2831    	return data === self.currentPage() ? 'active' : '';
2832    };
2833
2834	/*
2835	 * Uses paginationItems to construct an array that represents the pagination buttons at the bottom of the page.
2836	 * This is later used by the template to create these buttons. As an example: [1,2,3,4,5] will be returned if there are at least 5 pages, 
2837	 * and the current page is between 1 and 3.
2838	 * @return {Array} An array that represents the pagination buttons at the bottom of the page.
2839	 */
2840
2841    self.paginationArray = ko.computed(function() {
2842        var pageArray = [];
2843        var halfMax = (self.paginationItems() - 1) / 2;
2844
2845        /* updated 11/1 to fix for type coercion */
2846        var currentPage = typeof self.currentPage() === 'number' ? self.currentPage() : parseInt(self.currentPage());
2847        var paginationItems = typeof self.paginationItems() === 'number' ? self.paginationItems() : parseInt(self.paginationItems());
2848        var totalPages = typeof self.totalPages() === 'number' ? self.totalPages() : parseInt(self.totalPages());
2849
2850        if (currentPage <= (paginationItems - 1)) {																	//if there are less than 4 pages display all pages
2851            for (var i = 1; i <= Math.min(paginationItems, totalPages); i++) {
2852                pageArray.push(i);
2853            }
2854        } else if (currentPage >= paginationItems && ((currentPage + halfMax) <= totalPages)) { 		//if there are halfMax pages after current page, center the currentPage
2855            for (var j = (currentPage - halfMax); j < ((currentPage - halfMax) + paginationItems); j++) {
2856                pageArray.push(j);
2857            }
2858        } else if (currentPage >= paginationItems && ((currentPage + halfMax) > totalPages)) { 			//if there are fewer than halfMax pages after current page, then dis
2858play final 5 pages
2859            for (var k = (totalPages - paginationItems + 1) || 1; k <= totalPages; k++) {
2860                pageArray.push(k);
2861            }
2862        }
2863        return pageArray;
2864    });
2865
2866    self.init = function(totalResults) {
2867        self.totalResults(totalResults);
2868    };
2869
2870};
2871
2872/* Example HTML
2873<div class="pagination" data-sly-test="${!wcmmode.edit}" data-bind="if: showPagination">
2874	<p>Displaying <span class="first" data-bind="text: firstVisibleItem"></span>-<span data-bind="text: lastVisibleItem"></span> of <span class="total" data-bind="text: totalResults"></span></p>
2875		<div class="paging" data-bind="if: showPageButtons">
2876		    <a href="#" class="prev" data-bind="css: prevDisabled">
2877		        <span class="icon-angle-left" aria-hidden="true"></span>
2878		        <span class="sr-only">Previous</span>
2879		    </a>
2880
2881		    <ol>   
2882		        <li data-bind="template: { name: 'pagination-item-template', foreach: paginationArray }"></li>
2883		    </ol>
2884
2885		    <a href="#" class="next" data-bind="css: nextDisabled">
2886		        <span class="icon-angle-right" aria-hidden="true"></span>
2887		        <span class="sr-only">Next</span>
2888		    </a>
2889		</div>
2890</div>
2891
2892<script type="text/html" id="pagination-item-template">
2893	<li data-bind="css: $root.activeClass($data)"><a href="#" data-bind="text: $data"></a></li>
2894</script>
2895*/
2896
2897/*!
2898* simplePagination.js v1.6
2899* A simple jQuery pagination plugin.
2900* http://flaviusmatis.github.com/simplePagination.js/
2901*
2902* Copyright 2012, Flavius Matis
2903* Released under the MIT license.
2904* http://flaviusmatis.github.com/license.html
2905*/
2906/** @license
2907* simplePagination.js v1.6
2908* A simple jQuery pagination plugin.
2909* http://flaviusmatis.github.com/simplePagination.js/
2910*
2911* Copyright 2012, Flavius Matis
2912* Released under the MIT license.
2913* http://flaviusmatis.github.com/license.html
2914*/
2915(function($){
2916
2917	var methods = {
2918		init: function(options) {
2919			var o = $.extend({
2920				items: 1,
2921				itemsOnPage: 1,
2922				pages: 0,
2923				displayedPages: 5,
2924				edges: 2,
2925				currentPage: 0,
2926				useAnchors: true,
2927				hrefTextPrefix: '#page-',
2928				hrefTextSuffix: '',
2929				prevText: 'Prev',
2930				nextText: 'Next',
2931				ellipseText: '&hellip;',
2932				ellipsePageSet: true,
2933				cssStyle: 'light-theme',
2934				listStyle: '',
2935				labelMap: [],
2936				selectOnClick: true,
2937				nextAtFront: false,
2938				invertPageOrder: false,
2939				useStartEdge : true,
2940				useEndEdge : true,
2941				onPageClick: function(pageNumber, event) {
2942					// Callback triggered when a page is clicked
2943					// Page number is given as an optional parameter
2944				},
2945				onInit: function() {
2946					// Callback triggered immediately after initialization
2947				}
2948			}, options || {});
2949
2950			var self = this;
2951
2952			o.pages = o.pages ? o.pages : Math.ceil(o.items / o.itemsOnPage) ? Math.ceil(o.items / o.itemsOnPage) : 1;
2953			if (o.currentPage)
2954				o.currentPage = o.currentPage - 1;
2955			else
2956				o.currentPage = !o.invertPageOrder ? 0 : o.pages - 1;
2957			o.halfDisplayed = o.displayedPages / 2;
2958
2959			this.each(function() {
2960				self.addClass(o.cssStyle + ' simple-pagination').data('pagination', o);
2961				methods._draw.call(self);
2962			});
2963
2964			o.onInit();
2965
2966			return this;
2967		},
2968
2969		selectPage: function(page) {
2970			methods._selectPage.call(this, page - 1);
2971			return this;
2972		},
2973
2974		prevPage: function() {
2975			var o = this.data('pagination');
2976			if (!o.invertPageOrder) {
2977				if (o.currentPage > 0) {
2978					methods._selectPage.call(this, o.currentPage - 1);
2979				}
2980			} else {
2981				if (o.currentPage < o.pages - 1) {
2982					methods._selectPage.call(this, o.currentPage + 1);
2983				}
2984			}
2985			return this;
2986		},
2987
2988		nextPage: function() {
2989			var o = this.data('pagination');
2990			if (!o.invertPageOrder) {
2991				if (o.currentPage < o.pages - 1) {
2992					methods._selectPage.call(this, o.currentPage + 1);
2993				}
2994			} else {
2995				if (o.currentPage > 0) {
2996					methods._selectPage.call(this, o.currentPage - 1);
2997				}
2998			}
2999			return this;
3000		},
3001
3002		getPagesCount: function() {
3003			return this.data('pagination').pages;
3004		},
3005
3006		setPagesCount: function(count) {
3007			this.data('pagination').pages = count;
3008		},
3009
3010		getCurrentPage: function () {
3011			return this.data('pagination').currentPage + 1;
3012		},
3013
3014		destroy: function(){
3015			this.empty();
3016			return this;
3017		},
3018
3019		drawPage: function (page) {
3020			var o = this.data('pagination');
3021			o.currentPage = page - 1;
3022			this.data('pagination', o);
3023			methods._draw.call(this);
3024			return this;
3025		},
3026
3027		redraw: function(){
3028			methods._draw.call(this);
3029			return this;
3030		},
3031
3032		disable: function(){
3033			var o = this.data('pagination');
3034			o.disabled = true;
3035			this.data('pagination', o);
3036			methods._draw.call(this);
3037			return this;
3038		},
3039
3040		enable: function(){
3041			var o = this.data('pagination');
3042			o.disabled = false;
3043			this.data('pagination', o);
3044			methods._draw.call(this);
3045			return this;
3046		},
3047
3048		updateItems: function (newItems) {
3049			var o = this.data('pagination');
3050			o.items = newItems;
3051			o.pages = methods._getPages(o);
3052			this.data('pagination', o);
3053			methods._draw.call(this);
3054		},
3055
3056		updateItemsOnPage: function (itemsOnPage) {
3057			var o = this.data('pagination');
3058			o.itemsOnPage = itemsOnPage;
3059			o.pages = methods._getPages(o);
3060			this.data('pagination', o);
3061			methods._selectPage.call(this, 0);
3062			return this;
3063		},
3064
3065		getItemsOnPage: function() {
3066			return this.data('pagination').itemsOnPage;
3067		},
3068
3069		_draw: function() {
3070			var	o = this.data('pagination'),
3071				interval = methods._getInterval(o),
3072				i,
3073				tagName;
3074
3075			methods.destroy.call(this);
3076
3077			tagName = (typeof this.prop === 'function') ? this.prop('tagName') : this.attr('tagName');
3078
3079			// var $panel = tagName === 'UL' ? this : $('<ul' + (o.listStyle ? ' class="' + o.listStyle + '"' : '') + '></ul>').appendTo(this);
3080            var $panel = tagName === 'UL' ? this : $('<ul class="pagination-count text-right"></ul>').appendTo(this);
3081
3082			// Generate Prev link
3083			if (o.prevText) {
3084				// methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage - 1 : o.currentPage + 1, {text: o.prevText, classes: 'prev'});
3085                methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage - 1 : o.currentPage + 1, {text: '', classes: 'prev control_prev'});
3086			}
3087
3088			// Generate Next link (if option set for at front)
3089			if (o.nextText && o.nextAtFront) {
3090				// methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage + 1 : o.currentPage - 1, {text: o.nextText, classes: 'next'});
3091                methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage + 1 : o.currentPage - 1, {text: '', classes: 'next control_next'});
3092			}
3093
3094			// Generate start edges
3095			if (!o.invertPageOrder) {
3096				if (interval.start > 0 && o.edges > 0) {
3097					if(o.useStartEdge) {
3098						var end = Math.min(o.edges, interval.start);
3099						for (i = 0; i < end; i++) {
3100							methods._appendItem.call(this, i);
3101						}
3102					}
3103					if (o.edges < interval.start && (interval.start - o.edges != 1)) {
3104						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
3105					} else if (interval.start - o.edges == 1) {
3106						methods._appendItem.call(this, o.edges);
3107					}
3108				}
3109			} else {
3110				if (interval.end < o.pages && o.edges > 0) {
3111					if(o.useStartEdge) {
3112						var begin = Math.max(o.pages - o.edges, interval.end);
3113						for (i = o.pages - 1; i >= begin; i--) {
3114							methods._appendItem.call(this, i);
3115						}
3116					}
3117
3118					if (o.pages - o.edges > interval.end && (o.pages - o.edges - interval.end != 1)) {
3119						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
3120					} else if (o.pages - o.edges - interval.end == 1) {
3121						methods._appendItem.call(this, interval.end);
3122					}
3123				}
3124			}
3125
3126			// Generate interval links
3127			if (!o.invertPageOrder) {
3128				for (i = interval.start; i < interval.end; i++) {
3129					methods._appendItem.call(this, i);
3130				}
3131			} else {
3132				for (i = interval.end - 1; i >= interval.start; i--) {
3133					methods._appendItem.call(this, i);
3134				}
3135			}
3136
3137			// Generate end edges
3138			if (!o.invertPageOrder) {
3139				if (interval.end < o.pages && o.edges > 0) {
3140					if (o.pages - o.edges > interval.end && (o.pages - o.edges - interval.end != 1)) {
3141						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
3142					} else if (o.pages - o.edges - interval.end == 1) {
3143						methods._appendItem.call(this, interval.end);
3144					}
3145					if(o.useEndEdge) {
3146						var begin = Math.max(o.pages - o.edges, interval.end);
3147						for (i = begin; i < o.pages; i++) {
3148							methods._appendItem.call(this, i);
3149						}
3150					}
3151				}
3152			} else {
3153				if (interval.start > 0 && o.edges > 0) {
3154					if (o.edges < interval.start && (interval.start - o.edges != 1)) {
3155						$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>');
3156					} else if (interval.start - o.edges == 1) {
3157						methods._appendItem.call(this, o.edges);
3158					}
3159
3160					if(o.useEndEdge) {
3161						var end = Math.min(o.edges, interval.start);
3162						for (i = end - 1; i >= 0; i--) {
3163							methods._appendItem.call(this, i);
3164						}
3165					}
3166				}
3167			}
3168
3169			// Generate Next link (unless option is set for at front)
3170			if (o.nextText && !o.nextAtFront) {
3171				methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage + 1 : o.currentPage - 1, {text: '', classes: 'next control_next icon-chevron-right'});
3172			}
3173
3174			if (o.ellipsePageSet && !o.disabled) {
3175				methods._ellipseClick.call(this, $panel);
3176			}
3177
3178		},
3179
3180		_getPages: function(o) {
3181			var pages = Math.ceil(o.items / o.itemsOnPage);
3182			return pages || 1;
3183		},
3184
3185		_getInterval: function(o) {
3186			return {
3187				start: Math.ceil(o.currentPage > o.halfDisplayed ? Math.max(Math.min(o.currentPage - o.halfDisplayed, (o.pages - o.displayedPages)
3187), 0) : 0),
3188				end: Math.ceil(o.currentPage > o.halfDisplayed ? Math.min(o.currentPage + o.halfDisplayed, o.pages) : Math.min(o.displayedPages, o.pages))
3189			};
3190		},
3191
3192		_appendItem: function(pageIndex, opts) {
3193			var self = this, options, $link, o = self.data('pagination'), $linkWrapper = $('<li class="pagination-item"></li>'), $ul = self.find('ul');
3194
3195			pageIndex = pageIndex < 0 ? 0 : (pageIndex < o.pages ? pageIndex : o.pages - 1);
3196
3197			options = {
3198				text: pageIndex + 1,
3199				classes: ''
3200			};
3201
3202			if (o.labelMap.length && o.labelMap[pageIndex]) {
3203				options.text = o.labelMap[pageIndex];
3204			}
3205
3206			options = $.extend(options, opts || {});
3207
3208			if (pageIndex == o.currentPage || o.disabled) {
3209                if (o.disabled || options.classes.indexOf('prev') >= 0 || options.classes.indexOf('next') >= 0 ) {
3210					$linkWrapper.addClass('disabled');
3211				} else {
3212                    $linkWrapper.addClass('active selected');
3213				}
3214				$link = $('<a class="current">' + (options.text) + '</a>');
3215			} else {
3216				if (o.useAnchors) {
3217					// $link = $('<a href="' + o.hrefTextPrefix + (pageIndex + 1) + o.hrefTextSuffix + '" class="page-link">' + (options.text) + '</a>');
3218                    $link = $('<a class="page-link">' + (options.text) + '</a>');
3219				} else {
3220					$link = $('<span >' + (options.text) + '</span>');
3221				}
3222				$link.click(function(event){
3223					return methods._selectPage.call(self, pageIndex, event);
3224				});
3225			}
3226
3227			if (options.classes) {
3228				$link.addClass(options.classes);
3229			}
3230
3231			$linkWrapper.append($link);
3232
3233			if ($ul.length) {
3234				$ul.append($linkWrapper);
3235			} else {
3236				self.append($linkWrapper);
3237			}
3238		},
3239
3240		_selectPage: function(pageIndex, event) {
3241			var o = this.data('pagination');
3242			o.currentPage = pageIndex;
3243			if (o.selectOnClick) {
3244				methods._draw.call(this);
3245			}
3246			return o.onPageClick(pageIndex + 1, event);
3247		},
3248
3249
3250		_ellipseClick: function($panel) {
3251			var self = this,
3252				o = this.data('pagination'),
3253				$ellip = $panel.find('.ellipse');
3254			$ellip.addClass('clickable').parent().removeClass('disabled');
3255			$ellip.click(function(event) {
3256				if (!o.disable) {
3257					var $this = $(this),
3258						val = (parseInt($this.parent().prev().text(), 10) || 0) + 1;
3259					$this
3260						.html('<input type="number" min="1" max="' + o.pages + '" step="1" value="' + val + '">')
3261						.find('input')
3262						.focus()
3263						.click(function(event) {
3264							// prevent input number arrows from bubbling a click event on $ellip
3265							event.stopPropagation();
3266						})
3267						.keyup(function(event) {
3268							var val = $(this).val();
3269							if (event.which === 13 && val !== '') {
3270								// enter to accept
3271								if ((val>0)&&(val<=o.pages))
3272								methods._selectPage.call(self, val - 1);
3273							} else if (event.which === 27) {
3274								// escape to cancel
3275								$ellip.empty().html(o.ellipseText);
3276							}
3277						})
3278						.bind('blur', function(event) {
3279							var val = $(this).val();
3280							if (val !== '') {
3281								methods._selectPage.call(self, val - 1);
3282							}
3283							$ellip.empty().html(o.ellipseText);
3284							return false;
3285						});
3286				}
3287				return false;
3288			});
3289		}
3290
3291	};
3292
3293	$.fn.pagination = function(method) {
3294
3295		// Method calling logic
3296		if (methods[method] && method.charAt(0) != '_') {
3297			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
3298		} else if (typeof method === 'object' || !method) {
3299			return methods.init.apply(this, arguments);
3300		} else {
3301			$.error('Method ' +  method + ' does not exist on jQuery.pagination');
3302		}
3303
3304	};
3305
3306})(jQuery);
3307
3308/*! npm.im/object-fit-images 3.2.3 */
3309var objectFitImages=function(){"use strict";function t(t,e){return"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='"+t+"' height='"+e+"'%3E%3C/svg%3E"}function e(t){if(t.srcset&&!m&&window.picturefill){var e=window.picturefill._;t[e.ns]&&t[e.ns].evaled||e.fillImg(t,{reselect:!0}),t[e.ns].curSrc||(t[e.ns].supported=!1,e.fillImg(t,{reselect:!0})),t.currentSrc=t[e.ns].curSrc||t.src}}function i(t){for(var e,i=getComputedStyle(t).fontFamily,r={};null!==(e=l.exec(i));)r[e[1]]=e[2];return r}function r(e,i,r){var n=t(i||1,r||0);p.call(e,"src")!==n&&b.call(e,"src",n)}
3309function n(t,e){t.naturalWidth?e(t):setTimeout(n,100,t,e)}function c(t){var c=i(t),o=t[a];if(c["object-fit"]=c["object-fit"]||"fill",!o.img){if("fill"===c["object-fit"])return;if(!o.skipTest&&g&&!c["object-position"])return}if(!o.img){o.img=new Image(t.width,t.height),o.img.srcset=p.call(t,"data-ofi-srcset")||t.srcset,o.img.src=p.call(t,"data-ofi-src")||t.src,b.call(t,"data-ofi-src",t.src),t.srcset&&b.call(t,"data-ofi-srcset",t.srcset),r(t,t.naturalWidth||t.width,t.naturalHeight||t.height),t.srcset&&(t.srcset="");try{s(t)}catch(t){window.console&&console.warn("https://bit.ly/ofi-old-browser")}}e(o.img),t.style.backgroundImage='url("'+(o.img.currentSrc||o.img.src).replace(/"/g,'\\"')+'")',t.style.backgroundPosition=c["object-position"]||"center",t.style.backgroundRepeat="no-repeat",t.style.backgroundOrigin="content-box",/scale-down/.test(c["object-fit"])?n(o.img,function(){o.img.naturalWidth>t.width||o.img.naturalHeight>t.height?t.style.backgroundSize="contain":t.style.backgroundSize="auto"}):t.style.backgroundSize=c["object-fit"].replace("none","auto").replace("fill","100% 100%"),n(o.img,function(e){r(t,e.naturalWidth,e.naturalHeight)})}function s(t){var e={get:function(e){return t[a].img[e||"src"]},set:function(e,i){return t[a].img[i||"src"]=e,b.call(t,"data-ofi-"+i,e),c(t),e}};Object.defineProperty(t,"src",e),Object.defineProperty(t,"currentSrc",{get:function(){return e.get("currentSrc")}}),Object.defineProperty(t,"srcset",{get:function(){return e.get("srcset")},set:function(t){return e.set(t,"srcset")}})}function o(t,e){var i=!h&&!t;if(e=e||{},t=t||"img",f&&!e.skipTest||!d)return!1;"img"===t?t=document.getElementsByTagName("img"):"string"==typeof t?t=document.querySelectorAll(t):"length"in t||(t=[t]);for(var r=0;r<t.length;r++)t[r][a]=t[r][a]||{skipTest:e.skipTest},c(t[r]);i&&(document.body.addEventListener("load",function(t){"IMG"===t.target.tagName&&o(t.target,{skipTest:e.skipTest})},!0),h=!0,t="img"),e.watchMQ&&window.addEventListener("resize",o.bind(null,t,{skipTest:e.skipTest}))}var a="bfred-it:object-fit-images",l=/(object-fit|object-position)\s*:\s*([-\w\s%]+)/g,u="undefined"==typeof Image?{style:{"object-position":1}}:new Image,g="object-fit"in u.style,f="object-position"in u.style,d="background-size"in u.style,m="string"==typeof u.currentSrc,p=u.getAttribute,b=u.setAttribute,h=!1;return o.supportsObjectFit=g,o.supportsObjectPosition=f,function(){function t(t,e){return t[a]&&t[a].img&&("src"===e||"srcset"===e)?t[a].img:t}f||(HTMLImageElement.prototype.getAttribute=function(e){return p.call(t(this,e),e)},HTMLImageElement.prototype.setAttribute=function(e,i){return b.call(t(this,e),e,String(i))})}(),o}();
3310/*----------------------------------------
3311 * objectFitPolyfill 2.3.0
3312 *
3313 * Made by Constance Chen
3314 * Released under the MIT license
3315 *
3316 * https://github.com/constancecchen/object-fit-polyfill
3317 *--------------------------------------*/
3318!function(){"use strict";if("undefined"!=typeof window){var t=window.navigator.userAgent.match(/Edge\/(\d{2})\./),n=!!t&&16<=parseInt(t[1],10);if(!("objectFit"in document.documentElement.style!=!1)||n){var o=function(t,e,i){var n,o,l,a,d;if((i=i.split(" ")).length<2&&(i[1]=i[0]),"x"===t)n=i[0],o=i[1],l="left",a="right",d=e.clientWidth;else{if("y"!==t)return;n=i[1],o=i[0],l="top",a="bottom",d=e.clientHeight}if(n!==l&&o!==l){if(n!==a&&o!==a)return"center"===n||"50%"===n?(e.style[l]="50%",void(e.style["margin-"+l]=d/-2+"px")):void(0<=n.indexOf("%")?(n=parseInt(n))<50?(e.style[l]=n+"%",e.style["margin-"+l]=d*(n/-100)+"px"):(n=100-n,e.style[a]=n+"%",e.style["margin-"+a]=d*(n/-100)+"px"):e.style[l]=n);e.style[a]="0"}else e.style[l]="0"},l=function(t){var e=t.dataset?t.dataset.objectFit:t.getAttribute("data-object-fit"),i=t.dataset?t.dataset.objectPosition:t.getAttribute("data-object-position");e=e||"cover",i=i||"50% 50%";var n=t.parentNode;return function(t){var e=window.getComputedStyle(t,null),i=e.getPropertyValue("position"),n=e.getPropertyValue("overflow"),o=e.getPropertyValue("display");i&&"static"!==i||(t.style.position="relative"),"hidden"!==n&&(t.style.overflow="hidden"),o&&"inline"!==o||(t.style.display="block"),0===t.clientHeight&&(t.style.height="100%"),-1===t.className.indexOf("object-fit-polyfill")&&(t.className=t.className+" object-fit-polyfill")}(n),function(t){var e=window.getComputedStyle(t,null),i={"max-width":"none","max-height":"none","min-width":"0px","min-height":"0px",top:"auto",right:"auto",bottom:"auto",left:"auto","margin-top":"0px","margin-right":"0px","margin-bottom":"0px","margin-left":"0px"};for(var n in i)e.getPropertyValue(n)!==i[n]&&(t.style[n]=i[n])}(t),t.style.position="absolute",t.style.width="auto",t.style.height="auto","scale-down"===e&&(e=t.clientWidth<n.clientWidth&&t.clientHeight<n.clientHeight?"none":"contain"),"none"===e?(o("x",t,i),void o("y",t,i)):"fill"===e?(t.style.width="100%",t.style.height="100%",o("x",t,i),void o("y",t,i)):(t.style.height="100%",void("cover"===e&&t.clientWidth>n.clientWidth||"contain"===e&&t.clientWidth<n.clientWidth?(t.style.top="0",t.style.marginTop="0",o("x",t,i)):(t.style.width="100%",t.style.height="auto",t.style.left="0",t.style.marginLeft="0",o("y",t,i))))},e=function(t){if(void 0===t||t instanceof Event)t=document.querySelectorAll("[data-object-fit]");else if(t&&t.nodeName)t=[t];else{if("object"!=typeof t||!t.length||!t[0].nodeName)return!1;t=t}for(var e=0;e<t.length;e++)if(t[e].nodeName){var i=t[e].nodeName.toLowerCase();if("img"===i){if(n)continue;t[e].complete?l(t[e]):t[e].addEventListener("load",function(){l(this)})}else"video"===i?0<t[e].readyState?l(t[e]):t[e].addEventListener("loadedmetadata",function(){l(this)}):l(t[e])}return!0};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e(),window.addEventListener("resize",e),window.objectFitPolyfill=e}else window.objectFitPolyfill=function(){return!1}}}();
3319
3320var CQ = CQ || {};
3321
3322var stickyJumpNav = {
3323    scrollList:false,
3324    watching:true,
3325    stickinessPoint: 0,
3326
3327
3328    init:function(IDz) {
3329        // slowest throttled connection loaded in at 40 sec, but don't need to be that conservative
3330        // slow 4g 12sec, fast 4g 3sec, unthrottled 2sec
3331        const PAGE_LOAD_STICKY_CALC_INTERVAL = 1500;
3332        const PAGE_LOAD_STICKY_CALC_DURATION = 12000;
3333        const $stickyNav = $('.sticky-jump-nav');
3334
3335        // Keep trying to update the stickiness point as other code loads in
3336        let timerId = setInterval(() => {
3337            stickyJumpNav.stickinessPoint = stickyJumpNav.calculateStickinessPoint()
3338        }, PAGE_LOAD_STICKY_CALC_INTERVAL);
3339
3340        setTimeout(() => {
3341            clearInterval(timerId)
3342        }, PAGE_LOAD_STICKY_CALC_DURATION);
3343
3344
3345        $(window).on('resize', function(e) {
3346            stickyJumpNav.resize($(window).width(), $stickyNav);
3347        });
3348        $(window).on('scroll', function(e) {
3349            if(stickyJumpNav.scrollList === true) {
3350               stickyJumpNav.scroller($stickyNav, $(window).scrollTop(), stickyJumpNav.stickinessPoint);
3351            }
3352            stickyJumpNav.watch($stickyNav, IDz);
3353        });
3354        // Determines Mobile Behavior.
3355        stickyJumpNav.resize($(window).width(), $stickyNav);
3356    },
3357    watch:function(stik, IDz) {
3358        if(stickyJumpNav.watching === true) {
3359            let chapter;
3360            $.each(IDz, function(i, el) {
3361                if(!(IDz[i] === "")) {
3362                    var obj = $("#"+el+"");
3363                    if($(document).scrollTop() > obj.offset().top - 180) {
3364                        chapter = i;
3365                        return;
3366                    }
3367                } else {
3368                    chapter = 0;
3369                }
3370            });
3371            stickyJumpNav.updateChapter(IDz, chapter);
3372        }
3373    },
3374    resize:function(w, stik) {
3375        if(w < 768) {
3376            stickyJumpNav.mobileBehavior(stik);
3377        } else {
3378            stickyJumpNav.stickinessPoint = stickyJumpNav.calculateStickinessPoint();
3379            stickyJumpNav.killMobile(stik);
3380        }
3381    },
3382    scroller:function($stickyNav, windowScrollTop, stickinessPoint) {
3383        const $header = $('.header.component'),
3384            $body = $('body'),
3385            stickyNavMarginTop = parseInt($stickyNav.css('margin-top').replace('px', '')),
3386            stickyPromoBarHeight = $('.promo-bar-xpf.sticky').outerHeight();
3387        let currentIndent = Number(windowScrollTop + $header.outerHeight());
3388
3389        if($header.outerHeight() <= 0) {
3390            currentIndent = Number(windowScrollTop + parseInt($header.css('padding-top').replace('px', '')));
3391        }
3392        if(currentIndent >= stickinessPoint) {
3393            $stickyNav.addClass('stuck');
3394            $body.addClass('jump-stuck');
3395
3396            const ROUNDING_COMPENSATION = 3;
3397            $stickyNav.css({
3398                'top': $header.outerHeight() - stickyNavMarginTop - ROUNDING_COMPENSATION + stickyPromoBarHeight
3399            });
3400        } else {
3401            if($body.hasClass('jump-stuck')) {
3402                $body.removeClass('jump-stuck');
3403                $stickyNav.removeClass('stuck');
3404                $stickyNav.removeAttr('style');
3405                $body.css({
3406                    'padding-top': 0
3407                });
3408            }
3409        }
3410    },
3411    mobileBehavior:function($stickyNav) {
3412        const $btn = $stickyNav.find('.mobile-toggle button'),
3413            $tabs = $stickyNav.find('.nav-tabs'),
3414            $stickNavItems = $tabs.find('li');
3415
3416        $tabs.removeAttr('style');
3417        $stickNavItems.each(function (i, el) {
3418            $(el).on('click', function () {
3419                stickyJumpNav.mobileSet(i, el);
3420            });
3421        });
3422        if (!$stickyNav.hasClass('mobile')) {
3423            $stickyNav.addClass('mobile');
3424
3425            $btn.on('click', function (e) {
3426                stickyJumpNav.toggleDropdown(e);
3427            });
3428        }
3429        stickyJumpNav.scrollList = false;
3430    },
3431    killMobile:function(s) {
3432        var overflo = 0;
3433        $(s).removeClass('mobile');
3434        $(s).find('.nav-tabs').removeAttr('style');
3435        var btn = $(s).find('.mobile-toggle button'),
3436            cnct = $(s).find('.nav-tabs li');
3437        btn.off('click');
3438        stickyJumpNav.scrollList = true;
3439        cnct.each(function(i, el) {
3440            $(el).off('click');
3441            $(el).on('click', function() {
3442                stickyJumpNav.activeSelect(el);
3443            });
3444            const widthToUse = $(el).css('display') === 'none' ? 0 : $(el).outerWidth();
3445            overflo += widthToUse;
3446        });
3447        if(overflo > $(s).find('.nav-tabs').outerWidth()) {
3448            $(s).find('.nav-tabs').css({
3449                'width': overflo,
3450                'max-width': 'none',
3451                'flex-wrap': 'nowrap'
3452            });
3453        }
3454    },
3455    toggleDropdown:function(e) {
3456        var drp = $(e.currentTarget).parent().parent().find('.nav-tabs');
3457        if(drp.is(':visible') !== true) {
3458            drp.slideDown(250);
3459            $(e.currentTarget).addClass("open");
3460        } else {
3461            drp.slideUp(250);
3462            $(e.currentTarget).removeClass("open");
3463        }
3464    },
3465    mobileSelect:function(e) {
3466        var drp = $(e.currentTarget).parent().parent();
3467        drp.slideUp(250);
3468        stickyJumpNav.watching = false;
3469        setTimeout(function() {
3470            stickyJumpNav.watching = true;
3471        }, 350);
3472    },
3473    activeSelect:function(e) {
3474        var mnu = $(e).parent();
3475        if($(e).hasClass('active') !== true) {
3476            mnu.find('.active').removeClass('active');
3477            $(e).addClass('active');
3478            stickyJumpNav.watching = false;
3479        }
3480        setTimeout(function() {
3481            stickyJumpNav.watching = true;
3482        }, 350);
3483    },
3484    mobileSet:function(i, el) {
3485        const drp = $(el).parent(),
3486            btn = $(el).parent().parent().find('.mobile-toggle button');
3487        btn.find('.text').text($(el).find('a > span').text());
3488        drp.slideUp(250);
3489    },
3490    updateChapter:function(IDz, c) {
3491        const $tabs = $(".sticky-jump-nav .nav-tabs"),
3492            $buttonText = $(".sticky-jump-nav .mobile-toggle button .text"),
3493            overview = $(".sticky-jump-nav").next().offset().top - $('header').outerHeight() - $(".sticky-jump-nav").outerHeight();
3494        $tabs.find("li.active").removeClass('active');
3495        if($(window).scrollTop() > overview) {
3496            $tabs.find("li").eq(c).addClass('active');
3497            $buttonText.text($tabs.find('li').eq(c).text());
3498        } else {
3499            $buttonText.text('');
3500        }
3501    },
3502    calculateStickinessPoint: function () {
3503        const $stickyNav = $('.sticky-jump-nav');
3504        const $body = $('body');
3505        const stickyNavMarginTop = parseInt($stickyNav.css('margin-top').replace('px', ''));
3506        const stickyPromoBarHeight = $('.promo-bar-xpf.sticky').outerHeight();
3507
3508        return $stickyNav.prev().offset().top + $stickyNav.prev().height() + stickyNavMarginTop - ($body.outerHeight() - $body.height()) - stickyPromoBarHeight - $stickyNav.outerHeight();
3509    }
3510}
3511
3512$(document).ready(function() {
3513    var $body = $('body');
3514
3515    let $sectionsOnPageWithStickyNav = $(
3516        ".home .parbase.section, " +
3517        ".product-page .parbase.section, " +
3518        ".sku-page .parbase.section, " +
3519        ".generic-interior-page .parbase.section, " +
3520        ".category-page .parbase.section, " +
3521        ".macro-page .parbase.section, " +
3522        ".micro-page .parbase.section, " +
3523        ".blog-article-page .parbase.section, " +
3524        ".education-article-page .parbase.section"
3525    );
3526
3527
3528    // detect IE8 and above, and edge
3529    if (document.documentMode || /Edge/.test(navigator.userAgent)) {
3530        $body.attr('data-is-ie', 'youbetcha');
3531    }
3532
3533    //object-fit polyfill (runs on load as well)
3534    objectFitImages();
3535
3536    //detect firefox
3537    if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
3538        $('html').addClass('firefox');
3539    }
3540
3541    function setTileCategory() {
3542        var isHomePage = $body.attr('data-homepage') === 'true';
3543        var bodySolution = $body.attr('data-solution');
3544
3545        /* We only want this functionality on the homepage (for now) */
3546
3547        if (isHomePage && bodySolution.length) {
3548
3549            var tileSolutionList = $('.tile-callouts.component');
3550            tileSolutionList.each(function(i, tile) {
3551                var solutionCategory = $(tile).attr('data-solution-reference');
3552                var $tile = $(tile);
3553
3554                if (bodySolution !== solutionCategory) {
3555                    $tile.addClass('slide-up');
3556                } else {
3557                    $tile.hasClass('slide-up') ? $tile.toggleClass('slide-up') : null;
3558                }
3559            });
3560        }
3561    }
3562
3563    CQ.setTileCategory = setTileCategory;
3564
3565    //jump nav on homepage
3566    //SCROLLSPY
3567    $bodyHome = $('body.home');
3568    $bodyProduct = $('body.product-page');
3569    $bodySku = $('body.sku-page');
3570    // if ($bodyHome.length !== 0 && ($bodyProduct || $bodySku)) {
3571    //     $('body.home, body.product-page, body.sku-page').scrollspy({ target: '#stickyJumpNav' });
3572    // }
3573
3574    //populate side nav, bullets, and hamburger nav
3575    //actually populate the navs
3576    if($('#stickyJumpNav').length > 0) {
3577        $('#stickyJumpNav ul').append('<li style="display: none !important"><a href="#" "aria-label="Overview"><span>Overview</span></a></li>');
3578    }
3579    $sectionsOnPageWithStickyNav.each(function() {
3580        var theID = $(this).children('section').attr('id');
3581        var theIDTitle = $(this).children('section').attr('data-nav');
3582        if (theID && $('#jumpNav').length > 0) {
3583            $('#jumpNav ul').append('<li><a href="#' + theID + '" aria-label="' + theIDTitle + ' Jump Link"><span class="icon-plus"></span><span class="title">' + theIDTitle + '</span></a></li>');
3584            $('[data-spy="scroll"]').each(function() {
3585                $(this).scrollspy('refresh');
3586            });
3587        }
3588        if (theID && $('#stickyJumpNav').length > 0) {
3589            $('#stickyJumpNav ul').append('<li><a href="#' + theID + '" aria-label="' + theIDTitle + ' Jump Link"><span>' + theIDTitle + '</span></a></li>');
3590            $('[data-spy="scroll"]').each(function() {
3591                $(this).scrollspy('refresh');
3592            });
3593        }
3594    });
3595    if($('#stickyJumpNav').length > 0) {
3596        var IDz = [""];
3597        $sectionsOnPageWithStickyNav.each(function() {
3598            var thsId = $(this).children('section').attr('id');
3599            if(thsId) {
3600                IDz.push(thsId);
3601            }
3602        });
3603        if(IDz.length > 1) {
3604            stickyJumpNav.init(IDz);
3605        } else {
3606            $('#stickyJumpNav').remove();
3607        }
3608    }
3609
3610    var offset;
3611    //scroll to function for scrollspy
3612
3613    function moveFocus(jumpNavLink, e){
3614        const hash = jumpNavLink.getAttribute('href');
3615        if (!hash) return;
3616        const section = document.querySelector(hash);
3617        if (!section) return;
3618
3619        const tabbables = section.querySelectorAll('a, button, input, select, textarea, [tabindex]:not
3619([tabindex="-1"])');
3620        for (let i = 0; i < tabbables.length; i++) {
3621            const el = tabbables[i];
3622            const style = window.getComputedStyle(el);
3623            const isVisible = style.visibility !== 'hidden' && style.display !== 'none';
3624            if (!isVisible || el.disabled){
3625                return;
3626            } else {
3627                el.focus();
3628                e.preventDefault();
3629                break;
3630            }
3631        }
3632    }
3633
3634    //this function also controls the scroll for the toolbar component (uses anchors on the page)
3635    $("a[href^='#']").on('click', function(e) {
3636            var isAnchor = $(e.currentTarget).attr('href')[0] === '#';
3637            var nonEmptyAnchor = $(e.currentTarget).attr('href') !== '#';
3638            var emptyAnchor = $(e.currentTarget).attr('href') === '#';
3639            var hash = this.hash;
3640            var targetExists = ($(hash).length > 0);
3641            var isBrand = ($('.brand-grid').length > 0);
3642            var isContact = ($('.contact-grid').length > 0);
3643            var isStickyJumpNavAnchor = $(e.currentTarget).parents('.sticky-jump-nav').length > 0;
3644            const stickyPromoBarHeight = $('.promo-bar-xpf.sticky').outerHeight();
3645
3646        
3647            if (isAnchor && nonEmptyAnchor && targetExists && !isBrand && !isContact && isStickyJumpNavAnchor) {
3648                e.preventDefault();
3649                
3650                const SCROLL_DURATION = 300;
3651                const ADJUSTMENT_DURATION = 150;
3652                const MONITOR_INTERVAL = 50;
3653                
3654                const navHeight = Number($('.header.component').outerHeight());
3655                const $sticky = $('.sticky-jump-nav');
3656                const $mobileToggle = $sticky.find('.mobile-toggle');
3657                const $scrollContainer = $('html, body');
3658                
3659                let wasStuck = $sticky.hasClass('stuck');
3660                let scrollCheckInterval = null;
3661                let isAnimating = true;
3662                
3663                //Target element Y coord changes when nav elements become sticky - calculates new location for scroll 
3664                //so element doesn't hide behind sticky elements. 
3665                const calculateOffset = () => {
3666                    const baseOffset = $(hash).offset().top;
3667                    
3668                    if (!$sticky.length) {
3669                        return baseOffset;
3670                    }
3671                    
3672                    const stickyHeight = stickyJumpNav.scrollList 
3673                        ? $sticky.outerHeight() 
3674                        : $mobileToggle.outerHeight();
3675                    
3676                    return baseOffset - navHeight - stickyHeight - stickyPromoBarHeight;
3677                };
3678
3679                const stopMonitoring = () => {
3680                    isAnimating = false;
3681                    if (scrollCheckInterval) {
3682                        clearInterval(scrollCheckInterval);
3683                        scrollCheckInterval = null;
3684                    }
3685                };
3686
3687                const handleStickyStateChange = () => {
3688                    const isNowStuck = $sticky.hasClass('stuck');
3689                    
3690                    if (wasStuck !== isNowStuck) {
3691                        wasStuck = isNowStuck;
3692                        const newOffset = calculateOffset();
3693                        
3694                        $scrollContainer.stop().animate({
3695                            scrollTop: newOffset
3696                        }, ADJUSTMENT_DURATION, stopMonitoring);
3697                    }
3698                };
3699
3700                // Stop monitoring if user manually interacts
3701                $scrollContainer.one('wheel mousedown touchstart keydown', stopMonitoring);
3702
3703                // Monitor sticky state during animation
3704                scrollCheckInterval = setInterval(() => {
3705                    if (!isAnimating) {
3706                        clearInterval(scrollCheckInterval);
3707                        return;
3708                    }
3709                    handleStickyStateChange();
3710                }, MONITOR_INTERVAL);
3711
3712                // Start scroll animation
3713                $scrollContainer.animate({
3714                    scrollTop: calculateOffset()
3715                }, SCROLL_DURATION, () => {
3716                    stopMonitoring();
3717                    //window.location.hash = hash;
3718                });
3719
3720                moveFocus(this, e);
3721            } else if(isAnchor && emptyAnchor && !isBrand && !isContact) {
3722                e.preventDefault();
3723                var navHeight = Number($('.header.component').outerHeight()),
3724                    offset = 0,
3725                    $sticky = $('.sticky-jump-nav');
3726                if($(e.currentTarget).attr('aria-label') === "Overview" && $('body').hasClass('home') === false) {
3727                    offset = $sticky.prev().outerHeight() + $sticky.prev().offset().top + $('.header.component').outerHeight();
3728                }
3729                $('html,body').animate({
3730                    scrollTop: offset
3731                }, 300, function() {
3732                    //window.location.hash = hash;
3733                });
3734            }
3735    });
3736    //function to adjust offset of scrollspy
3737    function fixSpy() {
3738        var data = $body.data('bs.scrollspy');
3739        if (data) {
3740            offset = $(window).height() / 2;
3741            data.options.offset = offset;
3742            $body.data('bs.scrollspy', data);
3743            $body.scrollspy('refresh');
3744        }
3745    }
3746
3747    //svg conversion
3748    $('nav.main img[src$=".svg"], footer img[src$=".svg"], .help img[src$=".svg"]').each(function() {
3749        var $img = jQuery(this);
3750        var imgURL = $img.attr('src');
3751        var attributes = $img.prop("attributes");
3752
3753        $.get(imgURL, function(data) {
3754            // Get the SVG tag, ignore the rest
3755            var $svg = $(data).find('svg');
3756
3757            // Remove any invalid XML tags
3758            $svg = $svg.removeAttr('xmlns:a');
3759
3760            // Loop through IMG attributes and apply on SVG
3761            $.each(attributes, function() {
3762                $svg.attr(this.name, this.value);
3763            });
3764
3765            // Replace IMG with SVG
3766            $img.replaceWith($svg);
3767            $svg.get(0).setAttribute('preserveAspectRatio', 'xMidYMin meet');
3768        }, 'xml');
3769    });
3770
3771    $('.logo svg').each(function() {
3772        $(this).get(0).setAttribute('preserveAspectRatio', 'xMinYMin meet');
3773    });
3774
3775    //custom dropdown (chosen.js)
3776    $chosenSelect = $(".chosen-select");
3777    // if ($chosenSelect.length) {
3778    //     $chosenSelect.chosen({disable_search_threshold: 50});
3779    // }
3780
3781    //adding select dropdown arrow for mobile/tablet views only
3782    $('form select.chosen-select').each(function() {
3783        $(this).after('<span class="arrow" aria-hidden="true"></span>');
3784    });
3785
3786    //sticky nav and sticky jumpnav (jumpnav on homepage only)
3787    var position = $(window).scrollTop();
3788    var $jumpNav = $('#jumpNav');
3789    var ogOffset;
3790
3791    resetJumpOffset();
3792
3793    var $header = $('header:not(.landing-page-header)');
3794    var $hcs = $(".hero-channel-selector.component");
3795    if ($header.length && !$hcs.length) {
3796        $(window).on('scroll', function() {
3797            var scroll = $(window).scrollTop();
3798             if (scroll > 0) {
3799                if (!$header.hasClass("header")) {
3800                    $header.addClass('stuck').removeClass('not-stuck');
3801                }
3802             } else if (scroll === 0) {
3803                if (!$header.hasClass("header")) {
3804                    $header.removeClass('stuck').addClass('not-stuck');
3805                }
3806             }
3807            position = scroll;
3808            checkJumpPosition();
3809        });
3810    } else {
3811        $header.removeClass("not-stuck").addClass("stuck");
3812    }
3813
3814    //resize functions
3815    var resizeTimer;
3816    $(window).on('resize', function() {
3817        clearTimeout(resizeTimer);
3818        resizeTimer = setTimeout(function() {
3819            setViewWidth();
3820            fixSpy();
3821            resetJumpOffset();
3822            checkJumpPosition();
3823            if (typeof checkTipEdge === "function") {
3824                checkTipEdge();
3825            }
3826        }, 250);
3827    });
3828
3829    //jump nav positioning
3830    function checkJumpPosition() {
3831        if ($jumpNav.length > 0) {
3832            var navCenter = ($(window).height() / 2) - ($jumpNav.height() / 2);
3833            $jumpNav.css({ top: ogOffset }).removeClass('init');
3834            if (($jumpNav.offset().top - $(window).scrollTop()) <= navCenter && !$jumpNav.hasClass('stuck')) {
3835                $jumpNav.addClass('stuck');
3836            } else if ($(window).scrollTop() + navCenter <= ogOffset && $jumpNav.hasClass('stuck')) {
3837                $jumpNav.removeClass('stuck');
3838            }
3839            defineHorizontalPositionOfJumpNav();
3840        }
3841    }
3842
3843    function resetJumpOffset() {
3844        if ($jumpNav.length > 0) {
3845            ogOffset = $(window).height() - (($(window).height() * .35) + $jumpNav.height());
3846        }
3847    }
3848
3849    function getWidth() {
3850        return Math.floor(!!window.visualViewport ? window.visualViewport.width : window.outerWidth || window.innerWidth);
3851    }
3852
3853    /** Place the jumpnav just inside the right border of the body (1440px) */
3854    function defineHorizontalPositionOfJumpNav() {
3855        var buffer = 20;
3856        var placement = (getWidth() - 1440) / 2 + buffer;
3857        if (placement > 0) {
3858            $jumpNav.css('right', placement);
3859        } else {
3860            $jumpNav.css('right', '20px');
3861        }
3862    }
3863
3864    //function to assign view type to body
3865    function setViewWidth() {
3866        var desktop = 'tablet-desktop';
3867        var tablet = 'tablet';
3868        var mobile = 'mobile';
3869
3870        if (isMobile()) {
3871            CQ.isOnMobile = true;
3872            if ($(window).width() >= 992) {
3873                $body.removeClass(tablet + mobile).addClass(desktop);
3874            } else if ($(window).width() < 992 && $(window).width() >= 768) {
3875                $body.removeClass(desktop + mobile).addClass(tablet);
3876            } else if ($(window).width() < 768) {
3877                $body.removeClass(tablet + desktop).addClass(mobile);
3878            }
3879        } else {
3880            $body.removeClass(mobile + tablet + desktop);
3881            CQ.resolutionSetting = false;
3882        }
3883    }
3884
3885    //test for touch events, this is used to prevent default when at desktop tablet view for left side navigation
3886    function isMobile() {
3887        var userAgent = navigator.userAgent || navigator.vendor || window.opera;
3888        // Windows Phone must come first because its UA also contains "Android"
3889        if (/windows phone/i.test(userAgent)) {
3890            return true;
3891        }
3892
3893        if (/android/i.test(userAgent)) {
3894            return true;
3895        }
3896        // iOS detection from: http://stackoverflow.com/a/9039885/177710
3897        return /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream;
3898
3899    }
3900
3901    function testBrowser() {
3902        var ua = window.navigator.userAgent;
3903        var msie = ua.indexOf("MSIE ");
3904
3905        if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
3906            $body.addClass('ie');
3907        } else if (window.navigator.userAgent.indexOf("Edge") > -1) {
3908            $body.addClass('edge');
3909        } else {}
3910        return false;
3911    }
3912    testBrowser();
3913
3914    setTimeout(function() {
3915        $body.trigger('pentair.init');
3916    }, 10);
3917
3918    // Get GCLID from URL params and set in a cookie
3919    var gclid = getParam('gclid');
3920    if (gclid) {
3921        var gclsrc = getParam('gclsrc');
3922        if (!gclsrc || gclsrc.indexOf('aw') !== -1) {
3923            setCookie('gclid', gclid, 90);
3924        }
3925    }
3926});
3927// Call functions on load
3928$(window).load(function($stickyNav) {
3929    const headerHeight = $('header').height();
3930    $(window).resize();
3931
3932    // init jumpnav
3933    var $jumpNav = $('#jumpNav'),
3934        $stickyJump = $('#stickyJumpNav');
3935
3936    if ($jumpNav.length > 0) {
3937        if ($(window).scrollTop() >= ($(window).height() / 2) - ($jumpNav.height())) {
3938            $jumpNav.addClass('stuck').removeClass('init');
3939        }
3940    }
3941
3942    if ($stickyJump.length > 0) {
3943        $stickyJump.removeClass('init');
3944    }
3945
3946    // moves jump nav below header no matter header size
3947    if($(window).width() < 767) {
3948        $(".sticky-jump-nav").css("top", headerHeight+'px' )
3949    }
3950
3951    // if jump navigation is hidden, hide-jump-nav class is added for styling of hero
3952    $('main').each(function() {
3953		if(!$(this).find(".sticky-jump-nav").length)
3954            $(this).addClass('hide-jump-nav');
3955    });
3956
3957    //ADA hide cloned items from screenreaders
3958    $('.owl-carousel').find('.cloned').each(function() {
3959        $(this).attr('aria-hidden', 'true');
3960    });
3961
3962    //run resize functions on load
3963    objectFitImages();
3964});
3965
3966// Param getter
3967function getParam(p) {
3968    var match = RegExp('[?&]' + p + '=([^&]*)').exec(window.location.search);
3969    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
3970}
3971
3972// Cookie setter/getter
3973function setCookie(name, value, days) {
3974    var date = new Date();
3975    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
3976    var expires = "; expires=" + date.toGMTString();
3977    document.cookie = name + "=" + value + expires + ";path=/";
3978}
3979
3980function readCookie(name) {
3981    var n = name + "=";
3982    var cookie = document.cookie.split(';');
3983    for (var i = 0; i < cookie.length; i++) {
3984        var c = cookie[i];
3985        while (c.charAt(0) == ' ') {
3986            c = c.substring(1, c.length);
3987        }
3988        if (c.indexOf(n) == 0) {
3989            return c.substring(n.length, c.length);
3990        }
3991    }
3992    return null;
3993}
3994
3995
3996window.Pentair = window.Pentair || {};
3997
3998window.Pentair.helpers = (function(){
3999	
4000	/**
4001	 * Strips out /content/pentair/ when applicable.
4002	 * @param  {String} href Internal link uri.
4003	 * @return {String}      Internal link with /content/pentair/ removed.
4004	 */
4005	var shortUri = function (href) {
4006		if(href) {
4007			var parser = document.createElement('a');
4008			parser.href = $('link[rel="canonical"]').first().attr('href');
4009			var pathIndex = href.indexOf(parser.pathname.replace('.html', ''));
4010			return pathIndex !== -1 ? href.slice(pathIndex) : href;
4011		}
4012		return href;
4013	};
4014
4015	return { shortUri : shortUri }
4016
4017})();
4018
4019$(document).ready(function(){
4020
4021    //mobile nav
4022    var body = $('body');
4023    var hamburger = $('.hamburger-menu');
4024    var searchButton = $('.tertiary .icon-search');
4025    var mobileNav = $('.mobile-nav-wrap');
4026    var tabletNav = $('.tablet-nav-wrap');
4027
4028    hamburger.on('click', function(e) {
4029        e.preventDefault();
4030        if ($(this).hasClass('open')) {
4031            closeMobileNav();
4032        } else{
4033            closeMobileSearch();
4034            body.addClass('menu-open');
4035            hamburger.addClass('open');
4036            mobileNav.fadeIn('fast');
4037            tabletNav.addClass('tablet-open');
4038        }
4039    });
4040
4041    searchButton.on('click', function() {
4042        if ($(this).hasClass('open')){
4043            searchButton.removeClass('open');
4044            body.removeClass('menu-open');
4045        } else{
4046            closeMobileNav();
4047            body.addClass('menu-open');
4048            searchButton.addClass('open');
4049            focusSearchField(100); // 100 attempts in 10 milisecond intervals (net 1 second)
4050        }
4051    });
4052
4053    var legacySearchForm = $('#search-form');
4054    if (legacySearchForm.length) {
4055        legacySearchForm.parsley().on('field:validated', function() {
4056            var ok = $('.parsley-error').length === 0;
4057            $('.bs-callout-info').toggleClass('hidden', !ok);
4058            $('.bs-callout-warning').toggleClass('hidden', ok);
4059        })
4060        .on('form:submit', function() {
4061            return true;
4062        });
4063    }
4064
4065    var searchPath = $('#searchModal').find(".search-form").attr('action');
4066    var ua = window.navigator.userAgent;
4067    var msie = ua.indexOf('MSIE ');
4068    var trident = ua.indexOf('Trident/');
4069    var edge = ua.indexOf('Edge/');
4070    if (msie > 0 || trident > 0 || edge > 0) {
4071        // skip using shortURI because it breaks //TODO please fix
4072    } else {
4073      searchPath = window.Pentair.helpers.shortUri(searchPath);
4074    }
4075
4076    $('#searchModal').find(".search-form").attr('action', searchPath);
4077
4078    $('#searchModal .icon-close').on('click',function(e){
4079        searchButton.removeClass('open');
4080        body.removeClass('menu-open');
4081    });
4082
4083    function focusSearchField(limit) {
4084        // The .focus() event requires that the search field be visible on the page.
4085        // Its visibility is controlled by custom animations and the timing may be a moving target.
4086        // To account for this I've set a timed counter that will determine if the element is visible
4087        // then focus on it. (Usually runs for 80 to 110ms.)
4088        if(limit != null && typeof limit === 'number') {
4089            if (limit < 1) {
4090                $('#siteSearch').focus();
4091            } else {
4092                setTimeout(function() {
4093                    limit -= 1;
4094                    var searchIsVisible = $('#searchModal').hasClass('in');
4095                    if(searchIsVisible) {
4096                        $('#siteSearch').focus();
4097                    } else {
4098                        focusSearchField(limit);
4099                    }
4100                }, 10);
4101            }
4102        } else {
4103            console.error('focusSearchField called without a limit, or it is not a number.')
4104        }
4105    }
4106
4107    //close navigation, used when search is opened
4108    function closeMobileNav(){
4109        //set main nav back to normal;
4110        hamburger.removeClass('open');
4111        body.removeClass('menu-open');
4112        mobileNav.fadeOut('fast');
4113        tabletNav.removeClass('tablet-open');
4114        mobileNav.find('.slide').removeClass('slide');
4115        mobileNav.removeClass('slid');
4116    }
4117
4118    //close search, used when nav is opened
4119    function closeMobileSearch(){
4120        searchButton.removeClass('open');
4121        body.removeClass('menu-open');
4122        $('#searchModal').modal('hide');
4123    }
4124
4125    // PAWMS-652, dynamically adjust menu height to avoid excessive white space
4126    function adjustNavHeight(el) {
4127        // don't adjust height for .nav-style-simple-dropdown
4128        if ($(el).parents('.nav-style-simple-dropdown').length) {
4129            return;
4130        }
4131
4132        const activeTier2 = $(el).find('.tier-2').css('height', 'auto');
4133        const activeTier3 = $(activeTier2).find('.active .tier-3').css('height', 'auto');
4134        const activeTier4 = $(activeTier3).find('.active .tier-4').css('height', 'auto');
4135
4136        // PAWMS-2587 Add a 1px buffer to account for .outerheight() rounding down.
4137        const buffer = 1;
4138
4139        const maxHeight = Math.max(
4140            ...[activeTier2, activeTier3, activeTier4].map(tier => $(tier).outerHeight() || 0)
4141        ) + buffer;
4142
4143        $(activeTier2).css('height', maxHeight);
4144        $(activeTier3).css('height', maxHeight);
4145        $(activeTier4).css('height', maxHeight);
4146    }
4147
4148    const $topLevelLinks = $(".top-level-link");
4149    $topLevelLinks.hover(function () {
4150        adjustNavHeight($(this).find(".main-navigation.component"));
4151    });
4152
4153    //main navigation toggling
4154    const delay = 100;
4155    var timeoutId = -1;
4156    var $tier2 = $('ul.tier-2');
4157    var $tier3 = $('ul.tier-3');
4158    var $tier4 = $('ul.tier-4');
4159    var $secondary = $('.secondary ul.tier-2');
4160    $tier2.find(' > li:first-child').addClass('active').removeClass('not-active');
4161    $tier2.find(' > li').hover(function(){
4162        var thisLi = this;
4163        clearTimeout(timeoutId);
4164        timeoutId = setTimeout(function() {
4165            $(thisLi).closest('ul.tier-2').find(' > li').removeClass('active').addClass('not-active');
4166            $(thisLi).addClass('active').removeClass('not-active');
4167            adjustNavHeight($(thisLi).closest('.main-navigation.component'));
4168        }, delay);
4169    });
4170
4171    /* Start - New Main Navigation Toggling */
4172    var mainNavComponent = $(".main-navigation.component");
4173    var mainNavTier2 = mainNavComponent.find("ul.tier-2");
4174    var mainNavTier3 = mainNavComponent.find("ul.tier-3");
4175
4176    mainNavTier2.find(" > li").each(function() {
4177        if ($(this).find(".dropdown").children().length) {
4178            $(this).addClass("has-children");
4179        }
4180    });
4181
4182    mainNavTier3.find(" > li").each(function() {
4183        var dropdown = $(this).find("> .dropdown");
4184        if (dropdown.find("> .mobile-slider > ul").length && dropdown.find("> .mobile-slider > ul > li").length) {
4185            $(this).addClass("has-children");
4186        }
4187        else {
4188            $(this).addClass("no-children");
4189        }
4190    });
4191
4192    mainNavTier3.find(' > li:first-child').addClass('active').removeClass('not-active');
4193    mainNavTier3.find(' > li').hover(function(){
4194        var thisLi = this;
4195        clearTimeout(timeoutId);
4196        timeoutId = setTimeout(function() {
4197            $(thisLi).closest('ul.tier-3').find(' > li').removeClass('active').addClass('not-active');
4198            $(thisLi).addClass('active').removeClass('not-active');
4199            adjustNavHeight($(thisLi).closest('.main-navigation.component'));
4200        }, delay);
4201    });
4202    /* End - New Main Navigation Toggling */
4203
4204    //assign alt ul when there is no tier 4 present in nav
4205
4206    $tier3.each(function(){
4207        if ($(this).closest('.outer').hasClass('solutions')) {
4208            if ($(this).find('ul.tier-4').length > 0) {
4209            } else {
4210                $(this).addClass('alt');
4211            }
4212        }
4213    });
4214
4215    $tier3.each(function() {
4216        var totalCategories = 0;
4217        var categories = {};
4218
4219        // Add up total tier3 categories and link columns
4220        if ($(this).closest('.outer').hasClass('solutions')){
4221            $(this).children('li').each(function(){
4222                totalCategories++;
4223                if($(this).hasClass('split-4')){
4224                    categories["cat" + totalCategories] = 4;
4225                } else if ($(this).hasClass('split-3')) {
4226                    categories["cat" + totalCategories] = 3;
4227                } else if ($(this).hasClass('split-2')) {
4228                    categories["cat" + totalCategories] = 2;
4229                } else {
4230                    categories["cat" + totalCategories] = 1;
4231                }
4232            });
4233        }
4234        // balance the columns amongst category lists
4235        for (i=1; i < totalCategories; i++) {
4236            if (totalCategories > 3) {
4237                //if 4 categories
4238                categories["cat"+i] = 1;
4239            } else if (totalCategories > 2) {
4240                //if 3 categories
4241                if (categories["cat1"] >= 2) {
4242                    categories["cat1"] = 2;
4243                    categories["cat2"] = 1;
4244                    categories["cat3"] = 1;
4245                } else if (categories["cat1"] == 1 && categories["cat2"] >= 2) {
4246                    categories["cat1"] = 1;
4247                    categories["cat2"] = 2;
4248                    categories["cat3"] = 1;
4249                } else if (categories["cat3"] >= 2) {
4250                    categories["cat1"] = 1;
4251                    categories["cat2"] = 1;
4252                    categories["cat3"] = 2;
4253                }
4254            } else if (totalCategories > 1) {
4255                //if 2 categories
4256                if (categories["cat1"] >= 3 && categories["cat2"] == 1) {
4257                    categories["cat1"] = 3;
4258                    categories["cat2"] = 1;
4259                } else if (categories["cat1"] > 1 && categories["cat2"] > 1) {
4260                    categories["cat1"] = 2;
4261                    categories["cat2"] = 2;
4262                } else if (categories["cat1"] == 1 && categories["cat2"] > 1) {
4263                    categories["cat1"] = 1;
4264                    categories["cat2"] = 3;
4265                }
4266            }
4267        }
4268
4269        // loop children again and reset split class
4270        if ($(this).closest('.outer').hasClass('solutions')) {
4271            $(this).children('li').each(function (i, e) {
4272                var index = i + 1;
4273                if ($(this).hasClass('split-4') && categories["cat" + index] != 4) {
4274                    $(this).removeClass('split-4');
4275                } else if ($(this).hasClass('split-3') && categories["cat" + index] != 3) {
4276                    $(this).removeClass('split-3');
4277                } else if ($(this).hasClass('split-2') && categories["cat" + index] != 2) {
4278                    $(this).removeClass('split-2');
4279                }
4280                $(this).addClass('split-' + categories["cat" + index]);
4281
4282                // Truncate the link list based on columns
4283                $childList = $(this).find('.tier-4');
4284
4285                if (categories["cat" + index] > 3 && $childList.find('li').size() > 32) {
4286                    $childList.html($childList.find('li').slice(0, 31)).append(
4287                        "<li class='view-all'>" + $(this).parent().find('h4').html() + "</li>"
4288                    );
4289                } else if (categories["cat" + index] == 3 && $childList.find('li').size() > 24) {
4290                    $childList.html($childList.find('li').slice(0, 23)).append(
4291                        "<li class='view-all'>" + $(this).parent().find('h4').html() + "</li>"
4292                    );
4293                } else if (categories["cat" + index] == 2 && $childList.find('li').size() > 16) {
4294                    $childList.html($childList.find('li').slice(0, 15)).append(
4295                        "<li class='view-all'>" + $(this).parent().find('h4').html() + "</li>"
4296                    );
4297                } else if (categories["cat" + index] == 1 && $childList.find('li').size() > 8) {
4298                    $childList.html($childList.find('li').slice(0, 7)).append(
4299                        "<li class='view-all'>" + $(this).parent().find('h4').html() + "</li>"
4300                    );
4301                }
4302
4303                $childList.find('.view-all a').text($(this).find('.hidden-view-all').text());
4304            });
4305        }
4306    });
4307
4308    //main nav list splitting
4309    $tier3.each(function(){
4310        var $this = $(this);
4311        if ($this.hasClass('alt') && $this.closest('.outer').hasClass('solutions')){
4312            if ($this.find('li').length > 8 && $this.find('li').length <= 16){
4313                $this.addClass('two-col');
4314            } else if ($this.find('li').length > 16 && $this.find('li').length <= 24){
4315                $this.addClass('three-col');
4316            } else if ($this.find('li').length > 24){
4317                $this.addClass('four-col');
4318            }
4319        }
4320    });
4321
4322    //product list splitting
4323    $tier3.each(function(){
4324        var $this = $(this);
4325        if ($this.closest('.outer').find('.products').length > 0){
4326            if ($this.find('li').length > 13 && $this.find('li').length <= 26){
4327                $this.addClass('two-col');
4328            } else if ($this.find('li').length > 26){
4329                $this.addClass('three-col');
4330            }
4331        }
4332    });
4333
4334    //secondary nav list splitting
4335    $secondary.each(function(){
4336        var $this = $(this);
4337        if ($this.find('li').length > 4){
4338            $this.addClass('three-col');
4339        }
4340    });
4341
4342
4343    //prevent default on side nav at tablet desktop due to link jumping
4344    $('nav.main > ul > li > a, .tier-2 > li > a ').on('click', function(e){
4345        if (($('body').hasClass('tablet-desktop') || $('body').hasClass('tablet')) && !$(this).hasClass('hovered')){
4346            e.preventDefault();
4347            $('nav.main > ul > li > a').removeClass('hovered');
4348            $(this).addClass('hovered');
4349        }
4350    });
4351
4352
4353
4354    //mobile nav sliding
4355    $('nav.main .icon-angle-right').on('click', function(e){
4356        e.preventDefault();
4357        var $this = $(this);
4358        mobileNav.addClass('slid');
4359        $this.closest('.has-children').find('.mobile-slider:first').addClass('slide');
4360        mobileNav.scrollTop(0);
4361    });
4362
4363    //mobile back slide
4364    $('nav.main .back').on('click', function(e){
4365        var $this = $(this);
4366        $this.closest('.mobile-slider').removeClass('slide');
4367        if ($this.closest('ul').hasClass('tier-1') || $this.closest('ul').hasClass('secondary')){
4368            mobileNav.removeClass('slid');
4369        }
4370    });
4371
4372    var dropHeight;
4373
4374    $(".tier-1 > li.solutions").hover(function () {
4375        dropHeight = $(this).find(".dropdown > .wrap").outerHeight() + $(this).find(".tier-2 > .active .dropdown > .wrap").outerHeight();
4376        $(this).find("> .dropdown").height(dropHeight);
4377    });
4378
4379    $(".solutions .tier-2 > li").hover(function () {
4380        var thisLi = this;
4381        clearTimeout(timeoutId);
4382        timeoutId = setTimeout(function() {
4383            dropHeight = $(thisLi).closest(".wrap").outerHeight() + $(thisLi).find(".dropdown > .wrap").outerHeight();
4384            $(thisLi).closest(".dropdown").height(dropHeight);
4385        }, delay);
4386    });
4387
4388    // Accessibility for main navigation using the tab key
4389
4390    // Determine dropdown height on top level focus
4391    let topLevelAnchor = $('.top-level-link.has-children > a');
4392    topLevelAnchor.on("focus", function() {
4393        let thisTopLevelLi = $(this).parent();
4394        adjustNavHeight(thisTopLevelLi.find('.main-navigation.component'));
4395    });
4396
4397    // Common code to set the current li as active
4398    function setAsActive($thisLi) {
4399        clearTimeout(timeoutId);
4400        timeoutId = setTimeout(function() {
4401            // Remove active classes from all siblings and their children
4402            $thisLi.siblings().removeClass("active").addClass("not-active");
4403            $thisLi.siblings().find("ul.tier-3 > li, ul.tier-4 > li").removeClass("active").addClass("not-active");
4404
4405            // Add active class to the current li
4406            $thisLi.addClass("active").removeClass("not-active");
4407
4408            // Ensure all child tiers of the current li are marked as active
4409            $thisLi.find("ul.tier-3 > li:first-child").addClass("active").removeClass("not-active");
4410            $thisLi.find("ul.tier-4 > li:first-child").addClass("active").removeClass("not-active");
4411
4412            // Adjust navigation height after applying active classes
4413            adjustNavHeight($thisLi.closest(".main-navigation.component"));
4414        }, delay);
4415    }
4416
4417    // Tier 2 links
4418    let tier2Link = $tier2.find("> li").find("a");
4419    $(tier2Link).on("focus", function () {
4420        let tier2Li = $(this).parent();
4421        setAsActive(tier2Li);
4422    });
4423
4424    // Tier 3 Links
4425    let tier3Link = $tier3.find("> li").find("a");
4426    $(tier3Link).on("focus", function () {
4427        let tier3Li = $(this).parent();
4428        setAsActive(tier3Li);
4429    });
4430
4431    // Tier 4 Links
4432    let tier4Link = $tier4.find("> li").find("a");
4433    $(tier4Link).on("focus", function () {
4434        let tier4Li = $(this).parent();
4435        let thisTopLevelLi = tier4Li.parents(".top-level-link");
4436        let thisTier2Li = tier4Li.parents(".tier-2 > li");
4437        let thisTier3Li = tier4Li.parents(".tier-3 > li");
4438        setAsActive(thisTier2Li);
4439        setAsActive(thisTier3Li);
4440    });
4441
4442    // This closes the menu and resets focus to the top of the page body
4443    // if the menu is open and has focus. Does not work for mouse hover, only for focus.
4444    let topLevelLi = $(".top-level-link.has-children");
4445    topLevelLi.keydown(function (event) {
4446        if (event.keyCode == 27 && $(event.target).parents(".main-nav")) {
4447            $(document.activeElement).blur();
4448            $(body).focus();
4449        }
4450    });
4451});
4452
4453var GenericFilterViewModel = function(){
4454
4455    var self = this;
4456    var rootModel = this;
4457
4458    self.filters = ko.observableArray(); // array of FilterCategories
4459    self.filterCount = ko.observable(0);
4460    self.activeFilters = ko.computed(function(){
4461        var allFilterModels = [];
4462        self.filters().forEach(function(elem, index){
4463            allFilterModels = allFilterModels.concat(elem.activeFilters());
4464        });
4465        return allFilterModels;
4466    });
4467    self.filterRules = {};
4468    self.data = ko.observableArray();
4469
4470    /**
4471        Filter rules by name of each category.
4472        {
4473            'Distance' : function(dealerItem, currentFilter) {
4474                return currentFilter.value() >= dealerItem.distance; },
4475            'Dealer Name': function(dealerItem, currentFilter){
4476                return currentFilter.value() === dealerItem.name; }
4477        };
4478    */
4479
4480    self.setFilterRules = function (filterRules) {
4481        self.filterRules = filterRules;
4482    };
4483
4484    /**
4485     * Populates categories of either static or dynamic data. Dynamic categories are accumulated from the data object.
4486     * Example data:
4487     * var distanceValues = [{value : 5, title : 5}, {value : 10, title : 10}, {value : 25, title : 25}, {value : 50, title : 50}, {value : 100, title : 100}];
4488     * [{name: "Distance", type: "static", values: distanceValues}, {name: "Dealer Name", type: "dynamic", fromField: "name"}];
4489     */
4490    self.populateCategories = function(categoryArray, data){
4491        rootModel.data(data);
4492        categoryArray.forEach(function(categoryElem, categoryIndex){
4493            var newModel = new self.FilterCategory(categoryElem.name, categoryElem.name, categoryElem.name, categoryElem.inputType);
4494            var categoryId = categoryIndex + "_" + categoryElem.name.replace(/\s/g,"_");
4495            if(categoryElem.type === "static"){
4496                categoryElem.values.forEach(function(elem, index){
4497                    newModel.values.push(new self.FilterModel(elem.value, elem.title, categoryId + "_" + index, newModel));
4498                });
4499            } else if(categoryElem.type === "dynamic") { //accumulate the value array from dealerList
4500                var fieldValues = [];
4501                data.forEach(function(elem){
4502                    if(elem[categoryElem.fromField]){
4503                        fieldValues.push(elem[categoryElem.fromField]);
4504                    }
4505                });
4506
4507                fieldValues = ko.utils.arrayGetDistinctValues(fieldValues).sort();
4508
4509                fieldValues.forEach(function(elem, index){
4510                    newModel.values.push(new self.FilterModel(elem, elem, categoryId + "_" + index, newModel));
4511                });
4512            }
4513            self.filters.push(newModel);
4514        });
4515    };
4516
4517    self.filteredDataList = ko.computed(function(){
4518        var dataList = [];
4519        dataList = self.data().filter(function(dataItem, dataIndex){
4520            return self.filterResults()[dataIndex];
4521        });
4522        return dataList;
4523    }).extend({ rateLimit: 50 });
4524
4525    self.categoryFilterResults = ko.computed(function(){
4526        var categoryFilterResults = []; // array of arrays based on categories
4527        self.filters().forEach(function(categoryModel, categoryIndex){
4528
4529            var activeFilters = categoryModel.values().filter(function(filterModel){
4530                return filterModel.selected();
4531            });
4532
4533            // Returns true for data index if at least one filter in each category passes,
4534            // or there are no filters for that item
4535            var modelFilterResults = self.data().map(function(dataItem, dataIndex){
4536                var noActiveFilters = activeFilters.length === 0;
4537                return noActiveFilters || activeFilters.reduce(function(acc, currentFilter, currentIndex, filterArray){
4538                    return acc || currentFilter.filterResults()[dataIndex];
4539                }, false);
4540            });
4541
4542            categoryModel.filterResults(modelFilterResults);
4543            categoryFilterResults.push(modelFilterResults);
4544        });
4545
4546        return categoryFilterResults;
4547    });
4548
4549    self.filterResults = ko.computed(function(){
4550        var mergedFilterResult = [];
4551
4552        // At this point the array is filled with [[true, true, true, ...],[false, true, true, ...], ...]
4553        // Where each inner array contains whether or not each data element passes a filter,
4554        // and the outer array defines each filter. This section &&'s filter values between all categories.
4555
4556        self.categoryFilterResults().forEach(function(newElem){
4557            if(mergedFilterResult.length === 0){
4558                mergedFilterResult = newElem;
4559            } else {
4560                mergedFilterResult = mergedFilterResult.map(function(originalElem, originalIndex){
4561                    return originalElem && newElem[originalIndex];
4562                });
4563            }
4564        });
4565
4566        return mergedFilterResult;
4567    });
4568
4569
4570    // Each filter category contains individual filters.
4571    self.FilterCategory = function(name, title, label, inputType, valuesArray){
4572        var self = this;
4573        self.parent = rootModel;
4574
4575        self.name = ko.observable(name);
4576        self.title = ko.observable(title);
4577        self.values = ko.observableArray(valuesArray || []); // array of valueModels
4578        self.isOpen = ko.observable(false);
4579        self.label = ko.observable(label);
4580        self.inputType = ko.observable(inputType || "checkbox");
4581
4582        self.filterResults = ko.observableArray();
4583
4584        self.showCategory = ko.computed(function(){
4585            var noFilters = self.values().length === 0;
4586           var oneFilterContainsAllResults = ((self.values().length) === 1 && (self.values()[0].count() === rootModel.data().length));
4587           var oneFilterContainsNoResults = ((self.values().length) === 1 && (self.values()[0].count() === 0));
4588           return !(oneFilterContainsAllResults || oneFilterContainsNoResults || noFilters);
4589        }).extend({ rateLimit: 50 });
4590
4591
4592        self.showDistCategory = ko.computed(function(){
4593            var noFilters = self.values().length === 0;
4594           // var oneFilterContainsAllResults = ((self.values().length) === 1 && (self.values()[0].count() === rootModel.data().length));
4595           // var oneFilterContainsNoResults = ((self.values().length) === 1 && (self.values()[0].count() === 0));
4596           // return !(oneFilterContainsAllResults || oneFilterContainsNoResults || noFilters);
4597            return !(noFilters);
4598        }).extend({ rateLimit: 50 });
4599
4600        self.toggleState = function(context, event){ // for toggling open/closed state
4601            self.isOpen(!self.isOpen());
4602            if(self.isOpen()){
4603                $(event.currentTarget).parent().find('ul').slideDown('fast');
4604            } else {
4605                $(event.currentTarget).parent().find('ul').slideUp('fast');
4606            }
4607        };
4608
4609        self.activeFilters = ko.computed(function(){
4610            return self.values().filter(function(elem){return elem.selected()});
4611        });
4612
4613        self.otherCategoryFilterResults = ko.computed(function(){
4614            var otherCategories = rootModel.filters().filter(function(elem){return elem.title() !== self.title()});
4615            var filterResults = [];
4616
4617            otherCategories.forEach(function(categoryElem, categoryIndex){
4618                if(filterResults.length == 0){
4619                    filterResults = categoryElem.filterResults();
4620                } else {
4621                    filterResults = filterResults.map(function(filterElem, filterIndex){
4622                        return filterResults[filterIndex] && categoryElem.filterResults()[filterIndex];
4623                    })
4624                }
4625            });
4626
4627            return filterResults;
4628        });
4629
4630    };
4631
4632    // Each filter. inputType can be 'checkbox' or 'radio'
4633    self.FilterModel = function(value, title, uniqueId, parent){
4634        var self = this;
4635        self.parent = parent;
4636
4637        self.value = ko.observable(value);
4638        self.title = ko.observable(title);
4639        self.uniqueId = ko.observable(uniqueId);
4640        self.selected = ko.observable(false);
4641
4642        self.toggleSelection = function () {
4643            self.selected(!self.selected());
4644        };
4645
4646        // If only this filter was applied, this is the resulting dataList mapping, one level up we have a cumulative version of this.
4647        self.filterResults = ko.computed(function(){
4648            var filterMapping = rootModel.data().map(function(dataItem){
4649                return rootModel.filterRules[self.parent.name()](dataItem, self);
4650            });
4651            return filterMapping;
4652        });
4653
4654        // By overlaying self.filterResults && parent.otherCategoryFilterResults we get the total count for this filter
4655        self.count = ko.computed(function(){
4656            return self.filterResults().reduce(function(acc, elem, index){
4657                return acc + (elem && parent.otherCategoryFilterResults()[index] ? 1 : 0)
4658            }, 0);
4659        });
4660
4661        self.count.subscribe(function(newValue){
4662            if(newValue == 0 && self.selected()){
4663                self.selected(false);
4664            }
4665        });
4666
4667        self.selected.subscribe(function(newValue){  // Track number of selections
4668            if(parent.inputType() === "radio"){
4669                parent.activeFilters().forEach(function(filterModel){
4670                    if(filterModel.value() !== newValue){ filterModel.selected(false); }
4671                });
4672            } else {
4673                rootModel.filterCount(rootModel.filterCount() + (self.selected() ? 1 : -1));
4674            }
4675        });
4676
4677        return self;
4678    };
4679
4680};
4681var MicroApplProductGridViewModel = function (elem) {
4682    var self = this,
4683        $elem = $(elem),
4684        $win = $(window),
4685        $pagination=$(".pgrid-micro-appl-pagination"),
4686        $hintText = $(".hint-text"),
4687        isEditMode= $elem.attr('data-iseditmode'),
4688        microApplTagName= $elem.attr('data-appl-tag') || '';
4689
4690    // How many pagination buttons to display depends on screen size.
4691    var paginationItems = function(){
4692        if ( matchMedia('(max-width: 765px)').matches ) {
4693            return 3;
4694        }
4695        return 5;
4696    };
4697
4698    /* Start: variables initilization */
4699    self.initVariables = function(){
4700
4701        self.productsResults = ko.observableArray([]);
4702        self.productsSectionResults = ko.observableArray([]);
4703        self.productsFiltersFacets = ko.observableArray([]);
4704        self.selectedFiltersFacets = ko.observableArray([]);
4705        self.seeAllProducts = ko.observable(false);
4706        self.selectedTagName = ko.observable();
4707        self.resultsCount = ko.observable(0);
4708        self.paginator = new PaginationViewModel(0, 12, paginationItems()); // Params: totalResults, itemsPerPage, paginationItems
4709        self.noResults = ko.observable(false);
4710        self.noProductsMsg = ko.observable(false);
4711        self.isLoading = ko.observable(false);
4712
4713        //filters
4714        self.itemsPerPageArr = ko.observableArray([
4715            { text: '12',value:'12' },
4716            { text: '24',value:'24' },
4717            { text: '48',value:'48' }
4718        ]);
4719        self.sortItems = ko.observableArray([
4720            { text: 'Sort By', value: ''},
4721            { text: 'A-Z',value:'pTitle' },
4722            { text: 'Z-A',value:'pTitleDesc' }
4723        ]);
4724    };
4725    /* End: Valible initilization */
4726
4727    /*Start: Scroll Method */
4728
4729    self.scrollToGrid = function(){
4730        $('html, body').stop().animate({ scrollTop: $('.ko-micro-appl-product-grid').offset().top - 150 }, 900);
4731    };
4732
4733    /*End: Scroll Method */
4734
4735    /* Start: Checks for duplicate facets or facet values */
4736    self.isExistingFacetOrValue = function(facet, allFacets, param){
4737        var index = -1;
4738        param = param || 'name';
4739        allFacets.forEach(function(f,i){
4740            if(facet[param] === f[param]){
4741                index = i;
4742            }
4743        });
4744        return index;
4745    };
4746    /* End: Checks for duplicate facets or facet values */
4747
4748    /* Start: updates the selected filters */
4749    self.updateCheckedValues = function(){
4750        $('.filtered > span[data-id]').each(function(){
4751            var targetName = $(this).attr('data-name');
4752            var targetVal = $(this).text();
4753            var $targetEl = $('[name="'+targetName+'"][value="'+targetVal+'"]');
4754            $targetEl.prop('checked',true);
4755            $targetEl.closest('.filter-group').addClass('open');
4756            $targetEl.closest('.filter-group > ul').show();
4757        });
4758    };
4759    /* End: updates the selected filters */
4760
4761    /* Start: Sorting the facet values of each facet */
4762    self.sortFacetVals = function(v){
4763        v.sort(function(a,b){
4764            var aLabel = a.value,
4765                bLabel = b.value;
4766            if(aLabel && aLabel.indexOf(' ')){
4767                aLabel = a.value.split(' ')[0];
4768                aLabel = aLabel.split('-')[0];
4769                aLabel = +aLabel ? +aLabel : aLabel;
4770            }
4771            if(bLabel && bLabel.indexOf(' ')){
4772                bLabel = b.value.split(' ')[0];
4773                bLabel = bLabel.split('-')[0];
4774                bLabel = +bLabel ? +bLabel : bLabel;
4775            }
4776            return aLabel > bLabel ? 1 : -1;
4777        });
4778        return v;
4779    };
4780    /* End: Sorting the facet values of each facet */
4781
4782    /* Start: Updates the filter facet and values */
4783    self.updateFilterFacets = function(facets, isSectionsView){
4784        var updatedFacets = [];
4785        if(isSectionsView) {
4786            updatedFacets = self.productsFiltersFacets();
4787        } else {
4788            self.selectedFiltersFacets([]);
4789        }
4790        for(var i=0;i < facets.length;i++){
4791            var facet = facets[i];
4792            var existingIndex = self.isExistingFacetOrValue(facet, updatedFacets);
4793            if(facet.name){
4794                if(existingIndex >= 0) {
4795                    var prevFacetVals = updatedFacets[existingIndex].values;
4796                    var facetVals = facet.values;
4797                    var tempVals = prevFacetVals;
4798
4799                    /* Start: Checking for an existing facet value. Pushing it, if value doesn't exist
4800                              Updating the count value, if value exists */
4801                    for(var j=0;j < facetVals.length;j++){
4802                        if(facetVals[j] && facetVals[j].value) {
4803                            var facetIndex = self.isExistingFacetOrValue(facetVals[j], prevFacetVals,'value');
4804                            if( facetIndex === -1 ) {
4805                                prevFacetVals.push(facetVals[j]);
4806                            } else {
4807                                prevFacetVals[facetIndex].count = (+prevFacetVals[facetIndex].count + +facetVals[j].count);
4808                            }
4809                        }
4810                    }
4811                    /* End: Checking for an existing facet value. Pushing it, if value doesn't exist
4812                              Updating the count value, if value exists */
4813
4814                    var sortedFacets = self.sortFacetVals(prevFacetVals);
4815
4816                    updatedFacets[existingIndex].values = prevFacetVals;
4817
4818                } else {
4819                    facet.values = self.sortFacetVals(facet.values);
4820                    updatedFacets.push(facet);
4821                }
4822            }
4823        }
4824
4825        //sorting the facets alphabetically
4826        updatedFacets.sort(function(a,b){
4827            return a.label > b.label ? 1 : -1;
4828        });
4829
4830        // clearing the productsFiltersFacets before pushing the updatedFacets
4831        self.selectedFiltersFacets([]);
4832        self.selectedFiltersFacets(updatedFacets);
4833        if(isSectionsView) {
4834            self.productsFiltersFacets(updatedFacets);
4835        }
4836
4837        //updating selected facets
4838        self.updateCheckedValues();
4839    };
4840    /* End: Updates the filter facet and values */
4841
4842    /* Start : toggle views to see all products */
4843    self.toggleView = function(type){
4844        var seeAllProducts = self.seeAllProducts();
4845        if(seeAllProducts) {
4846            self.selectedTagName('');
4847            self.selectedFiltersFacets(self.productsFiltersFacets());
4848            self.updateCheckedValues();
4849        }
4850        self.seeAllProducts( !seeAllProducts );
4851    };
4852    /* End : toggle views to see all products */
4853
4854
4855    /*Start: showModel */
4856    self.showModel = function(data,event){
4857
4858        event.preventDefault();
4859
4860        //update model data
4861        var $quickViewModel= $('#quickviewModal');
4862        var $modelDom = $quickViewModel.find('.product-data .quick-view');
4863        $modelDom.find('.image img').attr('src',data['pFileReference']);
4864        $modelDom.find('.image img').attr('alt', data['pTitle']);
4865        $modelDom.find('.ribbon').attr('style', data['pBanner'] ? '' : 'display: none;');
4866        $modelDom.find('.ribbon').removeClass('dark-blue').removeClass('white').addClass(data['pBannerColor']);
4867        $modelDom.find('.ribbon span').text(data['pBannerLabel']);
4868
4869        $modelDom.find('.details h3').html( data['pTitle'] );
4870        $modelDom.find('.details p.desc').html( data['pImageMetadataDesc'] || data['pDescription']);
4871        $modelDom.find('.details a.learn-more-link').attr( 'href', data['pPath']);
4872        $modelDom.find('.p-info').html( data['pInfo'] );
4873        $modelDom.find('.bazaar-voice-rating').html('');
4874
4875        if(self.showRating.bind(data)()){
4876            var bvRatingsHtml = '<div data-bv-show=\"inline_rating\" data-bv-product-id=\"' + data['pBVProductId'] + '\"></div>';
4877            $modelDom.find('.bazaar-voice-rating').html(bvRatingsHtml);
4878        }
4879
4880        //get the content from the product item and update in the model
4881
4882        if( data['skus'].length > 0 && data['allSkusUnlinked'] === 'false'){
4883
4884            var skusStr="<ul>";
4885            for( var i=0;i<data['skus'].length;i++ ){
4886                if(self.getSkuHtml(data['skus'][i])){
4887                    skusStr = skusStr + self.getSkuHtml(data['skus'][i])
4888                }
4889            }
4890            skusStr = skusStr+"</ul>";
4891            $quickViewModel.find('.sku-products').html( skusStr  );
4892            $quickViewModel.find('.sku-products').addClass('hide');
4893            $quickViewModel.find('.see-items-link').addClass('active').removeClass('hide');
4894
4895        }else{
4896            $quickViewModel.find('.see-items-link').removeClass('active').addClass('hide');
4897            $quickViewModel.find('.sku-products').html('');
4898        }
4899
4900        $quickViewModel.modal('show');
4901    };
4902    /*End:showModel */
4903
4904    /*Start: SKU HTML construction from product data*/
4905    self.getSkuHtml = function(data){
4906        var skuLi = '';
4907        if(data['skuId']){
4908            skuLi = "<li>";
4909            var titleOrId = data['skuTitle'] || data['skuId'];
4910            skuLi = skuLi+'<a class="sku-link" href=\"'+data['skuPath']+'\">'+titleOrId+'</a>';
4911            skuLi = skuLi+"</li>";
4912        }
4913        return skuLi;
4914        /*var $clonedProduct = $('.product-data').clone();
4915		 var $modelDom = $clonedProduct.find('.quick-view');
4916		$modelDom.find('.image img').attr('src',data['skuFileReference']);
4917		$modelDom.find('.details h3').html( data['skuTitle'] );
4918		$modelDom.find('.details p.desc').html( data['skuDescription']);
4919		$modelDom.find('.details a.learn-more-link').attr( 'href', data['skuPath']);
4920		$modelDom.find('.p-info').html("");*/
4921        //return skuLi;
4922    };
4923    /*End: getSkuHtml*/
4924
4925    self.clickPage = function () {
4926        var targetPage = $(event.target);
4927        self.paginator.currentPage(parseInt(targetPage.text(),10));
4928    };
4929
4930    /*Start: filterSearch */
4931    self.filterSearch = function(searchType) {
4932        self.paginator.currentPage(1);
4933    };
4934    /*End: filterSearch */
4935
4936    var fsTimeout = null;
4937
4938    //binding change event for the sort and items per page dropdown
4939    $(".filters-sort-by").on('change', function(){
4940        self.filterSearch('sortbychange');
4941
4942    });
4943
4944    //change event bind for the results per page dropdown
4945    $(".filters-num-results").on('change', function(){
4946        self.paginator.itemsPerPage(parseInt($(this).val(),10));
4947        self.filterSearch('itemseperpage');
4948    });
4949
4950    //click event bind for facets filters
4951    $('.filter').on('click','fieldset > ul input[type = "checkbox"]', function(e){
4952        if($(this).prop("checked")){
4953            self.appendFilter($(this));
4954        }else{
4955            self.removeFilter($(this));
4956        }
4957        if(fsTimeout){
4958            clearTimeout(fsTimeout);
4959        }
4960        fsTimeout = setTimeout(function(){
4961            self.filterSearch( 'facetChange' );
4962        },800);
4963
4964    });
4965
4966    //event bind for the filter hint text
4967    $('.filtered').on('click','span',function(){
4968        var targetName = $(this).attr('data-name');
4969        var targetVal = $(this).attr('data-value');
4970        var $targetEl = $('[name="'+targetName+'"][value="'+targetVal+'"]');
4971        $targetEl.trigger('click');
4972        $(this).remove();
4973    });
4974
4975    //event bind to show all skus of product
4976    var $quickViewModal = $('#quickviewModal');
4977    $quickViewModal.on('click','.see-items-link',function(e){
4978        e.preventDefault();
4979        $quickViewModal.find('.sku-products').toggleClass('hide');
4980        $quickViewModal.find('.see-items-link').toggleClass('active');
4981    });
4982
4983    self.showRating = function () {
4984        return this.pBVProductId && (this.pBVProductGrid == '' || this.pBVProductGrid == 'true');
4985    };
4986
4987    self.prevPage = function () {
4988        if(self.paginator.previousPageExists()){
4989            var currentPage = self.paginator.currentPage();
4990            self.paginator.currentPage(currentPage - 1);
4991        }
4992    };
4993
4994    self.nextPage = function () {
4995        if(self.paginator.nextPageExists()){
4996            var currentPage = self.paginator.currentPage();
4997            self.paginator.currentPage(currentPage + 1);
4998        }
4999    };
5000
5001    self.appendFilter = function($elem){
5002        var htmlStr = "<span data-id='"+$elem.prop('id')+"' data-name='"+$elem.prop('name')+"' data-value='"+$elem.prop('value')+"'>"+$elem.prop('value')+"</span>";
5003        $('.filtered').append(htmlStr);
5004    };
5005    self.removeFilter= function($elem){
5006        var name= $elem.prop('name');
5007        var val= $elem.prop('value');
5008        $('.filtered').find("[data-name='" +name+ "'][data-value='"+val+"']").remove();
5009    };
5010
5011    self.loadedOnce = false;
5012
5013    /* Start : Loader Functionality */
5014    self.toggleLoader = function(show){
5015        if(show){
5016            $(".loader").removeClass('hide');
5017            if ( self.loadedOnce === false ) {
5018                $('.product-grid').addClass('loading init-load');
5019            } else {
5020                $('.product-grid').addClass('loading');
5021            }
5022            self.isLoading(true);
5023        }else {
5024            $(".loader").addClass('hide');
5025            $('.product-grid').removeClass('loading init-load');
5026            if ( self.loadedOnce === false ) {
5027                self.loadedOnce = true;
5028            } else {
5029                self.scrollToGrid();
5030            }
5031            self.isLoading(false);
5032        }
5033    };
5034    /* End : Loader Functionality */
5035
5036      /* Start: Init Method that starts the component */
5037    self.init = function(){
5038        self.initVariables();
5039    };
5040    /* End: Init Method that starts the component */
5041
5042    $(window).resize($.throttle(function(){
5043        self.paginator.paginationItems(paginationItems());
5044    }, 100));
5045
5046    self.init();
5047};
5048
5049$(document).ready(function () {
5050    $('.ko-micro-appl-product-grid').each(function () {
5051        $('.product-grid').closest('.section').append($(this).find('.loader-wrapper'));
5052        try {
5053            ko.applyBindings(new MicroApplProductGridViewModel($(this)), this);
5054        } catch (e) {
5055            console.log(e);
5056        }
5057    });
5058}); 
5059
5060//view models
5061var ProductModel = function (product,wcmmode) {
5062    // any manipulation towards the keys and values have to be done here;
5063
5064    var applProduct = {};
5065    var pPath = product['pPath'];
5066    if("edit" === wcmmode ){
5067        if( pPath && pPath.indexOf('/content/pentair') === -1 ){
5068            pPath = "/content/pentair"+pPath;
5069        }
5070    }
5071    applProduct['pPath'] = pPath;
5072    applProduct['pTitle']= product['pTitle'];
5073    applProduct['pDescription'] = product['pDescription'];
5074    applProduct['pImageMetadataDesc'] = product['pImageMetadataDesc'];
5075    applProduct['pInfo'] = product['pInfo'];
5076    applProduct['pAccessories'] = product['pAccessories'];
5077    applProduct['pAppl'] = product['pAppl'];
5078    applProduct['pBrands'] = product['pBrands'];
5079    applProduct['pCategories'] = product['pCategories'];
5080    applProduct['pCertTxt'] = product['pCertTxt'];
5081    applProduct['pCertImg'] = product['pCertImg'];
5082    applProduct['pFeatures'] = product['pFeatures'];
5083    applProduct['pBanner'] = product['pBanner'];
5084    applProduct['pBannerLabel'] = product['pBannerLabel'];
5085    applProduct['pBannerColor'] = product['pBannerColor'];
5086    applProduct['pBVProductId'] = product['pBVProductId'];
5087    applProduct['pBVProductGrid'] = product['pBVProductGrid'];
5088
5089    if (product['pFileReference']) {
5090        applProduct['pFileReference'] = product['pFileReference'];
5091    } else {
5092        applProduct['pFileReference'] = "/content/dam/extranet/product-related/product-photo/Pentair_ProductImagePlaceholder_300x300.jpg";
5093    }
5094    applProduct['pFooter']= product['pFooter'];
5095    applProduct['pOverview']= product['pOverview'];
5096    applProduct['pId']= product['pId'];
5097
5098    //getting skus data of product
5099    applProduct['skus']=[];
5100    applProduct['allSkusUnlinked'] = 'true';
5101    var skuUnlinked =  product['skuUnlinked'].split(',');
5102    var skuIds =  product['skuId'].split('|');
5103    var skuTitles =  product['skuTitle'].split('|');
5104    var skuPaths =  product['skuPath'].split('|');
5105    var skuDes =  product['skuDescription'].split('|');
5106    var skuRef =  product['skuFileReference'].split('|');
5107    /*skuDiscontnd ,skuFeatures,footer,skuOverview,capacities,heads */
5108
5109    if( skuIds.length > 0 && !!skuIds[0]){
5110        for( var i=0;i<skuIds.length; i++ ){
5111            var SKU = {};
5112            SKU['skuId'] = skuIds[i];
5113            SKU['skuTitle']= skuTitles[i];
5114            SKU['skuDescription']=skuDes[i];
5115
5116            SKU['skuFileReference']= skuRef[i];
5117            var skuPath = skuPaths[i];
5118            if("edit" === wcmmode ){
5119                if( skuPath && skuPath.indexOf('/content/pentair') === -1 ){
5120                    skuPath = "/content/pentair"+skuPath;
5121                }
5122            }
5123            //do we have atleast one sku which is not unlinked
5124            if(skuUnlinked[i] === 'false'){
5125               applProduct['allSkusUnlinked'] = 'false';
5126            }
5127            SKU['skuPath']= skuPath;
5128            applProduct['skus'].push(SKU);
5129        }
5130    }
5131    return applProduct;
5132};
5133
5134var FacetsFilter = function ( item ) { 
5135    // any manipulation towards the keys and values have to be done here;
5136    return item;
5137};
5138
5139var PageListViewModel = function(elem) {
5140    var self = this,
5141        $elem = $(elem),
5142        isEditMode = $elem.attr('data-iseditmode'),
5143        itemsPerPage = $elem.attr('data-per-page'),
5144        resultType = $elem.attr('data-result-type'),
5145        blogTag = $elem.attr('data-blog-tag') || '';
5146        self.selectedFilters = ko.observableArray();
5147
5148    // How many pagination buttons to display depends on screen size.
5149    var paginationItems = function() {
5150        if(matchMedia('(max-width: 765px)').matches) {
5151            return 3;
5152        }
5153        return 5;
5154    };
5155
5156    var updateAnalytics = function () {
5157
5158        var blogFilterValues = _.chain(self.selectedFilters())
5159            .map(function(elem){return elem.filterLabel + ':' + elem.name}, '')
5160            .value()
5161            .join('|');
5162
5163        var newDigitalData = {
5164            resources: {
5165                blogFilterValues: _.chain(self.selectedFilters()).map(function(elem){return elem.filterLabel + ':' + elem.name}, '').value().join('|')
5166            },
5167            event : {
5168                eventName: resultType.replace('blogs', 'blog') + ' filter',
5169                eventAction: 'click',
5170                type: resultType.replace('blogs', 'blog'),
5171                timeStamp: (new Date).toString()
5172            }
5173        };
5174
5175        $.extend(window.digitalData, newDigitalData);
5176
5177        return true;
5178    };
5179
5180    /* Start: variables initilization */
5181    self.initVariables = function() {
5182
5183        self.paginator = new PaginationViewModel(0, +itemsPerPage, paginationItems()); // Params: totalResults, itemsPerPage, paginationItems(method)
5184
5185        self.selectedFilters.subscribe(function(newValue){
5186            updateAnalytics();
5187        });
5188
5189    };
5190    /* End: Valible initilization */
5191
5192    // open/close tier-4 filters
5193    var $filterParentLink = $('.page-list.component .filter');
5194    $filterParentLink.on('click', 'fieldset > ul li > span', function() {
5195        var $this = $(this);
5196        if($this.parent('li').hasClass('open')) {
5197            $this.parent('li').removeClass('open');
5198            $this.next().stop().slideUp('fast');
5199        } else {
5200            $this.parent('li').addClass('open');
5201            $this.next().stop().slideDown('fast');
5202        }
5203    });
5204
5205    self.clickPage = function() {
5206        var targetPage = $(event.target);
5207        self.paginator.currentPage(parseInt(targetPage.text(), 10));
5208    };
5209
5210    self.prevPage = function() {
5211        if(self.paginator.previousPageExists()) {
5212            var currentPage = self.paginator.currentPage();
5213            self.paginator.currentPage(currentPage - 1);
5214        }
5215    };
5216
5217    self.nextPage = function() {
5218        if(self.paginator.nextPageExists()) {
5219            var currentPage = self.paginator.currentPage();
5220            self.paginator.currentPage(currentPage + 1);
5221        }
5222    };
5223
5224    self.removeFilter = function(index) {
5225        self.selectedFilters.splice(index, 1);
5226    };
5227
5228    /* Start: Init Method that starts the component */
5229    self.init = function() {
5230        self.initVariables();
5231    };
5232    /* End: Init Method that starts the component */
5233
5234    $(window).resize($.throttle(function() {
5235        if(self.paginator) {
5236            self.paginator.paginationItems(paginationItems());
5237        }
5238    }, 100));
5239    self.init();
5240
5241};
5242
5243$(document).ready(function() {
5244    $('.ko-page-list').each(function() {
5245        var koPageList = new PageListViewModel($(this));
5246        try {
5247            ko.applyBindings(koPageList, this);
5248        } catch(e) {
5249            console.log(e);
5250        }
5251    });
5252});
5253
5254//view models
5255//Model Object for Blogs/Events/News
5256var BNEModel = function(bneResult, wcmmode) {
5257    // any manipulation towards the keys and values have to be done here;
5258
5259    var bneModelObj = {};
5260    var bnePagePath = bneResult['bnePagePath'];
5261    if("edit" === wcmmode) {
5262        if(bnePagePath && bnePagePath.indexOf('/content/pentair') === -1) {
5263            bnePagePath = "/content/pentair" + bnePagePath;
5264        }
5265    }
5266    bneModelObj['bnePagePath'] = bnePagePath;
5267    bneModelObj['bneImgPath'] = bneResult['bneImgPath'];
5268    bneModelObj['bneTitle'] = bneResult['bneTitle'];
5269    bneModelObj['bneIndustry'] = bneResult['bneIndustry'];
5270    bneModelObj['bneDate'] = bneResult['bneDate'];
5271    bneModelObj['bneDateString'] = bneResult['bneDateString'];
5272    bneModelObj['bneDesc'] = bneResult['bneDesc'];
5273    bneModelObj['bneAuthor'] = bneResult['bneAuthor'];
5274    bneModelObj['bneName'] = bneResult['bneName'];
5275    bneModelObj['bneAuthorImg'] = bneResult['bneAuthorImg'];
5276    bneModelObj['bneEventLink'] = bneResult['bneEventLink'];
5277    bneModelObj['bneEventLocation'] = bneResult['bneEventLocation'];
5278
5279    return bneModelObj;
5280};
5281
5282var FacetsFilter = function(item) {
5283    // any manipulation towards the keys and values have to be done here;
5284    return item;
5285};
5286
5287var SiteSearchViewModel = function(elem) {
5288    var self = this,
5289        $elem = $(elem),
5290        $allPagination = $(".all .ko-site-search-pagination"),
5291        $productPagination = $(".product .ko-site-search-pagination"),
5292        $blogPagination = $(".blog .ko-site-search-pagination"),
5293        $eventPagination = $(".event .ko-site-search-pagination"),
5294        $newsPagination = $(".news .ko-site-search-pagination"),
5295        $allPaginationWrapper = $(".site-search-results .all.pagination"),
5296        $productPaginationWrapper = $(".site-search-results .product.pagination"),
5297        $blogPaginationWrapper = $(".site-search-results .blog.pagination"),
5298        $eventPaginationWrapper = $(".site-search-results .event.pagination"),
5299        $newsPaginationWrapper = $(".site-search-results .news.pagination"),
5300        $hintText = $(".hint-text"),
5301        itemsPerPageConf = $elem.attr('data-items-per-page'),
5302        isEditMode = $elem.attr('data-iseditmode');
5303
5304    /* Start: variables initialization */
5305    self.initVariables = function() {
5306
5307        // all
5308        self.searchResults = ko.observableArray([]);
5309        self.searchType = ko.observable();
5310        self.keyword = ko.observable('');
5311        self.type = ko.observable('all');
5312        self.currentPage = ko.observable(1);
5313        self.resultsStarts = ko.observable(1);
5314        self.resultsEnds = ko.observable();
5315        self.totalResultsCount = ko.observable();
5316        self.allNoResults = ko.observable(true);
5317        self.suggestedTerm = ko.observable('-- No Suggested Term --');
5318        self.showDidYouMean = ko.observable(false);
5319
5320        // product results
5321        self.productSearchResults = ko.observableArray([]);
5322        self.productResultsStarts = ko.observable(1);
5323        self.productResultsEnds = ko.observable();
5324        self.productTotalResultsCount = ko.observable();
5325        self.productNoResults = ko.observable(true);
5326        self.productCurrentPage = ko.observable(1);
5327
5328        // blog results
5329        self.blogSearchResults = ko.observableArray([]);
5330        self.blogResultsStarts = ko.observable(1);
5331        self.blogResultsEnds = ko.observable();
5332        self.blogTotalResultsCount = ko.observable();
5333        self.blogNoResults = ko.observable(true);
5334        self.blogCurrentPage = ko.observable(1);
5335
5336        // event results
5337        self.eventSearchResults = ko.observableArray([]);
5338        self.eventResultsStarts = ko.observable(1);
5339        self.eventResultsEnds = ko.observable();
5340        self.eventTotalResultsCount = ko.observable();
5341        self.eventNoResults = ko.observable(true);
5342        self.eventCurrentPage = ko.observable(1);
5343
5344        // news results
5345        self.newsSearchResults = ko.observableArray([]);
5346        self.newsResultsStarts = ko.observable(1);
5347        self.newsResultsEnds = ko.observable();
5348        self.newsTotalResultsCount = ko.observable();
5349        self.newsNoResults = ko.observable(true);
5350        self.newsCurrentPage = ko.observable(1);
5351
5352        self.toggleLoader();
5353
5354    };
5355    /* End: Valible initilization */
5356
5357    self.pushBrowserState = function(params) {
5358        var url = $.param.querystring(window.location.href, params, 2);
5359        window.history.pushState(params, '', url);
5360    };
5361
5362    self.doSearch = function(data, event) {
5363        if(self.keyword() && self.keyword().trim() !== "") {
5364            self.currentPage(1);
5365            self.productCurrentPage(1);
5366            self.blogCurrentPage(1);
5367            self.eventCurrentPage(1);
5368            self.newsCurrentPage(1);
5369            self.pushBrowserState(self.getBrowserParms('submit'));
5370        } else {
5371            console.warn('Search attempted with no term. Cancelled.');
5372        }
5373    };
5374
5375    self.getBrowserParms = function(type) {
5376        var queryParms = {};
5377        queryParms['q'] = self.keyword();
5378
5379        /*debug local*/
5380        // queryParms['wcmmode'] = 'disabled';
5381
5382        return queryParms;
5383    };
5384
5385    /* Start : Loader Functionality */
5386    self.toggleLoader = function(show) {
5387        var $resultBlockElement = $('.result-block');
5388        if(show) {
5389            $(".loader").removeClass('hide');
5390            $('ko-site-search').addClass('loading');
5391            var resultBlockHt = $(window).height() - ($resultBlockElement.offset().top - $(window).scrollTop());
5392            $resultBlockElement.css('maxHeight', resultBlockHt).addClass('results-loading');
5393        } else {
5394            $(".loader").addClass('hide');
5395            $('ko-site-search').removeClass('loading');
5396            $resultBlockElement.css('maxHeight', '').removeClass('results-loading');
5397        }
5398    };
5399    /* End : Loader Functionality */
5400
5401    /* Start: Init Method that starts the component */
5402    self.init = function() {
5403        self.initVariables();
5404        initOwlEvents();
5405    };
5406    /* End: Init Method that starts the component */
5407
5408    function initOwlEvents(){
5409        // Init count change on tab switch.
5410        elem.on('changed.owl.carousel', function(event) {
5411            var currentSlide = $(event.target).find(".owl-item").eq(event.item.index).children();
5412            var currentSlideCount = currentSlide.data('count');
5413            var currentFilter = currentSlide.data('filter');
5414            digitalData.search.searchFilter = currentFilter;
5415            digitalData.search.resultsNumber = currentSlideCount;
5416        });
5417    };
5418
5419    self.init();
5420};
5421
5422$(document).ready(function() {
5423    $('.ko-site-search').closest('.section').append($('.loader-wrapper'));
5424    $('.ko-site-search.component').each(function() {
5425        try {
5426            ko.applyBindings(new SiteSearchViewModel($(this)), this);
5427        } catch(e) {
5428            console.log(e);
5429        }
5430    });
5431});
5432
5433//view models
5434var SiteSearchModel = function(object, wcmmode) {
5435    // any manipulation towards the keys and values have to be done here;
5436
5437    var result = {};
5438    result['body'] = object['body'];
5439    if("edit" === wcmmode) {
5440        if(object['url'] !== "" && object['url'].indexOf('/content/pentair') === -1) {
5441            object['url'] = "/content/pentair" + object['url'];
5442        }
5443    }
5444    result['url'] = object['url'];
5445    return object;
5446};
5447
5448var PENTAIR = PENTAIR || {};
5449PENTAIR.Water = PENTAIR.Water || {};
5450PENTAIR.Water.mapStyle = PENTAIR.Water.mapStyle || 
5451  [
5452    {
5453        "featureType": "administrative",
5454        "elementType": "labels.text.fill",
5455        "stylers": [
5456            {
5457                "color": "#444444"
5458            }
5459        ]
5460    },
5461    {
5462        "featureType": "landscape",
5463        "elementType": "all",
5464        "stylers": [
5465            {
5466                "color": "#f2f2f2"
5467            }
5468        ]
5469    },
5470    {
5471        "featureType": "poi",
5472        "elementType": "all",
5473        "stylers": [
5474            {
5475                "visibility": "off"
5476            }
5477        ]
5478    },
5479    {
5480        "featureType": "road",
5481        "elementType": "all",
5482        "stylers": [
5483            {
5484                "saturation": -100
5485            },
5486            {
5487                "lightness": 45
5488            }
5489        ]
5490    },
5491    {
5492        "featureType": "road.highway",
5493        "elementType": "all",
5494        "stylers": [
5495            {
5496                "visibility": "simplified"
5497            }
5498        ]
5499    },
5500    {
5501        "featureType": "road.arterial",
5502        "elementType": "labels.icon",
5503        "stylers": [
5504            {
5505                "visibility": "off"
5506            }
5507        ]
5508    },
5509    {
5510        "featureType": "transit",
5511        "elementType": "all",
5512        "stylers": [
5513            {
5514                "visibility": "off"
5515            }
5516        ]
5517    },
5518    {
5519        "featureType": "water",
5520        "elementType": "all",
5521        "stylers": [
5522            {
5523                "color": "#46bcec"
5524            },
5525            {
5526                "visibility": "on"
5527            }
5528        ]
5529    }
5530];
5531  
5532PENTAIR.Water.MapHelper = function(mapElement){
5533  var self = this;
5534  var zipCodeRadius;
5535  var MetersPerMile = 1609.34;
5536  var MaxDistanceInMeters = MetersPerMile * 25;
5537  var iconLocation;
5538  self.mapElement = mapElement;
5539  self.initComplete = ko.observable(false);
5540  self.allMarkers = ko.observableArray().extend({ rateLimit: 100 });
5541  self.markerHtmlCallback = (function(item){return ''});
5542  self.zipMarkers = ko.computed(function(){
5543    var markersWithinZip = self.allMarkers().filter(function(elem, index){
5544      return self.markerIndexesWithinDistance().indexOf(index) !== -1;
5545    });
5546    return markersWithinZip;
5547  });
5548
5549  self.mapData = ko.observableArray();
5550  self.markerIndexesWithinDistance = ko.observableArray().extend({ rateLimit: 500 });
5551
5552  function getMapIconLocation() {
5553    var mapContainer = $('.map.where-content')[0].classList;
5554    if(!!mapContainer) {
5555      if (mapContainer.contains('pentair-bright-blue')) {
5556        return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/map-pin-pentair-bright-blue.png';
5557      } else if (mapContainer.contains('pentair-blue')) {
5558        return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/map-pin-pentair-blue.png';
5559      } else if (mapContainer.contains('green')) {
5560        return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/map-pin-green.png';
5561      }
5562    }
5563    return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/curve-green.png';
5564  }
5565
5566  function setInitComplete(){
5567    self.setInitComplete = self.allMarkers.subscribe(function(newValue){
5568      var nonEmptyLength = newValue.filter(function(elem){
5569        return !!elem;
5570      }).length;
5571      if(newValue.length === self.totalMarkers()){
5572        self.initComplete(true);
5573        updateZoom(self.map);
5574      }
5575      self.setInitComplete.dispose();
5576    });
5577  }
5578  
5579  self.totalMarkers = ko.observable(0);
5580  
5581  self.showPins = function(indexArray){
5582    $(self.allMarkers()).each(function(index, elem){
5583      if(elem && indexArray.indexOf(index) !== -1){
5584        elem.setMap(self.map);
5585      } else if(elem){          // avoids case where elem is empty because the address wasnt found.
5586        elem.setMap(null);
5587      }
5588    });
5589    updateZoom(self.map);
5590  };
5591
5592  // Only call once - add a re-init.
5593  function initMap(mapData, callback) {
5594    self.map = new google.maps.Map(self.mapElement[0], {
5595      center: new google.maps.LatLng(-34.397, 150.644),
5596      zoom: 1,
5597      minZoom: 1,
5598      mapTypeId: 'pentairWater'
5599    });
5600
5601    self.infowindow = new google.maps.InfoWindow();
5602
5603    self.geocoder = new google.maps.Geocoder();
5604    self.totalMarkers(mapData.length);
5605    self.mapData(mapData);
5606    self.allMarkers([]);
5607    self.map.mapTypes.set('pentairWater', new google.maps.StyledMapType(PENTAIR.Water.mapStyle, { name: 'Pentair Water' }));
5608    if(callback){
5609      callbackAfterInit(callback);
5610    }
5611
5612    setInitComplete();
5613    mapData.forEach(function(elem, index){
5614      var hasLatLong = elem.latitude && elem.longitude;
5615      if(hasLatLong){
5616        addLatLongAddress(elem);
5617      } else addGeocodeAddress(elem);
5618    });
5619
5620    return self.allMarkers;
5621  };
5622
5623  function callbackAfterInit(callback){
5624    self.callBackAfterInit = self.allMarkers.subscribe(function(newValue){
5625      if(newValue.length === self.totalMarkers()){
5626        callback();
5627      }
5628      self.callBackAfterInit.dispose();
5629    });
5630  };
5631
5632  function getMarkersWithinZip(zipCode){
5633    self.geocoder.geocode({
5634      'address': zipCode
5635    }, function(results, status) {
5636      if (status === google.maps.GeocoderStatus.OK) {
5637        var markerIndexesWithinDistance = [];
5638        var latLong = results[0].geometry.location;
5639        self.markerIndexesWithinDistance(self.allMarkers().reduce(function(acc, elem, index){
5640          var metersBetween = google.maps.geometry.spherical.computeDistanceBetween(latLong, elem.position);
5641          if(metersBetween < MaxDistanceInMeters){ acc.push(index); }
5642          return acc;
5643        }, []));
5644      } else {
5645        console.warn('Geocode was not successful for the following reason: ' + status);
5646      }
5647    });
5648  };
5649
5650  function addInfoWindowEvent(eventName, callback){
5651    google.maps.event.addDomListener(self.mapElement[0], eventName, callback);
5652  }
5653
5654  // tha call back is an anonymouse function that takes an item param
5655  function setMarkerHtmlCallback(callback){
5656    self.markerHtmlCallback = callback;
5657  }
5658
5659  self.openMarker = function (index) {
5660    self.infowindow.setContent(self.markerHtmlCallback(self.mapData()[index]));
5661    self.infowindow.open(self.map, self.allMarkers()[index]);
5662  };
5663
5664  self.closeMarker = function () {
5665    self.infowindow.close();
5666  };
5667
5668  function addMarker(position, item){
5669    if(!item.hideAddress){
5670      var marker = new google.maps.Marker({
5671        map: self.map,
5672        position: position,
5673        icon: getMapIconLocation()
5674      });
5675
5676      google.maps.event.addListener(marker, 'click', function() {
5677        self.infowindow.setContent(self.markerHtmlCallback(item));
5678        self.infowindow.open(self.map, marker);
5679      });
5680
5681      var markers = self.allMarkers();
5682      markers[item.index] = marker;
5683      self.allMarkers(markers);
5684    }
5685  };
5686
5687  function addLatLongAddress(item) {
5688    var latLong = new google.maps.LatLng(parseFloat(item.latitude,10), parseFloat(item.longitude,10));
5689    self.map.setCenter(latLong);
5690    addMarker(latLong, item);
5691  }
5692
5693  function addGeocodeAddress(item){
5694    if(item && item.address){
5695      self.geocoder.geocode({
5696        'address': item.address
5697      }, function(results, status) {
5698        if (status === google.maps.GeocoderStatus.OK) {
5699          var latLong = results[0].geometry.location;
5700          item.formatted_address = results[0].formatted_address;
5701          addMarker(latLong, item);
5702        } else {
5703          console.warn('Geocode was not successful for the following reason: ' + status);
5704          console.warn('Check address for \"' + item.name + '\"');
5705          console.warn(item);
5706        }
5707      });
5708    }
5709  };
5710
5711  function updateZoom() {
5712    var visibleMarkers = self.allMarkers().filter(function(elem){
5713      return !!elem.map;
5714    });
5715    if(visibleMarkers.length > 1){
5716      var bounds = new google.maps.LatLngBounds();
5717      for (i = 0; i < visibleMarkers.length; i++) {
5718          bounds.extend(visibleMarkers[i].getPosition());
5719      }
5720      self.map.fitBounds(bounds);
5721    } else if(visibleMarkers.length === 1){
5722      self.map.setCenter(visibleMarkers[0].getPosition());
5723      self.map.setZoom(15);
5724    }
5725  };
5726
5727  function setCenter(latLong){
5728    if (self.map) {
5729      self.map.setCenter(latLong);
5730      self.map.setZoom(15);
5731    } else {
5732      initMap([]);
5733    }
5734  }
5735
5736  return {
5737    initMap: initMap,
5738    addMarker: addMarker, 
5739    addLatLongAddress: addLatLongAddress, 
5740    addGeocodeAddress: addGeocodeAddress, 
5741    updateZoom: updateZoom,
5742    addInfoWindowEvent : addInfoWindowEvent,
5743    setMarkerHtmlCallback: setMarkerHtmlCallback,
5744    openMarker: self.openMarker,
5745    closeMarker: self.closeMarker,
5746    getMarkersWithinZip: getMarkersWithinZip,
5747    markerIndexesWithinDistance: self.markerIndexesWithinDistance,
5748    showPins: self.showPins,
5749    initComplete: self.initComplete,
5750    setCenter: setCenter
5751  }
5752};
5753// for analytics
5754var digitalData = {
5755    page: {
5756        attributes: {
5757            analytics: {}
5758        }
5759    },
5760    event: [],
5761    product: {},
5762    productItem: [],
5763    internalCampaign: {},
5764    search: {},
5765    resource: {},
5766    form: {},
5767    findDealer: {}
5768};
5769
5770document.addEventListener('DOMContentLoaded', function() {
5771    // analytics page name
5772    var pageName = 'pentair';
5773    var pagePath = window.location.pathname;
5774
5775    // sanitize page path
5776    pagePath = pagePath.replace(/\s/g, ''); // remove whitespace
5777    pagePath = pagePath.replace(/\.[^/.]+$/, ''); // remove extension
5778    pagePath = pagePath.replace(/\|/g, '-'); // replace all pipes with hyphens
5779    pagePath = pagePath.replace(/\//g, '|'); // replace all forward slashes with pipes
5780
5781    // logic for when to use 'homepage' or just the page path
5782    if(window.location.pathname === '/content/pentair/en-us.html') {
5783        pageName += '|homepage';
5784    } else {
5785        pageName += pagePath;
5786    }
5787
5788    // inject pagename into the data layer for analytics
5789    digitalData.page.attributes.analytics.pageName = pageName;
5790    digitalData.page.attributes.analytics.pageURL = window.location.href;
5791    digitalData.page.attributes.analytics.pagePath = window.location.pathname;
5792    digitalData.page.attributes.analytics.hostname = window.location.host;
5793    digitalData.page.attributes.analytics.pageCanonical = window.location.href;
5794
5795    //////////////////////////////////////////////////////////////
5796    //// Product page view data analytics layer object start ////
5797    ////////////////////////////////////////////////////////////
5798    var isProductPage = $('main.product-page');
5799    if(isProductPage.length > 0) {
5800        updateProductDetails();
5801    }
5802
5803    function updateProductDetails() {
5804        try {
5805            if(digitalData) {
5806
5807                if(digitalData.product) {
5808                    digitalData.product.productName = $('h1').text();
5809                }
5810                if(digitalData.event) {
5811                    var eventData = {};
5812                    eventData.eventName = "detailed product view";
5813                    eventData.eventAction = "product view";
5814                    eventData.type = "shopping";
5815                    eventData.timeStamp = new Date();
5816                    digitalData.event.push(eventData);
5817                }
5818            }
5819
5820        } catch(err) {
5821            console.log(err);
5822        }
5823
5824    }
5825
5826    //////////////////////////////////////////////////////////////
5827    //// Product page view data analytics layer object end //////
5828    ////////////////////////////////////////////////////////////
5829});
5830
5831var payloadQueue = [];
5832
5833// Start the queue
5834handleAnalyticsEventQueuing();
5835
5836/**
5837 * Passes the analytics payload to adobe analytics trackEvent if its defined on the page
5838 * If trackEvent is not defined yet due a timing issue, it will queue up the event and fire it when
5839 * trackEvent has been detected on the page
5840 * @param payload of the event
5841 */
5842function trackEventWithQueue(payload) {
5843    if(typeof trackEvent !== 'undefined') {
5844        trackEvent(payload);
5845    } else {
5846        payloadQueue.push(payload);
5847    }
5848}
5849
5850/**
5851 * Will check if any events have been queued up before trackEvent was loaded onto the page withing a time period
5852 * If trackEvent becomes available and we have events that were queued up, empty the queue and track their contents
5853 * Otherwise, the page likely doesn't have analytics enabled
5854 */
5855function handleAnalyticsEventQueuing() {
5856    var millisecondsPassed = 0;
5857    var timerId = setInterval(() => {
5858        millisecondsPassed += 1000; // 1 second interval
5859        if (payloadQueue.length > 0 && typeof trackEvent !== 'undefined') {
5860            trackAndClearPayloadQueue();
5861            clearInterval(timerId);
5862        }
5863
5864        if (millisecondsPassed === 5000) { // 5 second limit
5865            clearInterval(timerId);
5866            if (typeof trackEvent === 'undefined') {
5867                console.warn("Analytics is not enabled on this page");
5868            }
5869        }
5870    }, 1000); // 1 second interval
5871}
5872
5873/**
5874 * Loops through the payload queue and tracks all events that were present in it
5875 */
5876function trackAndClearPayloadQueue() {
5877    while (payloadQueue.length > 0) {
5878        var payload = payloadQueue.shift();
5879        trackEvent(payload);
5880    }
5881}
5882
5883/**
5884 * Gets the Business Unit ID from the page head meta elements.
5885 * @returns Business Unit ID string
5886 */
5887function getBusinessUnitID() {
5888    var businessUnitIDMetaData = document.head.querySelector('meta[name="businessUnitID"]');
5889    if (businessUnitIDMetaData && businessUnitIDMetaData.content) {
5890        return businessUnitIDMetaData.content;
5891    }
5892    return "";
5893}
5894
5895/**
5896 * Gets the Pentair Customer ID from the cookie.
5897 * @returns Pentair Customer ID string
5898 */
5899function getPentairCustomerID() {
5900    return getCookie("cif.sfContactId");
5901}
5902
5903/**
5904 * Gets the Dealer ID from the page head meta elements.
5905 * @returns Dealer ID string
5906 */
5907function getDealerID() {
5908    var dealerIDMetaData = document.head.querySelector('meta[name="dealerID"]');
5909    if (dealerIDMetaData && dealerIDMetaData.content) {
5910        return dealerIDMetaData.content;
5911    }
5912    return "";
5913}
5914
5915/**
5916 * Gets the Distributor ID from the page head meta elements.
5917 * @returns Distributor ID string
5918 */
5919 function getDistributorID() {
5920    var distributorIDMetaData = document.head.querySelector('meta[name="distributorID"]');
5921    if (distributorIDMetaData && distributorIDMetaData.content) {
5922        return distributorIDMetaData.content;
5923    }
5924    return "";
5925}
5926
5927/**
5928 * Sets a session cookie with the given name and value.
5929 * @param name cookie name
5930 * @param value cookie value
5931 * @returns the set session cookie
5932 */
5933function setSessionCookie(name, value) {
5934    return document.cookie = name + "=" + value + "; expires=; path=/";
5935}
5936
5937/**
5938 * Get the value of a cookie.
5939 * @param  {String} name name of the cookie
5940 * @return {String} cookie value if exists, otherwise undefined
5941 */
5942function getCookie(name) {
5943    var parts = document.cookie.split(';');
5944    for (var i = 0; i < parts.length; i++) {
5945        var trimmedPart = parts[i].trim();
5946        if (trimmedPart.startsWith(name + '=')) {
5947            var startIndex = trimmedPart.indexOf(name + '=') + name.length + 1;
5948            return trimmedPart.substring(startIndex);
5949        }
5950    }
5951    return "";
5952}
5953// Payload for base page view event
5954var eventPageViewPayload = {
5955    eventName: 'page view',
5956    eventType: 'pageview',
5957    attributes: {
5958        visitor:  {
5959            pentairCustomerID: undefined, //if this is available
5960            dealerID: undefined //if this is available
5961        },
5962        page: {
5963            pageCanonical: undefined,
5964            pageName: undefined,
5965            pagePath: undefined,
5966            pageType: undefined, //this will map to content type
5967            pageURL: undefined,
5968            pageTitle: undefined, // this is the value in the <title> tag
5969            pageSEOTags: undefined, // if this is available this will be a list of tags delimited by a comma driven by what the author puts in the 'tags'
5970            businessUnitID: undefined, // if this is available
5971            subBrand: undefined, // if this is available
5972            language: undefined, //if this is available
5973            author: undefined //if this is available
5974        }
5975    }
5976}
5977
5978/**
5979 * Gets the page attribute from the eventPageViewPayload if it exists.
5980 * @param {string} attribute page attribute to get
5981 * @returns the page attribute if it exists
5982 */
5983function getPageViewPageAttribute(attribute) {
5984    if (!eventPageViewPayload || !eventPageViewPayload.attributes || !eventPageViewPayload.attributes.page) {
5985        return undefined;
5986    }
5987    return eventPageViewPayload.attributes.page[attribute];
5988}
5989
5990/**
5991 * Gets the product attribute from the eventPageViewPayload if it exists.
5992 * @param {string} attribute product attribute to get
5993 * @returns the product attribute if it exists
5994 */
5995function getPageViewProductAttribute(attribute) {
5996    if (!eventPageViewPayload || !eventPageViewPayload.attributes || !eventPageViewPayload.attributes.product) {
5997        return undefined;
5998    }
5999    return eventPageViewPayload.attributes.product[attribute];
6000}
6001
6002// Fire the page load event when the page is loaded
6003window.addEventListener('load', function() {
6004
6005    // PageView for search page is handled in /pentair-commons/components/content/search/clientlib/js/search.js
6006    // due to race conditions between this files window onload and search.js's callback of the search results.
6007    if (isSearchPage()) {
6008        return;
6009    }
6010
6011    initBasePageViewPayload();
6012
6013    // Add any additional attributes for specific page view types
6014    if (isProductPage()) {
6015        eventPageViewPayload = getProductViewPayload(eventPageViewPayload);
6016    }
6017    if (isWhereToBuyNewDistComponent()) { // Check this first because isWhereToBuyPage() is true for both dealer and distributor
6018        const wheretoBuyNewDistResultsList = document.querySelector('.where-to-buy-new-distributor .loading-container .scroll-list');
6019        const whereToBuyNewDistComponent = document.querySelector('.where-to-buy-new-distributor.component');
6020        whereToBuyNewDistComponent.addEventListener('pageViewDistributorListLoaded', function(e) {
6021            var eventWTBPageViewPayload = getWTBPageViewPayload(eventPageViewPayload, e.detail.wtbSearch, true, e.detail.wtbBusinessInfo);
6022            trackEventWithQueue(eventWTBPageViewPayload);
6023        });
6024        if (!wheretoBuyNewDistResultsList) {
6025            trackEventWithQueue(eventPageViewPayload);
6026        }
6027    } else if (isWhereToBuyPage()) {
6028        var wheretoBuyResultsList = document.querySelector('.where-to-buy-new .loading-container .scroll-list');
6029        // Don't track the pageview yet, wait until where-to-buy component it is done loading
6030        var whereToBuyComponent = document.querySelector('.where-to-buy-new.component');
6031        var whereToBuyIsHidden = isHidden(whereToBuyComponent);
6032        if (whereToBuyComponent) {
6033            whereToBuyComponent.addEventListener('pageViewDealerListLoaded', function(e) {
6034                var eventWTBPageViewPayload = getWTBPageViewPayload(eventPageViewPayload, e.detail.wtbSearch, false, e.detail.wtbBusinessInfo);
6035                trackEventWithQueue(eventWTBPageViewPayload);
6036            });
6037            if (!wheretoBuyResultsList || whereToBuyIsHidden) {
6038                // this is to fire the pageview event with the launchEvents attribute when where to buy component doesn't perform a dealer search.
6039                trackEventWithQueue(eventPageViewPayload);
6040            }
6041        }
6042    } else {
6043        trackEventWithQueue(eventPageViewPayload);
6044    }
6045});
6046/**
6047 * Initializes the base page view payload.
6048 */
6049function initBasePageViewPayload() {
6050    var pageCanonical,
6051        pageName,
6052        pagePath,
6053        pageType,
6054        pageURL,
6055        pageTitle,
6056        pageSEOTags,
6057        subBrand,
6058        language,
6059        author;
6060    if (digitalData) {
6061        pageName = digitalData.page.attributes.analytics.pageName;
6062        pagePath = digitalData.page.attributes.analytics.pagePath;
6063        pageURL = digitalData.page.attributes.analytics.pageURL;
6064        pageType = digitalData.page.attributes.analytics.pageType;
6065    }
6066    pageCanonical = document.head.querySelector('link[rel="canonical"]')
6067        ? document.head.querySelector('link[rel="canonical"]').href
6068        : undefined;
6069    pageTitle = document.head.querySelector('title')
6070        ? document.head.querySelector('title').text
6071        : undefined;
6072    pageSEOTags = document.head.querySelector('meta[name="pageSEOTags"]')
6073        ? document.head.querySelector('meta[name="pageSEOTags"]').content
6074        : undefined;
6075    var subBrandTagsArray = document.head.querySelector('meta[name="brands"]')
6076        ? document.head.querySelector('meta[name="brands"]').content.split('|')
6077        : undefined;
6078    if (subBrandTagsArray) {
6079        subBrand = [];
6080        for (var index = 0; index < subBrandTagsArray.length; index++) {
6081            var element = subBrandTagsArray[index].split(',');
6082            subBrand.push(element[1]); // get just the brand title
6083        }
6084        subBrand = subBrand.join();
6085    }
6086    language = document.head.querySelector('meta[name="pageLocale"]')
6087        ? document.head.querySelector('meta[name="pageLocale"]').content
6088        : undefined;
6089    author = document.head.querySelector('meta[name="authorName"]')
6090        ? document.head.querySelector('meta[name="authorName"]').content
6091        : undefined;
6092
6093    // Payload for page view event
6094    eventPageViewPayload = {
6095        eventName: 'page view',
6096        eventType: 'pageview',
6097        attributes: {
6098            visitor:  {
6099                pentairCustomerID: getPentairCustomerID(), //if this is available
6100                dealerID: getDealerID() //if this is available
6101            },
6102            page: {
6103                pageCanonical: pageCanonical,
6104                pageName: pageName,
6105                pagePath: pagePath,
6106                pageType: pageType,  //this will map to content type
6107                pageURL: pageURL,
6108                pageTitle: pageTitle, // this is the value in the <title> tag
6109                pageSEOTags: pageSEOTags, // if this is available this will be a list of tags delimited by a comma driven by what the author puts in the 'tags'
6110                businessUnitID: getBusinessUnitID(), // if this is available
6111                subBrand: subBrand, // if this is available
6112                language: language, //if this is available
6113                author: author //if this is available
6114            }
6115        }
6116    }
6117}
6118
6119/**
6120 * Returns true if the page is a product page.
6121 * @returns {boolean} true/false if the page is a product page
6122 */
6123function isProductPage() {
6124    var mainSection = document.querySelector('main');
6125    return mainSection ? mainSection.classList.contains('product-page') : false;
6126}
6127
6128/**
6129 * Returns true if the page is a Where To Buy page.
6130 * Where To Buy pages either have the 'where-to-buy' class on the main section
6131 * or contain the "where-to-buy-new" component in the main section.
6132 * @returns {boolean} true/false if the page is a where to buy page
6133 */
6134function isWhereToBuyPage() {
6135    var mainSection = document.querySelector('main');
6136    if (!mainSection) {
6137        return false;
6138    }
6139    if (mainSection.classList.contains('where-to-buy') || document.querySelectorAll('#storelocatormodal')) {
6140        return true;
6141    }
6142    var whereToBuyComponent = mainSection.querySelector('.component.where-to-buy-new');
6143    return whereToBuyComponent ? true : false;
6144}
6145function isWhereToBuyNewDistComponent() {
6146    var mainSection = document.querySelector('main');
6147    var whereToBuyNewDistComponent = mainSection?.querySelector('.component.where-to-buy-new-distributor');
6148    return whereToBuyNewDistComponent && !isHidden(whereToBuyNewDistComponent) ? true : false;
6149}
6150
6151function isHidden(component) {
6152    return component?.style?.display === "none";
6153}
6154
6155/**
6156 * Returns true if the page is using the search page component.
6157 * @returns {boolean} true/false if the page is a search page
6158 */
6159function isSearchPage() {
6160    var templateType = document.querySelector('meta[name="pageType"]');
6161    return templateType ? templateType.content === "pentair/components/page/search" : false;
6162}
6163
6164/**
6165 * Gets the full product view payload reusing the current eventPageViewPayload.
6166 * @param eventPageViewPayload the current eventPageViewPayload
6167 * @returns product page view payload object
6168 */
6169function getProductViewPayload(eventPageViewPayload) {
6170    var productInfoSection = document.querySelector('.component.product-information');
6171    if (!productInfoSection) {
6172        return eventPageViewPayload;
6173    }
6174    // Get product category from the document head because "data-categories" from the product-information component
6175    // is the wtbCategories which is used for the WTB search component.
6176    const cartVal = typeof getCookiesCartId === 'function' ? getCookiesCartId() : '';
6177    var categoriesMetaElem = document.querySelector('meta[name="categories.lvl1"]');
6178    var eventProductViewPayload = {
6179        eventName: 'product view',
6180        eventType: eventPageViewPayload.eventType,
6181        attributes: {
6182            product: {
6183                category: categoriesMetaElem ? categoriesMetaElem.content : '',
6184                installation: productInfoSection.dataset.installationSku,
6185                productFindingMethod: getCookie("productFindingMethod"),
6186                productName: productInfoSection.dataset.productName,
6187                quantity: productInfoSection.dataset.stock,
6188                skuID: productInfoSection.dataset.productSku,
6189                type: productInfoSection.dataset.channel,
6190                unitPrice: productInfoSection.dataset.minimalPrice
6191            },
6192            cart: {
6193                cartID: cartVal
6194            },
6195            visitor: eventPageViewPayload.attributes.visitor,
6196            page: eventPageViewPayload.attributes.page
6197        }
6198    }
6199    return eventProductViewPayload;
6200}
6201
6202/**
6203 * Gets the full Where to Buy page view payload reusing the current eventPageViewPayload.
6204 * @param eventPageViewPayload the current eventPageViewPayload
6205 * @param wtbSearchAttr the where to buy search results custom event attributes
6206 *                      wtbSearchAttr: { wtbBrands: "Pentair",
6207 *                                       wtbCategories: "Pool & Spa Equipment",
6208 *                                       wtbDealerID: "1234,12345,123456",
6209 *                                       wtbNumberResults: 3,
6210 *                                       wtbSearchZip: "28374" }
6211 * @returns product page view payload object
6212 */
6213 function getWTBPageViewPayload(eventPageViewPayload, wtbSearchAttr, isDistributor, businesses) {
6214    if (!wtbSearchAttr) {
6215        return eventPageViewPayload;
6216    }
6217    const locatorEvent = isDistributor ? 'WTB Distributor page view' : 'WTB page view';
6218    const eventName = wtbSearchAttr.wtbNumberResults > 0 ? locatorEvent : locatorEvent + ' zero results';
6219    const eventWTBPageViewPayload = {
6220        eventName: eventName,
6221        eventType: eventPageViewPayload.eventType,
6222        attributes: {
6223            visitor: eventPageViewPayload.attributes.visitor,
6224            page: eventPageViewPayload.attributes.page,
6225            wtbSearch: {
6226                wtbBrands: wtbSearchAttr.wtbBrands,
6227                wtbCategories: wtbSearchAttr.wtbCategories,
6228                wtbDealerID: wtbSearchAttr.wtbDealerID,
6229                wtbNumberResults: wtbSearchAttr.wtbNumberResults,
6230                wtbSearchZip: wtbSearchAttr.wtbSearchZip
6231            },
6232            ...(businesses.length > 0 && {wtbBusinessInfo: businesses})
6233        }
6234    }
6235    return eventWTBPageViewPayload;
6236}
6237
6238/**
6239 * Constructs and tracks the Search Page view payload.
6240 * @param searchComponent the search component
6241 * @param currentTab search index name of the current tab
6242 * @param resultTotal number of results
6243 * @param queryID query ID(s) of the search
6244 */
6245function trackSearchPageViewPayload(searchComponent, currentTab, resultTotal, queryID) {
6246    initBasePageViewPayload();
6247    if (!searchComponent) {
6248        trackEventWithQueue(eventPageViewPayload);
6249        return;
6250    }
6251    var algoliaQueryID;
6252    var activeTabTitle;
6253
6254    // Get the cookie that was saved on the previous page as part of header.js self.doSearch
6255    var searchCookie = getCookie('pentairSearch');
6256    var searchAttributes = searchCookie ? JSON.parse(searchCookie) : {};
6257    // Consume/Clear the cookie for 'pentairSearch'
6258    setSessionCookie('pentairSearch', '');
6259
6260    var searchTerm = searchAttributes.searchTerm;
6261
6262    // If the searchAttributes.searchTerm is undefined, try to find it in the URL query params
6263    if (!searchTerm && window.location.search) {
6264        var urlQueryParamsMap = Object.fromEntries(window.location.search
6265            .slice(1)
6266            .split('&')
6267            .map(function(item) {
6268                return item.split('=');
6269            }));
6270        searchTerm = decodeURIComponent(urlQueryParamsMap.q ? urlQueryParamsMap.q : '').replace(/\+/g, ' ');
6271    }
6272
6273    // Get the active tab header
6274    var activeTabHeader = searchComponent.querySelector('[class="site-search-results"] [class~="' + currentTab + '"]');
6275
6276    // Get the tab name and result count
6277    if (activeTabHeader) {
6278        // Tab title format is "TabName (ResultsCount)" e.g. "Products (123)"
6279        var splitTabTitle = activeTabHeader.textContent.trim().split(' ');
6280        activeTabTitle = splitTabTitle[0];
6281    }
6282
6283    // If the queryID param is missing/null try to get the query IDs from the page
6284    if (queryID) {
6285        algoliaQueryID = queryID;
6286    } else if (activeTabHeader && (currentTab === "all" || activeTabTitle === "All")) {
6287        //get all 5 query ids
6288        var allTabContent = searchComponent.querySelector('div[class="all-tab"]');
6289        var allTabQueryIds = allTabContent ? allTabContent.querySelectorAll("[data-query-id]") : [];
6290        var uniqueQueryIds = Array.from(allTabQueryIds).map(function (item) {
6291            // Get only the query IDs from the elements
6292            return item.dataset.queryId;
6293        }).filter(function(queryID, index, self) {
6294            // Only get the first occurrence of the queryID
6295            return self.indexOf(queryID) === index;
6296        }).join();
6296 // Join into a single string
6297        algoliaQueryID = uniqueQueryIds ? uniqueQueryIds : '';
6298    } else if (activeTabHeader) {
6299        // get the active tab
6300        var activeTabContent = searchComponent.querySelector('[class~="tab-search-content"] [class~="active"]');
6301        algoliaQueryID = activeTabContent ? activeTabContent.querySelector('[data-query-ID]').dataset.queryId : '';
6302    }
6303
6304    // If not search component, assume product search for dealer/dist
6305    const searchType = searchComponent.getAttribute('class') === 'search component' ? 'search conducted' : 'product search conducted';
6306    const searchTypeWithResults = resultTotal > 0 ? searchType : searchType + ' zero results'
6307    var eventSearchConductedPayload = {
6308        eventName: searchTypeWithResults,
6309        eventType: 'page view',
6310        attributes: {
6311            search: {
6312                searchTerm: searchTerm,
6313                numberResults: resultTotal,
6314                algoliaQueryID: algoliaQueryID,
6315                searchType: searchAttributes.searchType,
6316                priorPageURL: searchAttributes.priorPageURL
6317            },
6318            visitor: eventPageViewPayload.attributes.visitor,
6319            page: {
6320                pageCanonical: eventPageViewPayload.attributes.page.pageCanonical,
6321                pageName: eventPageViewPayload.attributes.page.pageName,
6322                pagePath: eventPageViewPayload.attributes.page.pagePath,
6323                pageType: eventPageViewPayload.attributes.page.pageType,
6324                pageURL: eventPageViewPayload.attributes.page.pageURL,
6325                language: eventPageViewPayload.attributes.page.language
6326            }
6327        }
6328    }
6329    trackEventWithQueue(eventSearchConductedPayload);
6330}
6331
6332// Needs to be on load rather than $(document).ready so that enough time is given
6333//  for dialogtech.js to programatically add the tel links.
6334window.addEventListener('load', function () {
6335    var phoneLinks = document.querySelectorAll('a[href^="tel:"]');
6336    for (var i = 0; i < phoneLinks.length; i++) {
6337        phoneLinks[i].addEventListener('click', trackPhoneLinkClick);
6338    }
6339
6340    function trackPhoneLinkClick(clickEvent) {
6341        var eventClickToCallPayload = {
6342            eventName: 'click to call',
6343            eventType: 'event',
6344            attributes: {
6345                visitor: {
6346                    pentairCustomerID: getPentairCustomerID(), //if this is available
6347                    dealerID: getDealerID() //if this is available
6348                },
6349                page: {
6350                    pageCanonical: getPageViewPageAttribute("pageCanonical"),
6351                    pageName: getPageViewPageAttribute("pageName"),
6352                    pagePath: getPageViewPageAttribute("pagePath"),
6353                    pageType: getPageViewPageAttribute("pageType"),
6354                    pageURL: getPageViewPageAttribute("pageURL"),
6355                    pageTitle: getPageViewPageAttribute("pageTitle"),
6356                    pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
6357                    businessUnitID: getPageViewPageAttribute("businessUnitID"),
6358                    subBrand: getPageViewPageAttribute("subBrand"),
6359                    language: getPageViewPageAttribute("language"),
6360                    author: getPageViewPageAttribute("author"),
6361                },
6362                clickToCall: {
6363                    numberClicked: clickEvent.target.text
6364                },
6365                product: {
6366                    productName: getPageViewProductAttribute("productName"), // if on a product page and sku is available
6367                    skuID: getPageViewProductAttribute("skuID"), // if on a product page and sku is available
6368                    type: getPageViewProductAttribute("type") // if on a product page and sku is available
6369                }
6370            }
6371        }
6372        trackEventWithQueue(eventClickToCallPayload);
6373    }
6374});
6375
6376// Adobe analytics event payload tracking for clicking on rebate form links and submit rebate online CTAs.
6377// The analytics will be tracked based on these assumptions:
6378//    - The rebate form link href will contain "rebate-form" and end with ".pdf".
6379//    - The rebate submit CTA link will have the class "btn" and the href will
6380//       contain "https://www.pentairpartners.com/register".
6381window.addEventListener('load', function () {
6382
6383    // Get the links to pdf files that have 'rebate-form' in the path.
6384    var rebateFormLinks = document.querySelectorAll('a[href*="rebate-form"][href$=".pdf"]');
6385    for (var i = 0; i < rebateFormLinks.length; i++) {
6386        rebateFormLinks[i].addEventListener('click', trackRebateFormLinkClick);
6387    }
6388
6389    // Get the CTA(s) for submitting a rebate form online
6390    var rebateSubmitCtas = document.querySelectorAll('a[class*="btn"][href*="https://www.pentairpartners.com/register"]');
6391    for (var i = 0; i < rebateFormLinks.length; i++) {
6392        rebateSubmitCtas[i].addEventListener('click', trackRebateSubmitClick);
6393    }
6394
6395    /**
6396     * Constructs and tracks the rebate click event payload.
6397     * @param clickEvent the click event captured
6398     */
6399    function trackRebateFormLinkClick(clickEvent) {
6400        var eventRebateClickPayload = {
6401            eventName: 'click for rebate info',
6402            eventType: 'event',
6403            attributes: {
6404                visitor: {
6405                    pentairCustomerID: getPentairCustomerID(),
6406                    dealerID: getDealerID()
6407                },
6408                page: {
6409                    pageCanonical: getPageViewPageAttribute("pageCanonical"),
6410                    pageName: getPageViewPageAttribute("pageName"),
6411                    pagePath: getPageViewPageAttribute("pagePath"),
6412                    pageType: getPageViewPageAttribute("pageType"),
6413                    pageURL: getPageViewPageAttribute("pageURL"),
6414                    pageTitle: getPageViewPageAttribute("pageTitle"),
6415                    pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
6416                    businessUnitID: getPageViewPageAttribute("businessUnitID"),
6417                    subBrand: getPageViewPageAttribute("subBrand"),
6418                    language: getPageViewPageAttribute("language"),
6419                    author: getPageViewPageAttribute("author"),
6420                },
6421                rebate: {
6422                    rebateLinkClicked: clickEvent.target.text
6423                }
6424            }
6425        }
6426        trackEventWithQueue(eventRebateClickPayload);
6427    }
6428
6429    /**
6430     * Constructs and tracks the rebate submit CTA click event payload.
6431     */
6432    function trackRebateSubmitClick() {
6433        var eventRebateSubmitPayload = {
6434            eventName: 'click for rebate submit',
6435            eventType: 'event',
6436            attributes: {
6437                visitor: {
6438                    pentairCustomerID: getPentairCustomerID(),
6439                    dealerID: getDealerID()
6440                },
6441                page: {
6442                    pageCanonical: getPageViewPageAttribute("pageCanonical"),
6443                    pageName: getPageViewPageAttribute("pageName"),
6444                    pagePath: getPageViewPageAttribute("pagePath"),
6445                    pageType: getPageViewPageAttribute("pageType"),
6446                    pageURL: getPageViewPageAttribute("pageURL"),
6447                    pageTitle: getPageViewPageAttribute("pageTitle"),
6448                    pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
6449                    businessUnitID: getPageViewPageAttribute("businessUnitID"),
6450                    subBrand: getPageViewPageAttribute("subBrand"),
6451                    language: getPageViewPageAttribute("language"),
6452                    author: getPageViewPageAttribute("author"),
6453                }
6454            }
6455        }
6456        trackEventWithQueue(eventRebateSubmitPayload);
6457    }
6458});
6459
6460/**
6461 * Adobe analytics event payload tracking for clicking on "download app" image links.
6462 * The analytics will be tracked based on these assumptions:
6463 *    - Download app links will start with
6464 *        - "https://apps.apple.com/" for Apple app store and
6465 *        - "https://play.google.com/store/apps/" for Google play store.
6466 *    - "Commercial IQ" app link will contain
6467 *        - "commercial-iq/id1432873020" for Apple and
6468 *        - "id=com.pe_commercial_app" for Google play.
6469 *    - "Pentair Home" app link will contain
6470 *        - "pentair-home/id1448665466" for Apple and
6471 *        - "id=com.pentair.pentairhome" for Google play.
6472 *    - If the app URL does not contain the previous IDs, the link URL will
6473 *      be used in the payload for the app name instead.
6474 */
6475window.addEventListener('load', function () {
6476
6477    var ANDROID_DEVICE = 'Android';
6478    var APPLE_DEVICE = 'Apple';
6479    var COMMERICAL_IQ_GOOGLE_ID = 'id=com.pe_commercial_app';
6480    var COMMERICAL_IQ_APPLE_ID = 'commercial-iq/id1432873020';
6481    var PENTAIR_HOME_GOOGLE_ID = 'id=com.pentair.pentairhome';
6482    var PENTAIR_HOME_APPLE_ID = 'pentair-home/id1448665466';
6483
6484    // Get links to Google play store
6485    var googlePlayLinks = document.querySelectorAll('a[href*="https://play.google.com/store/apps/"]');
6486    for (var i = 0; i < googlePlayLinks.length; i++) {
6487        googlePlayLinks[i].addEventListener('click', function(clickEvent) {
6488            var appName = getAppName(ANDROID_DEVICE, clickEvent.currentTarget.href);
6489            trackDownloadAppLinkClick(appName);
6490        });
6491    }
6492
6493    // Get the links to Apple app store
6494    var appleAppStoreLinks = document.querySelectorAll('a[href*="https://apps.apple.com/"]');
6495    for (var i = 0; i < appleAppStoreLinks.length; i++) {
6496        appleAppStoreLinks[i].addEventListener('click', function(clickEvent) {
6497            var appName = getAppName(APPLE_DEVICE, clickEvent.currentTarget.href);
6498            trackDownloadAppLinkClick(appName);
6499        });
6500    }
6501
6502    /**
6503     * Gets the full appName property for the Download App click event payload.
6504     * The appName property is the device OS plus the app name seperated by a '|'.
6505     *   Example: "Android | Pentair Home"
6506     *
6507     * If the app url is not for Commercial IQ or Pentair Home, the full url will be
6508     * used in place of the app title.
6509     *
6510     * @param {string} deviceOsString device OS string, i.e. Android, Apple
6511     * @param {string} url URL of the download link
6512     * @returns appName property string
6513     */
6514    function getAppName(deviceOsString, url) {
6515        if (url.includes(COMMERICAL_IQ_APPLE_ID) || url.includes(COMMERICAL_IQ_GOOGLE_ID)) {
6516            return deviceOsString + " | Commercial IQ";
6517        } else if (url.includes(PENTAIR_HOME_APPLE_ID) || url.includes(PENTAIR_HOME_GOOGLE_ID)) {
6518            return deviceOsString + " | Pentair Home";
6519        } else {
6520            return deviceOsString + " | " + url;
6521        }
6522    }
6523
6524    /**
6525     * Constructs and tracks the Download App link click event payload.
6526     * @param {string} appName the device OS and the name of the app clicked e.g. "Android | Commercial IQ"
6527     */
6528    function trackDownloadAppLinkClick(appName) {
6529        var eventDownloadAppPayload = {
6530            eventName: 'click to download app',
6531            eventType: 'event',
6532            attributes: {
6533                visitor: {
6534                    pentairCustomerID: getPentairCustomerID(),
6535                    dealerID: getDealerID()
6536                },
6537                page: {
6538                    pageCanonical: getPageViewPageAttribute("pageCanonical"),
6539                    pageName: getPageViewPageAttribute("pageName"),
6540                    pagePath: getPageViewPageAttribute("pagePath"),
6541                    pageType: getPageViewPageAttribute("pageType"),
6542                    pageURL: getPageViewPageAttribute("pageURL"),
6543                    pageTitle: getPageViewPageAttribute("pageTitle"),
6544                    pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
6545                    businessUnitID: getPageViewPageAttribute("businessUnitID"),
6546                    subBrand: getPageViewPageAttribute("subBrand"),
6547                    language: getPageViewPageAttribute("language"),
6548                    author: getPageViewPageAttribute("author"),
6549                },
6550                clickDownloadApp: {
6551                    appName: appName
6552                }
6553            }
6554        }
6555        trackEventWithQueue(eventDownloadAppPayload);
6556    }
6557});
6558
6559$(function() {
6560
6561    $(document).ready(function() {
6562        const $prodPageV2Data = $('main.product-page-v2');
6563        if ($prodPageV2Data.length) {
6564            const isSkuPage = $prodPageV2Data.data('is-sku-page');
6565            if (isSkuPage) {
6566                const $breadcrumbsLinks = $('section.bread-section ul.breadcrumbs li a');
6567                const productFamilyName = $prodPageV2Data.data('product-family-name');
6568                if ($breadcrumbsLinks.length && productFamilyName) {
6569                    $breadcrumbsLinks.last().text(productFamilyName);
6570                }
6571            }
6572        }
6573    });
6574});
6575
6576$(function() {
6577    /* Once the Product Page SEO Markup Object is constructed - append to the <head> */
6578    function setProductPageSEOMarkup(data) {
6579        var productPageSEOScript = $('#productJDId');
6580        $(productPageSEOScript).text(JSON.stringify(data, null, 2));
6581    }
6582
6583    //removes line breaks
6584    function formatJsonStringValue(value) {
6585        return value ? value.replace(/\r/g, "").replace(/\n/g, "") : "";
6586    }
6587
6588    /* Construct the necessary SEO Product Page details and dynamically inject into the <head> */
6589    function constructProductPageSEOMarkup(page) {
6590        var productDescription = $(page).data('productDescription');
6591        const $seoScriptTag = $('#productJDId');
6592        const rawJson = $seoScriptTag.text();
6593        if (!rawJson) return;
6594
6595        var productData = JSON.parse(rawJson);
6596        productData.description = formatJsonStringValue(productDescription);
6597        setProductPageSEOMarkup(productData);
6598    }
6599
6600        var productPage = $(".product-page.content");
6601        if (productPage) {
6602            constructProductPageSEOMarkup(productPage);
6603        }
6604    });
6605
6606
6607//search bar analytic
6608$(document).ready(function(){
6609  $('.icon-search').on('click',function(){
6610    try{
6611        if( digitalData){
6612          if( digitalData.event ){
6613            var eventData = {};
6614            eventData.eventName = "search bar"
6615            eventData.eventAction = "initiate";
6616            eventData.type = "default";
6617            eventData.timeStamp = new Date();
6618            digitalData.event.push(eventData);
6619          }
6620        }
6621      }catch(err) {
6622        console.log(err)
6623      }
6624  });
6625
6626  var backToTop = document.querySelector('a[class~="back-to-top"]');
6627  var shareComponent = document.querySelector('.share');
6628  var mainContentWrapper = document.querySelector('[role="main"]');
6629  var dialogtechComp = document.querySelector('.dialogtech');
6630  var desktopChat = document.querySelector('.message-desktop');
6631
6632  if (desktopChat && mainContentWrapper) {
6633    var mainDOMRect = mainContentWrapper.getBoundingClientRect();
6634    if (mainDOMRect.width >= 1440) {
6635          desktopChat.style.right = `${mainDOMRect.left + 220}px`;
6636    }
6637  }
6638    setTimeout(function(){
6639      $('.chat-icon-long').hide();
6640      $('.chat-icon-circle').show();
6641    }
6642    , 5000);
6643
6644  if (backToTop && mainContentWrapper) {
6645    window.addEventListener('scroll', function() {
6646      if (document.body.scrollTop > 0 || document.documentElement.scrollTop > 0) {
6647        var mainDOMRect = mainContentWrapper.getBoundingClientRect();
6648        if (mainDOMRect.width >= 1440) {
6649          backToTop.style.right = `${mainDOMRect.left + 20}px`;
6650        } else {
6651          backToTop.style.right = '';
6652        }
6653        dialogtechComp ? backToTop.classList.add("back-to-top--active-with-call-us")
6654          : shareComponent ? backToTop.classList.add("back-to-top--active-with-share")
6655          : backToTop.classList.add("back-to-top--active");
6656      } else {
6657        backToTop.classList.remove("back-to-top--active");
6658        backToTop.classList.remove("back-to-top--active-with-share");
6659        backToTop.classList.remove("back-to-top--active-with-call-us");
6660        backToTop.style.right = '';
6661      }
6662    });
6663  }
6664
6665});
6666
6667// Set classes on various elements so that z-index forced.
6668// This ensures the mobile filter is on top while it is open.
6669// This may not cover all components, so add more as found.
6670// Note: Not a best practice. Quick fix instead of major re-work of all components.
6671function ensureOpenFilterZPosition() {
6672  $('header').removeClass('stuck');
6673  $('header .mobile-wrap').addClass('zero-z');
6674  $('.share.component').addClass('zero-z');
6675  $('.hero.component').addClass('unset-z');
6676  $('.owl-carousel').addClass('unset-z');
6677  $('.header-search-form button.icon-search-large').addClass('unset-z');
6678  $('.sticky-jump-nav.mobile').addClass('unset-z');
6679  $('.brand-grid.component').addClass('unset-z');
6680  $('section.component>article[aria-label!="Breadcrumbs"]').addClass('unset-z');
6681  $('section.component').addClass('unset-z');
6682}
6683
6684// The inverse of the previous function to remove classes,
6685// thus resetting back to how they were when mobile filter is closed.
6686function ensureClosedFilterZPosition() {
6687  $('header').addClass('stuck');
6688  $('header .mobile-wrap').removeClass('zero-z');
6689  $('.share.component').removeClass('zero-z');
6690  $('.hero.component').removeClass('unset-z');
6691  $('.owl-carousel').removeClass('unset-z');
6692  $('.header-search-form button.icon-search-large').removeClass('unset-z');
6693  $('.sticky-jump-nav.mobile').removeClass('unset-z');
6694  $('.brand-grid.component').removeClass('unset-z');
6695  $('section.component>article[aria-label!="Breadcrumbs"]').removeClass('unset-z');
6696  $('section.component').removeClass('unset-z');
6697}
6698
6699$(document).ready(function(){
6700    $('a[href*="#"]').click( function() {
6701        const hrefValue = $(this).attr('href');
6702        if($(hrefValue).length && $(hrefValue).hasClass('modal')) {
6703            $(hrefValue).modal('show');
6704        }
6705    });
6706});
6707
6708/* global $ */
6709/* global jQuery */
6710/* global modal  */
6711
6712var PENTAIR = PENTAIR || {};
6713    /***************************/
6714    /* SEO Schema Video Markup */
6715    /***************************/
6716    function setSEOVideoMarkup(data) {
6717        var seoScript = $('<script type="application/ld+json"></script>');
6718        $(seoScript).html(JSON.stringify(data));
6719        $("head").append(seoScript);
6720    }
6721
6722function initPlayButton() {
6723    const mediaComponents = $('.video-media-common.component');
6724    const $vidModal = $('#videoModal');
6725    const $videoModalClose = $vidModal.find('.icon-close');
6726    let activePlayButton = null;
6727
6728    mediaComponents.each(function(idx, mediaComponent) {
6729        // SEO Schema Video Markup
6730        const videoType = $(this).find("button.play-vid").attr("data-vidtype");
6731        const videoURL = $(this).find("button.play-vid").attr("data-vidid");
6732        const videoTitle = $(this).find("button.play-vid").attr("data-video-title");
6733        const videoDescription = $(this).find("input[name=videoDescription]").val();
6734        const videoThumbnailSrc = $(this).find(".imagevideo-callout img").attr("src");
6735        const thumbnailUrl = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + videoThumbnailSrc;
6736        const contentUrl = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + videoURL;
6737
6738        // Video Markup Data
6739        const videoMarkup = {
6740            "@context": "https://schema.org",
6741            "@type": "VideoObject",
6742            "name": "",
6743            "description": "",
6744            "thumbnailUrl": "",
6745            "duration": "",
6746            "contentUrl": ""
6747        };
6748
6749        videoMarkup["name"] = videoTitle;
6750        videoMarkup["description"] = videoDescription;
6751        videoMarkup["thumbnailUrl"] = [thumbnailUrl];
6752
6753        // Get duration of Media Source (DAM) for SEO markup
6754        if (videoType == "dam") {
6755            const videoEl = $('<video src="" controls="true"></video>');
6756            videoEl.attr("src", videoURL);
6757            $(videoEl).on("loadedmetadata", function(e) {
6758                const duration = $(videoEl).get(0).duration;
6759                const minutes = parseInt(duration / 60, 10);
6760                const seconds = parseInt(duration % 60, 10);
6761                if (typeof duration != undefined || !isNaN(duration)) {
6762                    const durationTime = "PT" + minutes + "M" + seconds + "S";
6763                    videoMarkup["duration"] = durationTime;
6764                }
6765                const contentUrl = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + videoURL;
6766                videoMarkup["contentUrl"] = contentUrl;
6767                setSEOVideoMarkup(videoMarkup);
6768            });
6769        }
6770
6771        // Play button functionality
6772        const videoWrapper = $(mediaComponent).find('.video-wrap');
6773        const damVideo = videoWrapper.find('video');
6774        const damVideoSrc = damVideo.children("source").attr("src");
6775        const playButton = videoWrapper.find('button.play-vid');
6776
6777        function deployDamAsset() {
6778            $vidModal.find('iframe').hide();
6779            $vidModal.find('video').show();
6780            $vidModal.find('video').attr('src', damVideoSrc);
6781            $vidModal.modal('show');
6782            $vidModal.find('video').trigger('play');
6783        }
6784
6785        // DAM PLAY BUTTON FUNCTION
6786        playButton.click(function() {
6787            activePlayButton = $(this);
6788            if ((damVideo.hasClass('inline'))) {
6789                $(this).hide();
6790                damVideo.trigger('play');
6791                damVideo.attr('controls',true);
6792            } else {
6793                    deployDamAsset();
6794                }
6795        });
6796
6797        // THUMBNAIL INIT MODAL/INLINE
6798        $(mediaComponent).find('.youtube-overlay.no-thumbnail')
6799            .off('click.videoMedia')
6800            .on('click.videoMedia', function(){
6801                activePlayButton = $(this).find('button');
6802                var youtubeSrc = $(this).siblings('iframe.youtube-iframe').attr('src');
6803                var youtubeSrcAuto = youtubeSrc += '&autoplay=1';
6804                $vidModal.find('iframe').show();
6805                $vidModal.find('video').hide();
6806                $vidModal.find('iframe').attr('src', youtubeSrcAuto);
6807                $vidModal.find('iframe').attr('tabindex', '0');
6808                addTabbableSentinel();
6809                $vidModal.modal('show');
6810            });
6811
6812        $(mediaComponent).find('.youtube-overlay')
6813            .off('click.videoMedia')
6814            .on('click keydown', function(e){
6815                activePlayButton = $(this).find("button");
6816                if ($(this).hasClass('inline-thumbnail')) {
6817                    if (e.type === "click") {
6818                        $(this).hide();
6819                        $(this).siblings('iframe.youtube-iframe')[0].src += "&autoplay=1";
6820                    }else if (e.type === "keydown" && e.key === "Enter") {
6821                        $(this).hide();
6822                        $(this).siblings('iframe.youtube-iframe')[0].src += "&autoplay=1";
6823                        $(this).parent().find("iframe").attr("tabindex", "0");
6824                        e.target.parentElement.parentElement.focus();
6825                    }
6826
6827                } else if ($(this).hasClass('modal-thumbnail')) {
6828                    if (e.type === "click" || (e.type === "keydown" && e.key === "Enter")) {
6829                        var youtubeSrc = $(this).siblings('iframe.youtube-iframe').attr('src');
6830                        var youtubeSrcAuto = youtubeSrc += '&autoplay=1';
6831                        $vidModal.find('iframe').show();
6832                        $vidModal.find('video').hide();
6833                        $vidModal.find('iframe').attr('src', youtubeSrcAuto);
6834                        $vidModal.find('iframe').attr('tabindex', '0');
6835                        addTabbableSentinel();
6836                        $vidModal.modal('show');
6837                    }
6838                }
6839            });
6840
6841        $(mediaComponent).find('.vimeo-overlay.no-thumbnail')
6842            .off('click.videoMedia')
6843            .on('click.videoMedia', function(){
6844                activePlayButton = $(this).find('button');
6845                var vimeoSrc = $(this).siblings('iframe').attr('src');
6846                var vimeoSrcAuto = vimeoSrc += '&autoplay=1';
6847                $vidModal.find('iframe').show();
6848                $vidModal.find('video').hide();
6849                $vidModal.find('iframe').attr('src', vimeoSrcAuto);
6850                $vidModal.find('iframe').attr('tabindex', '0');
6851                addTabbableSentinel();
6852                $vidModal.modal('show');
6853            });
6854
6855        $(mediaComponent).find('.vimeo-overlay')
6856            .off('click.videoMedia')
6857            .on('click keydown', function(e){
6858                activePlayButton = ($(this).find('button'));
6859                if ($(this).hasClass('inline-thumbnail')) {
6860                    if (e.type === 'click') {
6861                        $(this).hide();
6862                        $(this).siblings('iframe')[0].src += "&autoplay=1";
6863                    }else if(e.type === "keydown" && e.key === "Enter"){
6864                        $(this).hide();
6865                        $(this).siblings("iframe")[0].src += "&autoplay=1";
6866                        $(this).parent().find("iframe").attr("tabindex", "0");
6867                        e.target.parentElement.parentElement.focus();
6868                    }
6869                } else if ($(this).hasClass('modal-thumbnail')) {
6870                    if (e.type === 'click' || (e.type === 'keydown' && e.key === 'Enter')) {
6871                        var vimeoSrc = $(this).siblings('iframe.vimeo').attr('src');
6872                        var vimeoSrcAuto = (vimeoSrc += '&autoplay=1');
6873                        $vidModal.find('iframe').show();
6874                        $vidModal.find('video').hide();
6875                        $vidModal.find('iframe').attr('src', vimeoSrcAuto);
6876                        $vidModal.find('iframe').attr('tabindex', '0');
6877                        addTabbableSentinel();
6878                        $vidModal.modal('show');
6879                    }
6880                }
6881            });
6882    });
6883
6884    // Add tabbable sentinel for accessibility - prevents focus from automatically jumping to body tag when iframe is exited.
6885    function addTabbableSentinel() {
6886        if (!$vidModal.find('iframe').next('.tabbable-sentinel').length) {
6887            $vidModal.find('iframe').after('<span class="tabbable-sentinel" tabindex="0" aria-label="End of video modal">End of video modal</span>');
6888        }
6889    }
6890
6891    function killVideo() {
6892        $vidModal.hide();
6893        $vidModal.find('iframe').attr('src', '');
6894        $vidModal.find('video').get(0).pause();
6895        $vidModal.find('video').attr('src', '');
6896        $vidModal.find('iframe').hide();
6897        $vidModal.find('video').hide();
6898        if (activePlayButton && activePlayButton.length) {
6899            activePlayButton.focus();
6900        }
6901    }
6902
6903    $videoModalClose.off('click.videoMedia').on('click.videoMedia', function () {
6904        killVideo();
6905    });
6906
6907    $(document).off('keyup.videoMedia').on('keyup.videoMedia', function(e) {
6908        if (e.keyCode == 27) {
6909            killVideo();
6910        }
6911    });
6912
6913    // Focus trap: when tabbing from the sentinel, loop back to first focusable element in modal
6914    $vidModal.off('keydown.focusTrap').on('keydown.focusTrap', '.tabbable-sentinel', function(e) {
6915        if (e.key === 'Tab' && !e.shiftKey) {
6916            e.preventDefault();
6917            // Find first focusable element in modal (close button or iframe)
6918            const firstFocusable = $vidModal.find('.icon-close, iframe:visible').first();
6919            firstFocusable.focus();
6920        }
6921    });
6922
6923    $vidModal.off('click.videoMedia').on('click.videoMedia', function (e) {
6924        /* Stop video playback when clicking the darkened background */
6925        var clickedOnBackground = $(e.target).hasClass('modal in');
6926        return !clickedOnBackground ? false : killVideo();
6927    });
6928};
6929
6930(function() {
6931    $(document).ready(function() {
6932        initPlayButton();
6933    });
6934})();
6935
6936(function() {
6937    // Initialize the video carousel component for each instance
6938    function initVideoCarouselComponent() {
6939        // Selectors for main carousel elements
6940        const owlVideoPlayer = $(this).find('.owl-carousel__players');
6941        const owlThumbnails = $(this).find('.owl-carousel__thumbnails');
6942        const navigation = $(this).find('.video-carousel__navigation');
6943        const TOTAL_THUMBNAILS = $(this).find('.video-carousel__thumbnail').length;
6944        const DISPLAY_SINGLE_ITEM = 1;
6945        const DISPLAY_ITEM_NUM_MOBILE = 2;
6946        const DISPLAY_ITEM_NUM_TABLET = 3;
6947        const DISPLAY_ITEM_NUM_DESKTOP = 5;
6948        let numToDisplay = 5;
6949        let currentSlideNumber = 0;
6950
6951        // Live region for screen readers (accessibility)
6952        const liveRegion = $('[aria-live="polite"]');
6953
6954        // Announce the current slide for screen readers
6955        function announceCurrentSlide(slideNum, totalSlides) {
6956            liveRegion.text(`Item ${slideNum + 1} of ${totalSlides}`);
6957        }
6958
6959        // Set the number of thumbnails to display based on screen size
6960        function setNumToDisplay() {
6961            if (window.matchMedia("(max-width: 767px)").matches) {
6962                numToDisplay = DISPLAY_ITEM_NUM_MOBILE;
6963            } else if (window.matchMedia("(min-width: 768px) and (max-width: 1259px)").matches) {
6964                numToDisplay = DISPLAY_ITEM_NUM_TABLET;
6965            } else {
6966                numToDisplay = DISPLAY_ITEM_NUM_DESKTOP;
6967            }
6968        }
6969
6970        // Initialize the main video player carousel
6971        function initVideoPlayer(owlVideoPlayer) {
6972            owlVideoPlayer.owlCarousel({
6973                items: DISPLAY_SINGLE_ITEM,
6974                mouseDrag: false,
6975                nav: false,
6976                dots: false,
6977                animateOut: 'fadeOut',
6978                loop: false
6979            });
6980        }
6981
6982        // Show the iframe when a thumbnail is clicked
6983        function showIframe() {
6984            const thumbnail = $(this);
6985            const videoUrl = thumbnail.attr('data-video-url');
6986            const iframe = thumbnail.siblings('iframe');
6987            iframe.attr("src", videoUrl);
6988            thumbnail.hide();
6989            iframe.show();
6990        }
6991
6992        // Attach click event to video thumbnails to show iframe
6993        function initVideoPlayerPoster(owlVideoPlayer) {
6994            owlVideoPlayer.find('.owl-item .video-thumbnail').on('click', showIframe);
6995        }
6996
6997        // Pause any playing media (video or iframe)
6998        function pauseMedia(activeVideo) {
6999            const isIframe = activeVideo.find('iframe').length;
7000            if (!isIframe) {
7001                const vid = activeVideo.find('video');
7002                if (vid && vid.length) vid[0].pause();
7003            } else {
7004                const iframe = activeVideo.find('iframe');
7005                const src = iframe.attr('src');
7006                iframe.attr('src', '');
7007                iframe.attr('src', src.replace('&autoplay=1', ''));
7008                iframe.siblings('.video-thumbnail').show();
7009                iframe.hide();
7010                iframe.siblings('button').show();
7011            }
7012        }
7013
7014        // Update the main player to the selected slide
7015        function updatePlayerToSlide(slideNum, owlVideoPlayer) {
7016            const activeVideo = owlVideoPlayer.find('.owl-item.active');
7017            pauseMedia(activeVideo);
7018            activeVideo.find('button').hide();
7019            owlVideoPlayer.trigger('to.owl.carousel', [slideNum]);
7020            currentSlideNumber = slideNum;
7021            owlVideoPlayer.find('.owl-item.active').find('button').show();
7022            announceCurrentSlide(slideNum, TOTAL_THUMBNAILS);
7023        }
7024
7025        // Handle play button logic for both video and iframe
7026        function playButton(owlVideoPlayer) {
7027            owlVideoPlayer.find('.video-carousel__player--button').each(function() {
7028                $(this).on("click keydown", function(e) {
7029                    if (e.type === "click" || (e.type === "keydown" && e.key === "Enter")) {
7030                        const videoSibling = $(this).siblings("video")[0];
7031                        if (videoSibling) {
7032                            videoSibling.play();
7033                            videoSibling.onplay = (e) => {
7034                                $(this).css("visibility", "hidden").prop("disabled", true);
7035                                e.target.controls = true;
7036                            };
7037                            videoSibling.onpause = (e) => {
7038                                $(this).css("visibility", "visible").removeAttr("disabled");
7039                                e.target.controls = false;
7040                            };
7041                            if (e.type === "keydown" && e.key === "Enter") {
7042                                e.target.previousElementSibling.focus();
7043                            }
7044                        } else {
7045                            const iframe = $(this).siblings('iframe')[0];
7046                            $(this).hide();
7047                            const thumbnailframe = $(iframe).siblings('.video-thumbnail');
7048                            const autoVideoUrl = $(thumbnailframe).attr('data-video-url') + '&autoplay=1';
7049                            $(iframe).attr("src", autoVideoUrl);
7050                            $(iframe).attr("tabindex", "0");
7051                            $(thumbnailframe).hide();
7052                            $(iframe).show();
7053                            if (e.type === "keydown" && e.key === "Enter") {
7054                                e.target.previousElementSibling.parentElement.focus();
7055                            }
7056                        }
7057
7058                    }
7059                });
7060            });
7061        }
7062
7063        // Initialize the thumbnail carousel and handle thumbnail clicks
7064        // Note: owl considers all visible items 'active', not just the clicked item.
7065        function initThumbnailCarousel(owlThumbnails, owlVideoPlayer) {
7066            owlThumbnails.owlCarousel({
7067                slideBy: 1,
7068                loop: false,
7069                mouseDrag: false,
7070                nav: false,
7071                smartSpeed: 200,
7072                margin: 16,
7073                responsive: {
7074                    0: { items: DISPLAY_ITEM_NUM_MOBILE },
7075                    768: { items: DISPLAY_ITEM_NUM_TABLET },
7076                    1260: { items: DISPLAY_ITEM_NUM_DESKTOP }
7077                }
7078            }).on('click', '.owl-item', function(e) {
7079                e.preventDefault();
7080                owlThumbnails.find('.video-carousel__thumbnail.selected').removeClass('selected');
7081                $(this).find('.video-carousel__thumbnail').addClass('selected');
7082                const targetSlideNumber = $(this).index();
7083                updatePlayerToSlide(targetSlideNumber, owlVideoPlayer);
7084                announceCurrentSlide(targetSlideNumber, TOTAL_THUMBNAILS);
7085            });
7086        }
7087
7088        // Initialize navigation arrows for the thumbnail carousel
7089        function initThumbnailNav(navigation, owlThumbnails) {
7090            navigation.children().each(function() {
7091                const isLeft = $(this).hasClass("video-carousel__navigation--left");
7092                $(this).attr('aria-label', isLeft ? 'Previous thumbnails' : 'Next thumbnails')
7093                    .attr('role', 'button')
7094                    .attr('tabindex', '0');
7095            }).on('click keydown', function(e) {
7096                if (e.type === 'click' || (e.type === 'keydown' && e.key === 'Space')) {
7097                    e.preventDefault();
7098                    const targetSlideNumber = $(this).hasClass("video-carousel__navigation--left") ?
7099                        (currentSlideNumber <= 0 ? TOTAL_THUMBNAILS - 1 : currentSlideNumber - 1) :
7100                        (currentSlideNumber + 1 >= TOTAL_THUMBNAILS ? 0 : currentSlideNumber + 1);
7101                    
7102                    // Scroll thumbnail carousel to keep target item visible
7103                    const currentCarouselPos = owlThumbnails.data('owl.carousel')?.current() || 0;
7104                    const lastVisibleIndex = currentCarouselPos + numToDisplay - 1;
7105                    let newCarouselPos;
7106                    
7107                    if (targetSlideNumber > lastVisibleIndex) {
7108                        newCarouselPos = targetSlideNumber - numToDisplay + 1;
7109                    } else if (targetSlideNumber < currentCarouselPos) {
7110                        newCarouselPos = targetSlideNumber;
7111                    } else {
7112                        newCarouselPos = currentCarouselPos;
7113                    }
7114                    
7115                    if (newCarouselPos !== currentCarouselPos) {
7116                        // third param 'true' prevents owl from trying to snap back to the start when it thinks a target is out of range
7117                        // this is not listed in the owl docs as an available param of this update so documenting here.
7118                        owlThumbnails.trigger('to.owl.carousel', [newCarouselPos, 200, true]);
7119                    }
7120                    owlThumbnails.find('.owl-item').eq(targetSlideNumber).trigger('click');
7121                }
7122                if (e.type === 'keydown' && e.key === 'Enter') {
7123                    e.preventDefault();
7124                    const playButton = owlVideoPlayer.find('.owl-item')
7125                        .eq(currentSlideNumber)
7126                        .find('.video-carousel__player--button');
7127                    playButton.focus();
7128                }
7129            });
7130        }
7131
7132        // Keyboard arrow navigation for carousel
7133        function initKeyboardArrowNav() {
7134            $(this).on('keydown', function(e) {
7135                if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
7136                    const navLeft = navigation.find('.video-carousel__navigation--left');
7137                    const navRight = navigation.find('.video-carousel__navigation--right');
7138                    if (e.key === "ArrowRight") {
7139                        navRight.trigger('click');
7140                        navRight.focus();
7141                    } else if (e.key === "ArrowLeft") {
7142                        navLeft.trigger('click');
7143                        navLeft.focus();
7144                    }
7145                    e.preventDefault();
7146                }
7147            });
7148        }
7149
7150        // Init all carousel logic
7151        initVideoPlayer(owlVideoPlayer);
7152        initVideoPlayerPoster(owlVideoPlayer);
7153        playButton(owlVideoPlayer);
7154        initThumbnailCarousel(owlThumbnails, owlVideoPlayer);
7155        initThumbnailNav(navigation, owlThumbnails);
7156        setNumToDisplay();
7157        window.addEventListener("resize", setNumToDisplay);
7158        initKeyboardArrowNav.call(this);
7159    }
7160
7161    // Initialize the video carousel on document ready
7162    $(document).ready(function() {
7163        $('.video-carousel').each(initVideoCarouselComponent);
7164    });
7165})();
7166
7167$(document).ready(function(){
7168    var $toolbarComponent = $('.toolbar.component');
7169    var eventName;
7170
7171    if($toolbarComponent.length) {
7172        $toolbarComponent.each(function(){
7173            var numIcons = $(this).find('a').length;
7174            if (numIcons == 3 || numIcons == 2){
7175                $(this).addClass('three-items');
7176            }
7177        });
7178
7179        $toolbarComponent.on('click', '.toolbar-icons [data-toolbar-link]', function(e) {
7180            eventName = e.currentTarget.querySelector('span').innerText.toLocaleLowerCase();
7181            updateDataLayerObj(eventName);
7182        });
7183    }
7184
7185    $('.toolbar img[src$=".svg"]').each(function() {
7186        var $img = jQuery(this);
7187        var imgURL = $img.attr('src');
7188        var attributes = $img.prop("attributes");
7189
7190        $.get(imgURL, function(data) {
7191            // Get the SVG tag, ignore the rest
7192            var $svg = $(data).find('svg');
7193
7194            // Remove any invalid XML tags
7195            $svg = $svg.removeAttr('xmlns:a');
7196
7197            // Loop through IMG attributes and apply on SVG
7198            $.each(attributes, function() {
7199                $svg.attr(this.name, this.value);
7200            });
7201
7202            // Replace IMG with SVG
7203            $img.replaceWith($svg);
7204            $svg.get(0).setAttribute('preserveAspectRatio','xMaxYMin meet');
7205        }, 'xml');
7206    });
7207});
7208
7209function updateDataLayerObj(eventName) {
7210    var eventAction = 'icon toolbar click';
7211    var eventType = 'icon toolbar';
7212
7213    try {
7214        if(digitalData) {
7215            if(digitalData.event) {
7216                digitalData.event.eventAction = 'icon toolbar click';
7217                digitalData.event.eventName = eventName;
7218                digitalData.event.type = "icon toolbar";
7219                digitalData.event.timeStamp = new Date();
7220            }
7221        }
7222    } catch(err) {
7223        console.log(err);
7224    }
7225}
7226$(document).ready(function() {
7227    /* Intranet - Adding Email Share to Internal News/Blogs Pages - Update href with page URL */
7228    var internalNewsPage = $(".internal-news-page");
7229    var internalBlogPage = $(".blog-details-wrapper");
7230    if (internalNewsPage.length || internalBlogPage.length) {
7231        var internalShare = internalNewsPage.length ? internalNewsPage.find(".
7231internal-news-blog-share") : internalBlogPage.find(".internal-news-blog-share");
7232        var emailShare = internalShare.find(".email-share");
7233        var shareLink = "mailto:?subject=Check out what I found on mypentair.com&body=" + window.location.href;
7234        emailShare.attr("href", shareLink);
7235    }
7236});
7237
7238$(document).ready(function() {
7239
7240    $('.tile-callouts-tile a').hover(function(){
7241       $(this).find('div > div').stop().slideDown('fast');
7242    }, function(){
7243        $(this).find('div > div').stop().slideUp('fast');
7244    });
7245
7246    var initCalloutsCarousel = function(calloutsComponent) {
7247        var carousel = calloutsComponent.find(".wrap");
7248        var totalSlides = carousel.find(".tile-callouts-tile").length;
7249        var currentSlide = 0;
7250
7251        var addLeadingZero = function (numString) {
7252            return (parseInt(numString, 10) < 10) ? '0' + numString : numString;
7253        };
7254
7255        var update = function(){
7256            setTimeout(function(){
7257                var activeDot = carousel.find('.owl-dot.active');
7258                currentSlide = carousel.find('.owl-dot').index(activeDot) + 1;
7259                calloutsComponent.find('.owl-custom-nav .current').text(addLeadingZero(currentSlide));
7260            }, 10);
7261        };
7262
7263        calloutsComponent.find('.owl-custom-nav .total').text(addLeadingZero(totalSlides));
7264
7265        carousel.on('initialized.owl.carousel changed.owl.carousel resized.owl.carousel', function(e) {
7266            update();
7267        });
7268
7269        calloutsComponent.find('.owl-custom-nav .owl-next').on('click', function (e) {
7270            carousel.trigger('next.owl.carousel');
7271        });
7272
7273        calloutsComponent.find('.owl-custom-nav .owl-prev').on('click', function (e) {
7274            carousel.trigger('prev.owl.carousel');
7275        });
7276
7277        carousel.owlCarousel({
7278            loop: true,
7279            center: true,
7280            items: 1,
7281            animateIn: 'fadeIn',
7282            animateOut: 'fadeOut',
7283            dots: true,
7284            nav: false
7285        });
7286    };
7287
7288    var tileCalloutsComponents = $(".tile-callouts.component");
7289
7290    if (tileCalloutsComponents.length) {
7291        var owlCarousels = tileCalloutsComponents.find(".wrap");
7292
7293        if (owlCarousels.length) {
7294            tileCalloutsComponents.each(function(index,elem) {
7295                initCalloutsCarousel($(elem));
7296            });
7297        }
7298    }
7299});
7300
7301class Viewer360 {
7302    constructor(containerParent, options = {}) {
7303
7304        //Custom to AEM for facilitating the edit mode view, and not running js if not authored
7305        const container = containerParent.firstElementChild;
7306        if (!container || container.className === 'edit-in-dialog-msg') {
7307            return;
7308        }
7309        this.container = container;
7310
7311        // --- Configuration ---
7312        this.PARTS = parseInt(container.dataset.parts || options.parts || 5);
7313        this.FRAMES_PER_PART = parseInt(container.dataset.frames || options.frames || 36);
7314        this.EXT_PREFIX = container.dataset.externalPrefix || options.externalPrefix || "";
7315        this.EXT_FOLDER = container.dataset.externalFolder || options.externalFolder || "";
7316        this.INT_PREFIX = container.dataset.internalPrefix || options.internalPrefix || "";
7317        this.INT_FOLDER = container.dataset.internalFolder || options.internalFolder || "";
7318        this.IMAGE_EXT = ".webp";
7319        this.MODE = container.dataset.mode || '';
7320
7321        // Custom to AEM for displaying placeholder in edit mode
7322        if (this.MODE === 'edit') {
7323            const slash = this.EXT_FOLDER.endsWith("/") ? "" : "/";
7324            const placeholderPath = this.EXT_FOLDER + slash + this.EXT_PREFIX + "01_01" + this.IMAGE_EXT;
7325            container.innerHTML = '<p class="placeholder">3D Object Placeholder</p><img src="' + placeholderPath + '">';
7326            return;
7327        }
7328
7329        // --- Hotspots ---
7330        const dataHotspots = container.dataset.hotspots ? JSON.parse(container.dataset.hotspots) : null;
7331        this.hotspotDefs = dataHotspots || options.hotspotDefs || [];
7332        this.hotspots = this.hotspotDefs.flatMap(def =>
7333            def.frames.map((frame, i) => ({
7334                set: def.set,
7335                part: def.part,
7336                frame: frame,
7337                x: Array.isArray(def.x) ? def.x[i] : def.x,
7338                y: def.y,
7339                tooltip: def.tooltip,
7340                direction: def.direction || "top"
7341            }))
7342        );
7343
7344        // --- State Management ---
7345        this.imageCache = {};
7346        this.currentSet = "external";
7347        this.currentPart = Math.floor(this.PARTS / 2);
7348        this.currentFrame = 0;
7349        this.isDragging = false;
7350        this.lastX = 0;
7351        this.lastY = 0;
7352        this.velocityX = 0;
7353        this.velocityY = 0;
7354        this.animationFrameId = null;
7355        this.lastUpdateTime = 0;
7356        this.momentumActive = false;
7357
7358        this.activeTooltip = null;
7359        this.activeTooltipParent = null;
7360
7361        // --- Initialization ---
7362        this.buildUI();
7363        this.updateToggleUI();
7364        this.updateImage();
7365
7366        window.addEventListener('resize', () => this.renderHotspots());
7367        setTimeout(() => {
7368            window.dispatchEvent(new Event('resize')); // Need to do this for AEM so hotspots render in the right location. Some timing issue calling renderHotspots otherwise.
7369        }, 500);
7370    }
7371
7372    buildUI() {
7373        this.container.innerHTML = `
7374        <div class="viewer-header">
7375        <div class="toggle-wrap">
7376            <label class="switch">
7377            <input class="toggle-view" type="checkbox">
7378            <span class="slider"></span>
7379            </label>
7380            <span class="view-label">
7381            View: <span class="view-mode-label">External</span>
7382            </span>
7383        </div>
7384        <button class="reset-btn">
7385            <svg width="15" height="12" viewBox="0 0 15 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.9998 6.00958L12.9799 8.73146L10.9653 6.0057L12.501 6.00721C12.5055 4.84868 12.1105 3.72275 11.3569 2.8043C9.60114 0.664283 6.43776 0.356622 4.30511 2.11881C4.09858 2.28938 3.79351 2.2598 3.62334 2.05253C3.45338 1.84527 3.48285 1.53912 3.68939 1.36834C4.31221 0.853629 5.01721 0.476664 5.78461 0.248024C6.52618 0.027156 7.29358 -0.0466824 8.06635 0.0284514C8.83891 0.103585 9.5779 0.324021 10.2629 0.683498C10.9724 1.05571 11.592 1.56157 12.1049 2.18661C12.7043 2.917 13.113 3.75233 13.3202 4.66905C13.4192 5.1069 13.4682 5.55749 13.4674 6.00829L14.9998 6.00958ZM10.7123 9.88092C9.78121 10.6504 8.65367 11.0252 7.53238 11.025C6.0858 11.025 4.64976 10.4008 3.66056 9.19522C2.9093 8.27958 2.51452 7.15732 2.51646 6.00268L4.03425 6.00462L2.02035 3.27821L0 5.99965L1.55049 6.0016C1.55049 6.44916 1.59933 6.89629 1.69765 7.3309C1.90482 8.24762 2.31358 9.08273 2.91296 9.81334C3.42584 10.4384 4.04565 10.9442 4.75496 11.3165C5.43996 11.6759 6.17895 11.8964 6.95151 11.9715C7.14664 11.9905 7.34134 12 7.53539 12C8.11002 12 8.67863 11.9171 9.23261 11.7519C10 11.5233 10.705 11.1463 11.3278 10.6316C11.5344 10.4611 11.5638 10.1547 11.3939 9.94742C11.2239 9.74015 10.9188 9.71036 10.7123 9.88092Z" fill="black"/></svg>
7386            Reset
7387        </button>
7388        </div>
7389        <div class="viewer-container">
7390        <img class="viewer-image" src="" draggable="false" alt="360 viewer">
7391        <div class="hotspot-layer"></div>
7392        </div>
7393        `;
7394        this.viewerImage = this.container.querySelector('.viewer-image');
7395        this.toggleView = this.container.querySelector('.toggle-view');
7396        this.viewModeLabel = this.container.querySelector('.view-mode-label');
7397        this.resetBtn = this.container.querySelector('.reset-btn');
7398        this.hotspotLayer = this.container.querySelector('.hotspot-layer');
7399        this.viewerContainer = this.container.querySelector('.viewer-container');
7400
7401        this.addEventListeners();
7402    }
7403
7404    addEventListeners() {
7405        this.viewerImage.addEventListener('mousedown', e => this.startDrag(e));
7406        window.addEventListener('mousemove', e => this.duringDrag(e));
7407        window.addEventListener('mouseup', () => this.endDrag());
7408        this.viewerImage.addEventListener('touchstart', e => this.startDrag(e), { passive: false });
7409        window.addEventListener('touchmove', e => this.duringDrag(e), { passive: false });
7410        window.addEventListener('touchend', () => this.endDrag());
7411
7412        this.toggleView.addEventListener('change', () => {
7413            this.currentSet = this.toggleView.checked ? "internal" : "external";
7414            this.updateToggleUI();
7415            this.updateImage();
7416            this.hideTooltip();
7417        });
7418
7419        this.resetBtn.addEventListener('click', () => {
7420            this.currentPart = Math.floor(this.PARTS / 2);
7421            this.currentFrame = 0;
7422            this.updateImage();
7423            this.hideTooltip();
7424        });
7425
7426        this.container.addEventListener('keydown', e => {
7427            let changed = false;
7428            if (e.key === 'ArrowLeft') {
7429                this.currentFrame = this.wrapIndex(this.currentFrame + 1, this.FRAMES_PER_PART);
7430                changed = true;
7431            } else if (e.key === 'ArrowRight') {
7432                this.currentFrame = this.wrapIndex(this.currentFrame - 1, this.FRAMES_PER_PART);
7433                changed = true;
7434            } else if (e.key === 'ArrowUp') {
7435                this.currentPart = this.wrapIndex(this.currentPart + 1, this.PARTS);
7436                changed = true;
7437            } else if (e.key === 'ArrowDown') {
7438                this.currentPart = this.wrapIndex(this.currentPart - 1, this.PARTS);
7439                changed = true;
7440            }
7441            if (changed) {
7442                this.updateImage();
7443                this.hideTooltip();
7444            }
7445        });
7446
7447        // No document.body event listeners at all!
7448    }
7449
7450    getImageFilename(baseFolder, basePrefix, part, frame) {
7451        const partStr = String(part).padStart(2, "0");
7452        const frameStr = String(frame + 1).padStart(2, "0");
7453        return `${baseFolder}${basePrefix}${partStr}_${frameStr}${this.IMAGE_EXT}`;
7454    }
7455
7456    buildImageArray(baseFolder, basePrefix) {
7457        const arr = [];
7458        for (let p = 1; p <= this.PARTS; p++) {
7459            arr[p - 1] = [];
7460            for (let f = 0; f < this.FRAMES_PER_PART; f++) {
7461                arr[p - 1][f] = this.getImageFilename(baseFolder, basePrefix, p, f);
7462            }
7463        }
7464        return arr;
7465    }
7466
7467    getImageArray() {
7468        if (!this.imagesExternal) {
7469            this.imagesExternal = this.buildImageArray(this.EXT_FOLDER, this.EXT_PREFIX);
7470        }
7471        if (!this.imagesInternal) {
7472            this.imagesInternal = this.buildImageArray(this.INT_FOLDER, this.INT_PREFIX);
7473        }
7474        return this.currentSet === "external" ? this.imagesExternal : this.imagesInternal;
7475    }
7476
7477    loadImage(url) {
7478        return new Promise((resolve, reject) => {
7479            if (this.imageCache[url]) {
7480                return resolve(this.imageCache[url]);
7481            }
7482            const img = new window.Image();
7483            img.src = url;
7484            img.onload = () => {
7485                this.imageCache[url] = img;
7486                resolve(img);
7487            };
7488            img.onerror = () => {
7489                console.error(`Failed to load image: ${url}`);
7490                reject(`Failed to load image at ${url}`);
7491            };
7492        });
7493    }
7494
7495    updateToggleUI() {
7496        const isInternal = this.currentSet === "internal";
7497        this.viewModeLabel.textContent = isInternal ? "Internal" : "External";
7498        this.toggleView.checked = isInternal;
7499    }
7500
7501    async updateImage() {
7502        const imgArr = this.getImageArray();
7503        const url = imgArr[this.currentPart][this.currentFrame];
7504
7505        this.viewerImage.classList.add('is-loading');
7506        try {
7507            const loadedImage = await this.loadImage(url);
7508            this.viewerImage.src = loadedImage.src;
7509            this.renderHotspots();
7510        } catch (error) {
7511            console.error(error);
7512        } finally {
7513            this.viewerImage.classList.remove('is-loading');
7514        }
7515    }
7516
7517    renderHotspots() {
7518        if (!this.hotspotLayer) return; // In AEM seeing this being called too early, so bail out
7519        this.hotspotLayer.innerHTML = "";
7520        const relevant = this.hotspots.filter(
7521            h => h.set === this.currentSet && h.part === (this.currentPart + 1) && h.frame === this.currentFrame
7522        );
7523
7524        if (!relevant.length) return;
7525
7526        const imgRect = this.viewerImage.getBoundingClientRect();
7527        const containerRect = this.hotspotLayer.getBoundingClientRect();
7528        const imgLeft = imgRect.left - containerRect.left;
7529        const imgTop = imgRect.top - containerRect.top;
7530        const imgWidth = imgRect.width;
7531        const imgHeight = imgRect.height;
7532
7533        relevant.forEach((h, idx) => {
7534            // Parent wrapper
7535            const parent = document.createElement("div");
7536            parent.className = "hotspot-parent";
7537            parent.style.position = "absolute";
7538            parent.style.left = `${imgLeft + h.x * imgWidth}px`;
7539            parent.style.top = `${imgTop + h.y * imgHeight}px`;
7540            parent.style.transform = "translate(-50%, -50%)";
7541            parent.style.zIndex = 5; // Default z-index 5
7542
7543            // Hotspot button
7544            const hotspot = document.createElement("div");
7545            hotspot.className = "hotspot";
7546            hotspot.innerHTML = `<div class="hotspot-inner"></div>`;
7547
7548            // Tooltip (starts hidden)
7549            const tooltip = document.createElement("div");
7550            tooltip.className = "hotspot-tooltip hidden";
7551            tooltip.setAttribute("tabindex", "-1");
7552
7553            // Toggle logic: show on click, hide on click again, do not hide on outside click
7554            const toggleTooltip = (e) => {
7555                e.stopPropagation();
7556                // If this tooltip is already active, hide it
7557                if (tooltip.classList.contains('active')) {
7558                    tooltip.className = "hotspot-tooltip hidden";
7559                    parent.style.zIndex = 5;
7560                    this.activeTooltip = null;
7561                    this.activeTooltipParent = null;
7562                } else {
7563                    this.hideTooltip(); // Hide all other tooltips
7564                    tooltip.innerHTML = h.tooltip;
7565                    tooltip.className = `hotspot-tooltip active ${h.direction || "top"}`;
7566                    parent.style.zIndex = 10; // Set active z-index
7567                    this.activeTooltip = tooltip;
7568                    this.activeTooltipParent = parent;
7569                }
7570            };
7571            hotspot.addEventListener("click", toggleTooltip);
7572            hotspot.addEventListener("touchstart", toggleTooltip, { passive: false });
7573
7574            parent.appendChild(hotspot);
7575            parent.appendChild(tooltip);
7576            this.hotspotLayer.appendChild(parent);
7577        });
7578    }
7579
7580    /**
7581     * Hide tooltip (optionally pass tooltip, otherwise hide all)
7582     * Also resets all hotspot-parent z-index to 5
7583     */
7584    hideTooltip(tooltip = null) {
7585        if (!tooltip && this.hotspotLayer) {
7586            // Hide all tooltips
7587            this.hotspotLayer.querySelectorAll('.hotspot-tooltip').forEach(tip => {
7588                tip.className = "hotspot-tooltip hidden";
7589            });
7590            // Reset all hotspot-parent z-index to 5
7591            this.hotspotLayer.querySelectorAll('.hotspot-parent').forEach(parent => {
7592                parent.style.zIndex = 5;
7593            });
7594            this.activeTooltip = null;
7595            this.activeTooltipParent = null;
7596        } else if (tooltip) {
7597            tooltip.className = "hotspot-tooltip hidden";
7598            if (this.activeTooltip === tooltip) this.activeTooltip = null;
7599            if (this.activeTooltipParent) {
7600                this.activeTooltipParent.style.zIndex = 5;
7601                this.activeTooltipParent = null;
7602            }
7603        }
7604    }
7605
7606    wrapIndex(idx, len) {
7607        return (idx + len) % len;
7608    }
7609
7610    animateMomentum() {
7611        if (!this.momentumActive) return;
7612        const DAMPING = 0.93;
7613        this.velocityX *= DAMPING;
7614        this.velocityY *= DAMPING;
7615        let changed = false;
7616        if (Math.abs(this.velocityX) > 0.05) {
7617            let framesToMove = this.velocityX * 0.1;
7618            if (Math.abs(framesToMove) >= 1) {
7619                this.currentFrame = this.wrapIndex(this.currentFrame + Math.round(framesToMove), this.FRAMES_PER_PART);
7620                changed = true;
7621            }
7622        }
7623        if (Math.abs(this.velocityY) > 0.05) {
7624            let partsToMove = this.velocityY * 0.02;
7625            if (Math.abs(partsToMove) >= 1) {
7626                this.currentPart = this.wrapIndex(this.currentPart - Math.round(partsToMove), this.PARTS);
7627                changed = true;
7628            }
7629        }
7630        if (changed) this.updateImage();
7631        if (Math.abs(this.velocityX) < 0.05 && Math.abs(this.velocityY) < 0.05) {
7632            this.momentumActive = false;
7633            return;
7634        }
7635        this.animationFrameId = requestAnimationFrame(() => this.animateMomentum());
7636    }
7637
7638    startDrag(e) {
7639        this.isDragging = true;
7640        this.lastX = e.touches ? e.touches[0].pageX : e.pageX;
7641        this.lastY = e.touches ? e.touches[0].pageY : e.pageY;
7642        this.velocityX = 0;
7643        this.velocityY = 0;
7644        this.lastUpdateTime = Date.now();
7645        if (this.momentumActive && this.animationFrameId) {
7646            cancelAnimationFrame(this.animationFrameId);
7647            this.momentumActive = false;
7648        }
7649        e.preventDefault();
7650        // DO NOT hideTooltip here!
7651    }
7652
7653    duringDrag(e) {
7654        if (!this.isDragging) return;
7655        const x = e.touches ? e.touches[0].pageX : e.pageX;
7656        const y = e.touches ? e.touches[0].pageY : e.pageY;
7657        const dx = x - this.lastX;
7658        const dy = y - this.lastY;
7659        const SENSITIVITY_X = 5;
7660        const SENSITIVITY_Y = 40;
7661        let frameChange = dx / SENSITIVITY_X;
7662        let partChange = dy / SENSITIVITY_Y;
7663        let changed = false;
7664        if (Math.abs(frameChange) >= 1) {
7665            this.currentFrame = this.wrapIndex(this.currentFrame + Math.round(frameChange), this.FRAMES_PER_PART);
7666            this.lastX = x;
7667            changed = true;
7668        }
7669        if (Math.abs(partChange) >= 1) {
7670            this.currentPart = this.wrapIndex(this.currentPart - Math.round(partChange), this.PARTS);
7671            this.lastY = y;
7672            changed = true;
7673        }
7674        if (changed) this.updateImage();
7675        const now = Date.now();
7676        const dt = Math.max(now - this.lastUpdateTime, 1);
7677        this.velocityX = dx / dt * 16;
7678        this.velocityY = dy / dt * 16;
7679        this.lastUpdateTime = now;
7680        // DO NOT hideTooltip here!
7681    }
7682
7683    endDrag() {
7684        this.isDragging = false;
7685        if (Math.abs(this.velocityX) > 0.2 || Math.abs(this.velocityY) > 0.2) {
7686            this.momentumActive = true;
7687            this.animationFrameId = requestAnimationFrame(() => this.animateMomentum());
7688        }
7689    }
7690}
7691
7692// Slightly customized for AEM to call correctly for the component
7693window.onload = function() {
7694    const objects3D = document.querySelectorAll('.three-d-object')
7695    if (!objects3D.length) return;
7696    objects3D.forEach(el => new Viewer360(el));
7697};
7698
7699$(document).ready(function(){
7700    //readmore
7701    $('.text .readmore').each(function(){
7702        if ($('.edit-mode').length === 0){
7703            var $this = $(this);
7704            var $thisParent = $this.parent();
7705            var $removedReadmore = $this.parent().html().replace('<span class="readmore"></span>', '');
7706            $(this).parent().nextAll().wrapAll('<div class="readmore-text"></div>');
7707            $(this).closest('.text').find('.readmore-text').after($this);
7708            if ($removedReadmore==='&nbsp;') {
7709                $thisParent.remove();
7710            }
7711        }
7712    });
7713
7714    $('.pnt-hero-interior .readmore').each(function(){
7715        if ($('.edit-mode').length === 0){
7716            var $this = $(this);
7717            var $thisParent = $this.parent();
7718            var $removedReadmore = $this.parent().html().replace('<span class="readmore"></span>', '');
7719            $(this).parent().nextAll().wrapAll('<div class="readmore-text"></div>');
7720            $(this).closest('.pnt-hero-interior').find('.readmore-text').after($this);
7721            if ($removedReadmore==='&nbsp;') {
7722                $thisParent.remove();
7723            }
7724        }
7725    });
7726
7727    $('.readmore').on('click',function(){
7728        $(this).prev('.readmore-text').stop().slideToggle('fast');
7729        $(this).toggleClass('open');
7730    });
7731
7732    //add line to intro paragraph text, done this way to allow for centering of the line via text-align center
7733    $('.text .intro').each(function(){
7734       $(this).append('<span aria-hidden="true"></span>');
7735    });
7736
7737    //add line to intro paragraph text, done this way to allow for centering of the line via text-align center
7738    $('.pnt-hero-interior .intro').each(function(){
7739       $(this).append('<span aria-hidden="true"></span>');
7740    });
7741
7742    //tooltip text
7743    $('.text .tip').attr('tabindex','0').wrapInner( "<span></span>");
7744    $('.pnt-hero-interior .tip').attr('tabindex','0').wrapInner( "<span></span>");
7745    var el = document.getElementsByTagName("body")[0];
7746    el.addEventListener("touchstart", touchedStart, false);
7747    function touchedStart() {
7748        $('.tip').blur();
7749    }
7750    checkTipEdge(); //also runs on resize. adds class to prevent tooltip from going off the edge of the screen
7751    function checkTipEdge(){
7752        $('.tip').each(function(){
7753            var $this = $(this);
7754            var offNum = 110;
7755            var leftEdge = $this.offset().left;
7756            var rightEdge = $this.offset().left + $this.width();
7757            var screenWidth = $(window).width();
7758            if ( screenWidth-rightEdge < offNum) {
7759                $this.addClass('near-right').removeClass('near-left');
7760            }
7760 else  if (leftEdge < offNum) {
7761                $this.addClass('near-left').removeClass('near-right');
7762            } else {
7763                $this.removeClass('near-left near-right');
7764            }
7765        });
7766
7767    }
7768    // Text Arrow class re-assignment
7769    $('.text .text-arrow-link, .text .text-arrow-link-white').each(function(i, el) {
7770        var cls = $(el).attr('class');
7771
7772        $(el).removeAttr('class');
7773        $(el).parent().addClass(cls);
7774    });
7775
7776    $(".text a[href^='#']").on("click", function(e) {
7777        var hash = this.hash;
7778        var header = $("body").find("header").outerHeight();
7779        var stickyJumpNav = $("body").find(".sticky-jump-nav");
7780        var targetExists = $(hash).length > 0;
7781
7782        e.preventDefault();
7783        if (targetExists) {
7784            var offset = $(hash).offset().top - header;
7785
7786            if (stickyJumpNav.length) {
7787                offset -= (stickyJumpNav.hasClass("stuck") ? stickyJumpNav.outerHeight() : stickyJumpNav.outerHeight(true) );
7788            }
7789
7790            $('html, body').animate({
7791                scrollTop: offset
7792            }, 250);
7793        }
7794    });
7795});
7796// Tab panel slide animation logic
7797document.addEventListener('DOMContentLoaded', function() {
7798	const tabComponents = document.querySelectorAll('.tabs-core');
7799	tabComponents.forEach(function(component) {
7800		const tabs = Array.from(component.querySelectorAll('.cmp-tabs__tab'));
7801		const panels = Array.from(component.querySelectorAll('.cmp-tabs__tabpanel'));
7802		let lastIndex = tabs.findIndex(tab => tab.classList.contains('cmp-tabs__tab--active'));
7803
7804		tabs.forEach(function(tab, idx) {
7805			tab.addEventListener('click', function() {
7806				const newIndex = idx;
7807
7808				// Remove animation and active classes from all panels
7809				panels.forEach(panel => {
7810					panel.classList.remove('slide-left', 'slide-right', 'cmp-tabs__tabpanel--active');
7811				});
7812
7813				// Remove active class from all tabs
7814				tabs.forEach(t => t.classList.remove('cmp-tabs__tab--active'));
7815
7816				// Add active to new tab and panel
7817				tab.classList.add('cmp-tabs__tab--active');
7818				const newPanel = panels[newIndex];
7819				newPanel.classList.add('cmp-tabs__tabpanel--active');
7820
7821				// Add animation direction
7822				if (newIndex > lastIndex) {
7823					newPanel.classList.add('slide-left');
7824				} else if (newIndex < lastIndex) {
7825					newPanel.classList.add('slide-right');
7826				}
7827				lastIndex = newIndex;
7828			});
7829		});
7830	});
7831});
7832
7833$(document).ready(function(){
7834
7835    var initTabCarousel = function(carouselComponent){
7836        var tabCarousel = carouselComponent.find('.tab-name.owl-carousel');
7837        var contentCarousel = carouselComponent.find('.tab-content.owl-carousel');
7838        var currentSlide = 0;
7839        var totalSlides = carouselComponent.find('.tab-name .item').length;
7840
7841        contentCarousel.owlCarousel({
7842            nav:false,
7843            dots:false,
7844            mouseDrag: false,
7845            autoHeight: false,
7846            items: 1
7847            // center: true,
7848        }).on('initialized.owl.carousel changed.owl.carousel resized.owl.carousel', function(event) {
7849            tabCarousel.trigger('to.owl.carousel', [event.item.index, 300, true]);
7850            tabCarousel.find('.current').removeClass('current');
7851            tabCarousel.find('.owl-item .item').eq(event.item.index).addClass('current');
7852            update();
7853        });
7854
7855        tabCarousel.owlCarousel({
7856            nav: false,
7857            dots:false,
7858            mouseDrag: false,
7859            dragMove: false,
7860            // center: true,
7861            // onDragged: function(e){console.log('drg', e)},
7862            responsive: {
7863                0: {
7864                    items: Math.min(totalSlides, 3),
7865                    autoWidth:true
7866                },
7867                768: {
7868                    items: Math.min(totalSlides, 5)
7869                }
7870            }
7871        }).on('click', '.owl-item', function(event) {
7872            var targetIndex = $(event.target).parents('.owl-item').index();
7873            var dist = targetIndex - tabCarousel.find('.current').parent().index();
7874            var direction = (dist < 0) ? 'prev.owl.carousel' : 'next.owl.carousel';
7875            dist = Math.abs(dist);
7876            for(var i = 0; i < dist; i++){
7877                contentCarousel.trigger(direction);
7878            }
7879        });
7880
7881        tabCarousel.on('dragged.owl.carousel', function (event) {
7882            var dragDirection = event.relatedTarget['_drag']['direction'];
7883            if(dragDirection === 'left'){
7884                contentCarousel.trigger('next.owl.carousel');
7885            } else if(dragDirection === 'right'){
7886                contentCarousel.trigger('prev.owl.carousel');
7887            }
7888        });
7889
7890        //add titles to tab content areas for print view & position bottom carrot to tab
7891        tabCarousels.each(function(){
7892            var tabName = $(this);
7893            var tabItem = tabName.find('.item h5');
7894            var tabContent = $(this).find('.tab-content');
7895
7896            for (j = 0; j < tabContent.find('.item').length; j++){
7897                tabContent.find('.item:eq('+j+')').attr('data-title',tabItem.eq(j).text());
7898            }
7899
7900            var activeTabHeight = $(this).find(".owl-item.active").height();
7901            if (activeTabHeight > 61 && activeTabHeight < 82) {
7902                $(this).find('.icon-caret-down').addClass('wrap-2');
7903            }
7904            if (activeTabHeight > 81 && activeTabHeight < 101) {
7905                $(this).find('.icon-caret-down').addClass('wrap-3');
7906            }
7907            if (activeTabHeight > 100) {
7908                $(this).find('.icon-caret-down').addClass('wrap-4');
7909            }
7910        });
7911
7912        var update = function () {
7913            // If there's more items to the right that are hidden, add white overlay.
7914            
7915            var addRightOverlay = (tabCarousel.find('.owl-item.active').first().nextAll('.owl-item').length > 2);
7916
7917            if(addRightOverlay){
7918                tabCarousel.addClass('right-overlay');
7919            } else {
7920                tabCarousel.removeClass('right-overlay');
7921            }
7922        }
7923
7924        update();
7925    };
7926
7927    var tabCarousels = $('.tabs.component');
7928
7929    if(tabCarousels.length){
7930        var mode = tabCarousels.first().data('isedit');
7931        if (mode === 'noedit') {
7932            $(function(){
7933                tabCarousels.each(function(index, elem){
7934                    initTabCarousel($(elem));
7935                });
7936            });
7937        }
7938    }
7939
7940});
7941$(document).ready(function() {
7942    var tableRTE = $(".table-rte.component");
7943    var tableRows = tableRTE.find("tbody > tr").not(":first-child");
7944    var tableRowCells = tableRows.find("td");
7945    tableRowCells.each(function() {
7946        var textCount = $(this).text().trim().length;
7947        var thisIndex = $(this).index();
7948        var thisTable = $(this).closest('table');
7949        if (textCount <= 25) {
7950            thisTable.find('tbody tr:first-child td:eq(' + thisIndex + ')').addClass("small-width");
7951            $.fn.matchHeight._update();
7952        }
7953        else if (textCount > 25 && textCount < 75){
7954            thisTable.find('tbody tr:first-child td:eq(' + thisIndex + ')').addClass("medium-width");
7955            $.fn.matchHeight._update();
7956        } else if (textCount >= 75){
7957            thisTable.find('tbody tr:first-child td:eq(' + thisIndex + ')').addClass("large-width");
7958            $.fn.matchHeight._update();
7959        }
7960    });
7961});
7962var CQ = CQ || {};
7963
7964
7965$(document).ready(function(){
7966	var $body = $('body');
7967
7968    //set up carousel variables
7969    var sync1Selector = '.solutions.component .image-carousel.owl-carousel',
7970    	sync2Selector = '.solutions.component .text-carousel.owl-carousel',
7971    	sync3Selector = '.solutions.component .nav-carousel.owl-carousel';
7972
7973    var sync1 = $(sync1Selector),
7974        sync2 = $(sync2Selector),
7975        sync3 = $(sync3Selector);
7976
7977    var totalSlides = sync3.find('.item').length;
7978    var useNav = totalSlides > 5;
7979    var isCarouselStyle = !!$('.solutions.component.carousel-option').length;
7980
7981    function checkTypeSlides(){
7982        if ($('.solutions.component').hasClass('carousel-option')){
7983            if (totalSlides > 5){
7984                return true;
7985            } else{
7986                return false;
7987            }
7988        } else{
7989            return true;
7990        }
7991    }
7992
7993    function bindSolutionsToTiles() {
7994        var categoryList = $('.solutions.component .text-carousel.owl-carousel .owl-item');
7995
7996        var activeCategory;
7997
7998        categoryList.each(function(i,elem) {
7999            if ($(elem).hasClass('active')) {
8000                activeCategory = $(elem).find('h3').attr('data-category').toLowerCase();
8001                var bodySolution = $body.attr('data-solution');
8002                if (activeCategory != bodySolution) {
8003                	$body.attr('data-solution', activeCategory);
8004                }
8005            }
8006        });
8007
8008        if (CQ && CQ.setTileCategory) {
8009            CQ.setTileCategory();
8010        }
8011
8012    }
8013
8014    sync3.find('.item').hover(function(){
8015    	if(CQ && !CQ.isOnMobile) {
8016            if (!$(this).parent().hasClass('on')){
8017                $(this).parent('.owl-item').addClass('showing').removeClass('not-showing');
8018            }
8019        }
8020    }, function(){
8021        if (!$(this).parent().hasClass('on')) {
8022            $(this).parent('.owl-item').removeClass('showing').addClass('not-showing');
8023        }
8024    });
8025
8026    var update = function(eventType){
8027    	sync3.find('.owl-item.showing').removeClass('showing').removeClass('on').addClass('not-showing');
8028    	var activeClickElem = sync3.find('.owl-item.active .item[data-index="' + currentIndex + '"]').parent();
8029    	var activeDragElem = sync3.find('.owl-item.active').eq(0);
8030	    var current = eventType === 'click' ? activeClickElem : activeDragElem;
8031	    current.addClass('showing').removeClass('not-showing').addClass('on');
8032    };
8033
8034    var moveNav = function(){
8035    	if(checkTypeSlides()){
8036	    	sync3.find('.owl-prev').appendTo(sync3.parent().find('.nav-carousel-arrows')).removeClass('disabled');
8037	    	sync3.find('.owl-next').appendTo(sync3.parent().find('.nav-carousel-arrows')).removeClass('disabled');
8038            sync3.find('.owl-nav').removeClass('disabled');
8039            sync3.on('changed.owl.carousel', function(event) {
8040                sync3.find('.owl-nav').removeClass('disabled');
8041            });
8042    	}
8043    	setTimeout(function(){
8044    		bindSolutionsToTiles();
8045	    },0);
8046
8047    };
8048
8049    var addLeadingZero = function (numString) {
8050        return (parseInt(numString, 10) < 10) ? '0' + numString : numString;
8051    };
8052
8053    $('.nav-carousel-arrows').on('click', '> div', function(){
8054        if (!useNav){
8055            if (isNaN(currentIndex)){
8056                if ($(this).hasClass('owl-prev')) {
8057                    sync2.trigger('prev.owl.carousel');
8058                    currentIndex = totalSlides-1;
8059                } else {
8060                    sync2.trigger('next.owl.carousel');
8061                    currentIndex = 1;
8062                }
8063            } else{
8064                if ($(this).hasClass('owl-prev')) {
8065                    sync2.trigger('prev.owl.carousel');
8066                    if (currentIndex > 0) {
8067                        currentIndex--;
8068                    } else{
8069                        currentIndex = totalSlides-1;
8070                    }
8071                } else{
8072                    sync2.trigger('next.owl.carousel');
8073                    if (currentIndex < totalSlides-1){
8074                        currentIndex++;
8075                    } else{
8076                        currentIndex = 0;
8077                    }
8078                }
8079            }
8080            sync1.trigger('to.owl.carousel', [currentIndex]);
8081            sync3.trigger('to.owl.carousel', [currentIndex]);
8082            update('click');
8083            bindSolutionsToTiles();
8084        }
8085    });
8086
8087    var currentIndex;
8088
8089    // Start Carousel
8090    if(sync1.length) {
8091	    sync1.owlCarousel({
8092		    loop: true,
8093		    items : 1,
8094		    mouseDrag: false,
8095		    touchDrag: false,
8096		    margin:0,
8097		    nav : false,
8098		    dots: false,
8099		    animateOut: 'fadeOut',
8100		    linked: sync3Selector
8101	    });
8102    }
8103
8104    if(sync2.length) {
8105	    sync2.owlCarousel({
8106		    loop: true,
8107		    items : 1,
8108		    mouseDrag: false,
8109		    touchDrag: false,
8110		    margin:5,
8111		    nav: false,
8112		    dots: false,
8113		    autoHeight: true,
8114		    linked: sync3Selector
8115        });
8116    }
8117
8118    if(sync3.length) {
8119	    sync3.owlCarousel({
8120		    margin:0,
8121		    nav: checkTypeSlides(),
8122		    navText: ["<div class='icon-nav-left'></div>","<div class='icon-nav-right'></div>"],
8123		    dots: false,
8124		    linked: sync1Selector + ', ' + sync2Selector,
8125		    onInitialized: moveNav,
8126		    responsive : {
8127			    0 : {
8128				    loop: true,
8129				    touchDrag: true,
8130				    mouseDrag: true,
8131				    margin: isCarouselStyle ? 10 : 0, 
8132				    items: isCarouselStyle ? 3 : 4
8133			    },
8134			    768 : {
8135				    loop: useNav,
8136				    touchDrag: false,
8137				    mouseDrag: false,
8138				    items: isCarouselStyle ? 3 : 5
8139			    },
8140			    992 : {
8141				    loop: useNav,
8142				    touchDrag: false,
8143				    mouseDrag: false,
8144				    items: isCarouselStyle ? 4 : 5
8145			    },
8146			    1200 : {
8147			    	loop: useNav,
8148				    touchDrag: false,
8149				    mouseDrag: false,
8150			    	items: 5
8151			    }
8152		    }
8153	    }).on('click', '.owl-item' , function(event) {
8154			var sync3Data = sync3.data('owl.carousel');
8155			currentIndex = sync3Data.relative($(this).index());
8156			sync3.trigger('to.owl.carousel', [currentIndex]);	// Order of the triggers matters here. Avoids a carousel sync bug where desktop user clicks 3rd item with more than 5 total items in desktop & image carousel displays incorrect slide.
8157			sync1.trigger('to.owl.carousel', [currentIndex]);
8158			sync2.trigger('to.owl.carousel', [currentIndex]);
8159			update('click');
8160            bindSolutionsToTiles();
8161	    }).on('initialized.owl.carousel linked.to.owl.carousel', function(event) {
8162		    update('drag');
8163		});
8164
8165    }
8166
8167
8168
8169
8170    //set first owl-dot to active
8171    sync3.find('.owl-item').addClass('not-showing');
8172    sync3.find('.active:first').addClass('showing').addClass('on').removeClass('not-showing');
8173    $('.solutions.component.carousel-option').find('span.number').each(function(index, elem){
8174    	var finalNum = addLeadingZero($(this).text());
8175    	$(this).text(finalNum);
8176    });
8177
8178    //svg conversion
8179    $('.solutions.component img[src$=".svg"]').each(function() {
8180        var $img = jQuery(this);
8181        var imgURL = $img.attr('src');
8182        var attributes = $img.prop("attributes");
8183
8184        $.get(imgURL, function(data) {
8185            // Get the SVG tag, ignore the rest
8186            var $svg = $(data).find('svg');
8187
8188            // Remove any invalid XML tags
8189            $svg = $svg.removeAttr('xmlns:a');
8190
8191            // Loop through IMG attributes and apply on SVG
8192            $.each(attributes, function() {
8193                $svg.attr(this.name, this.value);
8194            });
8195
8196            // Replace IMG with SVG
8197            $img.replaceWith($svg);
8198            $svg.get(0).setAttribute('preserveAspectRatio','xMidYMin meet');
8199        }, 'xml');
8200    });
8201});
8202
8203var PENTAIR = PENTAIR || {};
8204PENTAIR.SHARE = PENTAIR.SHARE || {};
8205PENTAIR.SHARE.URLPARAMS = PENTAIR.SHARE.URLPARAMS || {};
8206
8207$(function(){
8208    /** Primary objective of the share component view model is to bind the dynamic query parameters, if they exist, to the various social media buttons. */
8209    var ShareViewModel = function ShareViewModel() {
8210        var self = this;
8211        var currentPageTitle = PENTAIR.SHARE.currentPageTitle ? PENTAIR.SHARE.currentPageTitle : '';
8212        var host = PENTAIR.SHARE.host ? PENTAIR.SHARE.host : '';
8213        var titleKey = '&title=';
8214
8215        /** KO Observable Variables */
8216        self.queryParamString = ko.observable('');
8217        self.mailingLink = ko.observable('');
8218        self.modifiedTwitterLink = ko.observable('');
8219        self.modifiedFbLink = ko.observable('');
8220        self.modifiedLinkedInLink = ko.observable('');
8221
8222        function setQueryString() {
8223            var query = window.location.href;
8224            var hasQueryString = query.indexOf('?');
8225            if(hasQueryString !== -1) {
8226                self.queryParamString('?' + window.location.href.split('?')[1]);
8227            }
8228        }
8229
8230        function getEncodedUrl(url) {
8231            if(self.queryParamString() !== '') {
8232                return url + encodeURIComponent(self.queryParamString());
8233            } else {
8234                return url;
8235            }
8236        }
8237
8238        function createMailToLink() {
8239            var mailToBase = 'mailto:?subject=';
8240            var bodyKey = '&body=';
8241            var mailToString = mailToBase + currentPageTitle + bodyKey + getEncodedUrl(host);
8242            self.mailingLink(mailToString);
8243        }
8244
8245        function createTwitterLink() {
8246            var twitterBase = 'http://twitter.com/intent/tweet?url=';
8247            var twitterUrl = twitterBase + getEncodedUrl(host) + '&text=' + currentPageTitle;
8248            self.modifiedTwitterLink(twitterUrl);
8249        }
8250
8251        function createFacebookLink() {
8252            var fbLinkBase = 'http://www.facebook.com/sharer/sharer.php?u=';
8253            var fbUrl = fbLinkBase + getEncodedUrl(host) + titleKey + currentPageTitle;
8254            self.modifiedFbLink(fbUrl);
8255        }
8256
8257        function createLinkedInLink() {
8258            var linkedInBase = 'http://www.linkedin.com/shareArticle?mini=true&url=';
8259            var liSourceParam = '&source=http://www.pentair.com';
8260            var linkedInUrl = linkedInBase + getEncodedUrl(host) + titleKey + currentPageTitle + liSourceParam;
8261            self.modifiedLinkedInLink(linkedInUrl);
8262        }
8263
8264        function updateShareLinks() {
8265            setQueryString();
8266            createMailToLink();
8267            createTwitterLink();
8268            createFacebookLink();
8269            createLinkedInLink();
8270        }
8271
8272        /** Since the url is dynamic on Download center pages, we need to check the query parameters every time the mouse moves towards the share links. */
8273        $('.share.component')
8274            .on('mouseenter', function() {
8275                updateShareLinks();
8276            });
8277
8278        /** Initialize the links on load */
8279        updateShareLinks();
8280
8281    };
8282
8283    $(document).ready(function() {
8284        $('.share.component').each(function() {
8285            try {
8286                ko.applyBindings(new ShareViewModel($(this)), this);
8287            } catch (koError) {
8288                console.log('Knockout JS error detected on the Share Component ==> ', koError);
8289            }
8290        });
8291    });
8292
8293});
8294$(document).ready(function(){
8295    var $secNav = $('.section-navigation select');
8296    $secNav.change( function(){
8297        var url = $(this).val();
8298            // target = $(this).find(":selected").attr('data-target');
8299
8300        window.location.href = url;
8301
8302    });
8303});
8304$(document).ready(function(){
8305
8306    var initTabCarousel = function(carouselComponent){
8307        var tabCarousel = carouselComponent.find('.tab-search-name.owl-carousel'); // click event & drag event
8308        var contentCarousel = carouselComponent.find('.tab-search-content.owl-carousel'); // drag event
8309        var currentSlide = 0;
8310        var totalSlides = carouselComponent.find('.tab-search-name .item').length;
8311
8312        contentCarousel.owlCarousel({
8313            nav:false,
8314            dots:false,
8315            mouseDrag: false,
8316            autoHeight: true,
8317            items: 1
8318            // center: true,
8319        }).on('initialized.owl.carousel changed.owl.carousel resized.owl.carousel', function(event) {
8320            tabCarousel.trigger('to.owl.carousel', [event.item.index, 300, true]);
8321            tabCarousel.find('.current').removeClass('current');
8322            tabCarousel.find('.owl-item .item').eq(event.item.index).addClass('current');
8323            update();
8324
8325            const nativeEvent = new CustomEvent('changed.owl.carousel', { bubbles: true });
8326            nativeEvent.item = { index: event.item.index };
8327            contentCarousel[0].dispatchEvent(nativeEvent);
8328        });
8329
8330        tabCarousel.owlCarousel({
8331            nav: false,
8332            dots:false,
8333            mouseDrag: false,
8334            dragMove: false,
8335            // center: true,
8336            // onDragged: function(e){console.log('drg', e)},
8337            responsive: {
8338                0: {
8339                    items: Math.min(totalSlides, 3),
8340                    autoWidth:true
8341                },
8342                768: {
8343                    items: Math.min(totalSlides, 10)
8344                }
8345            }
8346        }).on('click', '.owl-item', function(event) {
8347            var targetIndex = $(event.target).parents('.owl-item').index();
8348            if (targetIndex >= 0) {
8349                contentCarousel.trigger('to.owl.carousel', [targetIndex, 300, true]);
8350            }
8351        });
8352
8353        tabCarousel.on('dragged.owl.carousel', function (event) {
8354            var dragDirection = event.relatedTarget['_drag']['direction'];
8355            if(dragDirection === 'left'){
8356                contentCarousel.trigger('next.owl.carousel');
8357            } else if(dragDirection === 'right'){
8358                contentCarousel.trigger('prev.owl.carousel');
8359            }
8360        });
8361
8362        //add titles to tab content areas for print view
8363        tabCarousels.each(function(){
8364            var tabName = $(this);
8365            var tabItem = tabName.find('.item h5');
8366            var tabContent = $(this).find('.tab-search-content');
8367
8368            for (j = 0; j < tabContent.find('.item').length; j++){
8369                tabContent.find('.item:eq('+j+')').attr('data-title',tabItem.eq(j).text());
8370            }
8371        });
8372
8373        var update = function () {
8374            // If there's more items to the right that are hidden, add white overlay.
8375            
8376            var addRightOverlay = (tabCarousel.find('.owl-item.active').first().nextAll('.owl-item').length > 1);
8377
8378            if(addRightOverlay){
8379                tabCarousel.addClass('right-overlay');
8380            } else {
8381                tabCarousel.removeClass('right-overlay');
8382            }
8383        }
8384
8385        update();
8386    };
8387
8388    var tabCarousels = $('.search.component .tabs');
8389
8390    if(tabCarousels.length){
8391        var mode = tabCarousels.first().data('isedit');
8392        if (mode === 'noedit') {
8393            $(function(){
8394                tabCarousels.each(function(index, elem){
8395                    initTabCarousel($(elem));
8396                });
8397            });
8398        }
8399    }
8400
8401});
8402/**
8403 * Escapes HTML special characters for safe insertion of plain-text values into
8404 * raw template literals or innerHTML assignments.
8405 * @param {*} val
8406 * @returns {string}
8407 */
8408function escapeHtml(val) {
8409    return String(val == null ? '' : val)
8410        .replace(/&/g, '&amp;')
8411        .replace(/</g, '&lt;')
8412        .replace(/>/g, '&gt;')
8413        .replace(/"/g, '&quot;');
8414}
8415
8416/**
8417 * Sanitizes an Algolia _highlightResult value for safe innerHTML assignment.
8418 * Escapes all HTML, then restores only the <mark> and <em> wrapper tags that
8419 * Algolia injects around matched query terms.
8420 * @param {string} val - Raw Algolia highlight value
8421 * @returns {string}
8422 */
8423function sanitizeHighlight(val) {
8424    return String(val)
8425        .replace(/&/g, '&amp;')
8426        .replace(/</g, '&lt;')
8427        .replace(/>/g, '&gt;')
8428        .replace(/&lt;(mark|em)&gt;/gi, '<$1>')
8429        .replace(/&lt;\/(mark|em)&gt;/gi, '</$1>');
8430}
8431
8432(function() {
8433'use strict';
8434
8435// Ensure PENTAIR namespace exists on window
8436window.PENTAIR = window.PENTAIR || {};
8437
8438// ========================================
8439// GLOBAL HELPER FUNCTIONS
8440// ========================================
8441
8442/**
8443 * Creates star rating HTML with visual percentage indicator
8444 * @param {number} rating - Rating value (0-5)
8445 * @returns {string} HTML string for star rating display
8446 */
8447const createStarRating = (rating) => {
8448    if (!rating) return '';
8449    const percentage = Math.max(0, Math.min(5, parseFloat(rating))) * 20;
8450    return `<span class="stars"><span style="width: ${percentage}%"></span></span>`;
8451};
8452
8453/**
8454 * Adds responsive pagination widget to Algolia search instance
8455 * @param {object} search - Algolia search instance
8456 * @param {HTMLElement} containerElem - Container element for pagination
8457 * @param {HTMLElement} scrollTarget - Optional scroll target element
8458 */
8459const addResponsivePagination = (search, containerElem, scrollTarget) => {
8460    const isMobile = window.matchMedia('(max-width: 767px)').matches;
8461    search.addWidgets([
8462        instantsearch.widgets.pagination({
8463            container: containerElem.querySelector('.algolia-pagination'),
8464            showFirst: false,
8465            showLast: false,
8466            padding: isMobile ? 1 : 2,
8467            templates: { next: '', previous: '' },
8468            scrollTo: scrollTarget ?? containerElem
8469        })
8470    ]);
8471};
8472
8473/**
8474 * Generates pagination message template showing result range
8475 * @param {object} result - Algolia search result object
8476 * @returns {string} Pagination message (e.g., "Showing 1-10 of 100 results")
8477 */
8478const paginationMessageTemplate = (result) => {
8479    if (result.nbHits <= 1) return '';
8480    const firstItem = result.hitsPerPage * result.page + 1;
8481    const lastItem = Math.min(firstItem + result.hitsPerPage - 1, result.nbHits);
8482    return `Showing ${firstItem}-${lastItem} of ${result.nbHits} results`;
8483};
8484
8485/**
8486 * Selects filter modal element by index name and selector
8487 * @param {string} indexName - Algolia index name
8488 * @param {string} selector - CSS selector within the index filter modal
8489 * @returns {HTMLElement|null} Matching element or null
8490 */
8491const filterModalSelector = (indexName, selector) => 
8492    document.querySelector(`#searchFilterModal [data-index="${indexName}"] ${selector}`);
8493
8494/**
8495 * Shared builder for checkbox+label filter templates.
8496 * @param {string} suffix - Suffix for unique ID generation
8497 * @param {(label: string) => string} labelResolver - Maps item label to display label
8498 * @returns {(item: object, helpers: { html: Function }) => string}
8499 */
8500const buildFilterTemplate = (suffix, labelResolver) => (item, { html }) => {
8501    const resolvedLabel = labelResolver(item.label);
8502    const slugLbl = `${resolvedLabel}_${suffix}`.toLowerCase().replace(/ /g, "_");
8503    return html`<input type="checkbox" checked=${item.isRefined || null} id="${slugLbl}" name="${slugLbl}" /><label for="${slugLbl}"><span>${resolvedLabel}</span><span class="item-count">${item.count}</span><span class="sr-only">Filter</span></label>`;
8504};
8505
8506/**
8507 * Generates HTML template for filter checkbox item
8508 * @param {object} item - Filter item with label, isRefined, and count properties
8509 * @param {string} suffix - Suffix for unique ID generation
8510 * @returns {string} HTML string for filter checkbox
8511 */
8512const filterTemplate = (suffix) => buildFilterTemplate(suffix, (label) => label);
8513
8514/**
8515 * Generates HTML template for filter checkbox with pipe-delimited label
8516 * @param {object} item - Filter item with pipe-delimited label (e.g., "category|name")
8517 * @param {string} suffix - Suffix for unique ID generation
8518 * @returns {string} HTML string for filter checkbox using split label
8519 */
8520const splitLabelTemplate = (suffix) => buildFilterTemplate(suffix, (label) => label.split("|")[1]);
8521
8522// ========================================
8523// PENTAIR.AlgoliaHelpers
8524// ========================================
8525// Helper utilities for Algolia search functionality
8526
8527PENTAIR.AlgoliaHelpers = {
8528    getTarget: (url) => {
8529        const testLink = document.createElement('a');
8530        testLink.href = url;
8531        const openInNewWindow = !((testLink.protocol === window.location.protocol) && (testLink.host === window.location.host));
8532        return openInNewWindow;
8533    },
8534
8535    createStarRating,
8536    addResponsivePagination,
8537    paginationMessageTemplate,
8538    filterModalSelector,
8539    filterTemplate,
8540    splitLabelTemplate
8541};
8542
8543})();
8544
8545// ========================================
8546// ALGOLIA ANALYTICS HELPERS
8547// Shared analytics utilities used across brands (Pentair, IFT, Intranet).
8548// Loaded as part of pentair.commons.component — available as bare globals.
8549// ========================================
8550
8551/**
8552 * Fires an Algolia "convertedObjectIDsAfterSearch" event when the page was
8553 * reached via a Where-To-Buy Algolia click (queryID / objectID / indexName
8554 * present in the URL query string).
8555 */
8556function constructAlgoliaAnalyticsWTBObject() {
8557    const params = new URLSearchParams(window.location.search);
8558    if (params.has('queryID') && params.has('objectID') && params.has('indexName')) {
8559        let userToken = '';
8560        if (typeof _satellite !== 'undefined' && _satellite !== null) {
8561            userToken = _satellite.getVisitorId().getMarketingCloudVisitorID();
8562        }
8563        if (typeof window.aa === 'function') {
8564            window.aa('convertedObjectIDsAfterSearch', {
8565                userToken: userToken,
8566                eventName: 'Where_To_Buy',
8567                index: params.get('indexName'),
8568                queryID: params.get('queryID'),
8569                objectIDs: [params.get('objectID')]
8570            });
8571        }
8572    }
8573}
8574
8575(function() {
8576'use strict';
8577
8578// Ensure PENTAIR namespace exists on window
8579window.PENTAIR = window.PENTAIR || {};
8580
8581// ========================================
8582// PENTAIR.CustomAlgoliaWidgets
8583// ========================================
8584// Custom Algolia widgets for enhanced search functionality
8585
8586// ----------------------------------------
8587// Private helpers shared by hierarchical menu widgets
8588// ----------------------------------------
8589
8590/**
8591 * Attaches click-to-refine handlers to all <a> elements inside container.
8592 * @param {HTMLElement} container
8593 * @param {Function} refine - Algolia refine function
8594 */
8595function _attachRefineHandlers(container, refine) {
8596    container.querySelectorAll('a').forEach(element => {
8597        element.addEventListener('click', event => {
8598            event.preventDefault();
8599            refine(decodeURI(event.target.closest('a').dataset.value));
8600        });
8601    });
8602}
8603
8604/**
8605 * Adds 'arrow' CSS class to all top-level <li> elements in the first <ul>.
8606 * @param {HTMLElement} container
8607 */
8608function _addArrowsToTopLevel(container) {
8609    const firstUl = container.querySelector('ul');
8610    if (firstUl) {
8611        firstUl.querySelectorAll(':scope > li').forEach(li => li.classList.add('arrow'));
8612    }
8613}
8614
8615/**
8616 * Toggles parent element hidden state based on whether items exist.
8617 * @param {HTMLElement} container
8618 * @param {Array} items
8619 */
8620function _toggleParentVisibility(container, items) {
8621    container.parentElement?.classList.remove('hidden');
8622    if (!items.length) {
8623        container.parentElement?.classList.add('hidden');
8624    }
8625}
8626
8627/**
8628 * Checks whether a facet attribute is present in current search results.
8629 * Supports multiple InstantSearch result shapes used across sorted replicas.
8630 * @param {object} search
8631 * @param {string} facetAttribute
8632 * @returns {boolean}
8633 */
8634function _hasFacetInResults(search, facetAttribute) {
8635    const results = search?.results;
8636    if (!results || !facetAttribute) return false;
8637
8638    const disjunctiveFacet = results.disjunctiveFacets?.find(item => item.name === facetAttribute);
8639    if (disjunctiveFacet) return true;
8640
8641    if (results.facets && Object.prototype.hasOwnProperty.call(results.facets, facetAttribute)) {
8642        return true;
8643    }
8644
8645    return false;
8646}
8647
8648PENTAIR.CustomAlgoliaWidgets = {
8649
8650    // ----------------------------------------
8651    // Constants
8652    // ----------------------------------------
8653
8654    /** Delay in ms before clearing screen reader announcements */
8655    ANNOUNCEMENT_CLEAR_DELAY: 1000,
8656
8657    // ----------------------------------------
8658    // Accessibility helpers
8659    // ----------------------------------------
8660
8661    /**
8662     * Creates a visually hidden live region element for screen reader announcements.
8663     * @returns {HTMLElement} A div with role="status" and aria-live="polite"
8664     */
8665    createAnnouncementElement: () => {
8666        const div = document.createElement('div');
8667        div.className = 'sr-only';
8668        div.setAttribute('role', 'status');
8669        div.setAttribute('aria-live', 'polite');
8670        div.setAttribute('aria-atomic', 'true');
8671        return div;
8672    },
8673    
8674    /**
8675     * Sets a message on a live region element, then clears it after ANNOUNCEMENT_CLEAR_DELAY.
8676     * Cancels any in-flight clear timeout before setting the new message.
8677     * @param {HTMLElement} announcementElement - The live region element to update
8678     * @param {string} message - The message to announce
8679     * @param {number|null} currentTimeout - Previous setTimeout ID to cancel, if any
8680     * @returns {number} New setTimeout ID
8681     */
8682    announceAndClear: (announcementElement, message, currentTimeout) => {
8683        announcementElement.textContent = message;
8684        
8685        if (currentTimeout) {
8686            clearTimeout(currentTimeout);
8687        }
8688        return setTimeout(() => {
8689            announcementElement.textContent = '';
8690        }, PENTAIR.CustomAlgoliaWidgets.ANNOUNCEMENT_CLEAR_DELAY);
8691    },
8692    
8693    // ----------------------------------------
8694    // Filter panel factories
8695    // ----------------------------------------
8696
8697    /**
8698     * Creates a collapsible accordion filter panel wrapping a refinementList widget.
8699     * Panel is hidden when the facet has no results.
8700     * Used by: searchWidgets.js, searchGridSearchWidgets.js
8701     * @param {string} accordionTitle - Display title for the accordion header
8702     * @param {string} facetAttribute - Algolia facet attribute name
8703     * @returns {function} InstantSearch panel widget configured with refinementList
8704     */
8705    accordionFilterPanel: (accordionTitle, facetAttribute, alwaysVisible = false) => {
8706        return instantsearch.widgets.panel({
8707            hidden: search => (alwaysVisible ? false : !_hasFacetInResults(search, facetAttribute)),
8708            templates: {
8709                header: `<span data-filter-attribute="${facetAttribute}" data-filter-title="${accordionTitle}">${accordionTitle}</span>`
8710            }
8711        })(instantsearch.widgets.refinementList);
8712    },
8713    
8714    /**
8715     * Creates a collapsible accordion filter panel for use in dynamic widget configurations.
8716     * Collapses by default on mobile. Adds 'algolia-accordion-panel' CSS class to root.
8717     * Used by: product-finder-grid.js, solution-finder-grid.js
8718     * @param {string} accordionTitle - Display title for the accordion header
8719     * @param {string} facetAttribute - Algolia facet attribute name
8720     * @returns {function} InstantSearch panel widget configured with refinementList
8721     */
8722    dynamicAccordionFilterPanel: (accordionTitle, facetAttribute, alwaysVisible = false) => {
8723        return instantsearch.widgets.panel({
8724            hidden: search => (alwaysVisible ? false : !_hasFacetInResults(search, facetAttribute)),
8725            cssClasses: { root: ['algolia-accordion-panel'] },
8726            collapsed: () => window.matchMedia('(max-width: 767px)').matches,
8727            templates: {
8728                header: `<span data-filter-attribute="${facetAttribute}" data-filter-title="${accordionTitle}">${accordionTitle}</span>`,
8729                collapseButton: () => ''
8730            }
8731        })(instantsearch.widgets.refinementList);
8732    },
8733    
8734    /**
8735     * Creates a collapsible accordion filter panel wrapping a ratingMenu widget.
8736     * Panel is hidden when the facet has no results.
8737     * Used by: searchGridSearchWidgets.js
8738     * @param {string} ratingTitle - Display title for the accordion header
8739     * @param {string} facetAttribute - Algolia facet attribute name (expects numeric rating values)
8740     * @returns {function} InstantSearch panel widget configured with ratingMenu
8741     */
8742    ratingFilterPanel: (ratingTitle, facetAttribute) => {
8743        return instantsearch.widgets.panel({
8744            hidden: search => !_hasFacetInResults(search, facetAttribute),
8745            templates: {
8746                header: `<span data-filter-attribute="${facetAttribute}" data-filter-title="${ratingTitle}">${ratingTitle}</span>`
8747            }
8748        })(instantsearch.widgets.ratingMenu);
8749    },
8750    
8751    // ----------------------------------------
8752    // Refinement state widgets
8753    // ----------------------------------------
8754
8755    /**
8756     * Custom connector-based widget that renders a "Filtered by: Clear all" control.
8757     * The parent element is hidden when no refinements are active (or all active refinements
8758     * are in the hidden list). Announces "All search filters cleared" to screen readers on click.
8759     * Used by: searchWidgets.js, searchGridSearchWidgets.js
8760     * @param {string[]} [hiddenAttributes=[]] - Facet attributes to exclude from the has-refinements check
8761     * @returns {object} InstantSearch custom widget (connectClearRefinements)
8762     */
8763    clearRefinements: hiddenAttributes => {
8764        hiddenAttributes = hiddenAttributes || [];  // List of attributes to ignore for rendering. Used for product grid to hide prefilters.
8765        let announcementTimeout = null;
8766
8767        const renderClearRefinements = (renderOptions, isFirstRender) => {
8768            const container = renderOptions.widgetParams.container;
8769            if (!container) return;
8770
8771            if (isFirstRender) {
8772                const label = document.createElement('label');
8773                label.textContent = 'Filtered by:';
8774                
8775                const anchor = document.createElement('a');
8776                anchor.href = '#';
8777                anchor.textContent = 'Clear all';
8778                
8779                const announcement = PENTAIR.CustomAlgoliaWidgets.createAnnouncementElement();
8780                
8781                anchor.addEventListener('click', e => {
8782                    e.preventDefault();
8783                    renderOptions.refine();
8784                    announcementTimeout = PENTAIR.CustomAlgoliaWidgets.announceAndClear(
8785                        announcement,
8786                        'All search filters cleared',
8787                        announcementTimeout
8788                    );
8789                    return false;
8790                });
8791
8792                container.appendChild(label);
8793                container.appendChild(anchor);
8794                container.appendChild(announcement);
8795            }
8796            
8797            const disjunctiveFacetsRefinements = renderOptions.instantSearchInstance.helper?.state.disjunctiveFacetsRefinements;
8798            const hierarchicalFacetsRefinements = renderOptions.instantSearchInstance.helper?.state.hierarchicalFacetsRefinements;
8799            const currentRefinements = {...disjunctiveFacetsRefinements, ...hierarchicalFacetsRefinements};
8800            const hasOnlyHiddenRefinements = (hiddenAttributes.length > 0) && currentRefinements &&
8801                Object.keys(currentRefinements)
8802                    .filter(elem => currentRefinements[elem].length && (hiddenAttributes.indexOf(elem) == -1)).length == 0;
8803
8804            container.parentElement?.classList.remove('hidden');
8805            if (!renderOptions.hasRefinements || hasOnlyHiddenRefinements) {
8806                container.parentElement?.classList.add('hidden');
8807            }
8808        };
8809
8810        return instantsearch.connectors.connectClearRefinements(renderClearRefinements);
8811    },
8812    
8813    /**
8814     * Custom connector-based widget that renders the active refinement tags as a list of
8815     * removable buttons. Handles comma- and pipe-delimited label splitting for multi-value
8816     * facets. Announces removed filter name to screen readers on button click.
8817     * Used by: searchWidgets.js, searchGridSearchWidgets.js
8818     * @param {string[]} [hiddenAttributes=[]] - Facet attributes to exclude from the rendered list
8819     * @param {boolean} [shouldWrapLabel=false] - When true, wraps the label text in a <span>
8820     * @returns {object} InstantSearch custom widget (connectCurrentRefinements)
8821     */
8822    currentRefinements: (hiddenAttributes, shouldWrapLabel) => {
8823        hiddenAttributes = hiddenAttributes || [];  // List of attributes to ignore for rendering. Used for product grid to hide prefilters.
8824        const wrapLabelInSpan = shouldWrapLabel || false;  // Optional parameter to wrap label text in a span
8825        let announcementTimeout = null;
8826
8827        const createDataAttributes = refinement =>
8828            Object.keys(refinement)
8829                .map(key => `data-${key}="${refinement[key]}"`)
8830                .join(' ');
8831
8832        const getSplitLabel = (label, attribute) => {
8833            const splitLabels = ['brands','channel','channels','type','region','applications','categories','industrySolutions','documentType'];
8834            if (splitLabels.indexOf(attribute) != -1) {
8835                return label.split(",")[1] || label.split("|")[1];
8836            } else {
8837                return label;
8838            }
8839        };
8840
8841        const renderListItem = item =>
8842            item.refinements.map(refinement => {
8843                const labelText = getSplitLabel(refinement.label, refinement.attribute);
8844                const wrappedLabel = wrapLabelInSpan ? `<span>${labelText}</span>` : labelText;
8845                return `<li>
8846                    <button aria-label="Remove ${labelText}
8846 search filter" ${createDataAttributes(refinement)}></button>
8847                    ${wrappedLabel}
8848                </li>`;
8849            }).join('');
8850
8851        const renderCurrentRefinements = (renderOptions, isFirstRender) => {
8852            const container = renderOptions.widgetParams.container;
8853            if (!container) return;
8854            
8855            container.innerHTML = renderOptions.items.length ? 
8856                `<ul>${renderOptions.items
8857                    .filter(elem => hiddenAttributes.indexOf(elem.attribute) == -1)
8858                    .map(renderListItem)
8859                    .join('')}</ul>` : '';
8860
8861            // Ensure announcement div exists after innerHTML replacement
8862            let announcementEl = container.querySelector('.sr-only[role="status"]');
8863            if (!announcementEl) {
8864                announcementEl = PENTAIR.CustomAlgoliaWidgets.createAnnouncementElement();
8865                container.appendChild(announcementEl);
8866            }
8867
8868            container.querySelectorAll('button').forEach(element => {
8869                element.addEventListener('click', event => {
8870                    const item = Object.keys(event.currentTarget.dataset).reduce((acc, key) => {
8871                        acc[key] = event.currentTarget.dataset[key];
8872                        return acc;
8873                    }, {});
8874                    
8875                    const filterLabel = getSplitLabel(event.currentTarget.dataset.label, event.currentTarget.dataset.attribute);
8876                    const announcement = container.querySelector('.sr-only[role="status"]');
8877                    
8878                    if (announcement) {
8879                        announcementTimeout = PENTAIR.CustomAlgoliaWidgets.announceAndClear(
8880                            announcement,
8881                            `${filterLabel} search filter removed`,
8882                            announcementTimeout
8883                        );
8884                    }
8885                    
8886                    renderOptions.refine(item);
8887                });
8888            });
8889        };
8890
8891        return instantsearch.connectors.connectCurrentRefinements(renderCurrentRefinements);
8892    },
8893    
8894    // ----------------------------------------
8895    // Category navigation widgets
8896    // ----------------------------------------
8897
8898    /**
8899     * Custom connector-based hierarchical category menu with show more/less toggle.
8900     * Renders nested <ul> lists; top-level items receive the 'arrow' CSS class.
8901     * Parent element is hidden when there are no items.
8902     * Used by: searchWidgets.js
8903     * @returns {object} InstantSearch custom widget (connectHierarchicalMenu)
8904     */
8905    hierarchicalMenu: () => {
8906        const renderList = renderOptions =>
8907            `<ul>${renderOptions.items.map(item =>
8908                `<li ${item.isRefined ? 'class="refined"' : ''}>
8909                    <a href="${renderOptions.createURL(item.value)}"
8910                       data-value="${encodeURI(item.value)}"
8911                       style="font-weight: ${item.isRefined ? 'bold' : ''}">
8912                        ${escapeHtml(item.label)} <span class="count">${item.count}</span>
8913                    </a>
8914                    ${item.data ? renderList({ items: item.data, createURL: renderOptions.createURL }) : ''}
8915                </li>`
8916            ).join('')}</ul>`;
8917
8918        const renderHierarchicalMenu = (renderOptions, isFirstRender) => {
8919            const {items, isShowingMore, toggleShowMore, createURL} = renderOptions;
8920            const container = renderOptions.widgetParams.container;
8921            let contentContainer = container.querySelector(':scope > div');
8922            let showMoreButton = container.querySelector(':scope > button');
8923
8924            if (isFirstRender) {
8925                if (!container.querySelector(':scope > label')) {
8926                    const label = document.createElement('label');
8927                    label.textContent = 'Categories';
8928                    container.appendChild(label);
8929                }
8930                if (!contentContainer) {
8931                    contentContainer = document.createElement('div');
8932                    container.appendChild(contentContainer);
8933                }
8934                if (!showMoreButton) {
8935                    showMoreButton = document.createElement('button');
8936                    showMoreButton.addEventListener('click', () => toggleShowMore());
8937                    container.appendChild(showMoreButton);
8938                }
8939            }
8940
8941            const children = renderList({ items, createURL });
8942            if (!contentContainer) {
8943                contentContainer = container.querySelector(':scope > div') || document.createElement('div');
8944                if (!contentContainer.parentElement) container.appendChild(contentContainer);
8945            }
8946            contentContainer.innerHTML = children;
8947
8948            if (!showMoreButton) {
8949                showMoreButton = container.querySelector(':scope > button');
8950            }
8951            if (items && (items.length < renderOptions.widgetParams.limit)) {
8952                showMoreButton.className = 'hidden';
8953            } else {
8954                showMoreButton.className = 'ais-RefinementList-showMore';
8955            }
8956
8957            showMoreButton.textContent = isShowingMore ? 'Show less' : 'Show more';
8958
8959            _attachRefineHandlers(container, renderOptions.refine);
8960            _addArrowsToTopLevel(container);
8961            _toggleParentVisibility(container, items);
8962        };
8963
8964        return instantsearch.connectors.connectHierarchicalMenu(renderHierarchicalMenu);
8965    },
8966    
8967    /**
8968     * Custom connector-based hierarchical category menu with inline show more/less toggle.
8969     * Shows 5 items by default; extra items are hidden via CSS until toggled.
8970     * Supports cssClasses.root on widgetParams to add classes to the container.
8971     * Used by: searchGridSearchWidgets.js
8972     * @returns {object} InstantSearch custom widget (connectHierarchicalMenu)
8973     */
8974    dynamicHierarchicalMenu: () => {
8975        const renderList = renderOptions =>
8976            `<div class="ais-Refinements ais-Refinements--showLess">
8977                <ul>${renderOptions.items.map((item, index) => {
8978                    const isExtraRefinement = index >= renderOptions.limit;
8979                    return `<li class="${item.isRefined ? 'refined ' : ''}${isExtraRefinement ? 'ais-Refinement-extra' : ''}">
8980                        <a href="${renderOptions.createURL(item.value)}"
8981                           data-value="${encodeURI(item.value)}"
8982                           style="font-weight: ${item.isRefined ? 'bold' : ''}">
8983                            ${escapeHtml(item.label)} <span class="count">${item.count}</span>
8984                        </a>
8985                        ${item.data ? renderList({ items: item.data, createURL: renderOptions.createURL, limit: renderOptions.limit }) : ''}
8986                    </li>`;
8987                }).join('')}</ul>
8988                ${renderOptions.items.length > renderOptions.limit ?
8989                    '<button class="ais-RefinementList-showMore ais-Refinement-toggle">Show More</button>' : ''}
8990            </div>`;
8991
8992        const renderHierarchicalMenu = (renderOptions, isFirstRender) => {
8993            const {items, createURL} = renderOptions;
8994            const container = renderOptions.widgetParams.container;
8995            let contentContainer = container.querySelector(':scope > div');
8996
8997            if (isFirstRender) {
8998                if (!container.querySelector(':scope > label')) {
8999                    const label = document.createElement('label');
9000                    label.textContent = 'Categories';
9001                    container.appendChild(label);
9002                }
9003                if (!contentContainer) {
9004                    contentContainer = document.createElement('div');
9005                    container.appendChild(contentContainer);
9006                }
9007
9008                const cssClasses = renderOptions.widgetParams.cssClasses;
9009                if (cssClasses?.root) {
9010                    container.classList.add(...(Array.isArray(cssClasses.root) ? cssClasse
9010s.root : [cssClasses.root]));
9011                }
9012            }
9013
9014            // The limit is the number of items to display when showing less
9015            const children = renderList({ items, createURL, limit: 5 });
9016            if (!contentContainer) {
9017                contentContainer = container.querySelector(':scope > div') || document.createElement('div');
9018                if (!contentContainer.parentElement) container.appendChild(contentContainer);
9019            }
9020            contentContainer.innerHTML = children;
9021
9022            _attachRefineHandlers(container, renderOptions.refine);
9023            _addArrowsToTopLevel(container);
9024            _toggleParentVisibility(container, items);
9025
9026            container.querySelectorAll('.ais-Refinement-toggle').forEach(element => {
9027                element.addEventListener('click', () => {
9028                    element.closest('.ais-Refinements').classList.toggle('ais-Refinements--showLess');
9029                    element.textContent = element.textContent === 'Show More' ? 'Show Less' : 'Show More';
9030                });
9031            });
9032        };
9033
9034        return instantsearch.connectors.connectHierarchicalMenu(renderHierarchicalMenu);
9035    },
9036    
9037    // ----------------------------------------
9038    // Virtual (UI-less) widgets
9039    // ----------------------------------------
9040
9041    /**
9042     * A no-op search box widget required by InstantSearch when the visible search input
9043     * is managed externally (e.g. by a separate search bar component on the same page).
9044     * Used by: searchWidgets.js, search-bar.js
9045     * @returns {object} InstantSearch virtual searchBox widget
9046     */
9047    virtualSearchBox: () => instantsearch.connectors.connectSearchBox(() => null)(),
9048
9049    /**
9050     * A no-op refinement list widget that syncs a facet attribute's state across
9051     * multiple InstantSearch instances without rendering any UI.
9052     * Used by: searchGridSearchWidgets.js
9053     * @param {{attribute: string}} options - Standard refinementList widget options
9054     * @returns {object} InstantSearch virtual refinementList widget
9055     */
9056    virtualRefinementList: options => instantsearch.connectors.connectRefinementList(() => null)(options)
9057};
9058
9059})();
9060
9061(function() {
9062'use strict';
9063
9064window.PENTAIR = window.PENTAIR || {};
9065
9066// ========================================
9067// SHARED HELPERS
9068// ========================================
9069
9070/**
9071 * Factory for "All" tab search widgets. Every content type shares the same structure:
9072 * an index widget wrapping stats (hitsPerPage: 4), configure, and hits sub-widgets.
9073 * @param {Object}   opts
9074 * @param {Function} opts.buildItem  - (hit, { html, components, sendEvent }, indexName) => html
9075 * @param {string}   opts.emptyText  - Empty state prefix text
9076 * @returns {Function} (search, indexName, containerElem) => void
9077 */
9078function makeAllTabWidget({ buildItem, emptyText }) {
9079    return (search, indexName, containerElem) => {
9080        const widgets = [
9081            instantsearch.widgets.stats({
9082                container: containerElem.parentElement.querySelector('.results-count'),
9083                templates: {
9084                    text: ({ nbHits }) => nbHits === 1 ? '1 result' : nbHits + ' results'
9085                }
9086            }),
9087            instantsearch.widgets.configure({
9088                hitsPerPage: 4
9089            }),
9090            instantsearch.widgets.hits({
9091                container: containerElem.querySelector('.results'),
9092                templates: {
9093                    item: (hit, ctx) => buildItem(hit, ctx, indexName),
9094                    empty: ({ query }) => emptyText + (query ? ' for "' + query + '"' : '')
9095                }
9096            })
9097        ];
9098
9099        const isRootIndex = indexName === search.indexName;
9100        if (isRootIndex) {
9101            search.addWidgets(widgets);
9102        } else {
9103            search.addWidgets([
9104                instantsearch.widgets.index({ indexName }).addWidgets(widgets)
9105            ]);
9106        }
9107    };
9108}
9109
9110/**
9111 * Standard three-option sort items (Relevance / A-Z / Z-A).
9112 * @param {string} indexName - Base Algolia index name
9113 * @returns {Array}
9114 */
9115function defaultSortItems(indexName) {
9116    return [
9117        { value: indexName, label: 'Sort by Relevance' },
9118        { value: `${indexName}_sort_alpha_asc`, label: 'A-Z' },
9119        { value: `${indexName}_sort_alpha_dsc`, label: 'Z-A' }
9120    ];
9121}
9122
9123/**
9124 * Standard two-option hitsPerPage items.
9125 * @param {string} label - Content type label, e.g. 'products' → '12 products/page'
9126 * @returns {Array}
9127 */
9128function hppItems(label) {
9129    return [
9130        { label: `12 ${label}/page`, value: 12, default: true },
9131        { label: `24 ${label}/page`, value: 24 }
9132    ];
9133}
9134
9135// ========================================
9136// PENTAIR.AlgoliaAllTabSearchWidgets
9137// ========================================
9138// Hit templates and widget configuration for the "All" search tab.
9139// Each method adds an Algolia index widget with stats (hitsPerPage: 4), configure, and hits.
9140// Signature: (search, indexName, containerElem)
9141// Used by: search.js
9142
9143const allTabPages = makeAllTabWidget({
9144    buildItem: (hit, { html, components, sendEvent }) => {
9145        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.url);
9146        const breadcrumb = hit.breadcrumb?.trim() || '';
9147        const hitContent = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', hit, highlightedTagName: 'mark' })}</div>` : '';
9148        return html`${html([breadcrumb])}
9149            <a onclick="${(e) => { searchResultClickAnalytic(e, hit.title, 1); sendEvent('click', hit, 'Search Results: All Tab Page Click'); }}" href="${hit.url}" target="${isExternal ? '_blank' : '_self'}" data-query-ID="${hit.__queryID}">
9150                <div class="title-text">${components.Highlight({ attribute: 'title', hit, highlightedTagName: 'mark' })}</div>
9151                ${hitContent}
9152            </a>`;
9153    },
9154    emptyText: 'No page results'
9155});
9156
9157const allTabProducts = makeAllTabWidget({
9158    buildItem: (hit, { html, components, sendEvent }, indexName) => {
9159        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.url);
9160        const productName = hit.productName || hit.title;
9161        const productRating = hit.productRating ? html`<span class="rating">${hit.productRating}</span>` : '';
9162        const starsHtml = PENTAIR.AlgoliaHelpers.createStarRating(hit.productRating);
9163        const ratingHtml = (productRating && starsHtml) ? html`<div class="ratings-container">${html([starsHtml])}${productRating}</div>` : '';
9164        const thumbnail = hit.productThumbnail
9165            ? html`<img loading="lazy" src="${hit.productThumbnail}.thumb.319.319.png" alt="Product Image"/>`
9166            : html`<img loading="lazy" src="/content/dam/extranet/product-related/product-photo/Placeholder Image.png.thumb.319.319.png" alt="Product Image"/>`;
9167        const discontinued = hit.discontinueBanner === 'true' ? html`<div class="ribbon ribbon-top-left"><span>Discontinued</span></div>` : '';
9168        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, productName, 1); sendEvent('click', hit, 'Search Results: All Tab Product Click'); }}"
9169            href="${hit.url}?queryID=${hit.__queryID}&objectID=${hit.objectID}&indexName=${indexName}"
9170            aria-label="Link to ${productName}"
9171            target="${isExternal ? '_blank' : '_self'}"
9172            data-query-ID="${hit.__queryID}">
9173            <div class="top-image contain">${thumbnail}</div>
9174            <div class="title title-text">${components.Snippet({ attribute: 'productName', highlightedTagName: 'mark', hit }) || components.Snippet({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
9175            ${ratingHtml}
9176            ${discontinued}
9177        </a>`;
9178    },
9179    emptyText: 'No product results'
9180});
9181
9182const allTabNews = makeAllTabWidget({
9183    buildItem: (hit, { html, components, sendEvent }) => {
9184        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.pagePath);
9185        const content = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', highlightedTagName: 'mark', hit })}</div>` : '';
9186        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.title, 1); sendEvent('click', hit, 'Search Results: All Tab News Click'); }}"
9187            href="${hit.pagePath}.html"
9188            target="${isExternal ? '_blank' : '_self'}"
9189            data-query-ID="${hit.__queryID}">
9190            <div class="content-padding">
9191                <div class="info">
9192                    <div class="date">${hit.displayDate}</div>
9193                </div>
9194                <div class="title title-text">${components.Highlight({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
9195                ${content}
9196            </div>
9197        </a>`;
9198    },
9199    emptyText: 'No news results'
9200});
9201
9202const allTabEvents = makeAllTabWidget({
9203    buildItem: (hit, { html, components, sendEvent }) => {
9204        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.eventPagePath);
9205        const eventDescription = hit.eventDescription ? html`<div class="content">${components.Snippet({ attribute: 'eventDescription', highlightedTagName: 'mark', hit })}</div>` : '';
9206        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.eventTitle, 1); sendEvent('click', hit, 'Search Results: All Tab Event Click'); }}"
9207            href="${hit.eventPagePath}"
9208            target="${isExternal ? '_blank' : '_self'}"
9209            data-query-ID="${hit.__queryID}">
9210            <div class="content-padding">
9211                <div class="top">
9212                    <div class="event-date title-text">${hit.prettyDateRange}</div>
9213                    <div class="info">
9214                        <div>${hit.eventLocation}</div>
9215                    </div>
9216                </div>
9217                <div class="bottom">
9218                    <div class="title title-text">${components.Highlight({ attribute: 'eventTitle', highlightedTagName: 'mark', hit })}</div>
9219                    ${eventDescription}
9220                </div>
9221            </div>
9222        </a>`;
9223    },
9224    emptyText: 'No events results'
9225});
9226
9227const allTabBlog = makeAllTabWidget({
9228    buildItem: (hit, { html, components, sendEvent }) => {
9229        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.bnePagePath);
9230        const bneImage = hit.bneImgPath ? html`<div class="top-image cover"><img loading="lazy" src="${hit.bneImgPath}.thumb.319.319.png" alt="Article Image"/></div>` : '';
9231        const blogName = hit.blogName ? html`<div>${hit.blogName}</div>` : '';
9232        const content = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', highlightedTagName: 'mark', hit })}</div>` : '';
9233        const bneAuthorImage = hit.bneAuthorImage ? html`<div class="author-img-wrapper"><img loading="lazy" class="author-img" src="${hit.bneAuthorImage}.thumb.48.48.png" alt="Image of Author"/></div>` : '';
9234        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.bneTitle, 1); sendEvent('click', hit, 'Search Results: All Tab Blog Click'); }}"
9235            href="${hit.bnePagePath}"
9236            target="${isExternal ? '_blank' : '_self'}"
9237            data-query-ID="${hit.__queryID}">
9238            ${bneImage}
9239            <div class="content-padding">
9240                <div class="info">
9241                    ${blogName}
9242                    <div class="date">${hit.bneDate}</div>
9243                </div>
9244                <div class="title title-text">${components.Highlight({ attribute: 'bneTitle', highlightedTagName: 'mark', hit })}</div>
9245                ${content}
9246                <div class="flex-row left">
9247                    ${bneAuthorImage}
9248                    <div class="author-name">${hit.bneAuthorNm}</div>
9249                </div>
9250            </div>
9251        </a>`;
9252    },
9253    emptyText: 'No blog results'
9254});
9255
9256const allTabResources = makeAllTabWidget({
9257    buildItem: (hit, { html, components, sendEvent }) => {
9258        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.title, 1); sendEvent('click', hit, 'Search Results: All Tab Resource Click'); }}"
9259            href="${hit.path}#page=${hit.page + 1}"
9260            data-query-ID="${hit.__queryID}">
9261            <div class="content-padding">
9262                <div class="title title-text">${components.Highlight({ attribute: 'title', hit, highlightedTagName: 'mark' })}</div>
9263                <div class="content">${components.Snippet({ attribute: 'content', hit, highlightedTagName: 'mark' })}</div>
9264            </div>
9265        </a>`;
9266    },
9267    emptyText: 'No resource results'
9268});
9269
9270PENTAIR.AlgoliaAllTabSearchWidgets = {
9271    pentair_pages:     allTabPages,
9272    mypentair_pages:   allTabPages,     // identical to pentair_pages
9273    pentair_products:  allTabProducts,
9274    pentair_news:      allTabNews,
9275    mypentair_news:    allTabNews,      // identical to pentair_news
9276    pentair_events:    allTabEvents,
9277    pentair_blog:      allTabBlog,
9278    pentair_resources: allTabResources
9279};
9280
9281// ========================================
9282// PENTAIR.AlgoliaTabSearchWidgets
9283// ========================================
9284// Defines the full widget set for individual content-type search tabs.
9285// Each method wires up pagination, sorting, hits-per-page, filter panels, and hit templates.
9286// Signature: (search, indexName, containerElem)
9287// Used by: search.js
9288
9289PENTAIR.AlgoliaTabSearchWidgets = {
9290
9291    /**
9292     * Configures the pages tab — hit templates with title/content snippet, hitsPerPage
9293     * selector, sort widget, depth dynamic filter, and responsive pagination.
9294     * @param {object} search - InstantSearch instance
9295     * @param {string}
9295 indexName - Algolia index name
9296     * @param {HTMLElement} containerElem - Container element for this tab
9297     */
9298    pentair_pages: (search, indexName, containerElem) => {
9299        const pagesDynamicWidgets = [
9300            container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Depth', 'depth')({
9301                container,
9302                attribute: 'depth'
9303            })
9304        ];
9305
9306        search.addWidgets([
9307            instantsearch.widgets.hitsPerPage({
9308                attribute: 'hpp',
9309                container: containerElem.querySelector('.hits-per-page'),
9310                items: hppItems('results')
9311            }),
9312            instantsearch.widgets.sortBy({
9313                container: containerElem.querySelector('.sorting'),
9314                items: defaultSortItems(indexName)
9315            }),
9316            instantsearch.widgets.stats({
9317                container: containerElem.querySelector('.results-count'),
9318                templates: {
9319                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No page results' + q : nbHits === 1 ? '1 page result' + q : nbHits + ' page results' + q; }
9320                }
9321            }),
9322            instantsearch.widgets.stats({
9323                container: containerElem.querySelector('.pagination-message'),
9324                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
9325            }),
9326            instantsearch.widgets.hits({
9327                container: containerElem.querySelector('.results'),
9328                templates: {
9329                    item: (hit, { html, components, sendEvent }) => {
9330                        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.url);
9331                        const breadcrumb = hit.breadcrumb?.trim() || '';
9332                        const hitContent = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', hit, highlightedTagName: 'mark' })}</div>` : '';
9333                        return html`${html([breadcrumb])}
9334                            <a onclick="${(e) => { searchResultClickAnalytic(e, hit.title, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: Page Tab Page Click'); }}"
9335                                href="${hit.url}"
9336                                target="${isExternal ? '_blank' : '_self'}"
9337                                data-query-ID="${hit.__queryID}">
9338                                <div class="title-text">${components.Highlight({ attribute: 'title', hit, highlightedTagName: 'mark' })}</div>
9339                                ${hitContent}
9340                            </a>`;
9341                    },
9342                    empty: ''
9343                }
9344            }),
9345            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
9346        ]);
9347
9348        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem);
9349
9350        search.addWidgets([
9351            instantsearch.widgets.hitsPerPage({
9352                attribute: 'hpp',
9353                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
9354                items: hppItems('results')
9355            }),
9356            instantsearch.widgets.sortBy({
9357                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.sorting'),
9358                items: defaultSortItems(indexName)
9359            })
9360        ]);
9361
9362        search.addWidgets([
9363            instantsearch.widgets.dynamicWidgets({
9364                container: containerElem.querySelector('.dynamic-widgets-for-pages-filters'),
9365                widgets: pagesDynamicWidgets
9366            })
9367        ]);
9368    },
9369
9370    /**
9371     * Configures the products tab — hit templates with thumbnail/star rating/discontinued ribbon,
9372     * dynamic filter panels, hitsPerPage, sort, and responsive pagination.
9373     * @param {object} search - InstantSearch instance
9374     * @param {string} indexName - Algolia index name
9375     * @param {HTMLElement} containerElem - Container element for this tab
9376     */
9377    pentair_products: (search, indexName, containerElem) => {
9378        const normalizeRefinementLabel = (label) => {
9379            if (!label) return '';
9380            const commaParts = label.split(',');
9381            if (commaParts[1]) return commaParts[1].trim();
9382            const pipeParts = label.split('|');
9383            if (pipeParts[1]) return pipeParts[1].trim();
9384            return label;
9385        };
9386
9387        const productDynamicWidgetsConfig = {
9388            transformItems: items => {
9389                const required = ['channel', 'brands'];
9390                const attributes = Array.isArray(items) ? [...items] : [];
9391                const hasAttribute = attr => attributes.some(item => {
9392                    const attribute = typeof item === 'string' ? item : item?.attribute;
9393                    return attribute === attr;
9394                });
9395                required.forEach(attr => {
9396                    if (!hasAttribute(attr)) {
9397                        attributes.push(attr);
9398                    }
9399                });
9400                return attributes;
9401            },
9402            widgets: [
9403                container => PENTAIR.CustomAlgoliaWidgets.dynamicHierarchicalMenu()({
9404                    container,
9405                    limit: 20,
9406                    cssClasses: { root: 'categories' },
9407                    sortBy: ['count:desc'],
9408                    attributes: ['categories.lvl0', 'categories.lvl1']
9409                }),
9410                container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Product Type', 'channel', true)({
9411                    container,
9412                    attribute: 'channel',
9413                    transformItems: items => items.map(item => ({
9414                        ...item,
9415                        label: normalizeRefinementLabel(item.label),
9416                        highlighted: normalizeRefinementLabel(item.highlighted || item.label)
9417                    }))
9418                }),
9419                container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Brands', 'brands', true)({
9420                    container,
9421                    attribute: 'brands',
9422                    showMore: true,
9423                    showMoreLimit: 100,
9424                    transformItems: items => items.map(item => ({
9425                        ...item,
9426                        label: normalizeRefinementLabel(item.label),
9427                        highlighted: normalizeRefinementLabel(item.highlighted || item.label)
9428                    })),
9429                    templates: {
9430                        showMoreText: ({ isShowingMore }) => isShowingMore ? 'Show less' : 'Show more'
9431                    }
9432                })
9433            ]
9434        };
9435
9436        search.addWidgets([
9437            instantsearch.widgets.configure({
9438                facets: ['*'],
9439                maxValuesPerFacet: 100
9440            }),
9441            PENTAIR.CustomAlgoliaWidgets.clearRefinements()({
9442                container: containerElem.querySelector('.filters .clear-refinements')
9443            }),
9444            PENTAIR.CustomAlgoliaWidgets.currentRefinements()({
9445                container: containerElem.querySelector('.filters .current-refinements')
9446            }),
9447            instantsearch.widgets.hitsPerPage({
9448                attribute: 'hpp',
9449                container: containerElem.querySelector('.hits-per-page'),
9450                items: hppItems('products')
9451            }),
9452            instantsearch.widgets.sortBy({
9453                container: containerElem.querySelector('.sorting'),
9454                items: defaultSortItems(indexName)
9455            }),
9456            instantsearch.widgets.stats({
9457                container: containerElem.querySelector('.results-count'),
9458                templates: {
9459                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No product results' + q : nbHits === 1 ? '1 product result' + q : nbHits + ' product results' + q; }
9460                }
9461            }),
9462            instantsearch.widgets.stats({
9463                container: containerElem.querySelector('.pagination-message'),
9464                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
9465            }),
9466            instantsearch.widgets.hits({
9467                container: containerElem.querySelector('.results'),
9468                templates: {
9469                    item: (hit, { html, components, sendEvent }) => {
9470                        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.url);
9471                        const productName = hit.productName || hit.title;
9472                        const productRating = hit.productRating ? html`<span class="rating">${hit.productRating}</span>` : '';
9473                        const starsHtml = PENTAIR.AlgoliaHelpers.createStarRating(hit.productRating);
9474                        const ratingHtml = (productRating && starsHtml) ? html`<div class="ratings-container">${html([starsHtml])}${productRating}</div>` : '';
9475                        const thumbnail = hit.productThumbnail
9476                            ? html`<img loading="lazy" src="${hit.productThumbnail}.thumb.319.319.png" alt="Product Image"/>`
9477                            : html`<img loading="lazy" src="/content/dam/extranet/product-related/product-photo/Placeholder Image.png.thumb.319.319.png" alt="Product Image"/>`;
9478                        const discontinued = hit.discontinueBanner === 'true' ? html`<div class="ribbon ribbon-top-left"><span>Discontinued</span></div>` : '';
9479                        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, productName, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: Product Tab Product Click'); }}"
9480                            href="${hit.url}?queryID=${hit.__queryID}&objectID=${hit.objectID}&indexName=${indexName}"
9481                            aria-label="Link to ${productName}"
9482                            target="${isExternal ? '_blank' : '_self'}"
9483                            data-query-ID="${hit.__queryID}">
9484                            <div class="top-image contain">${thumbnail}</div>
9485                            <div class="title title-text">${components.Snippet({ attribute: 'productName', highlightedTagName: 'mark', hit }) || components.Snippet({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
9486                            ${ratingHtml}
9487                            ${discontinued}
9488                        </a>`;
9489                    },
9490                    empty: ''
9491                }
9492            }),
9493            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
9494        ]);
9495
9496        search.addWidgets([
9497            instantsearch.widgets.dynamicWidgets({
9498                container: containerElem.querySelector('.dynamic-widgets'),
9499                transformItems: productDynamicWidgetsConfig.transformItems,
9500                widgets: productDynamicWidgetsConfig.widgets
9501            })
9502        ]);
9503
9504        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem);
9505
9506        search.addWidgets([
9507            instantsearch.widgets.hitsPerPage({
9508                attribute: 'hpp',
9509                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
9510                items: hppItems('products')
9511            }),
9512            instantsearch.widgets.sortBy({
9513                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.sorting'),
9514                items: defaultSortItems(indexName)
9515            })
9516        ]);
9517    },
9518
9519    /**
9520     * Configures the news tab — hit templates, author/date/type filter panels,
9521     * hierarchical category menu, hitsPerPage, sort, and responsive pagination.
9522     * @param {object} search - InstantSearch instance
9523     * @param {string}
9523 indexName - Algolia index name
9524     * @param {HTMLElement} containerElem - Container element for this tab
9525     */
9526    pentair_news: (search, indexName, containerElem) => {
9527        search.addWidgets([
9528            PENTAIR.CustomAlgoliaWidgets.clearRefinements()({
9529                container: containerElem.querySelector('.filters .clear-refinements')
9530            }),
9531            PENTAIR.CustomAlgoliaWidgets.currentRefinements()({
9532                container: containerElem.querySelector('.filters .current-refinements')
9533            }),
9534            PENTAIR.CustomAlgoliaWidgets.hierarchicalMenu()({
9535                container: containerElem.querySelector('.filters .categories'),
9536                limit: 5,
9537                sortBy: ['count:desc'],
9538                attributes: ['categoryTitles']
9539            }),
9540            instantsearch.widgets.hitsPerPage({
9541                attribute: 'hpp',
9542                container: containerElem.querySelector('.hits-per-page'),
9543                items: hppItems('news articles')
9544            }),
9545            instantsearch.widgets.sortBy({
9546                container: containerElem.querySelector('.sorting'),
9547                items: defaultSortItems(indexName)
9548            }),
9549            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Author', 'authorName')({
9550                container: containerElem.querySelector('.filters .authors'),
9551                attribute: 'authorName',
9552                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('news') }
9553            }),
9554            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'dateFilter')({
9555                container: containerElem.querySelector('.filters .date'),
9556                attribute: 'dateFilter',
9557                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('news') }
9558            }),
9559            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('News Type', 'type')({
9560                container: containerElem.querySelector('.filters .type'),
9561                attribute: 'type',
9562                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('news_type') }
9563            }),
9564            instantsearch.widgets.stats({
9565                container: containerElem.querySelector('.results-count'),
9566                templates: {
9567                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No news results' + q : nbHits === 1 ? '1 news result' + q : nbHits + ' news results' + q; }
9568                }
9569            }),
9570            instantsearch.widgets.stats({
9571                container: containerElem.querySelector('.pagination-message'),
9572                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
9573            }),
9574            instantsearch.widgets.hits({
9575                container: containerElem.querySelector('.results'),
9576                templates: {
9577                    item: (hit, { html, components, sendEvent }) => {
9578                        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.pagePath);
9579                        const content = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', highlightedTagName: 'mark', hit })}</div>` : '';
9580                        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.title, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: News Tab Article Click'); }}"
9581                            href="${hit.pagePath}.html"
9582                            target="${isExternal ? '_blank' : '_self'}"
9583                            data-query-ID="${hit.__queryID}">
9584                            <div class="content-padding">
9585                                <div class="info">
9586                                    <div class="date">${hit.displayDate}</div>
9587                                </div>
9588                                <div class="title title-text">${components.Highlight({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
9589                                ${content}
9590                            </div>
9591                        </a>`;
9592                    },
9593                    empty: ''
9594                }
9595            }),
9596            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
9597        ]);
9598
9599        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem);
9600
9601        search.addWidgets([
9602            PENTAIR.CustomAlgoliaWidgets.hierarchicalMenu()({
9603                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .categories'),
9604                limit: 5,
9605                sortBy: ['count:desc'],
9606                attributes: ['categoryTitles']
9607            }),
9608            instantsearch.widgets.hitsPerPage({
9609                attribute: 'hpp',
9610                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
9611                items: hppItems('news articles')
9612            }),
9613            instantsearch.widgets.sortBy({
9614                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.sorting'),
9615                items: defaultSortItems(indexName)
9616            }),
9617            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Author', 'authorName')({
9618                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .authors'),
9619                attribute: 'authorName',
9620                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('news_modal') }
9621            }),
9622            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'dateFilter')({
9623                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .date'),
9624                attribute: 'dateFilter',
9625                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('news_modal') }
9626            }),
9627            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('News Type', 'type')({
9628                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .type'),
9629                attribute: 'type',
9630                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('news_type_modal') }
9631            })
9632        ]);
9633    },
9634
9635    /**
9636     * Configures the events tab — hit templates, date/region/brand/event-type filter panels,
9637     * hierarchical category menu, hitsPerPage, sort, and responsive pagination.
9638     * @param {object} search - InstantSearch instance
9639     * @param {string}
9639 indexName - Algolia index name
9640     * @param {HTMLElement} containerElem - Container element for this tab
9641     */
9642    pentair_events: (search, indexName, containerElem) => {
9643        search.addWidgets([
9644            instantsearch.widgets.hitsPerPage({
9645                attribute: 'hpp',
9646                container: containerElem.querySelector('.hits-per-page'),
9647                items: hppItems('events')
9648            }),
9649            instantsearch.widgets.sortBy({
9650                container: containerElem.querySelector('.sorting'),
9651                items: defaultSortItems(indexName)
9652            }),
9653            PENTAIR.CustomAlgoliaWidgets.clearRefinements()({
9654                container: containerElem.querySelector('.filters .clear-refinements')
9655            }),
9656            PENTAIR.CustomAlgoliaWidgets.currentRefinements()({
9657                container: containerElem.querySelector('.filters .current-refinements')
9658            }),
9659            PENTAIR.CustomAlgoliaWidgets.hierarchicalMenu()({
9660                container: containerElem.querySelector('.filters .categories'),
9661                limit: 5,
9662                sortBy: ['count:desc'],
9663                attributes: ['eventCategories']
9664            }),
9665            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'bneDateFacet')({
9666                container: containerElem.querySelector('.filters .date'),
9667                attribute: 'bneDateFacet',
9668                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_event') }
9669            }),
9670            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Region', 'region')({
9671                container: containerElem.querySelector('.filters .region'),
9672                attribute: 'region',
9673                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('_event') }
9674            }),
9675            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Brands', 'brands')({
9676                container: containerElem.querySelector('.filters .brands'),
9677                attribute: 'brands',
9678                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('_event') }
9679            }),
9680            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Event Type', 'type')({
9681                container: containerElem.querySelector('.filters .event-type'),
9682                attribute: 'type',
9683                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('_event_type') }
9684            }),
9685            instantsearch.widgets.stats({
9686                container: containerElem.querySelector('.results-count'),
9687                templates: {
9688                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No events results' + q : nbHits === 1 ? '1 events result' + q : nbHits + ' events results' + q; }
9689                }
9690            }),
9691            instantsearch.widgets.stats({
9692                container: containerElem.querySelector('.pagination-message'),
9693                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
9694            }),
9695            instantsearch.widgets.hits({
9696                container: containerElem.querySelector('.results'),
9697                templates: {
9698                    item: (hit, { html, components, sendEvent }) => {
9699                        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.eventPagePath);
9700                        const content = hit.eventDescription ? html`<div class="content">${components.Snippet({ attribute: 'eventDescription', hit, highlightedTagName: 'mark' })}</div>` : '';
9701                        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.eventTitle, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: Event Tab Event Click'); }}"
9702                            href="${hit.eventPagePath}"
9703                            target="${isExternal ? '_blank' : '_self'}"
9704                            data-query-ID="${hit.__queryID}">
9705                            <div class="content-padding">
9706                                <div class="top">
9707                                    <div class="event-date title-text">${hit.prettyDateRange}</div>
9708                                    <div class="info">
9709                                        <div>${hit.eventLocation}</div>
9710                                    </div>
9711                                </div>
9712                                <div class="bottom">
9713                                    <div class="title title-text">${components.Highlight({ attribute: 'eventTitle', hit, highlightedTagName: 'mark' })}</div>
9714                                    ${content}
9715                                </div>
9716                            </div>
9717                        </a>`;
9718                    },
9719                    empty: ''
9720                }
9721            }),
9722            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
9723        ]);
9724
9725        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem);
9726
9727        search.addWidgets([
9728            instantsearch.widgets.hitsPerPage({
9729                attribute: 'hpp',
9730                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
9731                items: hppItems('events')
9732            }),
9733            instantsearch.widgets.sortBy({
9734                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.sorting'),
9735                items: defaultSortItems(indexName)
9736            }),
9737            PENTAIR.CustomAlgoliaWidgets.hierarchicalMenu()({
9738                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .categories'),
9739                limit: 5,
9740                sortBy: ['count:desc'],
9741                attributes: ['eventCategories']
9742            }),
9743            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'bneDateFacet')({
9744                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .date'),
9745                attribute: 'bneDateFacet',
9746                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_event_modal') }
9747            }),
9748            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Region', 'region')({
9749                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .region'),
9750                attribute: 'region',
9751                templates: {
9752                    item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('event_region_modal')
9753                }
9754            }),
9755            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Brands', 'brands')({
9756                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .brands'),
9757                attribute: 'brands',
9758                templates: {
9759                    item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('brands_modal')
9760                }
9761            }),
9762            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Event Type', 'type')({
9763                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .event-type'),
9764                attribute: 'type',
9765                templates: {
9766                    item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('type_modal')
9767                }
9768            }),
9769            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
9770        ]);
9771    },
9772
9773    /**
9774     * Configures the blog tab — hit templates, category/author/date/type filter panels,
9775     * hitsPerPage, sort, and responsive pagination.
9776     * @param {object} search - InstantSearch instance
9777     * @param {string}
9777 indexName - Algolia index name
9778     * @param {HTMLElement} containerElem - Container element for this tab
9779     */
9780    pentair_blog: (search, indexName, containerElem) => {
9781        search.addWidgets([
9782            instantsearch.widgets.stats({
9783                container: containerElem.querySelector('.results-count'),
9784                templates: {
9785                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No blog results' + q : nbHits === 1 ? '1 blog result' + q : nbHits + ' blog results' + q; }
9786                }
9787            }),
9788            PENTAIR.CustomAlgoliaWidgets.clearRefinements()({
9789                container: containerElem.querySelector('.filters .clear-refinements')
9790            }),
9791            PENTAIR.CustomAlgoliaWidgets.currentRefinements()({
9792                container: containerElem.querySelector('.filters .current-refinements')
9793            }),
9794            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Categories', 'categoriesTitles')({
9795                container: containerElem.querySelector('.filter-container.category'),
9796                attribute: 'categoriesTitles',
9797                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_blog') }
9798            }),
9799            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Authors', 'bneAuthorNm')({
9800                container: containerElem.querySelector('.filter-container.authors'),
9801                attribute: 'bneAuthorNm',
9802                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_blog') }
9803            }),
9804            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Blog Type', 'type')({
9805                container: containerElem.querySelector('.filter-container.type'),
9806                attribute: 'type',
9807                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('_blog_type') }
9808            }),
9809            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'filterDate')({
9810                container: containerElem.querySelector('.filter-container.date'),
9811                attribute: 'filterDate',
9812                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_blog') }
9813            }),
9814            instantsearch.widgets.stats({
9815                container: containerElem.querySelector('.pagination-message'),
9816                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
9817            }),
9818            instantsearch.widgets.hitsPerPage({
9819                attribute: 'hpp',
9820                container: containerElem.querySelector('.hits-per-page'),
9821                items: hppItems('blogs')
9822            }),
9823            instantsearch.widgets.sortBy({
9824                container: containerElem.querySelector('.sorting'),
9825                items: defaultSortItems(indexName)
9826            }),
9827            instantsearch.widgets.hits({
9828                container: containerElem.querySelector('.results'),
9829                templates: {
9830                    item: (hit, { html, components, sendEvent }) => {
9831                        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.bnePagePath);
9832                        const bneImage = hit.bneImgPath ? html`<div class="top-image cover"><img loading="lazy" src="${hit.bneImgPath}.thumb.319.319.png" alt="Article Image"/></div>` : '';
9833                        const blogName = hit.blogName ? html`<div>${hit.blogName}</div>` : '';
9834                        const content = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', hit, highlightedTagName: 'mark' })}</div>` : '';
9835                        const bneAuthorImage = hit.bneAuthorImage ? html`<div class="author-img-wrapper"><img loading="lazy" class="author-img" src="${hit.bneAuthorImage}.thumb.48.48.png" alt="Image of Author"/></div>` : '';
9836                        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.bneTitle, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: Blog Tab Blog Article Click'); }}"
9837                            href="${hit.bnePagePath}"
9838                            target="${isExternal ? '_blank' : '_self'}"
9839                            data-query-ID="${hit.__queryID}">
9840                            ${bneImage}
9841                            <div class="content-padding">
9842                                <div class="info">
9843                                    ${blogName}
9844                                    <div class="date">${hit.bneDate}</div>
9845                                </div>
9846                                <div class="title title-text">${components.Highlight({ attribute: 'bneTitle', hit, highlightedTagName: 'mark' })}</div>
9847                                ${content}
9848                                <div class="flex-row left">
9849                                    ${bneAuthorImage}
9850                                    <div class="author-name">${hit.bneAuthorNm}</div>
9851                                </div>
9852                            </div>
9853                        </a>`;
9854                    },
9855                    empty: ''
9856                }
9857            }),
9858            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
9859        ]);
9860
9861        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem);
9862
9863        search.addWidgets([
9864            //     container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .categories'),
9865            //     limit: 5,
9866            //     sortBy: ['count:desc'],
9867            //     attributes: ['categories']
9868            // }),
9869            instantsearch.widgets.hitsPerPage({
9870                attribute: 'hpp',
9871                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
9872                items: hppItems('blogs')
9873            }),
9874            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Categories', 'categoriesTitles')({
9875                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filter-container.category'),
9876                attribute: 'categoriesTitles',
9877                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_categories_modal') }
9878            }),
9879            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Author', 'bneAuthorNm')({
9880                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filter-container.authors'),
9881                attribute: 'bneAuthorNm',
9882                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_author_modal') }
9883            }),
9884            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'filterDate')({
9885                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filter-container.date'),
9886                attribute: 'filterDate',
9887                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_date_modal') }
9888            }),
9889            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Blog Type', 'type')({
9890                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filter-container.type'),
9891                attribute: 'type',
9892                templates: {
9893                    item: item => {
9894                        const splitLabel = item.label.split('|')[1];
9895                        const slugLbl = `${splitLabel}_blog_type_modal`.toLowerCase().replace(/ /g, '_');
9896                        return `<input type="checkbox" ${item.isRefined ? 'checked' : ''} id="${slugLbl}" name="${slugLbl}">
9897                            <label for="${slugLbl}">
9898                                <span>${splitLabel}</span>
9899                                <span class="item-count">${item.count}</span>
9900                                <span class="sr-only">Filter</span>
9901                            </label>`;
9902                    }
9903                }
9904            })
9905        ]);
9906    },
9907
9908    /**
9909     * Configures the resources/documents tab — hit templates, hitsPerPage,
9910     * sort, and responsive pagination.
9911     * @param {object} search - InstantSearch instance
9912     * @param {string} indexName - Algolia index name
9913     * @param {HTMLElement} containerElem - Container element for this tab
9914     */
9915    pentair_resources: (search, indexName, containerElem) => {
9916        search.addWidgets([
9917            instantsearch.widgets.hitsPerPage({
9918                attribute: 'hpp',
9919                container: containerElem.querySelector('.hits-per-page'),
9920                items: hppItems('resources')
9921            }),
9922            instantsearch.widgets.sortBy({
9923                container: containerElem.querySelector('.sorting'),
9924                items: defaultSortItems(indexName)
9925            }),
9926            instantsearch.widgets.stats({
9927                container: containerElem.querySelector('.results-count'),
9928                templates: {
9929                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No resource results' + q : nbHits === 1 ? '1 resource result' + q : nbHits + ' resource results' + q; }
9930                }
9931            }),
9932            instantsearch.widgets.stats({
9933                container: containerElem.querySelector('.pagination-message'),
9934                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
9935            }),
9936            instantsearch.widgets.hits({
9937                container: containerElem.querySelector('.results'),
9938                templates: {
9939                    item: (hit, { html, components, sendEvent }) => {
9940                        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.path);
9941                        return html`<a onclick="${(e) => { searchResultClickAnalytic(e, hit.title, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: Resource Tab Resource Click'); }}"
9942                            href="${hit.path}#page=${hit.page + 1}"
9943                            target="${isExternal ? '_blank' : '_self'}"
9944                            data-query-ID="${hit.__queryID}">
9945                            <div class="content-padding">
9946                                <div class="title title-text">${components.Highlight({ attribute: 'title', hit, highlightedTagName: 'mark' })}</div>
9947                                <div class="content">${components.Snippet({ attribute: 'content', hit, highlightedTagName: 'mark' })}</div>
9948                            </div>
9949                        </a>`;
9950                    },
9951                    empty: ''
9952                }
9953            }),
9954            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
9955        ]);
9956
9957        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem);
9958
9959        search.addWidgets([
9960            instantsearch.widgets.hitsPerPage({
9961                attribute: 'hpp',
9962                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
9963                items: hppItems('resources')
9964            }),
9965            instantsearch.widgets.sortBy({
9966                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.sorting'),
9967                items: defaultSortItems(indexName)
9968            })
9969        ]);
9970    },
9971
9972    /**
9973     * Configures the myPentair news tab — same hit template as pentair_news, date and
9974     * type filters only (no author), explicit scroll target for pagination.
9975     * @param {object} search - InstantSearch instance
9976     * @param {string} indexName - Algolia index name
9977     * @param {HTMLElement} containerElem - Container element for this tab
9978     */
9979    mypentair_news: (search, indexName, containerElem) => {
9980        search.addWidgets([
9981            PENTAIR.CustomAlgoliaWidgets.clearRefinements()({
9982                container: containerElem.querySelector('.filters .clear-refinements')
9983            }),
9984            PENTAIR.CustomAlgoliaWidgets.currentRefinements()({
9985                container: containerElem.querySelector('.filters .current-refinements')
9986            }),
9987            PENTAIR.CustomAlgoliaWidgets.hierarchicalMenu()({
9988                container: containerElem.querySelector('.filters .categories'),
9989                limit: 5,
9990                sortBy: ['count:desc'],
9991                attributes: ['categoryTitles']
9992            }),
9993            instantsearch.widgets.hitsPerPage({
9994                container: containerElem.querySelector('.hits-per-page'),
9995                items: hppItems('news articles')
9996            }),
9997            instantsearch.widgets.sortBy({
9998                container: containerElem.querySelector('.sorting'),
9999                items: defaultSortItems(indexName)
10000            }),
10001            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'dateFilter')({
10002                container: containerElem.querySelector('.filters .date'),
10003                attribute: 'dateFilter',
10004                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_date') }
10005            }),
10006            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('News Type', 'type')({
10007                container: containerElem.querySelector('.filters .type'),
10008                attribute: 'type',
10009                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('_news_type') }
10010            }),
10011            instantsearch.widgets.stats({
10012                container: containerElem.querySelector('.results-count'),
10013                templates: {
10014                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No news results' + q : nbHits === 1 ? '1 news result' + q : nbHits + ' news results' + q; }
10015                }
10016            }),
10017            instantsearch.widgets.stats({
10018                container: containerElem.querySelector('.pagination-message'),
10019                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
10020            }),
10021            instantsearch.widgets.hits({
10022                container: containerElem.querySelector('.results'),
10023                templates: {
10024                    item: (hit, { html, components, sendEvent }) => {
10025                        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.pagePath);
10026                        const content = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', highlightedTagName: 'mark', hit })}</div>` : '';
10027                        return html`<a onclick="${(e) =>
10027 { searchResultClickAnalytic(e, hit.title, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: News Tab Article Click'); }}"
10028                            href="${hit.pagePath}.html"
10029                            target="${isExternal ? '_blank' : '_self'}"
10030                            data-query-ID="${hit.__queryID}">
10031                            <div class="content-padding">
10032                                <div class="info">
10033                                    <div class="date">${hit.displayDate}</div>
10034                                </div>
10035                                <div class="title title-text">${components.Highlight({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
10036                                ${content}
10037                            </div>
10038                        </a>`;
10039                    },
10040                    empty: ''
10041                }
10042            }),
10043            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
10044        ]);
10045
10046        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem, '#searchComponent');
10047
10048        search.addWidgets([
10049            PENTAIR.CustomAlgoliaWidgets.hierarchicalMenu()({
10050                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .categories'),
10051                limit: 5,
10052                sortBy: ['count:desc'],
10053                attributes: ['categoryTitles']
10054            }),
10055            instantsearch.widgets.hitsPerPage({
10056                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
10057                items: hppItems('news articles')
10058            }),
10059            instantsearch.widgets.sortBy({
10060                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.sorting'),
10061                items: defaultSortItems(indexName)
10062            }),
10063            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'dateFilter')({
10064                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .date'),
10065                attribute: 'dateFilter',
10066                templates: { item: PENTAIR.AlgoliaHelpers.filterTemplate('_date_modal') }
10067            }),
10068            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('News Type', 'type')({
10069                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.filters .type'),
10070                attribute: 'type',
10071                templates: { item: PENTAIR.AlgoliaHelpers.splitLabelTemplate('_news_type_modal') }
10072            })
10073        ]);
10074    },
10075
10076    /**
10077     * Configures the myPentair pages tab — same layout as pentair_pages but without depth
10078     * dynamic filter and with explicit scroll target for pagination.
10079     * @param {object} search - InstantSearch instance
10080     * @param {string} indexName - Algolia index name
10081     * @param {HTMLElement} containerElem - Container element for this tab
10082     */
10083    mypentair_pages: (search, indexName, containerElem) => {
10084        search.addWidgets([
10085            instantsearch.widgets.hitsPerPage({
10086                container: containerElem.querySelector('.hits-per-page'),
10087                items: hppItems('results')
10088            }),
10089            instantsearch.widgets.sortBy({
10090                container: containerElem.querySelector('.sorting'),
10091                items: defaultSortItems(indexName)
10092            }),
10093            instantsearch.widgets.stats({
10094                container: containerElem.querySelector('.results-count'),
10095                templates: {
10096                    text: ({ nbHits, query }) => { const q = query ? ' for "' + query + '"' : ''; return nbHits === 0 ? 'No page results' + q : nbHits === 1 ? '1 page result' + q : nbHits + ' page results' + q; }
10097                }
10098            }),
10099            instantsearch.widgets.stats({
10100                container: containerElem.querySelector('.pagination-message'),
10101                templates: { text: PENTAIR.AlgoliaHelpers.paginationMessageTemplate }
10102            }),
10103            instantsearch.widgets.hits({
10104                container: containerElem.querySelector('.results'),
10105                templates: {
10106                    item: (hit, { html, components, sendEvent }) => {
10107                        const breadcrumb = hit.breadcrumb?.trim() || '';
10108                        const content = hit.content ? html`<div class="content">${components.Snippet({ attribute: 'content', hit, highlightedTagName: 'mark' })}</div>` : '';
10109                        return html`${html([breadcrumb])}
10110                            <a onclick="${(e) =>
10110 { searchResultClickAnalytic(e, hit.title, (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1); sendEvent('click', hit, 'Search Results: Page Tab Page Click'); }}"
10111                                href="${hit.url}"
10112                                data-query-ID="${hit.__queryID}">
10113                                <div class="title-text">${components.Highlight({ attribute: 'title', hit, highlightedTagName: 'mark' })}</div>
10114                                ${content}
10115                            </a>`;
10116                    },
10117                    empty: ''
10118                }
10119            }),
10120            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()
10121        ]);
10122
10123        PENTAIR.AlgoliaHelpers.addResponsivePagination(search, containerElem, '#searchComponent');
10124
10125        search.addWidgets([
10126            instantsearch.widgets.hitsPerPage({
10127                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.hits-per-page'),
10128                items: hppItems('results')
10129            }),
10130            instantsearch.widgets.sortBy({
10131                container: PENTAIR.AlgoliaHelpers.filterModalSelector(indexName, '.sorting'),
10132                items: defaultSortItems(indexName)
10133            })
10134        ]);
10135    }
10136};
10137
10138// Accessibility: add aria-labels to select elements and fix any duplicate IDs
10139// introduced when multiple Algolia widget instances share the same template.
10140document.addEventListener('DOMContentLoaded', () => {
10141    setTimeout(() => {
10142        document.querySelectorAll('select').forEach(el => {
10143            if (el.classList.contains('ais-HitsPerPage-select')) {
10144                el.setAttribute('aria-label', 'Hits per page');
10145            }
10146            if (el.classList.contains('ais-SortBy-select')) {
10147                el.setAttribute('aria-label', 'Sort By');
10148            }
10149        });
10150
10151        document.querySelectorAll('[id]').forEach(el => {
10152            if (!el.id) return;
10153            const elid = '#' + CSS.escape(el.id);
10154            const duplicates = document.querySelectorAll(elid);
10155            if (duplicates.length > 1) {
10156                duplicates.forEach((dup, i) => {
10157                    dup.id = `${dup.id}_${i}`;
10158                });
10159            }
10160        });
10161    }, 1250);
10162});
10163
10164})();
10165
10166// ========================================
10167// GLOBAL HELPER FUNCTIONS
10168// ========================================
10169
10170/**
10171 * Returns a debounced version of fn that delays invoking it until after wait ms
10172 * have elapsed since the last call.
10173 * @param {Function} fn
10174 * @param {number} wait
10175 * @returns {Function}
10176 */
10177function debounce(fn, wait) {
10178  let timer;
10179  return function(...args) {
10180    clearTimeout(timer);
10181    timer = setTimeout(() => fn.apply(this, args), wait);
10182  };
10183}
10184
10185/**
10186 * Gets URL query parameters and builds an object
10187 * @returns {Object} Object containing all URL parameters
10188 */
10189function getParams() {
10190  // gets url parameters and builds an object
10191  return Object.fromEntries(
10192    location.search.slice(1).split('&').filter(Boolean).map(item => {
10193      const separatorIndex = item.indexOf('=');
10194      if (separatorIndex === -1) {
10195        return [item, ''];
10196      }
10197      return [item.slice(0, separatorIndex), item.slice(separatorIndex + 1)];
10198    })
10199  );
10200}
10201
10202/**
10203 * Parses URL parameters to extract Algolia refinements
10204 * @returns {Object} Object with hierarchical and disjunctive refinements
10205 */
10206function getRefinements(){
10207  const params = getParams();
10208
10209  const refinementHelper = (refinementType) => {
10210    return Object.entries(params).reduce((acc, [key, value]) => {
10211      const hierarchical = key.split('.' + refinementType);
10212      const returnObj = {};
10213      if(hierarchical.length > 1){
10214        returnObj[hierarchical[0]] = decodeURIComponent(value.replace(/\+/gm,"%20")).split(';');
10215      }
10216      return {...acc, ...returnObj};
10217    }, {});
10218  };
10219
10220  const hierarchical = refinementHelper('hierarchical');
10221  const disjunctive = refinementHelper('disjunctive');
10222
10223  return {hierarchical: hierarchical, disjunctive: disjunctive};
10224}
10225
10226// ========================================
10227// SEARCH INITIALIZATION
10228// ========================================
10229
10230// ========================================
10231// SEARCH COMPONENT FUNCTION
10232// ========================================
10233
10234function initSearch(componentElement) {
10235    // ----------------------------------------
10236    // State Variables (formerly Knockout observables)
10237    // ----------------------------------------
10238
10239    let userToken = HeaderUtil.getCloudVisitorId();
10240    const applicationId = componentElement.dataset.applicationId;
10241    const searchApiKey = componentElement.dataset.searchApiKey;
10242    const parsedTabIndexes = JSON.parse(componentElement.dataset.tabIndexes || '[]');
10243    const tabIndexConfigs = Array.isArray(parsedTabIndexes) ? parsedTabIndexes : [];
10244    const mobileIndexesParsed = JSON.parse(componentElement.dataset.mobileIndexes || '[]');
10245    const mobileIndexes = Array.isArray(mobileIndexesParsed) ? mobileIndexesParsed : [];
10246    const configuredMobileIndexNames = mobileIndexes
10247      .map(item => (typeof item === 'string' ? item : item?.indexName))
10248      .filter(Boolean);
10249    const defaultMobileIndexNames = tabIndexConfigs
10250      .map(item => item?.indexName)
10251      .filter(Boolean);
10252    const uniqueConfiguredMobileIndexNames = [...new Set(configuredMobileIndexNames)];
10253    const hasSpecificMobileTabs = uniqueConfiguredMobileIndexNames.some(indexName => indexName !== 'all');
10254    const mobileIndexNames = (uniqueConfiguredMobileIndexNames.length && hasSpecificMobileTabs)
10255      ? uniqueConfiguredMobileIndexNames
10256      : defaultMobileIndexNames;
10257    const searchClient = window.algoliasearch.algoliasearch(applicationId, searchApiKey);
10258    const dropdownSearchObjects = {
10259      productSuggestions: null,
10260      querySuggestions: null,
10261      popularPages: null
10262    };
10263    let allTabSearch = null;
10264    let tabsRootSearch = null;
10265    const tabSearchObjects = [];
10266    const tabLastResults = {};
10267    const tabIndexWidgets = {};
10268    let inputSearchQuery = getParams().q ? decodeURIComponent(getParams().q).replace(/\+/g, ' ') : ''; // Note: This binding is one-way since its rendered from algolia.
10269
10270    let searchBoxFocus = false;
10271    let currentTab = null;
10272    let currentTabElement=null;
10273    let isInitialPageViewSearch = true;
10274
10275    let totals = {};
10276
10277    const instantsearchWidgets = {};
10278
10279    let isMobile = window.matchMedia('(max-width: 767px)').matches;
10280
10281    // URL param names used for algolia search component
10282    const algoliaURLParams = ["perPage", "index", "tab", "q", "wcmmode"];
10283    // URL params suffixes used to identify algolia search refinements
10284    const algoliaURLParamIdentifiers = [".disjunctive", ".hierarchical"];
10285
10286    let queryIDList = [];
10287
10288    const aa = window.aa || function() {};
10289    if(userToken){
10290      aa('setUserToken', userToken);
10291    }
10292
10293    // ----------------------------------------
10294    // Helper Functions
10295    // ----------------------------------------
10296
10297    /**
10298     * Calculates the total across all tabs
10299     * @returns {number} Sum of all tab totals
10300     */
10301    function allTotal() {
10302      return Object.values(totals || {}).reduce((sum, value) => sum + (Number(value) || 0), 0);
10303    }
10304
10305    /**
10306     * Updates dropdown visibility based on search focus
10307     */
10308    function updateDropdownVisibility() {
10309      const dropdown = componentElement.querySelector('.dropdown-container');
10310      const shouldShow = !document.querySelector('.pentair') && searchBoxFocus;
10311      if (dropdown) {
10312        dropdown.style.display = shouldShow ? '' : 'none';
10313      }
10314    }
10315
10316    // ----------------------------------------
10317    // Functions - URL Parameters & State
10318    // ----------------------------------------
10319
10320    /**
10321     * Gets parameters from current search state
10322     * @returns {Object} Parameters object for browser state
10323     */
10324    function paramsFromCurrentState() {
10325
10326      let refinements = [];
10327      let paramRefinements = {};
10328      let currentTabResults = {};
10329
10330      if (currentTab && currentTab !== 'all' && tabLastResults[currentTab]) {
10331        currentTabResults = tabLastResults[currentTab];
10332        refinements = currentTabResults.getRefinements();
10333      }
10334
10335      // Ensure refinements is always an array
10336      const refinementsArray = Array.isArray(refinements) ? refinements : [];
10337      const _grouped = refinementsArray.reduce((acc, entity) => {
10338        const bucket = acc[entity.attributeName] || [];
10339        bucket.push(entity);
10340        acc[entity.attributeName] = bucket;
10341        return acc;
10342      }, {});
10343      paramRefinements = Object.fromEntries(
10344        Object.entries(_grouped).map(([key, vals]) => [key + '.' + vals[0].type, vals.map(v => v.name).join(';')])
10345      );
10346
10347      let otherOptions = {};
10348      if (currentTabResults) {
10349        const options = {
10350          page: (currentTabResults.page > 0) ? (currentTabResults.page + 1) : null,  // Only pass if not page 1
10351          index: currentTabResults.index === currentTab ? null : currentTabResults.index, // Only pass if sorted
10352          q: inputSearchQuery ? inputSearchQuery : null,
10353          perPage: currentTabResults.hitsPerPage === 12 ? null : currentTabResults.hitsPerPage,
10354          tab: currentTab === 'all' ? null : currentTab
10355        };
10356
10357        otherOptions = Object.fromEntries(Object.entries(options).filter(elem => !!elem[1]));
10358        // page, sortby, per page
10359      }
10360
10361      return { ...paramRefinements, ...otherOptions };
10362    }
10363
10364    // ----------------------------------------
10365    // Functions - Display & Results
10366    // ----------------------------------------
10367
10368    /**
10369     * Gets display string for result totals by index name
10370     * @param {string} indexName - Name of the search index
10371     * @returns {string} Formatted display string with total count
10372     */
10373    function displayResultTotalByIndex(indexName) {
10374      if(indexName === 'all'){
10375        return ' (' + allTotal() + ')';
10376      }
10377      return totals[indexName] ? ' (' + totals[indexName] + ')' : ' (0)';
10378    }
10379
10380    /**
10381     * Syncs the tab heading count spans with the current totals state.
10382     */
10383    function updateTabHeadingCounts() {
10384      componentElement.querySelectorAll('.tab-search-name .item').forEach((tabItem) => {
10385        const countElement = tabItem.querySelector('.count');
10386        if (!countElement) {
10387          return;
10388        }
10389
10390        const tabIndexName = Array.from(tabItem.classList).find((className) => {
10391          return className === 'all' || tabIndexConfigs.some((tab) => tab.indexName === className);
10392        });
10393
10394        if (!tabIndexName) {
10395          return;
10396        }
10397
10398        countElement.textContent = displayResultTotalByIndex(tabIndexName);
10399      });
10400    }
10401    /**
10402     * Shows or hides the "View all" links in the All tab based on result counts.
10403     */
10404    function updateAllTabSeeAllLinks() {
10405      componentElement.querySelectorAll('.all-tab > div').forEach(section => {
10406        const count = parseInt(section.querySelector('.results-count .ais-Stats-text')?.textContent.replace(/,/g, ''), 10) || 0;
10407        section.querySelectorAll('.see-all').forEach(link => link.style.display = count > 0 ? '' : 'none');
10408      });
10409    }
10410    /**
10411     * Helper function that sets height on the owl carousel based on the active item. Uses timeout to ensure hits are rendered.
10412     */
10413    const setOwlOuterHeight = debounce(() => {
10414      const owlActiveItem = componentElement.querySelector('.tab-search-content .owl-item.active .item');
10415      const owlOuter = owlActiveItem?.closest('.owl-stage-outer');
10416      if (!owlOuter || !owlActiveItem) return;
10417      owlOuter.style.height = owlActiveItem.offsetHeight + 'px';
10418    }, 100);
10419
10420    // ----------------------------------------
10421    // Functions - Filter & Refinements
10422    // ----------------------------------------
10423
10424    /**
10425     * Clears all refinements for a specific index
10426     * @param {string} indexName - Name of the search index
10427     * @returns {boolean} False to prevent default
10428     */
10429    function clearRefinements(indexName) {
10430      // Skip if trying to clear refinements on "all" tab (it doesn't have its own search instance)
10431      if (indexName === 'all' || !instantsearchWidgets[indexName]) {
10432        return false;
10433      }
10434      tabsRootSearch?.setUiState(prevState => ({
10435        ...prevState,
10436        [indexName]: { ...(prevState[indexName] || {}), refinementList: {}, hierarchicalMenu: {} }
10437      }));
10438      return false;
10439    }
10440
10441    /**
10442     * Handles filter click events and triggers analytics
10443     * @param {Event} event - Click event
10444     * @returns {boolean} True to allow propagation
10445     */
10446    function filterClick(event) {
10447      const isFilterClick = !!event.target.closest('li.ais-RefinementList-item');
10448      const isCategoryFilterClick = !!event.target.closest('.categories');
10449      const isButtonClick = event.target.matches('button');
10450
10451      if(isFilterClick || isCategoryFilterClick){
10452        const currentWidget = instantsearchWidgets[currentTab];
10453        if (currentWidget) {
10454          const debouncedFilterAnalytics = debounce(updateAnalytics, 500);
10455          currentWidget.once('render', () => {
10456            debouncedFilterAnalytics('refine', 'filter');
10457          });
10458        }
10459      }
10460
10461      if(isButtonClick){
10462        event.preventDefault();
10463      }
10464
10465      return true;
10466    }
10467
10468    // ----------------------------------------
10469    // Functions - Dropdown Click Handlers
10470    // ----------------------------------------
10471
10472    /**
10473     * Handles click on suggested search dropdown items
10474     * @param {Event} event - Click event
10475     * @returns {boolean} False to prevent default
10476     */
10477    function dropdownSuggestionClick(event) {
10478      // PAAS - Adobe Analytics
10479      const searchTerm = inputSearchQuery;
10480      const linkClicked = event.target.closest('a');
10481      const suggestedSearchTerm = linkClicked ? linkClicked.textContent.trim() : '';
10482      const queryID = linkClicked?.dataset.queryId || '';
10483      trackSuggestedSearchClickPayload(searchTerm, suggestedSearchTerm, queryID, false);
10484
10485      const captureElem = event.target.closest('a');
10486      const searchBoxInput = componentElement.querySelector('.search-box input');
10487      searchBoxInput.value = captureElem.dataset.query;
10488      inputSearchQuery = decodeURIComponent(captureElem.dataset.query);
10489      searchBoxFocus = false;
10490      doTabSearch();
10491
10492      if(!!window._satellite){
10493        _satellite.track('query result click', {
10494            query: inputSearchQuery,
10495            resultLink: `Suggestion|${Array.from(captureElem.closest('li').parentElement.children).indexOf(captureElem.closest('li')) + 1}|${captureElem.textContent.trim()}`
10496        });
10497      }
10498
10499      return false;
10500    }
10501
10502    /**
10503     * Handles click on popular pages dropdown items
10504     * @param {Event} event - Click event
10505     * @returns {boolean} True to allow default navigation
10506     */
10507    function dropdownSearchPopularPagesClick(event) {
10508      const captureElem = event.target.closest('a');
10509      if(!!window._satellite){
10510        const li = captureElem.closest('li');
10511        const liIndex = li ? Array.from(li.parentElement.children).indexOf(li) + 1 : 0;
10512        _satellite.track('query result click', {
10513            query: inputSearchQuery,
10514            resultLink: `Page Result|${liIndex}|${captureElem.textContent.trim()}`
10515        });
10516      }
10517
10518      // PAAS - Adobe Analytics
10519      const searchTerm = inputSearchQuery;
10520      const linkClicked = event.target.closest('a');
10521      const suggestedSearchResult = linkClicked ? linkClicked.textContent.trim() : '';
10522      const queryID = linkClicked?.dataset.queryId || '';
10523      trackSuggestedSearchClickPayload(searchTerm, suggestedSearchResult, queryID, true);
10524
10525      return true;
10526    }
10527
10528    /**
10529     * Handles click on popular products dropdown items
10530     * @param {Event} event - Click event
10531     * @returns {boolean} True to allow default navigation
10532     */
10533    function dropdownSearchProductClick(event) {
10534      userToken = HeaderUtil.getCloudVisitorId();
10535      const captureElem = event.target.closest('a');
10536      if(!!window._satellite){
10537        const li = captureElem.closest('li');
10538        const liIndex = li ? Array.from(li.parentElement.children).indexOf(li) + 1 : 0;
10539        _satellite.track('query result click', {
10540            query: inputSearchQuery,
10541            resultLink: `Product Result|${liIndex}|${captureElem.textContent.trim()}`
10542        });
10543      }
10544
10545      // PAAS - Adobe Analytics
10546      const searchTerm = inputSearchQuery;
10547      const linkClicked = event.target.closest('a');
10548      const suggestedSearchResult = linkClicked ? linkClicked.textContent.trim() : '';
10549      const queryID = linkClicked && linkClicked.dataset.queryId ? linkClicked.dataset.queryId : '';
10550      trackSuggestedSearchClickPayload(searchTerm, suggestedSearchResult, queryID, true);
10551
10552      return true;
10553    }
10554
10555    /**
10556     * Handles click on product count link to view all products
10557     * @param {Event} event - Click event
10558     * @returns {boolean} False to prevent default
10559     */
10560    function dropdownSearchProductCountClick(event) {
10561      const captureElem = event.target.closest('a');
10562      const productIndex = event.target.closest('.products-count').dataset.productTabIndex;
10563      openTab(productIndex);
10564      searchBoxFocus = false;
10565      doTabSearch();
10566      return false;
10567    }
10568
10569    /**
10570     * Handles click on popular pages count link to view all pages
10571     * @param {Event} event - Click event
10572     * @returns {boolean} False to prevent default
10573     */
10574    function dropdownPopularPagesCountClick(event) {
10575      const pageIndex = event.target.closest('.popular-pages-count').dataset.pageTabIndex;
10576      openTab(pageIndex);
10577      searchBoxFocus = false;
10578      doTabSearch();
10579      return false;
10580    }
10581
10582    // ----------------------------------------
10583    // Functions - UI Interaction
10584    // ----------------------------------------
10585
10586    /**
10587     * Handles Enter key press in search input
10588     * @param {Event} event - Keyboard event
10589     * @returns {boolean} True to allow propagation
10590     */
10591    function inputEnter(event) {
10592      if (event.which == 13) {
10593          event.target.dispatchEvent(new Event('focusout'));
10594          Object.values(instantsearchWidgets).forEach(search => {
10595            search.helper.clearRefinements();
10596          });
10597          doTabSearch();
10598      }
10599      return true;
10600    }
10601
10602    /**
10603     * Executes search across all tabs
10604     */
10605    function doTabSearch() {
10606      initRenderAnalyticsEvent();
10607
10608      allTabSearch.helper.setQuery(inputSearchQuery);
10609      allTabSearch.helper.search();
10610      tabsRootSearch?.helper?.setQuery(inputSearchQuery);
10611      tabsRootSearch?.helper?.search();
10612
10613      searchBoxFocus = false;
10614      updateDropdownVisibility();
10615    }
10616
10617    /**
10618     * Opens a specific tab by index
10619     * @param {string} tabIndex - Index of the tab to open
10620     * @returns {boolean} False to prevent default
10621     */
10622    function openTab(tabIndex) {
10623      currentTabElement = componentElement.querySelector('.tab-search-name .' + tabIndex);
10624      if(!currentTabElement) return;
10625
10626       currentTabElement.click();
10627       currentTabElement.classList.add('current');
10628    }
10629
10630    /**
10631     * Renders the refinement list for category filtering
10632     * @param {Object} renderOptions - Algolia render options
10633     * @param {boolean} isFirstRender - Whether this is the first render
10634     */
10635    function renderRefinementList(renderOptions, isFirstRender) {
10636        const container = componentElement.querySelector('.search-input-container .categories');
10637
10638        if (isFirstRender) {
10639          const ul = document.createElement('ul');
10640          container.appendChild(ul);
10641        }
10642
10643        container.querySelector('ul').innerHTML = renderOptions.items
10644          .map(item => {
10645            return `<li>
10646                <a href="#" data-value="${item.value}" style="font-weight: ${item.isRefined ? 'bold' : ''}">
10647                  ${item.label}(${item.count})
10648                </a>
10649              </li>`;
10650          })
10651          .join('');
10652      }
10653
10654    // ----------------------------------------
10655    // Helper Functions
10656    // ----------------------------------------
10657
10658    const initRenderAnalyticsEvent = () => {
10659      const debouncedRenderAnalytics = debounce(updateAnalytics, 500); // Ensures totals are set before this is triggered.
10660
10661      if(currentTab == 'all'){
10662        allTabSearch.once('render',function(){
10663          debouncedRenderAnalytics('initial');
10664        });
10665      } else {
10666        instantsearchWidgets[currentTab].once('render',function(){
10667          debouncedRenderAnalytics('initial');
10668        });
10669      }
10670    };
10671
10672    /**
10673     * Adds the click event handler to the dynamic accordian panel widgets.
10674     * Keeps Algolia's native collapse button/ARIA behavior, while allowing users
10675     * to click anywhere in the panel header (legacy UX).
10676     * @param filterContainer container for the filter widgets
10677     */
10678    const initDynamicWidgetAccordianPanel = filterContainer => {
10679        if (!filterContainer || filterContainer.dataset.accordionDelegationInitialized === 'true') return;
10680
10681        filterContainer.addEventListener('click', (event) => {
10682          const header = event.target.closest('.ais-Panel-header');
10683          if (!header) return;
10684
10685          // Let native button clicks run untouched.
10686          if (event.target.closest('.ais-Panel-collapseButton')) return;
10687
10688          const panel = header.closest('.ais-Panel');
10689          const collapseButton = panel?.querySelector('.ais-Panel-collapseButton');
10690          if (collapseButton) {
10691            collapseButton.click();
10692          }
10693        });
10694
10695        filterContainer.dataset.accordionDelegationInitialized = 'true';
10696    }
10697
10698    // ----------------------------------------\n    // Functions - Algolia Initialization
10699    // ----------------------------------------
10700
10701    /**
10702     * Initializes Algolia search box with dropdown suggestions
10703     * @param {Object} searchClient - Algolia search client
10704     * @param {string} indexName - Name of the search index
10705     * @param {HTMLElement} containerElem - Container element for the search box
10706     */
10707    function initAlgoliaSearchBox(searchClient, indexName, containerElem) {
10708
10709      // index() widgets share the root's query: all three dropdown sections travel in one Algolia request.
10710      dropdownSearchObjects['querySuggestions'] = instantsearch.widgets.index({
10711        indexName: containerElem.querySelector('.suggestions').dataset.index
10712      });
10713
10714      dropdownSearchObjects['popularPages'] = instantsearch.widgets.index({
10715          indexName: containerElem.querySelector(".popular-pages").dataset.index
10716      });
10717
10718      const renderPopularPagesDropdownStats = (renderOptions, isFirstRender) => {
10719          const popularPagesSection = renderOptions.widgetParams.container.closest('.popular-pages-container');
10720          if (popularPagesSection) {
10721          popularPagesSection.style.display = renderOptions.nbHits > 0 ? '' : 'none';
10722          }
10723
10724          if(renderOptions.nbHits > 1){
10725              renderOptions.widgetParams.container.innerHTML = `<a href="#" aria-label="See all page results">View ${renderOptions.nbHits} page results</a>`;
10726          } else {
10727              renderOptions.widgetParams.container.innerHTML = '';
10728          }
10729      };
10730
10731      const renderSuggestedSearchesDropdownStats = (renderOptions, isFirstRender) => {
10732          if (renderOptions.widgetParams.container) {
10733          renderOptions.widgetParams.container.style.display = renderOptions.nbHits > 0 ? '' : 'none';
10734          }
10735      };
10736
10737      const popularPagesStats = instantsearch.connectors.connectStats(renderPopularPagesDropdownStats);
10738      const suggestedSearchesStats = instantsearch.connectors.connectStats(renderSuggestedSearchesDropdownStats);
10739
10740      dropdownSearchObjects['querySuggestions'].addWidgets([
10741        instantsearch.widgets.configure({
10742          hitsPerPage: 3,
10743          clickAnalytics: true
10744        }),
10745        instantsearch.widgets.hits({
10746          container: containerElem.querySelector('.suggestions'),
10747          templates: {
10748            item: (hit, { html, components, sendEvent }) => html`
10749              <a href="#"
10750                class="suggested-searches"
10751                aria-label="Search for Suggested Query"
10752                data-query="${hit.query}"
10753                data-query-id="${hit.__queryID}"
10754                data-position="${hit.__position}"
10755                onClick="${() => sendEvent('click', hit, 'Search Bar: Dropdown Query Suggestion Click')}">
10756                ${components.Highlight({ hit, attribute: 'query', highlightedTagName: 'mark' })}
10757              </a>`
10758          }
10759        }),
10760        suggestedSearchesStats({
10761          container: containerElem.querySelector('.suggested-searches-container')
10762        })
10763      ]);
10764
10765      dropdownSearchObjects['popularPages'].addWidgets([
10766          instantsearch.widgets.configure({
10767              hitsPerPage: 4,
10768              clickAnalytics: true
10769          }),
10770          instantsearch.widgets.hits({
10771              container: containerElem.querySelector('.dropdown-container .popular-pages'),
10772              templates: {
10773                item: (hit, { html, components, sendEvent }) => html`
10774                  <a href="${hit.url}"
10775                    aria-label="Search for Popular Page ${hit.title}"
10776                    data-query="${hit.title}"
10777                    data-object-id="${hit.objectID}"
10778                    data-query-id="${hit.__queryID}"
10779                    data-position="${hit.__position}"
10780                    onClick="${() => sendEvent('click', hit, 'Search Bar: Dropdown Popular Pages Click')}">
10781                    ${components.Highlight({ hit, attribute: 'title', highlightedTagName: 'mark' })}
10782                  </a>`
10783              }
10784          }),
10785          popularPagesStats({
10786            container: containerElem.querySelector('.popular-pages-count')
10787          })
10788      ]);
10789
10790      // Root instance: owns the search box and drives queries for all child indexes.
10791      dropdownSearchObjects['productSuggestions'] = window.instantsearch({
10792          indexName: indexName,
10793          searchClient: searchClient,
10794          // Intercepts every query to keep inputSearchQuery current for downstream tab searches.
10795          searchFunction: function(helper) {
10796              inputSearchQuery = decodeURIComponent(helper.getQuery().query);
10797              helper.search();
10798            }
10799        });
10800
10801      const renderProductDropdownStats = (renderOptions, isFirstRender) => {
10802        if(renderOptions.nbHits > 1){
10803          renderOptions.widgetParams.container.innerHTML = `<a href="#" aria-label="See all product results">View ${renderOptions.nbHits} product results</a>`;
10804        } else {
10805          renderOptions.widgetParams.container.innerHTML = '';
10806        }
10807      };
10808
10809      const renderSearchBox = (renderOptions, isFirstRender) => {
10810        const container = renderOptions.widgetParams.container;
10811
10812        if(isFirstRender) {
10813          const searchIcon = document.createElement('span');
10814          searchIcon.className = 'search-icon glyphicon-search';
10815
10816          const placeholder = containerElem.closest('.component.search')?.dataset.placeHolder || 'Search';
10817          const input = document.createElement('input');
10818          input.className = 'input-box';
10819          input.setAttribute('aria-label', 'Search');
10820          input.placeholder = placeholder;
10821
10822          const removeBtn = document.createElement('button');
10823          removeBtn.className = 'ais-SearchBox-reset';
10824          removeBtn.textContent = 'X';
10825          removeBtn.type = 'button';
10826          removeBtn.setAttribute('aria-label', 'Clear search');
10827
10828          const debouncedRefine = debounce((value) => renderOptions.refine(value), 300);
10829          input.addEventListener('input', (event) => {
10830            debouncedRefine(event.target.value);
10831            removeBtn.style.display = event.target.value ? 'block' : 'none';
10832          });
10833
10834          renderOptions.refine(inputSearchQuery);
10835          //Listener to clear for both desktop and mobile
10836           removeBtn.addEventListener('click', () => {
10837            input.value = '';
10838            inputSearchQuery = '';
10839            renderOptions.clear();
10840            removeBtn.style.display = 'none';
10841            doTabSearch();
10842          });
10843
10844          if(window.matchMedia('(max-width: 768px)').matches){
10845            input.addEventListener('focus', () => {
10846              removeBtn.style.display = 'block';
10847              searchBoxFocus = true;
10848              updateDropdownVisibility();
10849            });
10850            input.addEventListener('blur', () => {
10851              searchBoxFocus = false;
10852              setTimeout(() => {
10853                updateDropdownVisibility();
10854              }, 150);
10855            });
10856            container.appendChild(searchIcon);
10857            container.appendChild(removeBtn);
10858            container.appendChild(input);
10859          }
10860          else{
10861            input.addEventListener('focus', () => {
10862              searchBoxFocus = true;
10863              updateDropdownVisibility();
10864            });
10865            input.addEventListener('blur', () => {
10866              setTimeout(() => {
10867                searchBoxFocus = false;
10868                updateDropdownVisibility();
10869              }, 100);
10870            });
10871            container.appendChild(input);
10872            container.appendChild(removeBtn);
10873
10874          }
10875        }
10876
10877        container.querySelector('input').value = renderOptions.query;
10878        const input = container.querySelector('input');
10879        const resetButton = container.querySelector('.ais-SearchBox-reset');
10880        if (input && resetButton) {
10881          resetButton.style.display = input.value ? 'block' : 'none';
10882        }
10883      };
10884
10885      const customSearchBox = instantsearch.connectors.connectSearchBox(
10886        renderSearchBox
10887      );
10888
10889      const productDropdownStats = instantsearch.connectors.connectStats(
10890        renderProductDropdownStats
10891      );
10892
10893      // Child indexes must be mounted before customSearchBox so their helpers exist
10894      // when refine() fires during customSearchBox.init()
10895      dropdownSearchObjects['productSuggestions'].addWidgets([
10896        dropdownSearchObjects['querySuggestions'],
10897        dropdownSearchObjects['popularPages']
10898      ]);
10899
10900      dropdownSearchObjects['productSuggestions'].addWidgets([
10901
10902        customSearchBox({
10903          container: containerElem.querySelector('.search-box'),
10904          placeholder: 'Search'
10905        }),
10906
10907        instantsearch.widgets.configure({
10908          hitsPerPage: 4,
10909          clickAnalytics: true
10910        }),
10911
10912        instantsearch.widgets.hits({
10913          container: containerElem.querySelector('.products'),
10914          hitsPerPage: 4,
10915          templates: {
10916            item: (hit, { html, components, sendEvent }) => {
10917              const imageSrc = hit.productThumbnail
10918                ? `${hit.productThumbnail}.thumb.319.319.png`
10919                : '/content/dam/extranet/product-related/product-photo/Placeholder Image.png.thumb.319.319.png';
10920              return html`
10921                <div class="flex-container">
10922                  <div class="image-container">
10923                    <img loading="lazy" src="${imageSrc}" alt="Product Image"/>
10924                  </div>
10925                  <div class="link-container">
10926                    <a href="${hit.url}" aria-label="Link to ${hit.productName}" data-object-id="${hit.objectID}" data-query-id="${hit.__queryID}" data-position="${hit.__position}" onClick="${() => sendEvent('click', hit, 'Search Bar: Dropdown Product Click')}">
10927                      ${components.Highlight({ hit, attribute: 'productName', highlightedTagName: 'mark' })}
10928                    </a>
10929                  </div>
10930                </div>`;
10931            }
10932          }
10933        }),
10934
10935        productDropdownStats({
10936          container: containerElem.querySelector('.products-count')
10937        })
10938      ]);
10939
10940      dropdownSearchObjects['productSuggestions'].start();
10941
10942    }
10943
10944    /**
10945     * Creates one root InstantSearch instance and registers each individual tab as a
10946     * child index() widget so all tabs are resolved in a single Algolia multiquery request.
10947     */
10948    function initAlgoliaTabsRoot() {
10949      const validTabElems = Array.from(componentElement.querySelectorAll('.tab-search-content .item:not(.all)'))
10950        .filter(elem => elem.dataset.index && !instantsearchWidgets[elem.dataset.index]);
10951
10952      if (!validTabElems.length) return;
10953
10954      const params = getParams();
10955      const initialUiState = {};
10956
10957      validTabElems.forEach(elem => {
10958        initialUiState[elem.dataset.index] = { query: inputSearchQuery };
10959      });
10960
10961      // Restore full URL state for the active individual tab
10962      if (currentTab && currentTab !== 'all' && initialUiState[currentTab]) {
10963        initialUiState[currentTab] = {
10964          query: inputSearchQuery,
10965          page: params.page,
10966          hitsPerPage: params.perPage,
10967          hierarchicalMenu: getRefinements().hierarchical,
10968          refinementList: getRefinements().disjunctive,
10969          sortBy: params.index
10970        };
10971      }
10972
10973      // Wrap the searchClient to intercept multiquery requests and isolate refinements by tab
10974      // This prevents filter bleed where one tab's filters contaminate other tabs' queries
10975      const wrappedSearchClient = {
10976        search(requests) {
10977          // Intercept multiquery requests before sending to Algolia
10978          // Clear refinements for non-active tabs to prevent filter bleed
10979          const cleanedRequests = requests.map(req => {
10980            // Only clean non-active tab indexes
10981            if (req.indexName !== currentTab) {
10982              return {
10983                ...req,
10984                params: {
10985                  ...req.params,
10986                  facetFilters: [], // Clear facet filters for non-active tabs
10987                  numericFilters: [], // Clear numeric filters for non-active tabs
10988                  optionalFilters: [] // Clear optional filters for non-active tabs
10989                }
10990              };
10991            }
10992            return req;
10993          });
10994
10995          return searchClient.search(cleanedRequests);
10996        },
10997        searchForFacetValues(requests) {
10998          return searchClient.searchForFacetValues(requests);
10999        }
11000      };
11001
11002      tabsRootSearch = window.instantsearch({
11003        indexName: validTabElems[0].dataset.index,
11004        searchClient: wrappedSearchClient,
11005        insights: {
11006          // Only fire hits-viewed for the tab the user is currently on.
11007          onEvent(event, aa) {
11008            if (event.insightsMethod === 'viewedObjectIDs' && event.payload.index !== currentTab) {
11009              return;
11010            }
11011            aa(event.insightsMethod, event.payload);
11012          }
11013        },
11014        initialUiState
11015      });
11016
11017      tabsRootSearch.addWidgets([PENTAIR.CustomAlgoliaWidgets.virtualSearchBox()]);
11018
11019      validTabElems.forEach(elem => {
11020        const indexName = elem.dataset.index;
11021        const cssClass = indexName.slice(indexName.indexOf('_') + 1).replace('_', '-');
11022        elem.classList.add(cssClass);
11023        initAlgoliaTabIndex(indexName, elem);
11024      });
11025
11026      tabsRootSearch.once('render', () => {
11027        initUiState();
11028      });
11029      tabsRootSearch.on('render', () => {
11030        validTabElems.forEach(elem => {
11031          const indexName = elem.dataset.index;
11032          const results = tabsRootSearch.renderState?.[indexName]?.hits?.results;
11033          if (results) {
11034            tabLastResults[indexName] = results;
11035            totals[indexName] = results.nbHits;
11036            if (currentTab === 'all' && isInitialPageViewSearch && results.queryID && !queryIDList.includes(results.queryID)) {
11037              queryIDList.push(results.queryID);
11038            }
11039          }
11040        });
11041
11042        updateTabHeadingCounts();
11043
11044        if (currentTab !== 'all') {
11045          setBrowserState(paramsFromCurrentState());
11046        }
11047
11048        setTimeout(() => {
11049          componentElement.querySelector('.tab-search-content')?.dispatchEvent(new CustomEvent('refresh.owl.carousel'));
11050          setOwlOuterHeight();
11051        }, 100);
11052      });
11053
11054      tabsRootSearch.start();
11055    }
11056
11057    /**
11058     * Registers a single tab index as a child index() widget on tabsRootSearch.
11059     * Strips virtualSearchBox from the child widget — a child virtualSearchBox overrides
11060     * the inherited root query with an empty string, producing 0 results.
11061     * @param {string} indexName
11062     * @param {HTMLElement} containerElem
11063     */
11064    function initAlgoliaTabIndex(indexName, containerElem) {
11065      const indexWithoutEnvironment = indexName.split('_').slice(1).join('_');
11066      if (!PENTAIR.AlgoliaTabSearchWidgets[indexWithoutEnvironment]) return;
11067
11068
11069      const isRootIndex = indexName === tabsRootSearch.indexName;
11070      let searchTarget;
11071
11072      if (isRootIndex) {
11073        // Root index: add widgets directly to avoid a second Algolia query against the same index.
11074        searchTarget = tabsRootSearch;
11075      } else {
11076        const indexWidget = instantsearch.widgets.index({ indexName });
11077        tabIndexWidgets[indexName] = indexWidget;
11078
11079
11080        const _addWidgets = indexWidget.addWidgets.bind(indexWidget);
11081        indexWidget.addWidgets = function(widgets) {
11082          return _addWidgets(widgets.filter(w => w.$$type !== 'ais.searchBox'));
11083        };
11084        searchTarget = indexWidget;
11085      }
11086
11087      PENTAIR.AlgoliaTabSearchWidgets[indexWithoutEnvironment](searchTarget, indexName, containerElem);
11088
11089      // Proxy preserves the helper/event API expected by the rest of the component.
11090      instantsearchWidgets[indexName] = {
11091        indexName,
11092        firstRender: false,
11093        get helper() {
11094          return {
11095            get lastResults() { return tabLastResults[indexName] ?? null; },
11096            clearRefinements() { return clearRefinements(indexName); },
11097            search() { tabsRootSearch?.helper?.search(); }
11098          };
11099        },
11100        once(event, fn) { return tabsRootSearch?.once(event, fn); },
11101        on(event, fn) { return tabsRootSearch?.on(event, fn); }
11102      };
11103
11104      if (!isRootIndex) {
11105        tabsRootSearch.addWidgets([searchTarget]);
11106      }
11107    }
11108
11109    /**
11110     * Initializes the "all" tab search that combines all indexes
11111     */
11112    function initAlgoliaAllTab() {
11113      const allTabElements = componentElement.querySelectorAll('.all-tab [data-index]');
11114
11115      // Safety check - ensure we have valid index elements
11116      if (!allTabElements || allTabElements.length === 0) {
11117        console.error('No index elements found in .all-tab');
11118        return;
11119      }
11120
11121      // Filter out any elements that might have 'all' as the index name,
11122      // and keep only one element per index to avoid duplicate widget mounts.
11123      const seenAllTabIndexes = new Set();
11124      const validElements = Array.from(allTabElements).filter(elem => {
11125        const idx = elem.dataset.index;
11126        if (!idx || idx === 'all' || seenAllTabIndexes.has(idx)) {
11127          return false;
11128        }
11129        seenAllTabIndexes.add(idx);
11130        return true;
11131      });
11132
11133      if (validElements.length === 0) {
11134        console.error('No valid index elements found (all were "all" or empty)');
11135        return;
11136      }
11137
11138      const initialUiState = {};
11139      validElements.forEach(elem => {
11140        initialUiState[elem.dataset.index] = {query: inputSearchQuery};
11141      });
11142
11143      allTabSearch = window.instantsearch({
11144        indexName: validElements[0].dataset.index,
11145        searchClient: searchClient,
11146        insights: {
11147          // Only fire hits-viewed when the user is actually on the All tab.
11148          onEvent(event, aa) {
11149            if (event.insightsMethod === 'viewedObjectIDs' && currentTab !== 'all') {
11150              return;
11151            }
11152            aa(event.insightsMethod, event.payload);
11153          }
11154        },
11155        initialUiState : initialUiState
11156      });
11157
11158      const allTabConfigureParams = { clickAnalytics: true };
11159      if (userToken) { allTabConfigureParams.userToken = userToken; }
11160      allTabSearch.addWidgets([
11161        PENTAIR.CustomAlgoliaWidgets.virtualSearchBox(),
11162        instantsearch.widgets.configure(allTabConfigureParams)
11163      ]);
11164
11165      validElements.forEach((elem, index) => {
11166        initAlgoliaAllTabIndex(allTabSearch, elem.dataset.index, elem);
11167      });
11168
11169      allTabSearch.on('render', () => {
11170        updateAllTabSeeAllLinks();
11171
11172        if(currentTab === 'all'){
11173          setBrowserState(paramsFromCurrentState());
11174        }
11175        setOwlOuterHeight();
11176      });
11177
11178      allTabSearch.start();
11179
11180    }
11181
11182    /**
11183     * Initializes a specific index within the "all" tab search
11184     * @param {Object} search - Algolia search instance
11185     * @param {string} indexName - Name of the search index
11186     * @param {HTMLElement} containerElem - Container element for the index
11187     */
11188    function initAlgoliaAllTabIndex(search, indexName, containerElem) {
11189
11190      const indexWithoutEnvironment = indexName.split('_').slice(1).join('_');
11191
11192      if(PENTAIR.AlgoliaAllTabSearchWidgets[indexWithoutEnvironment]){
11193        PENTAIR.AlgoliaAllTabSearchWidgets[indexWithoutEnvironment](search, indexName, containerElem);
11194      }
11195    }
11196
11197    /**
11198     * Updates browser state (URL) with current search parameters
11199     * @param {Object} params - Parameters to set in browser state
11200     */
11201    function setBrowserState(params) {
11202        //maintain wcmmode=disabled for author view-as-published mode
11203        // and other url params e.g. params used for tracking media performance in analytics solutions
11204        const nonAlgoliaURLParams = Object.fromEntries(
11205            Object.entries(getParams()).filter(entry => {
11206                const paramName = entry[0];
11207                const partialMatch = algoliaURLParamIdentifiers.some(identifier => {
11208                    return paramName.includes(identifier);
11209                });
11210                const exactMatch = algoliaURLParams.includes(paramName);
11211                return !partialMatch && !exactMatch;
11212            })
11213        );
11214        const mergedParams = {...params, ...nonAlgoliaURLParams};
11215
11216        // Build query string from merged params
11217        const url = new URL(window.location.href);
11218        const searchParams = new URLSearchParams();
11219        Object.entries(mergedParams).forEach(([key, value]) => {
11220          if (value !== null && value !== undefined && value !== '') {
11221            searchParams.set(key, value);
11222          }
11223        });
11224        url.search = searchParams.toString();
11225
11226        window.history.replaceState(mergedParams, null, url.toString());
11227    }
11228
11229    // ----------------------------------------
11230    // Initialization
11231    // ----------------------------------------
11232
11233    /**
11234     * Initializes the search component
11235     */
11236    function init() {
11237        reorderTabsForMobile();
11238        updateTabHeadingCounts();
11239
11240        initAlgoliaTabsRoot();
11241
11242        // Apply CSS class to all-tab index containers so card-width selectors (e.g. .all-tab .pentair-products) match
11243        componentElement.querySelectorAll('.all-tab .all-index[data-index]').forEach(elem => {
11244          const cssClass = elem.dataset.index.slice(elem.dataset.index.indexOf('_') + 1).replace('_', '-');
11245          elem.classList.add(cssClass);
11246        });
11247
11248        const searchInputContainer = componentElement.querySelector('.search-input-container');
11249        initAlgoliaSearchBox(searchClient, searchInputContainer.dataset.index, searchInputContainer);
11250
11251        initDropdownEventListeners();
11252
11253        initAlgoliaAllTab();
11254
11255        const debouncedInitialLoadAnalytics = debounce(updateAnalytics, 500);
11256
11257        allTabSearch.once('render', () => {
11258          initUiState();
11259
11260          debouncedInitialLoadAnalytics('initial');
11261
11262        });
11263
11264        initMobileFilters();
11265        initOwlEvents();
11266        initSeeAllLinks();
11267        const searchRoot = componentElement.closest('#search-root');
11268        initDynamicWidgetAccordianPanel(searchRoot?.querySelector('.dynamic-widgets'));
11269    }
11270
11271    /**
11272     * Wires "See All" / "View All" links in the All tab to open the corresponding
11273     * individual search tab. These links lost their click handlers when KO was removed.
11274     */
11275    function initSeeAllLinks() {
11276      const allTab = componentElement.querySelector('.all-tab');
11277      if (!allTab) return;
11278
11279      allTab.addEventListener('click', (event) => {
11280        const link = event.target.closest('.see-all a');
11281        if (!link) return;
11282        event.preventDefault();
11283        const wrapper = link.closest('.all-tab > div');
11284        const indexName = wrapper?.querySelector('.all-index[data-index]')?.dataset.index;
11285
11286        if (indexName) {
11287          openTab(indexName);
11288
11289        }
11290      });
11291    }
11292
11293    /**
11294     * Initializes event listeners for dropdown search interactions
11295     * Uses event delegation since Algolia widgets generate content dynamically
11296     */
11297    function initDropdownEventListeners() {
11298      const searchInputContainer = componentElement.querySelector('.search-input-container');
11299      const dropdownContainer = searchInputContainer?.querySelector('.dropdown-container');
11300
11301      if (!dropdownContainer) return;
11302
11303      // Dropdown suggestion clicks (query suggestions)
11304      const suggestionsContainer = dropdownContainer.querySelector('.suggestions');
11305      if (suggestionsContainer) {
11306        suggestionsContainer.addEventListener('click', (event) => {
11307          const link = event.target.closest('a');
11308          if (link) {
11309            event.preventDefault();
11310            dropdownSuggestionClick(event);
11311          }
11312        });
11313      }
11314
11315      // Dropdown popular pages clicks
11316      const popularPagesContainer = dropdownContainer.querySelector('.popular-pages');
11317      if (popularPagesContainer) {
11318        popularPagesContainer.addEventListener('click', (event) => {
11319          const link = event.target.closest('a');
11320          if (link) {
11321            dropdownSearchPopularPagesClick(event);
11322          }
11323        });
11324      }
11325
11326      // Dropdown popular pages count link clicks ("View X page results")
11327      const popularPagesCountContainer = dropdownContainer.querySelector('.popular-pages-count');
11328      if (popularPagesCountContainer) {
11329        popularPagesCountContainer.addEventListener('click', (event) => {
11330          const link = event.target.closest('a');
11331          if (link) {
11332            event.preventDefault();
11333            dropdownPopularPagesCountClick(event);
11334          }
11335        });
11336      }
11337
11338      // Dropdown product clicks (from hits widget)
11339      const productsContainer = dropdownContainer.querySelector('.products');
11340      if (productsContainer) {
11341        productsContainer.addEventListener('click', (event) => {
11342          const link = event.target.closest('a');
11343          if (link) {
11344            dropdownSearchProductClick(event);
11345          }
11346        });
11347      }
11348
11349      // Dropdown product count link clicks ("View X product results")
11350      const productsCountContainer = dropdownContainer.querySelector('.products-count');
11351      if (productsCountContainer) {
11352        productsCountContainer.addEventListener('click', (event) => {
11353          const link = event.target.closest('a');
11354          if (link) {
11355            event.preventDefault();
11356            dropdownSearchProductCountClick(event);
11357          }
11358        });
11359      }
11360
11361      // Search input Enter key handling
11362      const searchBoxes = componentElement.querySelectorAll('.search-box input');
11363      searchBoxes.forEach(searchBox => {
11364        searchBox.addEventListener('keypress', (event) => {
11365          if (event.which === 13 || event.keyCode === 13) {
11366            inputEnter(event);
11367          }
11368        });
11369      });
11370
11371      // Search button click
11372      const searchButton = componentElement.querySelector('.all-search');
11373      if (searchButton) {
11374        searchButton.addEventListener('click', doTabSearch);
11375      }
11376
11377      // Filter panel clicks for analytics tracking
11378      const filterContainers = componentElement.querySelectorAll('.filters');
11379      filterContainers.forEach(filterContainer => {
11380        filterContainer.addEventListener('click', (event) => {
11381          filterClick(event);
11382        });
11383      });
11384
11385      // Close dropdown when clicking outside this search component.
11386      document.addEventListener('click', (event) => {
11387        if (!componentElement.contains(event.target)) {
11388          searchBoxFocus = false;
11389          updateDropdownVisibility();
11390        }
11391      });
11392
11393      // Close dropdown on Escape when focus is inside this search component.
11394      document.addEventListener('keydown', (event) => {
11395        if (event.key === 'Escape' && componentElement.contains(document.activeElement)) {
11396          searchBoxFocus = false;
11397          updateDropdownVisibility();
11398        }
11399      });
11400    }
11401
11402    /**
11403     * Initializes mobile filter modal
11404     */
11405    function initMobileFilters(){
11406      const searchFilterModal = document.querySelector('#searchFilterModal');
11407      if (searchFilterModal) {
11408        const modalState = {
11409          mountedIndexName: null,
11410          sourceContainer: null,
11411          sourceParent: null,
11412          sourceNextSibling: null,
11413          placeholderContainer: null,
11414          placeholderDisplay: ''
11415        };
11416
11417        const getModalPanelByIndex = (indexName) => {
11418          return searchFilterModal.querySelector(`.filter-item[data-index="${indexName}"]`);
11419        };
11420
11421        const showOnlyModalSection = (indexName) => {
11422          searchFilterModal.querySelectorAll('article > div').forEach((sectionWrapper) => {
11423            const sectionFilterItem = sectionWrapper.querySelector('.filter-item[data-index]');
11424            if (!sectionFilterItem) {
11425              sectionWrapper.style.display = 'none';
11426              return;
11427            }
11428
11429            sectionWrapper.style.display = sectionFilterItem.dataset.index === indexName ? '' : 'none';
11430          });
11431        };
11432
11433        const getSourceContainerByIndex = (indexName) => {
11434          if (indexName === 'all') return null;
11435
11436          const activeTabContent = componentElement.querySelector(`.tab-search-content .item[data-index="${indexName}"]`);
11437          if (!activeTabContent) return null;
11438
11439          return activeTabContent.querySelector('.algolia-filter-container');
11440        };
11441
11442        const mountMobileFilters = (indexName) => {
11443          if (!indexName || indexName === 'all') return;
11444
11445          const modalPanel = getModalPanelByIndex(indexName);
11446          if (!modalPanel) return;
11447
11448          const modalFilterDropdown = modalPanel.querySelector('.filter-dropdown');
11449          if (!modalFilterDropdown) return;
11450
11451          if (modalState.mountedIndexName === indexName) return;
11452
11453          restoreMobileFilters();
11454          showOnlyModalSection(indexName);
11455
11456          const modalPlaceholder = modalFilterDropdown.querySelector('.algolia-filter-container');
11457
11458          const sourceContainer = getSourceContainerByIndex(indexName);
11459          if (!sourceContainer) return;
11460          modalState.mountedIndexName = indexName;
11461          modalState.sourceContainer = sourceContainer;
11462          modalState.sourceParent = sourceContainer.parentElement;
11463          modalState.sourceNextSibling = sourceContainer.nextSibling;
11464          modalState.placeholderContainer = modalPlaceholder;
11465          modalState.placeholderDisplay = modalPlaceholder?.style.display || '';
11466
11467          if (modalPlaceholder) {
11468            modalPlaceholder.style.display = 'none';
11469          }
11470
11471          modalFilterDropdown.appendChild(sourceContainer);
11472        };
11473
11474        const restoreMobileFilters = () => {
11475          if (!modalState.sourceContainer || !modalState.sourceParent) return;
11476
11477          if (modalState.sourceNextSibling && modalState.sourceNextSibling.parentNode === modalState.sourceParent) {
11478            modalState.sourceParent.insertBefore(modalState.sourceContainer, modalState.sourceNextSibling);
11479          } else {
11480            modalState.sourceParent.appendChild(modalState.sourceContainer);
11481          }
11482
11483          if (modalState.placeholderContainer) {
11484            modalState.placeholderContainer.style.display = modalState.placeholderDisplay;
11485          }
11486
11487          modalState.mountedIndexName = null;
11488          modalState.sourceContainer = null;
11489          modalState.sourceParent = null;
11490          modalState.sourceNextSibling = null;
11491          modalState.placeholderContainer = null;
11492          modalState.placeholderDisplay = '';
11493        };
11494
11495        // Capture which tab opened the modal (e.g., Product tab Filter Results button)
11496        // and only display that tab's filter section inside the modal.
11497        componentElement.querySelectorAll('[data-target="#searchFilterModal"]').forEach((trigger) => {
11498          trigger.addEventListener('click', (event) => {
11499            const tabItem = event.currentTarget.closest('.item[data-index]');
11500            const targetIndex = tabItem?.dataset.index || currentTab;
11501            mountMobileFilters(targetIndex);
11502          });
11503        });
11504
11505        // Fallback when modal is opened programmatically.
11506        if (!searchFilterModal.dataset.filterPanelObserverInitialized) {
11507          const observer = new MutationObserver(() => {
11508            const isOpen = searchFilterModal.classList.contains('in') || searchFilterModal.classList.contains('show');
11509            if (isOpen) {
11510              mountMobileFilters(currentTab);
11511            } else {
11512              restoreMobileFilters();
11513            }
11514          });
11515
11516          observer.observe(searchFilterModal, {
11517            attributes: true,
11518            attributeFilter: ['class']
11519          });
11520
11521          searchFilterModal.dataset.filterPanelObserverInitialized = 'true';
11522        }
11523
11524        mountMobileFilters(currentTab);
11525
11526        searchFilterModal.querySelectorAll('.dynamic-widgets').forEach((container) => {
11527          initDynamicWidgetAccordianPanel(container);
11528        });
11529
11530        // Wire up "Clear filters" links
11531        const clearFiltersLinks = searchFilterModal.querySelectorAll('a.green');
11532        clearFiltersLinks.forEach(link => {
11533          link.addEventListener('click', (event) => {
11534            event.preventDefault();
11535            const filterItem = event.target.closest('.filter-item');
11536            if (filterItem) {
11537              const indexName = filterItem.dataset.index;
11538              if (indexName && indexName !== 'all' && instantsearchWidgets[indexName]) {
11539                clearRefinements(indexName);
11540              }
11541            }
11542          });
11543        });
11544
11545        // Wire up "See Results" buttons to close modal
11546        const seeResultsButtons = searchFilterModal.querySelectorAll('.bottom-container .btn-primary');
11547        seeResultsButtons.forEach(button => {
11548          button.addEventListener('click', () => {
11549            restoreMobileFilters();
11550            searchFilterModal.querySelector('[data-dismiss="modal"]')?.click();
11551          });
11552        });
11553
11554        searchFilterModal.querySelector('[data-dismiss="modal"]')?.addEventListener('click', () => {
11555          restoreMobileFilters();
11556        });
11557      }
11558    }
11559
11560    /**
11561     * Reorders tabs for mobile view based on mobile index configuration
11562     */
11563    function reorderTabsForMobile(){
11564      const isMobile = window.matchMedia('(max-width: 767px)').matches;
11565      if(isMobile && mobileIndexNames?.length){
11566        const tabSearchName = componentElement.querySelector('.tab-search-name.owl-carousel');
11567        const tabSearchContent = componentElement.querySelector('.tab-search-content.owl-carousel');
11568        if(!tabSearchName || !tabSearchContent) return;
11569
11570        // If Owl already initialized, do not replace innerHTML.
11571        // Replacing markup after init removes Owl stage wrappers and breaks tab nav.
11572        const owlAlreadyInitialized =
11573          tabSearchName.classList.contains('owl-loaded') ||
11574          tabSearchContent.classList.contains('owl-loaded') ||
11575          !!tabSearchName.querySelector('.owl-stage-outer') ||
11576          !!tabSearchContent.querySelector('.owl-stage-outer');
11577
11578        if (owlAlreadyInitialized) {
11579          return;
11580        }
11581
11582        const reorderedTabNames = document.createElement('div');
11583        mobileIndexNames.forEach(indexName => {
11584          const elem = componentElement.querySelector(`.tab-search-name.owl-carousel .item.${indexName}`);
11585          if(elem) reorderedTabNames.appendChild(elem);
11586        });
11587
11588        const reorderedContentNames = document.createElement('div');
11589        mobileIndexNames.forEach(indexName => {
11590          const elem = componentElement.querySelector(`.tab-search-content .item[data-index="${indexName}"]`);
11591          if(elem) reorderedContentNames.appendChild(elem);
11592        });
11593
11594        // Fail safe: only replace when every configured index was matched.
11595        // This prevents partial matches from collapsing mobile tabs to only one item.
11596        const hasFullTabMatch = reorderedTabNames.children.length === mobileIndexNames.length;
11597        const hasFullContentMatch = reorderedContentNames.children.length === mobileIndexNames.length;
11598
11599        if(hasFullTabMatch) {
11600          tabSearchName.innerHTML = reorderedTabNames.innerHTML;
11601        }
11602
11603        if(hasFullContentMatch) {
11604          tabSearchContent.innerHTML = reorderedContentNames.innerHTML;
11605        }
11606      }
11607
11608    };
11609
11610    /**
11611     * Initializes UI state from URL parameters
11612     */
11613    function initUiState(){
11614      const paramObj = getParams();
11615      const firstTabInMobile = mobileIndexNames?.[0] || 'all';
11616      const defaultTab = isMobile ? firstTabInMobile : 'all';
11617      currentTab = !!paramObj.tab ? paramObj.tab : defaultTab;
11618
11619      openTab(currentTab);
11620
11621    }
11622
11623    /**
11624     * Initializes Owl Carousel event handlers for tab navigation
11625     */
11626    function initOwlEvents(){
11627      const debouncedCarouselChange = debounce(carouselChange, 500); // Prevents it from firing multiple times.
11628
11629      window.addEventListener('load', () => {
11630        componentElement.addEventListener('changed.owl.carousel', (event) => {
11631          const owlItems = event.target.querySelectorAll('.owl-item');
11632          const currentSlide = owlItems[event.item.index]?.children[0];
11633          if(currentSlide){
11634            const slideIndex = currentSlide.dataset.index;
11635            currentTab = slideIndex;
11636            debouncedCarouselChange(slideIndex);
11637          }
11638        });
11639      });
11640
11641      // Analytics Refinement Events
11642      window.addEventListener('load', () => {
11643        const tabCarousel = componentElement.querySelector('.tabs .tab-search-name.owl-carousel');
11644        const contentCarousel = componentElement.querySelector('.tabs .tab-search-content.owl-carousel');
11645
11646        if(tabCarousel){
11647          tabCarousel.addEventListener('click', (event) => {
11648            const owlItem = event.target.closest('.owl-item');
11649            if(owlItem && event.isTrusted){   // Distinguish from programmatic click events - they have their own AA events.
11650              updateAnalytics('refine');
11651              setOwlOuterHeight();
11652            }
11653          });
11654          tabCarousel.addEventListener('dragged.owl.carousel', () => {
11655            updateAnalytics('refine');
11656            setOwlOuterHeight();
11657          });
11658        }
11659
11660        if(contentCarousel){
11661          contentCarousel.addEventListener('dragged.owl.carousel', () => {
11662            updateAnalytics('refine');
11663          });
11664        }
11665      });
11666
11667    }
11668
11669    /**
11670     * Handles carousel slide change and updates browser state
11671     * @param {string} slideIndex - Index of the new slide
11672     */
11673    function carouselChange(slideIndex){
11674      setBrowserState(paramsFromCurrentState());
11675    }
11676
11677    const buildCleanRefinements = (refinements, filterContainer) => {
11678      if (!refinements.length) return [];
11679
11680      const grouped = refinements.reduce((acc, refinement) => {
11681        const bucket = acc[refinement.attributeName] || [];
11682        bucket.push(refinement);
11683        acc[refinement.attributeName] = bucket;
11684        return acc;
11685      }, {});
11686
11687      return Object.entries(grouped).map(([attr, vals]) => {
11688        const titleEl = filterContainer?.querySelector(`[data-filter-attribute="${attr}"]`);
11689        const filterName = (titleEl?.dataset.filterTitle || 'Categories') + ':';
11690        const valueStr = vals
11691          .map((refinement, index) => {
11692            const normalized = refinement.name.split(',').slice(-1)[0].split('|').slice(-1)[0];
11693            return normalized + (index < vals.length - 1 ? '^' : '');
11694          })
11695          .join('');
11696        return filterName + valueStr;
11697      });
11698    };
11699
11700    /**
11701     * Updates analytics tracking with search events
11702     * @param {string} eventType - Type of event (initial, refine, etc.)
11703     * @param {string} eventAction - Action performed (search, filter, etc.)
11704     */
11705    function updateAnalytics(eventType, eventAction) {
11706      const total = currentTab === 'all' ? allTotal() : totals[currentTab];
11707      let refinements = [];
11708      let lastResults;
11709      if(currentTab !== 'all'){
11710        lastResults = tabLastResults[currentTab] ?? null;
11711
11712        refinements = lastResults ? lastResults.getRefinements() : [];
11713      }
11714
11715      const filterContainer = componentElement.querySelector(
11716        `.tab-search-content .item[data-index="${currentTab}"] .algolia-filter-container`
11717      );
11718      const cleanRefinements = buildCleanRefinements(refinements, filterContainer);
11719
11720      if(typeof digitalData !== 'undefined' && digitalData && digitalData.event){
11721        const eventArr = {};
11722        eventArr.eventName = "site search";
11723        eventArr.eventAction = eventAction || (total ? "search" : "null");
11724        eventArr.type = eventType;
11725        eventArr.timeStamp = new Date();
11726        digitalData.event.push(eventArr);
11727      }
11728
11729      if(typeof digitalData !== 'undefined' && digitalData && digitalData.search){
11730        digitalData.search.searchType = "internal search";
11731        digitalData.search.searchQuery = inputSearchQuery;
11732        digitalData.search.searchFilter = currentTab.split('_').slice(-1)[0];
11733        digitalData.search.resultsNumber = parseInt(total);
11734        digitalData.search.searchFacet = refinements.length ? cleanRefinements.join('|') : "";
11735      }
11736
11737      // PAAS - Adobe Analytics Implementation
11738      const searchComponent = document.querySelector('#searchComponent');
11739      if (searchComponent && isInitialPageViewSearch) {
11740        isInitialPageViewSearch = false;
11741        const queryID = currentTab !== 'all' && lastResults ? lastResults.queryID : queryIDList.join(',');
11742        // Track the page view event, handled in clientlib-site/js/analytics/pageView.js
11743        trackSearchPageViewPayload(searchComponent, currentTab, total, queryID);
11744      }
11745    }
11746
11747    /**
11748     * Tracks the suggested search term/result click event payload.
11749     * @param searchTerm term typed in the box
11750     * @param suggestedSearchText term or result text in suggested area clicked on
11751     * @param queryID algolia query ID
11752     * @param isDirectResult true/false if the link clicked on was a suggested result linking directly to a page or product
11753     */
11754    function trackSuggestedSearchClickPayload(searchTerm, suggestedSearchText, queryID, isDirectResult) {
11755      const eventSearchSuggestedTermClickPayload = {
11756        eventName: isDirectResult ? 'search suggested result clicked' : 'search suggested term clicked',
11757        eventType: 'event',
11758        attributes: {
11759          search: {
11760            searchTerm: searchTerm,
11761            algoliaQueryID: queryID,
11762            searchType: "suggested search",
11763          },
11764          visitor: {
11765            pentairCustomerID: getPentairCustomerID(), //if this is available
11766            dealerID: getDealerID() //if this is available
11767          },
11768          page: {
11769            pageCanonical: getPageViewPageAttribute("pageCanonical"),
11770            pageName: getPageViewPageAttribute("pageName"),
11771            pagePath: getPageViewPageAttribute("pagePath"),
11772            pageType: getPageViewPageAttribute("pageType"),
11773            pageURL: getPageViewPageAttribute("pageURL"),
11774            language: getPageViewPageAttribute("language")
11775          }
11776        }
11777      }
11778      // Only add one of the keys; suggestedSearchTerm or suggestedSearchResult
11779      // This is done after inital creation of the object bc ternary operators can't be done with property id names
11780      const searchTextAttrName = isDirectResult ? 'suggestedSearchResult' : 'suggestedSearchTerm';
11781      eventSearchSuggestedTermClickPayload.attributes.search[searchTextAttrName] = suggestedSearchText;
11782      trackEventWithQueue(eventSearchSuggestedTermClickPayload);
11783    }
11784
11785    init();
11786  }
11787
11788// ========================================
11789// COMPONENT INITIALIZATION
11790// ========================================
11791
11792document.addEventListener('DOMContentLoaded', () => {
11793  // Initialize search components
11794  document.querySelectorAll('.search.component').forEach(element => {
11795    initSearch(element);
11796  });
11797});
11798
11799
11800document.addEventListener('DOMContentLoaded', function() {
11801  //View product click analytic
11802  document.querySelector('.products-count')?.addEventListener('click', function() {
11803    try {
11804        if (typeof digitalData !== 'undefined' && digitalData) {
11805          digitalData.searchBar = {};
11806          const query = document.querySelector('.search-box input')?.value ?? '';
11807          if (digitalData.event) {
11808            const eventData = {};
11809            eventData.eventName = "search bar"
11810            eventData.eventAction = "view product";
11811            eventData.type = "user Input";
11812            eventData.timeStamp = new Date();
11813            digitalData.event.push(eventData);
11814          }
11815          if (digitalData.searchBar) {
11816            digitalData.searchBar.searchQuery = query;
11817          }
11818        }
11819      } catch(err) {
11820        console.log(err)
11821      }
11822    });
11823
11824    document.querySelector('header a.icon-search')?.addEventListener('click', function() {
11825      searchBarInitiate();
11826    });
11827
11828    function searchBarInitiate() {
11829      if (typeof digitalData !== 'undefined' && digitalData && digitalData.event) {
11830          const eventData = {};
11831          eventData.eventName = "search bar"
11832          eventData.eventAction = "initiate";
11833          eventData.type = "default";
11834          eventData.timeStamp = new Date();
11835          digitalData.event.push(eventData);
11836        }
11837    }
11838
11839    searchResultClickAnalytic = function(event, title, pageDepth) {
11840      if (window._satellite) {
11841        _satellite.track('search page result click', {searchPageResultLink: title, searchPageResultDepth: pageDepth});
11842      }
11843
11844      // PAAS - Adobe Analytics
11845      let queryID;
11846      let hitItem;
11847      if (event.currentTarget) {
11848        if (event.currentTarget.dataset) {
11849          queryID = event.currentTarget.dataset.queryId;
11850        }
11851        hitItem = event.currentTarget.closest(".ais-Hits-item");
11852      }
11853      const hitsListElem = hitItem ? hitItem.closest(".ais-Hits-list") : '';
11854      const hitsList = hitsListElem ? Array.from(hitsListElem.children) : [];
11855      // Hit index should start at 1 for analytics not 0
11856      const hitIndex = hitsList.includes(hitItem) ? hitsList.indexOf(hitItem) + 1 : -1;
11857
11858      // Default search term and active tab
11859      let searchTerm = '';
11860      let activeTab = 'all';
11861
11862      // Get search term and active tab from url query params if exists
11863      if (window.location.search) {
11864        const urlQueryParamsMap = Object.fromEntries(window.location.search
11865            .slice(1)
11866            .split('&')
11867            .map(function(item) {
11868              return item.split('=');
11869            }));
11870        searchTerm = decodeURIComponent(urlQueryParamsMap.q ? urlQueryParamsMap.q : '').replace(/\+/g, ' ');
11871        const tabParam = decodeURIComponent(urlQueryParamsMap.tab ? urlQueryParamsMap.tab : '').replace(/\+/g, ' ');
11872        activeTab = tabParam.includes('_')
11873            ? tabParam.slice(tabParam.indexOf('_') + 1) // Take off the environment from the index name
11874            : tabParam ? tabParam : 'all'; // Default to 'all' if tabParam is undefined/empty/null
11875      }
11876
11877      const eventSearchResultClickPayload = {
11878        eventName: 'search result clicked',
11879        eventType: 'event',
11880        attributes: {
11881          search: {
11882            searchTerm: searchTerm,
11883            searchResultClicked: title,
11884            searchResultIndex: activeTab + '|page' + pageDepth + '|index' + hitIndex,
11885            algoliaQueryID: queryID
11886          },
11887          visitor: {
11888            pentairCustomerID: getPentairCustomerID(),
11889            dealerID: getDealerID()
11890          }
11891        }
11892      }
11893      trackEventWithQueue(eventSearchResultClickPayload);
11894    }
11895});
11896
11897$(document).ready(function () {
11898    // document.querySelectorAll('.product-grid-carousel').forEach(function() {
11899    $('.product-grid-carousel').owlCarousel({
11900        autoplay: false,
11901        lazyLoad: true,
11902        /*
11903        animateOut: 'fadeOut',
11904        animateIn: 'fadeIn',
11905        */
11906        /* responsiveClass: true,
11907            autoHeight: true,
11908            autoplayTimeout: 7000,
11909            smartSpeed: 800,*/
11910        nav: true,
11911        touchDrag: true,
11912        rewind: true,
11913        navText: true,
11914        autoWidth: true,
11915
11916        responsive: {
11917            0: {
11918                items: 1,
11919                margin: 10,
11920            },
11921            600: {
11922                items: 2,
11923                margin: 15,
11924            },
11925            992: {
11926                items: 3,
11927                margin: 20,
11928            },
11929        },
11930    });
11931
11932});
11933
11934// });
11935
11936const PLACEHOLDER_IMAGE = '/content/dam/extranet/product-related/product-photo/Placeholder Image.png.thumb.319.319.png';
11937const THUMB_EXTENSION = '.thumb.319.319.png';
11938const HTML_TAG_REGEX = /<\/?[a-z][^>]*>/gi;
11939const SPACE_REGEX = / /g;
11940const NON_NUMERIC_REGEX = /[^0-9.-]+/g;
11941const DEFAULT_SHIPPING_LIMIT = 49;
11942
11943/**
11944 * Shared factory for Algolia product/search grid widget sets.
11945 * Shared wiring lives here; callers supply hit renderers and component ID.
11946 *
11947 * Config:
11948 *   componentId       {string}    DOM id whose data-attr-filters / data-attr-labels drive dynamic filters
11949 *   extraSKUGridTypes {string[]}  Additional gridItemType values that use SKU rendering (default [])
11950 *   fixShowMore       {boolean}   Call fixShowMoreButtons() on every render (default false)
11951 *   renderSKUHit      {Function}  (hit, { html, sendEvent, indexName, currentPage, freeShipingPriceLimit }) => html
11952 *   renderProductHit  {Function}  (hit, { html, components, sendEvent, indexName, currentPage }) => html
11953 */
11954function createGridSearchWidgets(config) {
11955    const {
11956        componentId,
11957        extraSKUGridTypes = [],
11958        fixShowMore = false,
11959        renderSKUHit,
11960        renderProductHit
11961    } = config;
11962
11963    const FILTER_LIMITS = {
11964        DEFAULT: 10,
11965        CATEGORIES: 20,
11966        RATING: 50,
11967        RATING_MODAL: 100,
11968        SHOW_MORE: 50
11969    };
11970
11971    function fixShowMoreButtons() {
11972        document.querySelectorAll('.ais-RefinementList-showMore').forEach(btn => btn.type = 'button');
11973    }
11974
11975    function displayBackLink() {
11976        const resultsElement = document.querySelector('.results-count');
11977        if (!resultsElement) return;
11978        const resultsTextElement = resultsElement.querySelector('.ais-Stats-text');
11979        if (resultsTextElement?.innerHTML === 'No product results') {
11980            resultsElement.classList.add('results-count__no-results');
11981            resultsTextElement.classList.add('results-count__no-results--text');
11982            if (!resultsElement.querySelector('.results-count__no-results--link')) {
11983                resultsTextElement.insertAdjacentHTML('afterend',
11984                    `<div class="results-count__no-results--link"><a href="${window.location.href}"><span>Return to previous page</span></a></div>`
11985                );
11986            }
11987        }
11988    }
11989
11990    // Keep this analogous to searchWidgets.js normalizeRefinementLabel
11991    const normalizeRefinementLabel = (label) => {
11992        const labelText = String(label || '');
11993        const commaParts = labelText.split(',')[1]?.trim() || labelText;
11994        return commaParts.split('|')[1]?.trim() || commaParts;
11995    };
11996
11997    const normalizeFilterItems = items => items.map(item => ({
11998        ...item,
11999        label: normalizeRefinementLabel(item.label),
12000        highlighted: normalizeRefinementLabel(item.highlighted || item.label)
12001    }));
12002
12003    const ratingItemTemplate = ({ count, cssClasses, value, url, stars }) => {
12004        const wrapper = count
12005            ? `<a class="${cssClasses.link}" aria-label="${value} & up" href="${url}">`
12006            : `<div class="${cssClasses.link}" aria-label="${value} & up" disabled>`;
12007        const starsHtml = stars.map(filled =>
12008            `<svg class="${cssClasses.starIcon} ${filled ? cssClasses.fullStarIcon : cssClasses.emptyStarIcon}" aria-hidden="true" width="24" height="24">` +
12009            `<use xlink:href="${filled ? '#ais-RatingMenu-starSymbol_0' : '#ais-RatingMenu-starEmptySymbol_0'}"></use></svg>`
12010        ).join('');
12011        const closeTag = count ? '</a>' : '</div>';
12012        return wrapper + starsHtml +
12013            `<span class="${cssClasses.label}">&amp; Up</span>` +
12014            (count ? `<span class="${cssClasses.count}">${count.toLocaleString()}</span>` : '') +
12015            closeTag;
12016    };
12017
12018    const hideZeroItems = items => items.filter(item => item.count > 0 || item.isRefined);
12019
12020    function getDynamicFilterWidgets(search, indexName, containerElem, prefix, hideZeroCount) {
12021        const gridComponent = document.getElementById(componentId);
12022        if (!gridComponent) return [];
12023        let dynamicFilters = [];
12024        let dynamicLabels = {};
12025        try {
12026            dynamicFilters = gridComponent.dataset.attrFilters ? JSON.parse(gridComponent.dataset.attrFilters) : [];
12027            dynamicLabels = gridComponent.dataset.attrLabels ? JSON.parse(gridComponent.dataset.attrLabels) : {};
12028        } catch (error) {
12029            console.error('Error parsing dynamic filter data:', error);
12030            return [];
12031        }
12032        const options = dynamicFilters.map(attributeName => {
12033            const labelParts = attributeName.split('_');
12034            const defaultLabel = labelParts[1] ? labelParts[1].replace('_', ' ') : attributeName;
12035            const attributeLabel = dynamicLabels[`${attributeName}_label`] || defaultLabel;
12036            return {
12037                name: attributeLabel,
12038                attribute: attributeName,
12039                containerElem: containerElem?.querySelector(`.filters .${attributeName}`),
12040                prefix: prefix || '',
12041                limit: FILTER_LIMITS.DEFAULT,
12042                showMore: true,
12043                showMoreLimit: FILTER_LIMITS.SHOW_MORE
12044            };
12045        });
12046        return options.map(widgetOptions =>
12047            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel(widgetOptions.name, widgetOptions.attribute)({
12048                container: widgetOptions.containerElem,
12049                attribute: widgetOptions.attribute,
12050                limit: widgetOptions.limit || FILTER_LIMITS.DEFAULT,
12051                showMore: widgetOptions.showMore || false,
12052                showMoreLimit: widgetOptions.showMoreLimit || FILTER_LIMITS.SHOW_MORE,
12053                transformItems: items => normalizeFilterItems(hideZeroCount ? hideZeroItems(items) : items)
12054            })
12055        );
12056    }
12057
12058    // Named to match index
12059    function pentair_products(search, indexName, containerElem, hiddenFilterAttributes, gridItemType, freeShipingPriceLimit) {
12060        let currentPage = 1;
12061        const isSkuType = gridItemType === 'sku' || extraSKUGridTypes.includes(gridItemType);
12062
12063        let sortByItems = [
12064            { value: indexName,                     label: 'Sort by Relevance' },
12065            { value: indexName + '_price_asc',      label: 'Price low to high' },
12066            { value: indexName + '_price_dsc',      label: 'Price high to low' },
12067            { value: indexName + '_sort_alpha_asc', label: 'A-Z' },
12068            { value: indexName + '_sort_alpha_dsc', label: 'Z-A' }
12069        ];
12070        if (!isSkuType) sortByItems = sortByItems.filter(item => !item.value.includes('_price'));
12071
12072        const statsResultsText = ({ nbHits, query }) => {
12073            const q = query ? ` for "${query}"` : '';
12074            return nbHits === 0 ? `No product results${q}` : nbHits === 1 ? `1 product result${q}` : `${nbHits} product results${q}`;
12075        };
12076
12077        const statsPaginationText = (result) => {
12078            displayBackLink();
12079            if (result.nbHits <= 1) return '';
12080            const first = result.hitsPerPage * result.page + 1;
12081            const last = Math.min(first + result.hitsPerPage - 1, result.nbHits);
12082            return `Showing ${first}-${last} of ${result.nbHits} results`;
12083        };
12084
12085        const mainWidgets = [
12086            PENTAIR.CustomAlgoliaWidgets.clearRefinements(hiddenFilterAttributes)({
12087                container: containerElem.querySelector('.filters .clear-refinements')
12088            }),
12089            PENTAIR.CustomAlgoliaWidgets.currentRefinements(hiddenFilterAttributes)({
12090                container: containerElem.querySelector('.filters .current-refinements')
12091            }),
12092            PENTAIR.CustomAlgoliaWidgets.dynamicHierarchicalMenu()({
12093                container: containerElem.querySelector('.filters .categories'),
12094                limit: FILTER_LIMITS.CATEGORIES,
12095                sortBy: ['count:desc'],
12096                attributes: ['categories.lvl0', 'categories.lvl1']
12097            }),
12098            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Product Type', 'channel')({
12099                container: containerElem.querySelector('.filters .channel'),
12100                attribute: 'channel',
12101                limit: FILTER_LIMITS.DEFAULT,
12102                showMore: true,
12103                showMoreLimit: FILTER_LIMITS.SHOW_MORE,
12104                transformItems: normalizeFilterItems
12105            }),
12106            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Brands', 'brands')({
12107                container: containerElem.querySelector('.filters .brands'),
12108                attribute: 'brands',
12109                limit: FILTER_LIMITS.DEFAULT,
12110                showMore: true,
12111                showMoreLimit: FILTER_LIMITS.SHOW_MORE,
12112                transformItems: normalizeFilterItems
12113            }),
12114            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Applications', 'applications')({
12115                container: containerElem.querySelector('.filters .applications'),
12116                attribute: 'applications',
12117                limit: FILTER_LIMITS.DEFAULT,
12118                showMore: true,
12119                showMoreLimit: FILTER_LIMITS.SHOW_MORE,
12120                transformItems: normalizeFilterItems
12121            }),
12122            PENTAIR.CustomAlgoliaWidgets.ratingFilterPanel('Average Customer Rating', 'productRating')({
12123                container: '.filters .rating.filter-container',
12124                attribute: 'productRating',
12125                limit: FILTER_LIMITS.DEFAULT,
12126                showMore: true,
12127                showMoreLimit: FILTER_LIMITS.RATING,
12128                templates: { item: ratingItemTemplate }
12129            }),
12130            instantsearch.widgets.hitsPerPage({
12131                container: containerElem.querySelector('.hits-per-page'),
12132                items: [
12133                    { label: '12 products/page', value: 12, default: true },
12134                    { label: '24 products/page', value: 24 },
12135                    { label: 'View All', value: 1000 }
12136                ]
12137            }),
12138            instantsearch.widgets.sortBy({
12139                container: containerElem.querySelector('.sorting'),
12140                items: sortByItems
12141            }),
12142            instantsearch.widgets.stats({
12143                container: containerElem.querySelector('.results-count'),
12144                templates: { text: statsResultsText }
12145            }),
12146            instantsearch.widgets.stats({
12147                container: containerElem.querySelector('.pagination-message'),
12148                templates: { text: statsPaginationText }
12149            }),
12150            instantsearch.widgets.hits({
12151                container: containerElem.querySelector('.results'),
12152                templates: {
12153                    item: (hit, { html, components, sendEvent }) => {
12154                        const ctx = { html, components, sendEvent, indexName, currentPage, freeShipingPrice
12154Limit };
12155                        return isSkuType ? renderSKUHit(hit, ctx) : renderProductHit(hit, ctx);
12156                    },
12157                    empty: ''
12158                }
12159            }),
12160            PENTAIR.CustomAlgoliaWidgets.virtualSearchBox(),
12161            PENTAIR.CustomAlgoliaWidgets.virtualRefinementList({ attribute: 'microApplications' }),
12162            PENTAIR.CustomAlgoliaWidgets.virtualRefinementList({ attribute: 'channel' }),
12163            PENTAIR.CustomAlgoliaWidgets.virtualRefinementList({ attribute: 'brands' }),
12164            PENTAIR.CustomAlgoliaWidgets.virtualRefinementList({ attribute: 'applications' }),
12165            PENTAIR.CustomAlgoliaWidgets.virtualRefinementList({ attribute: 'flatCategories' })
12166        ];
12167
12168        search.addWidgets(mainWidgets.concat(getDynamicFilterWidgets(search, indexName, containerElem)));
12169
12170        const modalElem = document.getElementById('productGridModal');
12171        search.addWidgets(getDynamicFilterWidgets(search, indexName, modalElem, 'modal_', true));
12172        search.addWidgets([
12173            PENTAIR.CustomAlgoliaWidgets.dynamicHierarchicalMenu()({
12174                container: modalElem?.querySelector('.filters .categories'),
12175                limit: FILTER_LIMITS.CATEGORIES,
12176                sortBy: ['count:desc'],
12177                attributes: ['categories.lvl0', 'categories.lvl1']
12178            }),
12179            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Product Type', 'channel')({
12180                container: modalElem?.querySelector('.filters .channel'),
12181                attribute: 'channel',
12182                limit: FILTER_LIMITS.DEFAULT,
12183                showMore: true,
12184                showMoreLimit: FILTER_LIMITS.SHOW_MORE,
12185                transformItems: items => normalizeFilterItems(hideZeroItems(items))
12186            }),
12187            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Brands', 'brands')({
12188                container: modalElem?.querySelector('.filters .brands'),
12189                attribute: 'brands',
12190                limit: FILTER_LIMITS.DEFAULT,
12191                showMore: true,
12192                showMoreLimit: FILTER_LIMITS.SHOW_MORE,
12193                transformItems: items => normalizeFilterItems(hideZeroItems(items))
12194            }),
12195            PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Applications', 'applications')({
12196                container: modalElem?.querySelector('.filters .applications'),
12197                attribute: 'applications',
12198                limit: FILTER_LIMITS.DEFAULT,
12199                showMore: true,
12200                showMoreLimit: FILTER_LIMITS.SHOW_MORE,
12201                transformItems: items => normalizeFilterItems(hideZeroItems(items))
12202            }),
12203            PENTAIR.CustomAlgoliaWidgets.ratingFilterPanel('Average Customer Rating', 'productRating')({
12204                container: '#productGridModal .rating.filter-container',
12205                attribute: 'productRating',
12206                limit: FILTER_LIMITS.DEFAULT,
12207                showMore: true,
12208                showMoreLimit: FILTER_LIMITS.RATING_MODAL,
12209                templates: { item: ratingItemTemplate }
12210            }),
12211            instantsearch.widgets.hitsPerPage({
12212                container: modalElem?.querySelector('.hits-per-page'),
12213                items: [
12214                    { label: '12 products/page', value: 12, default: true },
12215                    { label: '24 products/page', value: 24 }
12216                ]
12217            }),
12218            instantsearch.widgets.sortBy({
12219                container: modalElem?.querySelector('.sorting'),
12220                items: sortByItems
12221            })
12222        ]);
12223
12224        const isMobile = window.matchMedia('(max-width: 767px)').matches;
12225        search.addWidgets([
12226            instantsearch.widgets.pagination({
12227                container: containerElem.querySelector('.algolia-pagination'),
12228                showFirst: false,
12229                showLast: false,
12230                padding: isMobile ? 1 : 2,
12231                templates: { next: '', previous: '' },
12232                ...(isMobile ? { scrollTo: containerElem } : {})
12233            })
12234        ]);
12235
12236        search.on('render', () => {
12237            currentPage = (search.renderState?.[indexName]?.pagination?.currentPage ?? 0) + 1;
12238            if (fixShowMore) fixShowMoreButtons();
12239        });
12240    }
12241
12242    return { pentair_products, getDynamicFilterWidgets };
12243}
12244
12245(function () {
12246    'use strict';
12247
12248    window.PENTAIR = window.PENTAIR || {};
12249
12250    function renderSKUHit(hit, { html, sendEvent, indexName, currentPage, freeShipingPriceLimit }) {
12251        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.url);
12252        const productRating = hit.productRating ? html`<span class="rating">${hit.productRating}</span>` : '';
12253        const reviewCountHtml = hit.productReviewCount ? html`<span class="review-count">(${hit.productReviewCount} reviews)</span>` : '';
12254        const stars = PENTAIR.AlgoliaHelpers.createStarRating(hit.productRating);
12255        const ratingHtml = (productRating && stars) ? html`<div class="ratings-container">${html([stars])}${productRating} ${reviewCountHtml}</div>` : '';
12256        const title = hit.productName || hit.title;
12257        const fullDescription = hit.skuDescription || '';
12258        const description = fullDescription ? fullDescription.replace(HTML_TAG_REGEX, ' ') : '';
12259        const isInStock = hit.stockStatus === 'IN STOCK';
12260        const notInStock = hit.stockStatus === 'OUT OF STOCK';
12261        const skuId = hit.skuId || '';
12262        const hitThumbnail = hit.productThumbnail;
12263        const thumbExtension = hitThumbnail?.startsWith('/content/dam') && hitThumbnail.includes('thumb.319.319') ? THUMB_EXTENSION : '';
12264        const displayPrice = hit.salePrice || '';
12265        const startPrice = hit.startPrice || '';
12266        const displayPriceToCompare = displayPrice || startPrice;
12267        const shipLimit = freeShipingPriceLimit || DEFAULT_SHIPPING_LIMIT;
12268        const priceToCompare = displayPriceToCompare ? Number(displayPriceToCompare.replace(NON_NUMERIC_REGEX, '')) : -1;
12269        const freeShippingHtml = (priceToCompare > 0 && priceToCompare > shipLimit)
12270            ? html`<div class="free-shipping-container"><img class="free-shipping-container_icon" src="/content/dam/extranet/enterprise/images/icons/shipping.svg" alt=""/><span class="free-shipping-container_text">Free Shipping!</span></div>`
12271            : '';
12272        const skuStatus = hit.skuStatus?.toLowerCase();
12273        const isDiscontinued = skuStatus === 'discontinued';
12274        const isFeatured = skuStatus === 'featured';
12275        const isRecommended = skuStatus === 'recommended';
12276        const imgSrc = hitThumbnail ? `${hitThumbnail}${thumbExtension}` : PLACEHOLDER_IMAGE;
12277        const priceHtml = displayPrice
12278            ? html`<span class="sale-price">${displayPrice}</span><span class="starting-price-strike">${startPrice}</span>`
12279            : html`<span class="starting-price">${startPrice}</span>`;
12280        let buttonHtml = '';
12281        if (isInStock && !isDiscontinued) {
12282            buttonHtml = html`<button class="sku-view-product-btn sku-atc-btn-impact-green" data-sku-id="${skuId}" onClick="${() => sendEvent('conversion', hit, 'Product Grid: View Product Button Click')}" target="${isExternal ? '_blank' : '_self'}">VIEW PRODUCT</button>`;
12283        } else if (notInStock && !isDiscontinued) {
12284            buttonHtml = html`<button class="sku-out-of-stock-btn" data-sku-id="${skuId}">OUT OF STOCK</button>`;
12285        } else if (isDiscontinued) {
12286            buttonHtml = html`<button class="sku-out-of-stock-btn" disabled data-sku-id="${skuId}">DISCONTINUED</button>`;
12287        }
12288
12289        // Ribbon logic
12290        const showRibbon = hit.discontinueBanner !== 'true' && !isDiscontinued;
12291        let ribbonHtml = '';
12292        if (showRibbon) {
12293            if (isFeatured) {
12294                ribbonHtml = html`<div class="ribbon ribbon-top-left featured-color"><span>Featured</span></div>`;
12295            } else if (isRecommended) {
12296                ribbonHtml = html`<div class="ribbon ribbon-top-left recommended-color"><span>Recommended</span></div>`;
12297            }
12298        }
12299
12300        return html`<a class="sku-item" data-page="${currentPage}" href="${hit.url}?queryID=${hit.__queryID}&objectID=${hit.objectID}&indexName=${indexName}" aria-label="Link to ${title}" onClick="${() => sendEvent('click', hit, 'Product Grid: Product SKU Click')}" target="${isExternal ? '_blank' : '_self'}">
12301            <div class="top-image contain"><img loading="lazy" src="${imgSrc}" alt="Product Image"/></div>
12302            <div class="title title-text">${title}</div>
12303            <div class="model-number">SKU #: <strong>${skuId}</strong></div>
12304            <span class="description description-text">${description}</span>
12305            ${ratingHtml}
12306            <div class="card-footer">
12307                <div class="price-container">${priceHtml}</div>
12308                ${freeShippingHtml}
12309                ${buttonHtml}
12310            </div>
12311            ${ribbonHtml}
12312        </a>`;
12313    }
12314
12315    function renderProductHit(hit, { html, components, sendEvent, indexName, currentPage }) {
12316        const isExternal = PENTAIR.AlgoliaHelpers.getTarget(hit.url);
12317        const productRating = hit.productRating ? html`<span class="rating">${hit.productRating}</span>` : '';
12318        const stars = PENTAIR.AlgoliaHelpers.createStarRating(hit.productRating);
12319        const ratingHtml = (productRating && stars) ? html`<div class="ratings-container">${html([stars])}${productRating}</div>` : '';
12320
12321        const titleProp = hit.productName ? 'productName' : 'title';
12322        const title = components.Snippet({ attribute: titleProp, highlightedTagName: 'mark', hit });
12323        const imgSrc = hit.productThumbnail ? `${hit.productThumbnail}${THUMB_EXTENSION}` : PLACEHOLDER_IMAGE;
12324        const discontinuedBanner = hit.discontinueBanner === 'true' ? html`<div class="ribbon ribbon-top-left"><span>Discontinued</span></div>` : '';
12325        return html`<a class="product-item" data-page="${currentPage}" href="${hit.url}?queryID=${hit.__queryID}&objectID=${hit.objectID}&indexName=${indexName}" aria-label="Link to ${hit[titleProp]}" onClick="${() => sendEvent('click', hit, 'Product Grid: Product Click')}" target="${isExternal ? '_blank' : '_self'}">
12326            <div class="top-image contain"><img loading="lazy" src="${imgSrc}" alt="Product Image"/></div>
12327            <div class="title title-text">${title}</div>
12328            ${ratingHtml}${discontinuedBanner}
12329        </a>`;
12330    }
12331
12332    PENTAIR.AlgoliaProductGridSearchWidgets = createGridSearchWidgets({
12333        componentId: 'productGridComponent',
12334        fixShowMore: true,
12335        renderSKUHit,
12336        renderProductHit
12337    });
12338
12339})();
12340
12341(function() {
12342'use strict';
12343
12344// ========================================
12345// GLOBAL HELPER FUNCTIONS
12346// ========================================
12347
12348/**
12349 * Parses URL query parameters into an object
12350 * @returns {object} Object mapping parameter names to values
12351 */
12352const getParams = () => {
12353    // gets url parameters and builds an object
12354    return _.chain(location.search.slice(1).split('&'))
12355           .map(item => { if (item) { return item.split('='); } })
12356           .compact()
12357           .object()
12358           .value();
12359};
12360
12361/**
12362 * Extracts refinement filters from URL parameters
12363 * @returns {object} Object with hierarchical and disjunctive refinements
12364 */
12365const getRefinements = () => {
12366    const params = getParams();
12367
12368    const refinementHelper = (refinementType) => {
12369        return _.reduce(params, (acc, value, key) => {
12370            const hierarchical = key.split('.' + refinementType);
12371            const returnObj = {};
12372            if(hierarchical.length > 1){
12373                returnObj[hierarchical[0]] = decodeURIComponent(value.replace(/\+/gm,"%20")).split(';');
12374            }
12375            return Object.assign(acc, returnObj);
12376        }, {});
12377    };
12378
12379    const hierarchical = refinementHelper('hierarchical');
12380    const disjunctive = refinementHelper('disjunctive');
12381
12382    return {hierarchical: hierarchical, disjunctive: disjunctive};
12383};
12384
12385/**
12386 * Sets up click event listeners for quickview buttons
12387 * Prevents navigation to SKU page and opens modal instead
12388 */
12389const setupQuickviewClickListeners = () => {
12390    const quickviewBtns = document.querySelectorAll('.quickview');
12391    quickviewBtns.forEach((quickviewBtnElement) => {
12392        quickviewBtnElement.addEventListener('click', (e) => {
12393            // Prevent add to cart btn click from going to sku page
12394            e.preventDefault();
12395
12396            const skuPage = quickviewBtnElement.dataset.skuPage;
12397            if (!skuPage) {
12398                return;
12399            }
12400
12401            requestAndBuildQuickview(skuPage);
12402        });
12403    });
12404};
12405
12406/**
12407 * Changes the SKU in quickview modal when user selects a different variant
12408 * Similar to product-information component but modified for modal context
12409 * @param {string} keyname - Key containing new SKU ID in format "key#skuid"
12410 * @param {string} oldSkuPage - Current SKU page URL
12411 * @param {string}
12411 oldSku - Current SKU identifier
12412 * @param {boolean} isConfigurable - Whether product is configurable
12413 */
12414const changeSku = (keyname, oldSkuPage, oldSku, isConfigurable) => {
12415    if(keyname !== '' && keyname != 'undefined'){
12416        const keyArr = keyname.split("#");
12417        if(keyArr.length == 2){
12418            const skuid = keyArr[1];
12419            const productFindingMethod = localStorage.getItem("productFindingMethodTemp");
12420
12421            // Set productFindingMethod for Analytics
12422            localStorage.setItem("productFindingMethod", productFindingMethod);
12423            document.cookie="productFindingMethod=" + productFindingMethod +"; domain=.pentair.com; path=/";
12424
12425            oldSkuPage = oldSkuPage.replace(oldSku, skuid);
12426            requestAndBuildQuickview(oldSkuPage, '');
12427        }
12428    }
12429};
12430
12431/**
12432 * Populates quickview modal with product information and overview
12433 * @param {Document} doc - Parsed HTML document
12434 * @param {HTMLElement} modalDom - Modal DOM element
12435 */
12436const populateQuickviewProductInfo = (doc, modalDom) => {
12437    const productInformationContainer = doc.querySelector('.component.product-information');
12438    const productOverviewContainer = doc.querySelector('.product-overview');
12439
12440    if (productInformationContainer) {
12441        const quickViewProductInfo = modalDom.querySelector('.quick-view-product-information');
12442        if (quickViewProductInfo) {
12443            quickViewProductInfo.innerHTML = productInformationContainer.outerHTML;
12444        }
12445        const productInfoInModal = document.querySelector('#skuQuickviewModal .component.product-information');
12446        if (productInfoInModal) {
12447            new ProductBuyCard(productInfoInModal);
12448        }
12449    }
12450
12451    if (productOverviewContainer) {
12452        const quickViewOverview = modalDom.querySelector('.quick-view-overview');
12453        if (quickViewOverview) {
12454            quickViewOverview.innerHTML = productOverviewContainer.innerHTML;
12455        }
12456    }
12457};
12458
12459/**
12460 * Adds SKU title and full details link to quickview modal
12461 * @param {HTMLElement} modalDom - Modal DOM element
12462 * @param {string} skuPage - SKU page URL
12463 */
12464const addQuickviewTitleAndLink = (modalDom, skuPage) => {
12465    const productSku = modalDom.querySelector('.prod-sku');
12466    const productInfoComp = modalDom.querySelector('.component.product-information');
12467    const skuTitle = productInfoComp?.dataset.productName;
12468    if (productSku && skuTitle) {
12469        productSku.insertAdjacentHTML('beforebegin', `<h3>${skuTitle}</h3>`);
12470    }
12471
12472    const productBuyCard = modalDom.querySelector('.product-buy-card');
12473    if (productBuyCard) {
12474        productBuyCard.insertAdjacentHTML('afterend', `<div class="view-full-details"><a href="${skuPage}" class="btn btn-secondary" target="_blank" rel="noopener noreferrer">VIEW FULL DETAILS</a></div>`);
12475    }
12476};
12477
12478/**
12479 * Handles out of stock state in quickview modal
12480 * @param {HTMLElement} modalDom - Modal DOM element
12481 */
12482const handleQuickviewOutOfStock = (modalDom) => {
12483    const productInfoComp = modalDom.querySelector('.component.product-information');
12484    const outOfStock = productInfoComp?.dataset.stock === "OUT_OF_STOCK";
12485
12486    if (outOfStock) {
12487        const stockElem = modalDom.querySelector('.stock');
12488        if (stockElem) stockElem.classList.add('out-of-stock');
12489
12490        const productBuyCard = modalDom.querySelector('.product-buy-card');
12491        const buttonsElem = productBuyCard?.querySelector('.buttons');
12492        if (buttonsElem) {
12493            buttonsElem.innerHTML = '<div class="out-of-stock"><a class="btn btn-disabled" target="_blank" rel="noopener noreferrer">OUT OF STOCK</a></div>';
12494        }
12495    }
12496};
12497
12498/**
12499 * Sets up SKU selector event listener in quickview modal
12500 * @param {HTMLElement} modalDom - Modal DOM element
12501 * @param {string} skuPage - SKU page URL
12502 */
12503const setupQuickviewSkuSelector = (modalDom, skuPage) => {
12504    const skuSelector = modalDom.querySelector('.skuselector');
12505    if (skuSelector) {
12506        skuSelector.addEventListener('click', (e) => {
12507            const valuesDiv = e.target.closest('div.values');
12508            if (valuesDiv) {
12509                const keyname = valuesDiv.dataset.keyname;
12510                const productInfo = modalDom.querySelector('.component.product-information');
12511                const isConfigurable = productInfo?.dataset.productC
12511onfigurable;
12512                const oldSku = productInfo?.dataset.productSku;
12513                changeSku(keyname, skuPage, oldSku, isConfigurable);
12514            }
12515        });
12516    }
12517};
12518
12519/**
12520 * Removes loading spinner from modal
12521 * @param {HTMLElement} modal - Modal element
12522 */
12523const removeQuickviewLoader = (modal) => {
12524    const loaderWrapper = modal.querySelector('.loader-wrapper');
12525    if (loaderWrapper) loaderWrapper.remove();
12526};
12527
12528/**
12529 * Fetches SKU page content and builds quickview modal
12530 * Shows loading spinner, makes AJAX request, and populates modal with product info
12531 * @param {string} skuPage - URL of the SKU page to fetch
12532 */
12533const requestAndBuildQuickview = (skuPage) => {
12534    const skuQuickviewModal = document.getElementById('skuQuickviewModal');
12535    if (!skuQuickviewModal) return;
12536
12537    const modalDom = skuQuickviewModal.querySelector('.sku-data .quick-view');
12538    if (!modalDom) return;
12539
12540    // Add loading spinner while we build the quickview. This will allow instant feedback to the user while AJAX request processes.
12541    const productInfo = modalDom.querySelector('.quick-view-product-information');
12542    const overview = modalDom.querySelector('.quick-view-overview');
12543    if (productInfo) productInfo.innerHTML = '';
12544    if (overview) overview.innerHTML = '';
12545    modalDom.insertAdjacentHTML('beforeend', '<div class="loader-wrapper loader"><div class="results-loader"></div></div>');
12546
12547    // Trigger Bootstrap modal
12548    if (window.bootstrap?.Modal) {
12549        const modal = new bootstrap.Modal(skuQuickviewModal);
12550        modal.show();
12551    } else if (skuQuickviewModal.modal) {
12552        skuQuickviewModal.modal('show');
12553    }
12554
12555    fetch(skuPage)
12556        .then(response => response.text())
12557        .then(data => {
12558            const parser = new DOMParser();
12559            const doc = parser.parseFromString(data, 'text/html');
12560
12561            populateQuickviewProductInfo(doc, modalDom);
12562            addQuickviewTitleAndLink(modalDom, skuPage);
12563            handleQuickviewOutOfStock(modalDom);
12564            setupQuickviewSkuSelector(modalDom, skuPage);
12565
12566            // Refire the load event, which will allow owl carousel to rebuild itself
12567            dispatchEvent(new Event('load'));
12568
12569            removeQuickviewLoader(skuQuickviewModal);
12570        })
12571        .catch(error => {
12572            const quickViewProductInfo = modalDom.querySelector('.quick-view-product-information');
12573            if (quickViewProductInfo) {
12574                quickViewProductInfo.innerHTML = '<div class="error-message">An error occurred when processing the request.</div>';
12575            }
12576
12577            removeQuickviewLoader(skuQuickviewModal);
12578        });
12579};
12580
12581/**
12582 * Initializes click tracking analytics for product grid items
12583 * Tracks product clicks with micro application tag, link name, and position
12584 * @param {HTMLElement} componentElement - Product grid component element
12585 */
12586const productGridResultClickAnalyticInit = (componentElement) => {
12587    const productItems = componentElement.querySelectorAll(".product-item");
12588    productItems.forEach(item => {
12589        item.addEventListener("click", function() {
12590            const microApplicationTag = componentElement.dataset.microAppTag;
12591            const titleElem = item.querySelector(".title");
12592            const linkName = titleElem ? titleElem.textContent : '';
12593            const linkPage = item.dataset.page;
12594            if(!_.isUndefined(window._satellite)){
12595                _satellite.track('productGridResultClick', {pgType: microApplicationTag, pgLinkName: linkName, pgPosition: linkPage} );
12596            }
12597        });
12598    });
12599};
12600
12601
12602
12603/**
12604 * Updates Adobe Analytics with product grid filter events
12605 * @param {HTMLElement} componentElement - Product grid component element
12606 * @param {object} state - Product grid state object with totals, currentTab, tabSearchObjects
12607 * @param {string} eventType - Type of analytics event
12608 * @param {string} eventAction - Action to track
12609 */
12610const updateAnalytics = (componentElement, state, eventType, eventAction) => {
12611    const total = state.totals[state.currentTab];
12612    let refinements = [];
12613    let cleanRefinements = [];
12614    let filterNameValue = "";
12615
12616    if(state.currentTab != 'all'){
12617        const lastResults = state.tabSearchObjects.filter(elem => elem.indexName === state.currentTab)[0].helper.lastResults;
12618
12619        refinements = lastResults ? lastResults.getRefinements().filter(filter => filter.attributeName != 'microApplications') : [];
12620
12621        const filterContainer = componentElement.querySelector('.algolia-filter-container');
12622
12623        cleanRefinements = _.chain(refinements).groupBy('attributeName').map((value, key) => {
12624
12625            const filterElem = filterContainer ? filterContainer.querySelector('[data-filter-attribute="' + key +'"]') : null;
12626            const filterTitle = filterElem?.dataset.filtertitle || 'Categories';
12627            const filterName = filterTitle + ':'; // Title Case
12628            filterNameValue = filterName;
12629
12630            return filterName + value.reduce((acc, elem, index) => {
12631                let attributeName = elem.name.split(',').slice(-1)[0];
12632                attributeName = attributeName.split('|').slice(-1)[0];
12633                return acc + attributeName + ((index < value.length - 1) ? '^' : '')
12634            }, "")
12635        }).value();
12636    }
12637
12638    if(digitalData?.event){
12639        const eventArr = {
12640            eventName: "product filter",
12641            eventAction: eventAction || (total ? "search" : "null"),
12642            type: eventType,
12643            timeStamp: new Date()
12644        };
12645        digitalData.event.push(eventArr);
12646    }
12647
12648    digitalData.productGrid = digitalData.productGrid || {};
12649
12650    const hasMicroFilters = state.preFilters && !!state.preFilters['microApplications']?.name?.length;
12651
12652    if(digitalData?.productGrid){
12653        digitalData.productGrid.type = hasMicroFilters ? state.preFilters['microApplications'].name[0].split(',')[1] : '';
12654        const refinementValues = [];
12655        for (const refinement of cleanRefinements) {
12656            const filterTitle = refinement.split(":")[0];
12657            const filterTitleUpperCase = filterTitle.charAt(0).toUpperCase() + filterTitle.slice(1);
12658            if (refinement.indexOf("^") > 0) {
12659                const filterItems = refinement.split(":")[1];
12660                const filterItemsSplit = filterItems.split("^");
12661                for (const filterItemValue of filterItemsSplit) {
12662                    const filterItem = `${filterTitleUpperCase}:${filterItemValue}`;
12663                    refinementValues.push(filterItem);
12664                }
12665            } else {
12666                const filterItem = `${filterTitleUpperCase}:${refinement.split(":")[1]}`;
12667                refinementValues.push(filterItem);
12668            }
12669        }
12670
12671        digitalData.productGrid.filterValues = refinements.length ? refinementValues.join("|") : "";
12672    }
12673};
12674
12675/**
12676 * Handles filter panel click to toggle open/closed state
12677 * @param {HTMLElement} panel - Filter panel element
12678 * @param {Event} e - Click event
12679 */
12680const handleFilterPanelClick = (panel, e) => {
12681    const headerClick = e.target.closest('.ais-Panel-header') !== null;
12682    if(!headerClick) {
12683        return;
12684    }
12685
12686    panel.classList.toggle("open");
12687    const panelBody = panel.querySelector('.ais-Panel-body');
12688
12689     if(!panelBody) {
12690           return;
12691     }
12692
12693    if(panel.classList.contains("open")) {
12694        panelBody.style.display = 'block';
12695        panelBody.style.overflow = 'hidden';
12696        panelBody.style.transition = 'max-height 300ms ease-in-out';
12697        panelBody.style.maxHeight = '0';
12698        setTimeout(() => {
12699            panelBody.style.maxHeight = panelBody.scrollHeight + 'px';
12700
12701            // Observe content changes (e.g. Show More)
12702            if(panelBody._filterPanelObserver) {
12703               return;
12704            }
12705
12706            panelBody._filterPanelObserver  = new MutationObserver(() => {
12707                panelBody.style.maxHeight = panelBody.scrollHeight + 'px';
12708            });
12709
12710            panelBody._filterPanelObserver.observe(panelBody, {
12711                childList: true,
12712                subtree: true,
12713            });
12714
12715        }, 10);
12716
12717        return;
12718    }
12719    panelBody.style.maxHeight = '0';
12720    setTimeout(() => {
12721        panelBody.style.display = 'none';
12722        panelBody.style.overflow = '';
12723         if(panelBody._filterPanelObserver ) {
12724                panelBody._filterPanelObserver.disconnect();
12725                panelBody._filterPanelObserver  = null;
12726            }
12727    }, 300);
12728
12729};
12730
12731
12732/**
12733 * Processes search term for special cases like EV codes
12734 * @param {string} searchTerm - Raw search term to process
12735 * @returns {string} Processed search term
12736 */
12737const processSearchTerm = (searchTerm) => {
12738    const regexPattern =  /^[eE][vV](?=.*\d)(?=.*-).*$/;
12739    if(searchTerm==="" || !searchTerm){
12740        return "";
12741    }
12742    else if (regexPattern.test(searchTerm)){
12743        searchTerm = searchTerm.replace(/-/g, '');
12744    }
12745    else if (typeof searchTerm === 'object' || typeof searchTerm === 'function'){
12746        searchTerm= searchTerm.toString();
12747    }
12748    return searchTerm;
12749};
12750
12751// ========================================
12752// PRODUCT GRID VIEWMODEL
12753// ========================================
12754
12755function initProductGrid(componentElement) {
12756    // ----------------------------------------
12757    // State Variables (Closure-scoped)
12758    // ----------------------------------------
12759
12760    const userToken = HeaderUtil.getCloudVisitorId();
12761    const aa = window.aa || function() {};
12762    const applicationId = componentElement.dataset.applicationId;
12763    const searchApiKey = componentElement.dataset.searchApiKey;
12764    const searchClient = window.algoliasearch.algoliasearch(applicationId, searchApiKey);
12765    // URL param names used for algolia search
12766    const algoliaURLParams = new Set(["perPage", "index", "tab", "q"]);
12767    // URL params suffixes used to identify algolia search refinements
12768    const algoliaURLParamIdentifiers = [".disjunctive", ".hierarchical"];
12769
12770    let preFilters = componentElement.dataset.preFilters ? JSON.parse(componentElement.dataset.preFilters) : {};
12771    const hideAllFilters = componentElement.dataset.hideAllFilters === 'true';
12772    const addSearchBar = componentElement.dataset.addSearchBar;
12773
12774    let searchQuery = '';
12775
12776    const productIndex = componentElement.dataset.productsIndex;
12777    const skuIndex = componentElement.dataset.skusIndex;
12778    const gridItemType = componentElement.dataset.gridItemType;
12779    const indexToSearch = gridItemType === 'sku' ? skuIndex : productIndex;
12780    let currentTab = indexToSearch;
12781
12782    // Apply CSS class based on index name to .item div
12783    const itemDiv = componentElement.querySelector('.item');
12784    if (itemDiv) {
12785        const cssClass = indexToSearch.slice(indexToSearch.indexOf('_') + 1).replace('_', '-');
12786        itemDiv.classList.add(cssClass);
12787    }
12788
12789    let totals = {};
12790    const instantsearchWidgets = {};
12791    const tabSearchObjects = [];
12792
12793    let isPaginationWasClicked = false;
12794    let hasFilter = false;
12795
12796    if(userToken){
12797        aa('setUserToken', userToken);
12798    }
12799
12800    // ----------------------------------------
12801    // Helper Functions
12802    // ----------------------------------------
12803
12804    /**
12805     * Show a searchbar in the product grid if checked in authoring dialog
12806     * @returns {boolean} Whether to show search bar
12807     */
12808    function showSearchBar() {
12809        // Handles both boolean and string "true"
12810        return !!addSearchBar && addSearchBar !== "false";
12811    }
12812
12813    /**
12814     * Gets list of filter attributes that should be hidden
12815     * @returns {Array<string>} Array of attribute names to hide
12816     */
12817    function hiddenFilterAttributes() {
12818        const alwaysHiddenAttributes = ['microApplications'];
12819        const preFilterKeys = _.uniq(_.keys(preFilters).filter(key => preFilters[key].prefilter)); // If prefilter option is true, hide the filter dropdown.
12820        if(preFilterKeys.indexOf('flatCategories') != -1){
12821            preFilterKeys.push('categories');
12822        }
12823        return preFilterKeys.concat(alwaysHiddenAttributes);
12824    }
12825
12826    /**
12827     * Determines whether to show filters
12828     * @returns {boolean} True if filters should be shown
12829     */
12830    function showFilters() {
12831        return hasFilter && !hideAllFilters;
12832    }
12833
12834    // ----------------------------------------
12835    // Instance Methods
12836    // ----------------------------------------
12837
12838    //handle search and show filtered results
12839    function runSearch() {
12840        const searchInstance = instantsearchWidgets[currentTab];
12841        const searchHelper = searchInstance?.helper;
12842        if (searchHelper) {
12843            searchHelper.setQuery(searchQuery).search();
12844
12845            // Use this to track the search in Adobe Analytics, built for SRP but using here too.
12846            searchInstance.once('render', function () {
12847                const searchTermRaw = searchQuery;
12848                const searchTerm = searchTermRaw ? processSearchTerm(decodeURIComponent(searchTermRaw).replace(/\+/g, ' ')) : '';
12849                const currentPage = document.head.querySelector('link[rel="canonical"]')
12850                    ? document.head.querySelector('link[rel="canonical"]').href
12851                    : document.location.origin + document.location.pathname;
12852                const pentairSearchJSON = {
12853                    priorPageURL: currentPage,
12854                    searchType: "product grid search",
12855                    searchTerm: searchTerm ? searchTerm : "clear"
12856                };
12857                setSessionCookie('pentairSearch', JSON.stringify(pentairSearchJSON));
12858
12859                const hits = searchHelper.lastResults.nbHits;
12860                const lastQueryID = tabSearchObjects.find(elem => elem.indexName === currentTab).helper.lastResults.queryID
12861                trackSearchPageViewPayload(document.querySelector('#productGridComponent'), currentTab, hits, lastQueryID);
12862            }, {once: true});
12863        }
12864    }
12865
12866
12867
12868    function isFilterVisible(attributeName){
12869      return !hiddenFilterAttributes().includes(attributeName); // If attribute is not in hidden filter list, return true.
12870    }
12871
12872
12873
12874    function paramsFromCurrentState(){
12875      let refinements = {};
12876      let paramRefinements = {};
12877      let currentTabResults = {};
12878
12879      if(currentTab && currentTab !== 'all' && instantsearchWidgets[currentTab]?.helper?.lastResults){
12880        currentTabResults = instantsearchWidgets[currentTab].helper.lastResults;
12881        refinements = currentTabResults.getRefinements();
12882      }
12883
12884      const ignoreAttributes = _.chain(preFilters).keys().reduce((acc, attribute) => { // For ignoring attributes that are prefilters.
12885          acc.push(preFilters[attribute]['name'].length ? attribute : '');
12886          return acc;
12887        }
12887, []).compact().value();
12888
12889      paramRefinements = _.chain(refinements)
12890        .filter(elem => ignoreAttributes.indexOf(elem.attributeName) == -1)
12891        .groupBy(entity => entity.attributeName)
12892        .map((vals, key) => [key + '.' + vals[0].type, _.pluck(vals, 'name').join(';')])
12893        .object()
12894        .value();
12895
12896      let otherOptions = {};
12897      if(currentTabResults){
12898        otherOptions = {
12899          page: (currentTabResults.page > 0) ? (currentTabResults.page + 1) : null,  // Only pass if not page 1
12900          index: currentTabResults.index === currentTab ? null : currentTabResults.index,
12901          perPage: currentTabResults.hitsPerPage === 12 ? null : currentTabResults.hitsPerPage
12902        };
12903
12904       otherOptions = _.chain(otherOptions).pairs().filter(elem => !!elem[1]).object().value()
12905        // page, sortby, per page
12906      }
12907
12908      return { ...paramRefinements, ...otherOptions };
12909    }
12910
12911
12912
12913    function hasResults(indexName) {
12914      return totals[indexName] ? !!totals[indexName] : false;
12915    }
12916
12917
12918
12919    // Component-scoped debouncer: created once per initProductGrid so
12920    // consecutive filter clicks share the same 500ms wait window.
12921    const debouncedUpdateAnalytics = _.debounce((state, eventType, eventAction) => {
12922      updateAnalytics(componentElement, state, eventType, eventAction);
12923    }, 500);
12924
12925    function filterClick(event) {
12926      const isFilterClick = event.target.tagName === 'INPUT';
12927      const isCategoryFilterClick = event.target.closest('.categories') !== null;
12928      const state = { totals, currentTab, tabSearchObjects, preFilters };
12929      if(isFilterClick || isCategoryFilterClick){
12930        instantsearchWidgets[currentTab].once('render', function(){
12931          debouncedUpdateAnalytics(state, 'refine', 'filter');
12932        });
12933      }
12934      return false;
12935    }
12936
12937    function initAlgoliaTab(searchClient, indexName, containerElem) {
12938
12939        const params = getParams();
12940
12941        let initialUiState = {};
12942
12943        if(currentTab === indexName){  // UI state for selected tabs.
12944          initialUiState[currentTab] = {
12945              hitsPerPage: params.perPage,
12946              hierarchicalMenu: getRefinements().hierarchical,
12947              refinementList: getRefinements().disjunctive,
12948              //sortBy: params.index
12949            }
12950        }
12951
12952        const search = window.instantsearch({
12953          indexName: indexName,
12954          searchClient: searchClient,
12955          insights: true,
12956          initialUiState: initialUiState,
12957          searchFunction: (helper) => {
12958            const preFilterList = ['flatCategories', 'brands', 'channel', 'microApplications', 'applications'];
12959            const currentPage = search.ignorePageParam ? helper.getPage() : ((Number.parseInt(params.page, 10) - 1) || 0); // Use param for first render.
12960            preFilterList.forEach(preFilterName => {
12961              if(preFilters[preFilterName]?.name && preFilters[preFilterName]?.prefilter && helper.state.disjunctiveFacets.indexOf(preFilterName) > -1){
12962                preFilters[preFilterName].name.forEach((categoryName, index) => {
12963                  helper.addDisjunctiveFacetRefinement(preFilterName, categoryName);
12964                });
12965            }
12966            });
12967            helper.setPage(currentPage).search(); // Note: addDisjunctiveFacetRefinement resets page to firstPage, so if this is first render, we need to make sure page is reset to param.
12968            search.ignorePageParam = helper.ignorePageParam || true;
12969          }
12970        });
12971
12972        // TODO: Fix this
12973        const indexWithoutEnvironment = 'pentair_products' //indexName.split('_').slice(1).join('_');
12974
12975        const gridItemType = componentElement.dataset.gridItemType;
12976        const freeShipingPriceLimit = componentElement.dataset.freeshipingpricelimit;
12977
12978        if(PENTAIR.AlgoliaProductGridSearchWidgets[indexWithoutEnvironment]){
12979          PENTAIR.AlgoliaProductGridSearchWidgets[indexWithoutEnvironment](search, indexName, containerElem, hiddenFilterAttributes(), gridItemType, freeShipingPriceLimit);
12980        }
12981
12982        search.once('render',function(){
12983          const categoryList = componentElement.querySelector('.category-container ul');
12984
12985          if (categoryList) {
12986            const firstChild = categoryList.children[0];
12987            const autoExpandCategory = categoryList.children.length === 1 &&
12988                                       firstChild &&
12989                                       !firstChild.classList.contains('refined');
12990
12991            if(autoExpandCategory){
12992              const firstLink = firstChild.querySelector('a');
12993              const categoryVal = firstLink?.dataset.value;
12994              const decodedCategoryVal = categoryVal ? decodeURI(categoryVal) : categoryVal;
12995              this.helper.addHierarchicalFacetRefinement('categories.lvl0', decodedCategoryVal);
12996              search.ignorePageParam = false;
12997              this.helper.search();
12998            }
12999          }
13000
13001          const panelBodies = containerElem.querySelectorAll('.algolia-filter-container .ais-Panel-body');
13002          panelBodies.forEach(panelBody => {
13003            panelBody.style.display = 'none';
13004          });
13005
13006          const productGridModal = document.getElementById('productGridModal');
13007          if (productGridModal) {
13008            const modalPanelBodies = productGridModal.querySelectorAll('.algolia-filter-container .ais-Panel-body');
13009            modalPanelBodies.forEach(panelBody => {
13010              panelBody.style.display = 'none';
13011            });
13012
13013          }
13014          // Panel headers are divs — make them keyboard-focusable and triggerable
13015          const panelHeaderContainers = [containerElem, document.getElementById('productGridModal')].filter(Boolean);
13016          panelHeaderContainers.forEach(container => {
13017            container.querySelectorAll('.algolia-filter-container .ais-Panel-header').forEach(header => {
13018              header.setAttribute('tabindex', '0');
13019              header.setAttribute('role', 'button');
13020              header.addEventListener('keydown', (e) => {
13021                if (e.key === 'Enter' || e.key === ' ') {
13022                  e.preventDefault();
13023                  header.click();
13024                }
13025              });
13026            });
13027          });
13028        });
13029
13030        search.on('render', function(){
13031          if(this.helper.lastResults) {
13032            const panels = containerElem.querySelectorAll('.algolia-filter-container .ais-Panel:not(.ais-Panel--noRefinement)');
13033            hasFilter = panels.length > 0;
13034            totals[this.indexName] = this.helper.lastResults.nbHits;
13035          }
13036
13037          if(currentTab === indexName && search.helper.lastResults){
13038            setBrowserState(paramsFromCurrentState())
13039          }
13040
13041          if (isPaginationWasClicked) {
13042              const firstItem = componentElement.querySelector(".product-results a");
13043              if (firstItem) {
13044                  firstItem.focus();
13045              }
13046          }
13047        });
13048
13049        tabSearchObjects.push(search);
13050
13051        search.start();
13052
13053        return search;
13054    }
13055
13056    function setBrowserState(params) {
13057        //maintain wcmmode=disabled for author view-as-published mode
13058        // and other url params e.g. params used for tracking media performance in analytics solutions
13059        const nonAlgoliaURLParams = _.chain(getParams())
13060            .pairs()
13061            .filter(entry => {
13062                const paramName = entry[0];
13063                const partialMatch = algoliaURLParamIdentifiers.some(identifier => paramName.includes(identifier));
13064                const exactMatch = algoliaURLParams.has(paramName);
13065                return !partialMatch && !exactMatch;
13066            })
13067            .object()
13068            .value();
13069        const mergedParams = { ...params, ...nonAlgoliaURLParams };
13070
13071        // Build query string manually
13072        const searchParams = new URLSearchParams();
13073        Object.keys(mergedParams).forEach(key => {
13074            if (mergedParams[key] !== null && mergedParams[key] !== undefined) {
13075                searchParams.set(key, mergedParams[key]);
13076            }
13077        });
13078        const queryString = searchParams.toString();
13079        const url = window.location.pathname + (queryString ? '?' + queryString : '');
13080        window.history.replaceState(mergedParams, null, url);
13081    }
13082
13083    function scrollToTopContainer() {
13084        isPaginationWasClicked = true;
13085
13086        const componentElementPosition = componentElement.getBoundingClientRect().top + window.pageYOffset;
13087        const headerElement = document.querySelector(".header.component");
13088        const headerHeight = headerElement ? headerElement.offsetHeight : 0;
13089        const stickyJumpNav = document.getElementById("stickyJumpNav");
13090        let position = componentElementPosition - headerHeight;
13091        if (stickyJumpNav) {
13092            position -= stickyJumpNav.offsetHeight;
13093        }
13094        window.scrollTo(0, position);
13095    }
13096
13097    function clearSearchAndShowAll() {
13098        const desktopInput = componentElement.querySelector('.product-grid-search-input');
13099        if (desktopInput) {
13100            desktopInput.value = '';
13101        }
13102
13103        const mobileInput = document.querySelector('#productGridModal')?.querySelector('.product-grid-search-input');
13104        if (mobileInput) {
13105            mobileInput.value = '';
13106        }
13107        
13108        searchQuery = '';
13109        runSearch();
13110    }
13111
13112    function clearRefinements() {
13113        const activeIndex = currentTab || indexToSearch;
13114        const activeSearchHelper = instantsearchWidgets[activeIndex]?.helper;
13115        if (!activeSearchHelper) return;
13116
13117        activeSearchHelper.clearRefinements();
13118        activeSearchHelper.search();
13119    }
13120
13121    // ----------------------------------------
13122    // Event Listeners Setup
13123    // ----------------------------------------
13124
13125    /**
13126     * Handles filter click for analytics tracking
13127     */
13128    function handleFilterClickForAnalytics(e) {
13129        const isFilterClick = e.target.tagName === 'INPUT';
13130        const isCategoryFilterClick = e.target.closest('.categories') !== null;
13131        if(isFilterClick || isCategoryFilterClick){
13132            filterClick(e);
13133        }
13134    }
13135
13136    /**
13137     * Sets up all vanilla JS event listeners
13138     */
13139    function setupEventListeners() {
13140        // Search input
13141        const searchInput = componentElement.querySelector('.product-grid-search-input');
13142        if (searchInput) {
13143            searchInput.addEventListener('input', (e) => {
13144                searchQuery = e.target.value;
13145            });
13146            searchInput.addEventListener('keydown', (e) => {
13147                if (e.key === "Enter" || e.keyCode === 13) {
13148                    runSearch();
13149                    e.preventDefault();
13150                }
13151            });
13152        }
13153
13154        // Search button
13155        const searchBtn = componentElement.querySelector('.product-grid-search-btn');
13156        if (searchBtn) {
13157            searchBtn.addEventListener('click', () => {
13158                runSearch();
13159            });
13160        }
13161
13162        // Clear search button - Desktop, shows only when no results
13163        const clearSearchBtn = componentElement.querySelector('#viewAllProducts');
13164        if (clearSearchBtn) {
13165            clearSearchBtn.addEventListener('click', () => {
13166                clearSearchAndShowAll();
13167            });
13168        }
13169
13170        // Pagination click listener
13171        const paginationContainer = componentElement.querySelector('.algolia-pagination');
13172        if (paginationContainer) {
13173            paginationContainer.addEventListener('click', () => {
13174                scrollToTopContainer();
13175            });
13176        }
13177
13178        // Filter panel click listeners
13179        const filterPanels = componentElement.querySelectorAll('.filter-panel');
13180        filterPanels.forEach(panel => {
13181            panel.addEventListener('click', (e) => handleFilterPanelClick(panel, e));
13182        });
13183
13184        // Filter click listeners (for analytics tracking)
13185        const filterContainers = componentElement.querySelectorAll('.category-container, .algolia-filter-container');
13186        filterContainers.forEach(container => {
13187            container.addEventListener('click', handleFilterClickForAnalytics);
13188        });
13189
13190        // Product result click analytics (delegated - handles dynamically rendered hits)
13191        componentElement.addEventListener('click', function(event) {
13192            const item = event.target.closest('.product-item');
13193            if (!item) return;
13194            const microApplicationTag = componentElement.dataset.microAppTag;
13195            const titleElem = item.querySelector('.title');
13196            const linkName = titleElem ? titleElem.textContent : '';
13197            const linkPage = item.dataset.page;
13198            if (!_.isUndefined(window._satellite)) {
13199                _satellite.track('productGridResultClick', {pgType: microApplicationTag, pgLinkName: linkName, pgPosition: linkPage});
13200            }
13201        });
13202
13203        // Quickview click handler (delegated - handles dynamically rendered quickview buttons)
13204        if (gridItemType === 'sku') {
13205            componentElement.addEventListener('click', function(event) {
13206                const btn = event.target.closest('.quickview');
13207                if (!btn) return;
13208                event.preventDefault();
13209                const skuPage = btn.dataset.skuPage;
13210                if (!skuPage) return;
13211                requestAndBuildQuickview(skuPage);
13212            });
13213        }
13214    }
13215
13216    /**
13217     * Updates search bar visibility
13218     */
13219    function updateSearchBarVisibility() {
13220        const searchInput = componentElement.querySelector('.product-grid-search-input');
13221        const searchBtn = componentElement.querySelector('.product-grid-search-btn');
13222        const shouldShowSearch = showSearchBar();
13223        if (searchInput) searchInput.style.display = shouldShowSearch ? 'block' : 'none';
13224        if (searchBtn) searchBtn.style.display = shouldShowSearch ? 'inline-block' : 'none';
13225    }
13226
13227    /**
13228     * Updates filter visibility based on state and rules
13229     */
13230    function updateFilterVisibility(container) {
13231        if (!container) return;
13232        // Show/hide main filters container
13233        const filtersDiv = container.querySelector('.filters');
13234        if (filtersDiv) {
13235           filtersDiv.style.display = showFilters() ? '' : 'none';
13236        }
13237
13238        // Show/hide filter panels based on visibility rules
13239        const filterPanels = container.querySelectorAll('.filter-panel[data-filter-attribute]');
13240         if (!filterPanels.length) return;
13241
13242        filterPanels.forEach(panel => {
13243            const attributeName = panel.dataset.filterAttribute;
13244            if (!attributeName) return;
13245            panel.style.display = isFilterVisible(attributeName) ? 'list-item' : 'none';
13246
13247        });
13248
13249        // Show/hide category container
13250        const categoryContainer = container.querySelector('.category-container');
13251        if (categoryContainer) {
13252            categoryContainer.style.display = isFilterVisible('categories') ? 'block' : 'none';
13253        }
13254    }
13255
13256    /**
13257     * Updates results and related elements visibility
13258     */
13259    function updateResultsVisibility() {
13260        const hasResultsValue = hasResults(indexToSearch);
13261        const isModalOpen = document.body.classList.contains('modal-open');
13262
13263        // Show/hide clear search
13264        const clearSearchDiv = componentElement.querySelector('.product-grid-clear-search');
13265        if (clearSearchDiv && !isModalOpen) {
13266            clearSearchDiv.style.display = hasResultsValue ? 'none' : 'block';
13267        }
13268
13269        // Show/hide filter dropdown
13270        const filterDropdown = componentElement.querySelector('.filter-dropdown');
13271        if (filterDropdown) {
13272            filterDropdown.style.display = hasResultsValue ? 'block' : 'none';
13273        }
13274
13275        // Note: Don't manipulate .product-results display - Algolia handles its own rendering
13276    }
13277
13278    /**
13279     * Updates visibility of elements based on state
13280     */
13281    function updateVisibility() {
13282        updateSearchBarVisibility();
13283        updateFilterVisibility(componentElement);
13284        updateResultsVisibility();
13285    }
13286
13287    /**
13288     * Initializes the product grid filter modal (page-level modal)
13289     * Wires up event handlers for modal-specific elements
13290     */
13291    function setupModalEventListeners() {
13292        const modal = document.getElementById('productGridModal');
13293        if (!modal) return;
13294
13295        // Modal search input
13296        const modalSearchInput = modal.querySelector('.modal-search-input');
13297        if (modalSearchInput) {
13298            modalSearchInput.addEventListener('input', (e) => {
13299                searchQuery = e.target.value;
13300            });
13301            modalSearchInput.addEventListener('keydown', (e) => {
13302                if (e.key === "Enter" || e.keyCode === 13) {
13303                    runSearch();
13304                    e.preventDefault();
13305                }
13306            });
13307        }
13308
13309        // Modal search button
13310        const modalSearchBtn = modal.querySelector('.modal-search-btn');
13311        if (modalSearchBtn) {
13312            modalSearchBtn.addEventListener('click', () => {
13313                runSearch();
13314            });
13315        }
13316
13317        // Modal clear search button
13318        const modalClearSearchBtn = modal.querySelector('.modal-clear-search-btn'); // This is deliberately display none
13319        if (modalClearSearchBtn) {
13320            modalClearSearchBtn.addEventListener('click', () => {
13321                clearSearchAndShowAll();
13322            });
13323        }
13324
13325        // Modal clear filters link
13326        const modalClearFilters = modal.querySelector('.modal-clear-filters');
13327        if (modalClearFilters) {
13328            modalClearFilters.addEventListener('click', (e) => {
13329                e.preventDefault();
13330                clearRefinements();
13331            });
13332        }
13333
13334        // Wire filter panel accordion click handlers for the modal
13335        const modalFilterPanels = modal.querySelectorAll('.filter-panel');
13336        modalFilterPanels.forEach(panel => {
13337            panel.addEventListener('click', (e) => handleFilterPanelClick(panel, e));
13338        });
13339
13340        // Update modal visibility states when it opens
13341        modal.addEventListener('shown.bs.modal', () => {
13342            updateModalVisibility();
13343        });
13344
13345        // Also listen for older Bootstrap event (with jQuery)
13346        if (typeof $ !== 'undefined') {
13347            $(modal).on('shown.bs.modal', () => {
13348                updateModalVisibility();
13349            });
13350        }
13351    }
13352
13353    /**
13354     * Updates visibility of modal elements based on current state
13355     */
13356    function updateModalVisibility() {
13357        const modal = document.getElementById('productGridModal');
13358        if (!modal) return;
13359
13360        updateFilterVisibility(modal);
13361
13362        const hasResultsValue = hasResults(indexToSearch);
13363        const resultCount = totals[indexToSearch] || 0;
13364
13365        // Update result counts
13366        const modalResultsCount = modal.querySelector('.modal-results-count');
13367        if (modalResultsCount) {
13368            modalResultsCount.textContent = resultCount > 0 ? `(${resultCount})` : '';
13369        }
13370
13371        const modalResultCount = modal.querySelector('.modal-result-count');
13372        if (modalResultCount) {
13373            modalResultCount.textContent = resultCount;
13374        }
13375
13376        // Show/hide no results message
13377        const modalNoResults = modal.querySelector('.modal-no-results');
13378        if (modalNoResults) {
13379            modalNoResults.style.display = hasResultsValue ? 'none' : 'block';
13380        }
13381
13382        // Show/hide filter dropdown
13383        const modalFilterDropdown = modal.querySelector('.modal-filter-dropdown');
13384        if (modalFilterDropdown) {
13385            modalFilterDropdown.style.display = hasResultsValue ? 'block' : 'none';
13386        }
13387
13388        // Show/hide search bar based on config
13389        const modalSearchBar = modal.querySelector('.modal-search-bar');
13390        if (modalSearchBar) {
13391            modalSearchBar.style.display = showSearchBar() ? 'block' : 'none';
13392        }
13393
13394        // Show/hide filters
13395        const modalFilters = modal.querySelector('.modal-filters');
13396        if (modalFilters) {
13397            modalFilters.style.display = showFilters() ? 'block' : 'none';
13398        }
13399
13400        // Show/hide see results button
13401        const modalSeeResults = modal.querySelector('.modal-see-results');
13402        if (modalSeeResults) {
13403            modalSeeResults.style.display = hasResultsValue ? 'inline-block' : 'none';
13404        }
13405    }
13406
13407    // ----------------------------------------
13408    // Initialization
13409    // ----------------------------------------
13410
13411    //Init stand-alone tabs
13412    const items = componentElement.querySelectorAll('.item');
13413    items.forEach((elem) => {
13414      instantsearchWidgets[indexToSearch] = initAlgoliaTab(searchClient, indexToSearch, elem);
13415    });
13416
13417    // Setup event listeners
13418    setupEventListeners();
13419
13420    // Setup modal event listeners (page-level modal)
13421    setupModalEventListeners();
13422
13423    // Initial visibility update
13424    updateVisibility();
13425
13426    // Update visibility on Algolia render events
13427    if (instantsearchWidgets[indexToSearch]) {
13428        instantsearchWidgets[indexToSearch].on('render', () => {
13429            updateVisibility();
13430            updateModalVisibility();
13431        });
13432    }
13433}
13434
13435// ========================================
13436// INITIALIZATION
13437// ========================================
13438
13439document.addEventListener('DOMContentLoaded', function() {
13440    const productGridComponents = document.querySelectorAll('.product-grid.component');
13441    productGridComponents.forEach(function(component) {
13442      // Validate required dependencies and configuration before initializing
13443      if (!window.algoliasearch?.algoliasearch) {
13444          console.error('Product Grid: Algolia library (algoliasearch) is not loaded.');
13445          return;
13446      }
13447
13448      const applicationId = component.dataset.applicationId;
13449      const searchApiKey = component.dataset.searchApiKey;
13450
13451      if (!applicationId || !searchApiKey) {
13452          console.error('Product Grid: Algolia applicationId or searchApiKey is missing. Please check configuration');
13453          return;
13454      }
13455
13456      initProductGrid(component);
13457    });
13458});
13459
13460})();
13461
13462$(document).ready(function() {
13463
13464    var PressListCarouselModel = function(pressListComponent) {
13465
13466        var self = this;
13467
13468        self.pressListCarousel = pressListComponent.find('.owl-carousel');
13469        self.pagination = pressListComponent.find('.pagination');
13470        self.currentSlide = 0;
13471
13472        self.pressListCarousel.owlCarousel({
13473            nav: false,
13474            dots: true,
13475            mouseDrag: false,
13476            items: 1,
13477            autoHeight: true
13478        }).on('initialized.owl.carousel changed.owl.carousel resized.owl.carousel', function(event) {
13479            self.paginator.paginationItems(self.paginationItems());
13480            self.update();
13481        });
13482
13483        // How many pagination buttons to display depends on screen size.
13484        self.paginationItems = function() {
13485            if(matchMedia('(max-width: 991px)').matches) {
13486                return 3 + "";
13487            }
13488            return 5 + "";
13489        };
13490
13491        self.update = function() {
13492            setTimeout(function() {
13493                var activeDot = self.pressListCarousel.find('.owl-dot.active');
13494                self.currentSlide = self.pressListCarousel.find('.owl-dot').index(activeDot) + 1;
13495                self.paginator.currentPage(self.currentSlide);
13496                reInitEvents();
13497            }, 10);
13498        };
13499
13500        var reInitEvents = function() {
13501            self.pagination.find('a').on('click', function(e) {
13502                e.preventDefault();
13503            });
13504
13505            self.pagination.find('li a').on('click', function(e) {
13506                var targetPage = $(e.target).text();
13507                var targetIndex = targetPage - 1;
13508                var dist = targetPage - self.paginator.currentPage();
13509                var direction = (dist < 0) ? 'prev.owl.carousel' : 'next.owl.carousel';
13510                dist = Math.abs(dist);
13511                for(var i = 0; i < dist; i++) {
13512                    self.pressListCarousel.trigger(direction);
13513                }
13514                self.paginator.currentPage(targetPage);
13515            });
13516        };
13517
13518        self.prevPage = function prevPage() {
13519            if(self.paginator.previousPageExists()) {
13520                var currentPage = self.paginator.currentPage();
13521                self.paginator.currentPage(currentPage - 1);
13522                self.pressListCarousel.trigger('prev.owl.carousel');
13523            }
13524        };
13525
13526        self.nextPage = function nextPage() {
13527            if(self.paginator.nextPageExists()) {
13528                var currentPage = self.paginator.currentPage();
13529                self.paginator.currentPage(currentPage + 1);
13530                self.pressListCarousel.trigger('next.owl.carousel');
13531            }
13532        };
13533
13534        self.init = function() {
13535            self.totalItems = pressListComponent.find('.owl-item .press-item').length;
13536            self.itemsPerPage = pressListComponent.find('.active.owl-item .press-item').length;
13537            self.paginator = new PaginationViewModel(self.totalItems, self.itemsPerPage, self.paginationItems());
13538            self.paginator.init(self.totalItems);
13539            self.update();
13540        };
13541
13542        self.init();
13543    };
13544
13545    var pressListCarousels = $('.press-list.component:not(.edit)');
13546    if(pressListCarousels.length) {
13547        $(function() {
13548            pressListCarousels.each(function() {
13549                ko.applyBindings(new PressListCarouselModel($(this)), this);
13550            });
13551        });
13552    }
13553});
13554
13555$(function(){
13556
13557    // Remove autoplay param from iframe src
13558    function removeAutoplayParam(match, separator, autoplayValue, trailingSeparator) {
13559        // If there's another parameter after autoplay, keep the separator
13560        return trailingSeparator === '&' ? separator : '';
13561    }
13562
13563    // Utility to get cookie by name
13564    function getCookie(name) {
13565        const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
13566        return match ? match[2] : null;
13567    }
13568
13569    // Early exit if cookie is present and valid
13570    if (getCookie('pnt_mdl') === 'closed') {
13571        // Modal should not show, skip all modal JS
13572        return;
13573    }
13574
13575    function initModalComponent(instance) {
13576        const $iframes = $(instance).find('iframe');
13577        const $videos = $(instance).find('video');
13578
13579        // When the modal is hidden, stop videos and iframes
13580        $(instance).on('hidden.bs.modal', function() {
13581            // Stop HTML5 videos
13582            $videos.each(function() {
13583                this.pause && this.pause();
13584                this.currentTime = 0;
13585            });
13586            // Stop iframe videos
13587            $iframes.each(function() {
13588                const $iframe = $(this);
13589                const src = $iframe.attr('src');
13590                if (src) {
13591                    // This regex finds and removes the autoplay param (with any common value) from the URL,
13592                    // so YouTube/Vimeo iframes don't autoplay when the modal is reopened.
13593                    let newSrc = src.replace(
13594                        /([?&])autoplay=(1|true|yes|on|0|false|no|off)(&|$)/gi,
13595                        removeAutoplayParam
13596                    );
13597                    // Remove trailing ? or & if left at the end
13598                    newSrc = newSrc.replace(/[?&]$/, '');
13599                    $iframe.attr('src', newSrc);
13600                }
13601            });
13602
13603            // Set the pnt_mdl cookie if cookieDuration is set and > 0
13604            let cookieDuration = parseInt($(instance).data('cookieDuration'), 10);
13605            if (cookieDuration >
13605 0 && typeof setCookie === 'function') {
13606                setCookie('pnt_mdl', 'closed', cookieDuration);
13607            }
13608        });
13609
13610        //verify the modal is loaded and focus it.
13611        const observer = new MutationObserver(function(mutations) {
13612            mutations.forEach(function(mutation) {
13613                if (mutation.attributeName !== "class") {
13614                    return;
13615                } else {
13616                    if ($(instance).hasClass("in")) {
13617                        setTimeout(() => {
13618                            $(instance).find("#modal-live-region").text("Modal Open");  
13619                        }, 2000);                                   
13620                        const $focusable = $(instance).find('.icon-close');
13621                        if ($focusable.length) {
13622                            $focusable.focus();
13623                        } else {
13624                            $(instance).focus();
13625                        }
13626                    } else {
13627                        $(instance).find("#modal-live-region").text("Modal Closed"); 
13628                        $(document).find("#skipLink").focus();
13629                    }
13630                }
13631            });
13632        });
13633        observer.observe(instance, { attributes: true, attributeFilter: ["class"] });
13634
13635        const showModalOnPageLoad = $(instance).data("showOnPageLoad");
13636        const modalDelaySpeed = $(instance).data("modalDelay");
13637        showModalOnPageLoad === true ? setTimeout(function(){
13638            $(instance).modal("show");
13639        }, modalDelaySpeed) : $(instance).modal("hide");
13640    }
13641
13642    $(document).ready(function() {
13643        const modalComponents = $(".modal-component.component");
13644        if (modalComponents.length) {
13645            modalComponents.each(function() {
13646                // Pass cookieDuration as data attribute for use in JS
13647                let cookieDuration = $(this).attr('data-cookie-duration');
13648                $(this).data('cookieDuration', cookieDuration);
13649                initModalComponent(this);
13650            });
13651        }
13652    });
13653
13654});
13655/* global $ */
13656/* global jQuery */
13657/* global modal  */
13658
13659var PENTAIR = PENTAIR || {};
13660
13661function hostedVid() {
13662    var vidWrap = $('.media-common.component figure.video');
13663
13664    vidWrap.each(function(i, el) {
13665        var poster = $(el).find('video').attr('poster');
13666        $(el).prepend('<img loading="lazy" src="'+poster+'">');
13667        $(el).prepend('<button class="play-vid" alt="Play video"><span class="play-icon"><svg class="dot" version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M32 16q0 4.354-2.146 8.031t-5.823 5.823-8.031 2.146-8.031-2.146-5.823-5.823-2.146-8.031 2.146-8.031 5.823-5.823 8.031-2.146 8.031 2.146 5.823 5.823 2.146 8.031z"></path></svg><svg class="pla" version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M4.8 30.4c-0.3 0-0.7-0.1-1-0.3-0.6-0.4-1-1-1-1.7v-24.8c0-0.7 0.4-1.4 1-1.7 0.6-0.4 1.4-0.3 2 0l20.6 12.4c0.6 0.4 1 1 1 1.7s-0.4 1.4-1 1.7l-20.5 12.4c-0.4 0.2-0.7 0.3-1.1 0.3zM4.8 2.6c-0.2 0-0.3 0-0.5 0.1-0.3 0.3-0.5 0.6-0.5 0.9v24.7c0 0.4 0.2 0.7 0.5 0.9s0.7 0.2 1 0l20.7-12.3c0.3-0.2 0.5-0.5 0.5-0.9s-0.2-0.7-0.5-0.9l-20.7-12.3c-0.1-0.1-0.3-0.2-0.5-0.2z"></path></svg></span></button>');
13668
13669        $(el).find('button').on('click touch', function(e) {
13670            var trgt = $(e.currentTarget),
13671                img = trgt.parent().find('img'),
13672                vid = trgt.parent().find('video');
13673
13674            trgt.animate({
13675                'opacity': 0
13676            }, 250, function() {
13677                trgt.remove();
13678            });
13679            img.animate({
13680                'opacity': 0
13681            }, 250, function() {
13682                img.remove();
13683            });
13684            $(vid).trigger('play');
13685        })
13686    })
13687};
13688
13689$(function () {
13690    var $vidModal = $('#videoModal');
13691    var $videoModalClose = $vidModal.find('.icon-close');
13692
13693    var isIE = /*@cc_on!@*/false || !!document.documentMode; // Internet Explorer 6-11
13694    if(isIE) {
13695        $('.imagevideo-callout.component .play-vid > img').addClass('is-ie');
13696    }
13697
13698    if($('figure.video').length > 0) {
13699        hostedVid();
13700    }
13701    function deployYoutubeClip(videoID, videoAlt) {
13702        var videoURL = 'https://www.youtube.com/embed/' + videoID +'?rel=0&showinfo=0';
13703        $vidModal.find('iframe').show();
13704        $vidModal.find('video').hide();
13705        $vidModal.find('iframe').attr('src', videoURL);
13706        $vidModal.find('iframe').attr('alt', videoAlt);
13707        $vidModal.modal('show');
13708    }
13709
13710    function deployVimeoClip(videoID, videoAlt) {
13711        var videoURL = 'https://player.vimeo.com/video/' + videoID;
13712        $vidModal.find('iframe').show();
13713        $vidModal.find('video').hide();
13714        $vidModal.find('iframe').attr('src', videoURL);
13715        $vidModal.find('iframe').attr('alt', videoAlt);
13716        $vidModal.modal('show');
13717    }
13718
13719    function deployDamAsset(videoUrl, videoAlt, s7VideoUrl) {
13720        $vidModal.find('iframe').hide();
13721        $vidModal.find('video').show();
13722        $vidModal.find('video').attr('alt', videoAlt);
13723        if (typeof s7VideoUrl === "undefined" || s7VideoUrl === null) {
13724            $vidModal.find('video').attr('src', videoUrl);
13725        } else {
13726            $vidModal.find('video').attr('src', s7VideoUrl);
13727        }
13728        $vidModal.modal('show');
13729    }
13730
13731    function killVideo() {
13732        $vidModal.hide();
13733        $vidModal.find('iframe').attr('src', '');
13734        $vidModal.find('video').get(0).pause();
13735        $vidModal.find('video').attr('src', '');
13736        $vidModal.find('iframe').hide();
13737        $vidModal.find('video').hide();
13738    }
13739
13740    var videoOptions = {
13741        youtube: function (id, videoAlt) {
13742            deployYoutubeClip(id, videoAlt);
13743        },
13744        vimeo: function (id, videoAlt) {
13745            deployVimeoClip(id, videoAlt);
13746        },
13747        dam: function (id, videoAlt, s7VideoUrl) {
13748            deployDamAsset(id, videoAlt, s7VideoUrl);
13749        }
13750    };
13751
13752    $('.media-common button.play-vid').on('click', function(e){
13753        e.preventDefault();
13754        var vidID = $(this).attr('data-vidid');
13755        var videoAlt = $(this).attr('data-video-alt');
13756        var vidType = $(this).attr('data-vidtype');
13757        var s7Url = $(this).attr('data-s7-enabled');
13758        videoOptions[vidType](vidID, videoAlt, s7Url);
13759
13760    });
13761
13762
13763    $videoModalClose.on('click', function () {
13764        killVideo();
13765    });
13766
13767    $vidModal.on('click', function (e) {
13768        /* Stop video playback when clicking the darkened background */
13769        var clickedOnBackground = $(e.target).hasClass('modal in');
13770        return !clickedOnBackground ? false : killVideo();
13771    });
13772
13773    /***************************/
13774    /* SEO Schema Video Markup */
13775    /***************************/
13776    function setSEOVideoMarkup(data) {
13777        var seoScript = $('<script type="application/ld+json"></script>');
13778        $(seoScript).html(JSON.stringify(data));
13779        $("head").append(seoScript);
13780    }
13781    var hostname = window.location.hostname;
13782    var mediaComponents = $(".media-common.component");
13783    if (mediaComponents.length) {
13784        mediaComponents.each(function(index, element) {
13785            // Video Data
13786            var videoType = $(this).find("button.play-vid").attr("data-vidtype");
13787            var videoURL = $(this).find("button.play-vid").attr("data-vidid");
13788            var videoTitle = $(this).find("button.play-vid").attr("data-video-title");
13789            var videoDescription = $(this).find("input[name=videoDescription]").val();
13790            var videoThumbnailSrc = $(this).find(".imagevideo-callout.component img").attr("src");
13791            var thumbnailUrl = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + videoThumbnailSrc;
13792            var contentUrl = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + videoURL;
13793
13794            // Google API Key to fetch YouTube Data
13795            var API_KEY = $(this).find("input[name=gKey]").val();
13796
13797            // Video Markup Data
13798            var videoMarkup = {
13799                "@context": "https://schema.org",
13800                "@type": "VideoObject",
13801                "name": "",
13802                "description": "",
13803                "thumbnailUrl": "",
13804                "duration": "",
13805                "contentUrl": ""
13806            };
13807
13808            videoMarkup["name"] = videoTitle;
13809            videoMarkup["description"] = videoDescription;
13810            videoMarkup["thumbnailUrl"] = [thumbnailUrl];
13811
13812            // Get duration of Media Source (DAM, YouTube, Vimeo) with respect to their API's
13813            if (videoType == "dam") {
13814                var videoEl = $('<video src="" controls="true"></video>');
13815                videoEl.attr("src", videoURL);
13816                $(videoEl).on("loadedmetadata", function(e) {
13817                    var duration = $(videoEl).get(0).duration;
13818                    var minutes = parseInt(duration / 60, 10);
13819                    var seconds = parseInt(duration % 60, 10);
13820                    if (typeof duration != undefined || !isNaN(duration)) {
13821                        var durationTime = "PT" + minutes + "M" + seconds + "S";
13822                        videoMarkup["duration"] = durationTime;
13823                    }
13824                    var contentUrl = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + videoURL;
13825                    videoMarkup["contentUrl"] = contentUrl;
13826                    setSEOVideoMarkup(videoMarkup);
13827                });
13828            } else if (videoType == "youtube") {
13829                var contentUrl = "https://www.youtube.com/watch?v=" + videoURL;
13830                $.ajax({
13831                    type: 'GET',
13832                    url: 'https://www.googleapis.com/youtube/v3/videos',
13833                    data: {
13834                        key: API_KEY,
13835                        id: videoURL,
13836                        part: 'contentDetails',
13837                    },
13838                    success: function(data){
13839                        videoMarkup["duration"] = data.items[0].contentDetails.duration;
13840                        videoMarkup["contentUrl"] = contentUrl;
13841                        setSEOVideoMarkup(videoMarkup);
13842                    },
13843                    error: function(response){
13844                        console.log("Request Failed - " + response);
13845                    }
13846                });
13847            } else if (videoType == "vimeo") {
13848                var CLIENT_ID = "c9b7197ce3aeb6fcbc2338800800a7f568570524";
13849                var requestURL = "https://api.vimeo.com/videos/" + videoURL + "?client_id=${CLIENT_ID}";
13850                var contentUrl = "https://vimeo.com/" + videoURL;
13851                $.ajax({
13852                    type: 'GET',
13853                    url: requestURL,
13854                    headers : {
13855                        'Authorization' : 'Bearer 675be8cb881b96be57b413c506fa9098',
13856                    },
13857                    success: function(data){
13858                        var duration = data.duration;
13859                        var minutes = parseInt(duration / 60, 10);
13860                        var seconds = parseInt(duration % 60, 10);
13861                        var durationTime = "PT" + minutes + "M" + seconds + "S";
13862                        videoMarkup["duration"] = durationTime;
13863                        videoMarkup["contentUrl"] = contentUrl;
13864                        setSEOVideoMarkup(videoMarkup);
13865                    },
13866                    error: function(response){
13867                        console.log("Request Failed - " + response);
13868                    }
13869                });
13870            }
13871        });
13872    }
13873});
13874
13875(function() {
13876    /**
13877     * Uses data attributes for authored height and width.
13878     * If iframe doesnt exist, no custom values should be applied.
13879     * Wrapper addinng-bottom should match iframe height value.
13880     */
13881    function setVideoDimensions() {
13882        var mediaComponents = $('.media-common.component');
13883        $(mediaComponents).each(function(idx, mediaComponent) {
13884            var videoWrapper = $(mediaComponent).find('.videoWrapper');
13885            var iframe = $(videoWrapper).find('iframe');
13886            if (iframe.length == 0) { return; }
13887
13888            var iframeWidth = $(iframe).data('width');
13889            var iframeHeight = $(iframe).data('height');
13890            if (iframeWidth) {
13891                $(iframe).css('width', iframeWidth + 'px');
13892            }
13893            if (iframeHeight) {
13894                $(iframe).css('height', iframeHeight + 'px');
13895                $(videoWrapper).css('padding-bottom', iframeHeight + 'px');
13896                $(videoWrapper).css('padding-top', '0px');
13897            }
13898        });
13899    }
13900
13901    $(document).ready(function() {
13902        setVideoDimensions();
13903        Array.from(document.getElementsByClassName("fluidimage")).forEac
13903h(function(elem) {
13904            s7responsiveImage(elem);
13905        });
13906    });
13907})();
13908
13909var PENTAIR = PENTAIR || {};
13910PENTAIR.Water = PENTAIR.Water || {};
13911PENTAIR.Water.mapStyle = PENTAIR.Water.mapStyle || [{
13912        "featureType": "administrative",
13913        "elementType": "labels.text.fill",
13914        "stylers": [{
13915            "color": "#444444"
13916        }]
13917    },
13918    {
13919        "featureType": "landscape",
13920        "elementType": "all",
13921        "stylers": [{
13922            "color": "#f2f2f2"
13923        }]
13924    },
13925    {
13926        "featureType": "poi",
13927        "elementType": "all",
13928        "stylers": [{
13929            "visibility": "off"
13930        }]
13931    },
13932    {
13933        "featureType": "road",
13934        "elementType": "all",
13935        "stylers": [{
13936                "saturation": -100
13937            },
13938            {
13939                "lightness": 45
13940            }
13941        ]
13942    },
13943    {
13944        "featureType": "road.highway",
13945        "elementType": "all",
13946        "stylers": [{
13947            "visibility": "simplified"
13948        }]
13949    },
13950    {
13951        "featureType": "road.arterial",
13952        "elementType": "labels.icon",
13953        "stylers": [{
13954            "visibility": "off"
13955        }]
13956    },
13957    {
13958        "featureType": "transit",
13959        "elementType": "all",
13960        "stylers": [{
13961            "visibility": "off"
13962        }]
13963    },
13964    {
13965        "featureType": "water",
13966        "elementType": "all",
13967        "stylers": [{
13968                "color": "#46bcec"
13969            },
13970            {
13971                "visibility": "on"
13972            }
13973        ]
13974    }
13975];
13976
13977$(function() {
13978    $(window).load(function() {
13979
13980        var map;
13981        var geocoder;
13982        var markers = [];
13983        var infowindow;
13984
13985        var iconLocation;
13986
13987        function getMapIconLocation(elem) {
13988            if (elem) {
13989                if (elem === 'pentair-bright-blue') {
13990                    return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/map-pin-pentair-bright-blue.png';
13991                } else if (elem === 'pentair-blue') {
13992                    return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/map-pin-pentair-blue.png';
13993                } else if (elem === 'green') {
13994                    return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/map-pin-green.png';
13995                }
13996            }
13997            return '/etc.clientlibs/settings/wcm/designs/pentair/clientlib-site/resources/img/curve-green.png';
13998        }
13999
14000        function isJsonString(str) {
14001            try {
14002                JSON.parse(str);
14003            } catch (e) {
14004                return false;
14005            }
14006            return true;
14007        }
14008
14009        function initMap(i, elem) {
14010            iconLocation = getMapIconLocation(elem);
14011            var map = new google.maps.Map(elem.find('.map-container')[0], {
14012                center: new google.maps.LatLng(-34.397, 150.644),
14013                zoom: 1,
14014                minZoom: 1,
14015                mapTypeId: 'pentairWater'
14016            });
14017
14018            infowindow = new google.maps.InfoWindow();
14019            geocoder = new google.maps.Geocoder();
14020
14021            // window.Pentair = window.Pentair || {};
14022            // window.Pentair.Maps = window.Pentair.Maps || {};
14023            // window.Pentair.Maps.mapJSON = window.Pentair.Maps.mapJSON || [];
14024            var mapData = mps[i];
14025            // console.log(mapData[0]);
14026            // console.log(mps[i]);
14027            // console.log(mapData);
14028            mapData.forEach(function(elem) {
14029                geocodeAddress(elem, geocoder, map);
14030            });
14031
14032            map.mapTypes.set('pentairWater', new google.maps.StyledMapType(PENTAIR.Water.mapStyle, { name: 'Pentair Water' }));
14033        }
14034
14035        function getMarkerHtml(item) {
14036            var infoHtml = $('<div>').addClass('marker');
14037            if (item.name) {
14038                infoHtml.append($('<p>').addClass('location-name').html(item.name));
14039            }
14040            if (item.formatted_address) {
14041                infoHtml.append($('<p>').html(item.formatted_address.split(',')[0] + '<br>' + item.formatted_address.split(',').slice(1).join(',')));
14042            }
14043            if (item.phoneOne) {
14044                infoHtml.append($('<p>').addClass('phone-one').append('<span class="icon-phone" aria-hidden="true"></span>').append($('<a>').attr('href', 'tel:' + item.phoneOne).html(item.phoneOne)));
14045            }
14046            if (item.phoneTwo) {
14047                infoHtml.append($('<p>').addClass('phone-two').append('<span class="icon-phone" aria-hidden="true"></span>').append($('<a>').attr('href', 'tel:' + item.phoneTwo).html(item.phoneTwo)));
14048            }
14049            if (item.linkText && item.linkLocation) {
14050
14051                /*  under normal circumstances the dispatcher will clean the url.
14052                 *   However in this case since the link is being sent to the application in the form of JSON we need
14053                 *   to strip out /content/pentair from relative paths.  ** EXCEPT when on AUTHOR
14054                 *
14055                 *   homepage: href="/"
14056                 *   pages under homepage: href="/en-us/path/under/homepage.html"
14057                 *
14058                 * */
14059                var updatedLink = item.linkLocation;
14060                var location = window.location.hostname;
14061                var authorInstances = ['dev.pentair.com', 'localhost', 'aem-stage.pentair.com', 'aem.pentair.com', 'pentair-author.r2iadobe.com'];
14062                var isAuth = authorInstances.indexOf(location);
14063                if (isAuth === -1) {
14064                    var regExpression = /\/content\/(pentair|intranet|pentair-microsite)\//i;
14065                    updatedLink = (item.linkLocation).replace(regExpression, '/');
14066                    if (updatedLink === '/en-us.html') {
14067                        updatedLink = '/';
14068                    }
14069                }
14070                infoHtml.append($('<div class="map-cta"><a href="' + (updatedLink) + '" target="' + (item.target ? '_blank' : '_self') + '">' + (item.linkText) + '</a></div>'));
14071            }
14072            return infoHtml[0].outerHTML;
14073        }
14074
14075        function addMarker(resultsMap, position, item) {
14076            var marker = new google.maps.Marker({
14077                map: resultsMap,
14078                position: position,
14079                icon: getMapIconLocation(item.pinColor)
14080            });
14081
14082            google.maps.event.addListener(marker, 'click', function() {
14083                infowindow.setContent(getMarkerHtml(item));
14084                infowindow.open(map, marker);
14085            });
14086
14087            markers.push(marker);
14088        }
14089
14090        function geocodeAddress(item, geocoder, resultsMap) {
14091            geocoder.geocode({
14092                'address': item.address
14093            }, function(results, status) {
14094                if (status === google.maps.GeocoderStatus.OK) {
14095                    var latLong = results[0].geometry.location;
14096                    item.formatted_address = results[0].formatted_address;
14097                    resultsMap.setCenter(latLong);
14098                    addMarker(resultsMap, latLong, item);
14099                    updateZoom(resultsMap);
14100                } else {
14101                    console.warn('Geocode was not successful for the following reason: ' + status);
14102                }
14103            });
14104        }
14105
14106        function updateZoom(resultsMap) {
14107            var bounds = new google.maps.LatLngBounds();
14108            for (i = 0; i < markers.length; i++) {
14109                bounds.extend(markers[i].getPosition());
14110            }
14111
14112            resultsMap.fitBounds(bounds);
14113        }
14114
14115        var mapComponents = $('.map.component');
14116        if (mapComponents.length) {
14117            mapComponents.each(function(index, elem) {
14118                initMap(index, $(elem));
14119            });
14120        }
14121    });
14122});
14123$(document).ready(function() {
14124
14125    var largeImageHotspot = $(".large-image-hotspot.component");
14126
14127    if (largeImageHotspot.length) {
14128
14129        var $mbSpotList = $('.large-image-hotspot .spots .mobile-list'),
14130            $spotList = $('.large-image-hotspot .spots .spot-list'),
14131            $mbSpots = $('.large-image-hotspot .mobile-spots'),
14132            thsSpotList,
14133            thsmbSpotList,
14134            thsmbSpots;
14135
14136        $('.large-image-hotspot .spots .mobile-list, .large-image-hotspot .mobile-spots, .large-image-hotspot .spots .spot-list').find('li').on('click', function() {
14137            var index = $(this).index(),
14138                deskRent = $(this).parent().parent().parent(),
14139                mobileRent = $(this).parent().parent(),
14140                rent = "";
14141
14142            if (mobileRent.hasClass('large-image-hotspot') === true) {
14143                rent = mobileRent;
14144            } else if (deskRent.hasClass('large-image-hotspot') === true) {
14145                rent = deskRent;
14146            }
14147            thsSpotList = $(rent).find('.spots .spot-list');
14148            thsmbSpotList = $(rent).find('.spots .mobile-list');
14149            thsmbSpots = $(rent).find('.mobile-spots');
14150
14151            if ((!thsSpotList.find('.spots .spot-list').hasClass('spot-modal-open') && !thsmbSpots.find('li').hasClass('open')) || $(this).closest('ul').hasClass('mobile-list')) {
14152                if (!$(this).hasClass('active')) {
14153                    thsSpotList.slideUp('fast', function() {
14154                        thsmbSpotList.find('.active').removeClass('active');
14155                        thsmbSpots.find('.active').removeClass('active');
14156                        thsSpotList.find('.active').removeClass('active').hide().find('.spot-modal').removeClass('open');
14157
14158                        thsSpotList.find('li').eq(index).addClass('active').show().find('.spot-modal').addClass('open');
14159                        thsmbSpots.find('li').eq(index).addClass('active');
14160                        thsmbSpotList.find('li').eq(index).addClass('active');
14161
14162                        thsSpotList.slideDown('fast');
14163                        thsSpotList.addClass('spot-modal-open');
14164                    });
14165                } else {
14166                    thsmbSpots.find('li').removeClass('active');
14167                    thsmbSpotList.find('li').removeClass('active');
14168                    thsSpotList.find('li').removeClass('active').slideUp('fast').find('.spot-modal').removeClass('open');
14169                    thsSpotList.removeClass('spot-modal-open');
14170                }
14171            }
14172        });
14173
14174        $('.spot-modal > a').on('click', function(e) {
14175            e.preventDefault();
14176            thsmbSpots.find('li').removeClass('active');
14177            thsmbSpotList.find('li').removeClass('active');
14178            thsmbSpotList.find('.spot-modal').removeClass('open');
14179            thsSpotList.removeClass('spot-modal-open').find('.spot-modal').removeClass('open');
14180        });
14181
14182        $spotList.find('.spot-anchor').on('click', function(e) {
14183            e.preventDefault();
14184        });
14185
14186
14187        $(document).mouseup(function(e) {
14188            var container = $('.large-image-hotspot .spots .spot-list, .large-image-hotspot .spots .mobile-list');
14189            if (!container.is(e.target) && container.has(e.target).length === 0) {
14190                if (thsmbSpots) {
14191                    thsmbSpots.find('li').removeClass('active');
14192                }
14193                if (thsmbSpotList) {
14194                    thsmbSpotList.find('li').removeClass('active')
14195                }
14196                if (thsSpotList) {
14197                    thsSpotList.find('li').removeClass('active').slideUp('fast').find('.spot-modal').removeClass('open');
14198                    thsSpotList.removeClass('spot-modal-open');
14199                }
14200            }
14201        });
14202
14203        /* [PENW-2949] - Mobile - Pre-select first item in mobile-spots/list */
14204        if ($(window).width() < 768) {
14205            if(thsmbSpotList) {
14206                thsmbSpotList.find("li:first").trigger("click");
14207            }
14208        }
14209
14210    }
14211});
14212$(document).ready(function() {
14213    var ImageComponentLink = function(componentElement) {
14214    	var self = this;
14215    	self.copyModalImage = function(){
14216    		$('#imageModal article').html(componentElement.find('img').clone(false).attr('src', componentElement.data('fileReference')).attr('width', 'auto').attr('height', 'auto'));
14217            setTimeout(function(){
14218                $('#imageModal').focus();
14219            }, 350);
14220            return true;
14221    	}
14222    }
14223
14224    $('.image-component-link').each(function() {
14225      ko.applyBindings(new ImageComponentLink($(this)), this);
14226    });
14227
14228    Array.from(document.getElementsByClassName("fluidimage")).forEac
14228h(function(elem) {
14229        s7responsiveImage(elem);
14230    });
14231});
14232// =============================================================================
14233// UTILITY HELPER FUNCTIONS
14234// =============================================================================
14235
14236/**
14237 * Returns a debounced version of fn that delays invoking it until after `delay` ms.
14238 * @param {Function} fn
14239 * @param {number} delay
14240 */
14241function debounce(fn, delay) {
14242    let timer;
14243    return function(...args) {
14244        clearTimeout(timer);
14245        timer = setTimeout(() => fn.apply(this, args), delay);
14246    };
14247}
14248
14249/**
14250 * Checks the menu state and hides it if there are no navigation items
14251 * @param {HTMLElement} component - The header component element
14252 */
14253function checkMenuState(component) {
14254    const header = component;
14255    const hasUtilNavItems = component.querySelectorAll(".mobile-menu .utility-nav > ul");
14256    const hasMainNavItems = component.querySelectorAll(".mobile-menu .top-level-links > li");
14257    const hasSearchDisabled = component.querySelector(".mobile-menu .top-level-links")?.classList.contains("no-search");
14258    const mobileMenu = component.querySelector(".mobile-menu .menu");
14259    if(hasUtilNavItems.length === 0 && hasMainNavItems.length === 0 && hasSearchDisabled && mobileMenu) {
14260        mobileMenu.style.display = 'none';
14261    }
14262}
14263
14264/**
14265 * Processes and sanitizes search terms
14266 * @param {string} searchTerm - The search term to process
14267 * @returns {string} The processed search term
14268 */
14269function processSearchTerm(searchTerm) {
14270    const regexPattern =  /^[eE][vV](?=.*\d)(?=.*-).*$/;
14271    if(searchTerm==="" || !searchTerm){
14272        return "";
14273    }
14274    else if(regexPattern.test(searchTerm)){
14275        searchTerm = searchTerm.replace(/-/g, '');
14276    }
14277    else if(searchTerm && (typeof searchTerm === 'object' || typeof searchTerm === 'function')){
14278        searchTerm = String(searchTerm);
14279    }
14280    return searchTerm;
14281}
14282
14283/**
14284 * Builds a URL with the provided path and query parameters
14285 * @param {string} path - The path to navigate to
14286 * @param {string} queryString - The query parameters (already formatted with ?)
14287 * @returns {string} The complete URL
14288 */
14289function buildUrl(path, queryString = '') {
14290    const protocol = window.location.protocol;
14291    const hostname = window.location.hostname;
14292    const port = window.location.port ? `:${window.location.port}` : '';
14293    return `${protocol}//${hostname}${port}${path}${queryString}`;
14294}
14295
14296/**
14297 * Gets the 1-based position of an element within its parent's children
14298 * @param {HTMLElement} element - The element to find the position of
14299 * @returns {number} The 1-based position (1, 2, 3...), or 0 if element is not found
14300 */
14301function getElementPosition(element) {
14302    if(!element?.parentElement) return 0;
14303    return Array.from(element.parentElement.children).indexOf(element) + 1;
14304}
14305
14306/**
14307 * Detects if the user is on a mobile or desktop device
14308 * @returns {string} 'mobile' or 'desktop'
14309 */
14310function getPlatform() {
14311    return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'mobile' : 'desktop';
14312}
14313
14314/**
14315 * Uses screenwidth to determine if mobile/tablet or not (1260px is desktop).
14316 * @returns true of tablet or mobile
14317 */
14318function isMobileTablet() {
14319    return window.matchMedia('(max-width: 1259px)').matches;
14320}
14321
14322/**
14323 * Gets the business unit filter from the header search form
14324 * @returns {string} The formatted BU filter string or empty string
14325 */
14326function getBUFilter() {
14327    const form = document.querySelector('.header-search-form');
14328    const preFilterBU = form?.getAttribute('data-prefilterBU');
14329    return preFilterBU ? `(${preFilterBU})` : '';
14330}
14331
14332/**
14333 * Gets the business unit suggested filter from the header search form
14334 * @returns {string} The formatted BU suggested filter string or empty string
14335 */
14336function getBUSuggestedFilter() {
14337    const form = document.querySelector('.header-search-form');
14338    const preFilterBU = form?.getAttribute('data-business-units-suggested');
14339    return preFilterBU ? `(${preFilterBU})` : '';
14340}
14341
14342// =============================================================================
14343// ALGOLIA WIDGET HELPER FUNCTIONS
14344// =============================================================================
14345
14346/**
14347 * Adds search box widgets to the widgets array
14348 * @param {Array} widgets - The widgets array to add to
14349 * @param {HTMLElement} containerElem - The container element
14350 * @param {Function} customSearchBox - The custom search box widget
14351 * @param {Function}
14351 customSearchBoxMobile - The mobile custom search box widget
14352 */
14353function addSearchBoxWidgets(widgets, containerElem, customSearchBox, customSearchBoxMobile) {
14354    const searchBoxDesktop = containerElem[0].querySelector('.search-box');
14355    const searchBoxMobile = containerElem[1].querySelector('.search-box');
14356
14357    if(searchBoxDesktop) {
14358        widgets.push(customSearchBox({
14359            container: searchBoxDesktop,
14360            placeholder: 'Search',
14361            queryHook: debounce(function(query, search) {
14362                search(processSearchTerm(query));
14363            }, 400)
14364        }));
14365    }
14366    if(searchBoxMobile) {
14367        widgets.push(customSearchBoxMobile({
14368            container: searchBoxMobile,
14369            placeholder: 'Search',
14370            queryHook: debounce(function(query, search) {
14371                search(processSearchTerm(query));
14372            }, 400)
14373        }));
14374    }
14375}
14376
14377/**
14378 * Adds product widgets to the widgets array
14379 * @param {Array} widgets - The widgets array to add to
14380 * @param {HTMLElement} containerElem - The container element
14381 * @param {Function} dropdownProductHitTemplate - Template function for product hits
14382 * @param {Function} productDropdownStats - Stats connector for products
14383 */
14384function addProductWidgets(widgets, containerElem, dropdownProductHitTemplate, productDropdownStats) {
14385    const productsDesktop = containerElem[0].querySelector('.products');
14386    const productsMobile = containerElem[1].querySelector('.products');
14387    const productsCount = containerElem[0].querySelector('.products-count');
14388    const productsMobileCount=containerElem[1].querySelector('.products-count');
14389
14390
14391    if(productsDesktop) {
14392        widgets.push(instantsearch.widgets.hits({
14393            container: productsDesktop,
14394            templates: {
14395                item: dropdownProductHitTemplate
14396            }
14397        }));
14398    }
14399    if(productsMobile) {
14400        widgets.push(instantsearch.widgets.hits({
14401            container: productsMobile,
14402            templates: {
14403                item: dropdownProductHitTemplate
14404            }
14405        }));
14406    }
14407    if(productsCount) {
14408        widgets.push(productDropdownStats({
14409            container: productsCount
14410        }));
14411    }
14412    if(productsMobileCount) {
14413        widgets.push(productDropdownStats({
14414            container: productsMobileCount
14415        }));
14416    }
14417
14418}
14419
14420/**
14421 * Adds suggestion widgets to the widgets array
14422 * @param {Array} widgets - The widgets array to add to
14423 * @param {HTMLElement} containerElem - The container element
14424 * @param {Function} dropdownSuggestionsHitTemplate - Template function for suggestion hits
14425 * @param {Function} getPlatform - Function to get the platform type
14426 * @param {Function} getBUSuggestedFilter - Function to get business unit filter
14427 */
14428function addSuggestionWidgets(widgets, containerElem, dropdownSuggestionsHitTemplate, getPlatform, getBUSuggestedFilter) {
14429    const suggestionsDesktop = containerElem[0].querySelector('.dropdown-container .suggestions');
14430    const suggestionsMobile = containerElem[1].querySelector('.dropdown-container .suggestions');
14431
14432    if(suggestionsDesktop?.dataset.index) {
14433        const suggestionsWidgets = [];
14434        suggestionsWidgets.push(instantsearch.widgets.configure({
14435            analyticsTags: [getPlatform()],
14436            hitsPerPage: 3,
14437            filters: getBUSuggestedFilter()
14438        }));
14439
14440        if(suggestionsDesktop) {
14441            suggestionsWidgets.push(instantsearch.widgets.hits({
14442                container: suggestionsDesktop,
14443                templates: {
14444                    // Override Algolia's default "No results found" text with blank
14445                    empty: () => '',
14446                    item: dropdownSuggestionsHitTemplate
14447                }
14448            }));
14449        }
14450        if(suggestionsMobile) {
14451            suggestionsWidgets.push(instantsearch.widgets.hits({
14452                container: suggestionsMobile,
14453                templates: {
14454                    // Override Algolia's default "No results found" text with blank
14455                    empty: () => '',
14456                    item: dropdownSuggestionsHitTemplate
14457                }
14458            }));
14459        }
14460
14461        const suggestionsIndex = instantsearch.widgets.index({
14462            indexName: suggestionsDesktop.dataset.index
14463        });
14464        suggestionsIndex.addWidgets(suggestionsWidgets);
14465        widgets.push(suggestionsIndex);
14466    }
14467}
14468
14469/**
14470 * Adds popular pages widgets to the widgets array
14471 * @param {Array} widgets - The widgets array to add to
14472 * @param {HTMLElement} containerElem - The container element
14473 * @param {Function} dropdownPagesHitTemplate - Template function for page hits
14474 * @param {Function} renderPopularPagesDropdownStats - Stats renderer for popular pages
14475 * @param {Function} getPlatform - Function to get the platform type
14476 */
14477function addPopularPagesWidgets(widgets, containerElem, dropdownPagesHitTemplate, renderPopularPagesDropdownStats, getPlatform) {
14478    const popularPagesDesktop = containerElem[0].querySelector('.dropdown-container .popular-pages');
14479    const popularPagesMobile = containerElem[1].querySelector('.dropdown-container .popular-pages');
14480    const popularPagesCount = containerElem[0].querySelector('.popular-pages-count');
14481    const productsCountMobile = containerElem[1].querySelector('.popular-pages-count');
14482
14483    if(popularPagesDesktop?.dataset.index) {
14484        const popularPagesWidgets = [];
14485        popularPagesWidgets.push(instantsearch.widgets.configure({
14486            analyticsTags: [getPlatform()],
14487            hitsPerPage: 4
14488        }));
14489
14490        if(popularPagesDesktop) {
14491            popularPagesWidgets.push(instantsearch.widgets.hits({
14492                container: popularPagesDesktop,
14493                templates: {
14494                    // Override Algolia's default "No results found" text with blank
14495                    empty: () => '',
14496                    item: dropdownPagesHitTemplate
14497                }
14498            }));
14499        }
14500        if(popularPagesMobile) {
14501            popularPagesWidgets.push(instantsearch.widgets.hits({
14502                container: popularPagesMobile,
14503                templates: {
14504                    // Override Algolia's default "No results found" text with blank
14505                    empty: () => '',
14506                    item: dropdownPagesHitTemplate
14507                }
14508            }));
14509        }
14510        if(popularPagesCount) {
14511            popularPagesWidgets.push(instantsearch.connectors.connectStats(
14512                renderPopularPagesDropdownStats
14513            )({
14514                container: popularPagesCount
14515            }));
14516        }
14517        if(productsCountMobile) {
14518            popularPagesWidgets.push(instantsearch.connectors.connectStats(
14519               renderPopularPagesDropdownStats
14520           )({
14521               container: productsCountMobile
14522           }));
14523        }
14524
14525        const popularPagesIndex = instantsearch.widgets.index({
14526            indexName: popularPagesDesktop.dataset.index
14527        });
14528        popularPagesIndex.addWidgets(popularPagesWidgets);
14529        widgets.push(popularPagesIndex);
14530    }
14531}
14532
14533// =============================================================================
14534// MAIN HEADER INITIALIZATION
14535// =============================================================================
14536
14537/**
14538 * Sets up Algolia search, dropdown interactions, and event listeners for a header component
14539 * Manages search state, dropdown visibility, and analytics tracking
14540 * @param {HTMLElement} componentElement - The header component element
14541 */
14542function setupHeaderSearchAndDropdown(componentElement) {
14543    // Component state (closure-scoped)
14544    let userToken = HeaderUtil.getCloudVisitorId();
14545    const applicationId = componentElement.dataset.applicationId;
14546    const searchApiKey = componentElement.dataset.searchApiKey;
14547
14548    // Initialize search client only if Algolia is available
14549    let searchClient = null;
14550    if(window.algoliasearch?.algoliasearch) {
14551        searchClient = window.algoliasearch.algoliasearch(applicationId, searchApiKey);
14552    }
14553
14554    let dropdownSearchObjects = null;
14555    let afterFirstFocusOnSearchBar = false;
14556    let hasSuggestions = false;
14557    let hasPopularPages = false;
14558    let searchBoxFocus = false;
14559    let inputSearchQuery = getParams().q ? processSearchTerm(decodeURIComponent(getParams().q).replace(/\+/g, ' ')) : '';
14560
14561    /**
14562     * Updates dropdown visibility and body menu-open class
14563     */
14564    function updateDropdownVisibility() {
14565        const isOpen = !document.querySelector('.pentair') && searchBoxFocus;
14566        if(!isOpen) {
14567            document.body.classList.remove("menu-open");
14568        } else {
14569            document.body.classList.add("menu-open");
14570        }
14571
14572        // Update dropdown display
14573        const dropdownContainers = componentElement.querySelectorAll('.dropdown-container');
14574        const dropdown = isMobileTablet() ? dropdownContainers[1] : dropdownContainers[0];
14575        if(dropdown) {
14576            dropdown.style.display = isOpen ? 'block' : 'none';
14577        }
14578    }
14579
14580    /**
14581     * Updates visibility of suggestion/page containers based on state
14582     */
14583    function updateContainerVisibility() {
14584        const suggestionsContainer = componentElement.querySelector('.suggested-searches-container');
14585        if(suggestionsContainer) {
14586            suggestionsContainer.style.display = hasSuggestions ? 'block' : 'none';
14587        }
14588
14589        const pagesContainer = componentElement.querySelector('.popular-pages-container');
14590        if(pagesContainer) {
14591            pagesContainer.style.display = hasPopularPages ? 'block' : 'none';
14592        }
14593    }
14594
14595    // -------------------------------------------------------------------------
14596    // EVENT HANDLER FUNCTIONS
14597    // -------------------------------------------------------------------------
14598
14599    // "Popular Pages"
14600    function dropdownSearchPopularPagesClick(event) {
14601            const captureElem = event.target.closest('a');
14602            if(!!window._satellite){
14603                const li = captureElem.closest('li');
14604                const liIndex = getElementPosition(li);
14605                _satellite.track('query result click', {
14606                    query: inputSearchQuery,
14607                    resultLink: `Page Result|${liIndex}|${captureElem.textContent.trim()}`
14608                });
14609            }
14610
14611            // PAAS - Adobe Analytics
14612            const searchTerm = inputSearchQuery;
14613            const linkClicked = event.target.closest('a');
14614            const suggestedSearchResult = linkClicked ? linkClicked.textContent.trim() : '';
14615            const queryID = linkClicked && linkClicked.dataset.queryId ? linkClicked.dataset.queryId : '';
14616            trackSuggestedSearchClickPayload(searchTerm, suggestedSearchResult, queryID, true);
14617
14618            return true;
14619    }
14620
14621    // "Popular Products"
14622    function dropdownSearchProductClick(event) {
14623            const captureElem = event.target.closest('a');
14624            if(!!window._satellite){
14625                const li = captureElem?.closest('li');
14626                const index = getElementPosition(li);
14627                _satellite.track('query result click', {
14628                    query: inputSearchQuery,
14629                    resultLink: `Product Result|${index}|${captureElem?.textContent.trim() || ''}`
14630                });
14631            }
14632
14633            // PAAS - Adobe Analytics
14634            const searchTerm = inputSearchQuery;
14635            const linkClicked = event.target.closest('a');
14636            const suggestedSearchResult = linkClicked ? linkClicked.textContent.trim() : '';
14637            const queryID = linkClicked && linkClicked.dataset.queryId ? linkClicked.dataset.queryId : '';
14638            trackSuggestedSearchClickPayload(searchTerm, suggestedSearchResult, queryID, true);
14639
14640            searchBoxFocus = false;
14641            updateDropdownVisibility();
14642
14643            return true;
14644    }
14645
14646    // "View _ product results"
14647    function dropdownSearchProductCountClick(event) {
14648            const productIndex = event.target.closest('.products-count')?.dataset.productTabIndex;
14649            const searchPage = componentElement.querySelector(".header-search-form")?.dataset.searchPage;
14650            const pageType = document.head.querySelector('meta[name="pageType"]')?.content;
14651            let query = inputSearchQuery;
14652            if(pageType?.indexOf("ift") > -1){
14653                query = typeof query === 'object' || typeof query === 'function' ? '' : query;
14654            }
14655            const queryWithTabParams = `?q=${query}&tab=${productIndex}`;
14656            searchBoxFocus = false;
14657            updateDropdownVisibility();
14658            const url = buildUrl(searchPage, queryWithTabParams);
14659            window.location.assign(url);
14660            return false;
14661    }
14662
14663    // "Suggested Searches"
14664    function dropdownSuggestionClick(event) {
14665        const captureElem = event.target.closest('a');
14666        searchBoxFocus = false;
14667        updateDropdownVisibility();
14668            const searchPage = componentElement.querySelector(".header-search-form")?.dataset.searchPage;
14669            const suggestedQuery = captureElem?.dataset.query?.split(" ").join("+");
14670            const queryParams = `?q=${suggestedQuery}`;
14671            const url = buildUrl(searchPage, queryParams);
14672
14673            // PAAS - Adobe Analytics
14674            const searchTerm = inputSearchQuery;
14675            const linkClicked = event.target.closest('a');
14676            const suggestedSearchTerm = linkClicked ? linkClicked.textContent.trim() : '';
14677            const queryID = linkClicked && linkClicked.dataset.queryId ? linkClicked.dataset.queryId : '';
14678            trackSuggestedSearchClickPayload(searchTerm, suggestedSearchTerm, queryID, false);
14679
14680            window.location.assign(url);
14681
14682            if(!!window._satellite){
14683                const li = captureElem?.closest('li');
14684                const index = getElementPosition(li);
14685                _satellite.track('query result click', {
14686                    query: inputSearchQuery,
14687                    resultLink: `Suggestion|${index}|${captureElem?.textContent.trim() || ''}`
14688                });
14689            }
14690
14691            return false;
14692    }
14693
14694    // Handler for "View _ page results"
14695    function dropdownSearchPopularPagesCountClick(event) {
14696        const pageIndex = event.target.closest('.popular-pages-count')?.dataset.pageTabIndex;
14697        const searchPage = componentElement.querySelector(".header-search-form")?.dataset.searchPage;
14698        const query = inputSearchQuery;
14699        const queryWithTabParams = `?q=${query}&tab=${pageIndex}`;
14700        searchBoxFocus = false;
14701        updateDropdownVisibility();
14702            const url = buildUrl(searchPage, queryWithTabParams);
14703            window.location.assign(url);
14704            return false;
14705    }
14706
14707    function inputEnter(event) {
14708        const captureElem = event.target.closest('input');
14709        if(event.key === 'Enter') {
14710            event.target.blur();
14711            doSearch(event);
14712        }
14713        return true;
14714    }
14715
14716    function doSearch(event) {
14717            const searchInput = event.currentTarget.closest('.header-search-form')?.querySelector('.search-box input');
14718            let searchTerm = searchInput?.value || '';
14719            searchTerm = searchTerm ? processSearchTerm(decodeURIComponent(searchTerm).replace(/\+/g, ' ')) : '';
14720
14721            // Searched from header search bar using enter or by clicking search icon
14722            const currentPage = document.head.querySelector('link[rel="canonical"]')
14723                ? document.head.querySelector('link[rel="canonical"]')
14724                : document.location.origin + document.location.pathname;
14725            const pentairSearchJSON = {
14726                priorPageURL: currentPage,
14727                searchType: "search bar",
14728                searchTerm: searchTerm
14729            };
14730            setSessionCookie('pentairSearch', JSON.stringify(pentairSearchJSON));
14731            const searchPage = componentElement.querySelector(".header-search-form")?.dataset.searchPage;
14732            const queryParams = `?q=${searchTerm}`;
14733            const url = buildUrl(searchPage, queryParams);
14734            window.location.assign(url);
14735    }
14736
14737    // -------------------------------------------------------------------------
14738    // ALGOLIA SEARCH INITIALIZATION
14739    // -------------------------------------------------------------------------
14740
14741    function initAlgoliaSearchBox(searchClientParam, indexName, containerElem) {
14742        dropdownSearchObjects = window.instantsearch({
14743                indexName: indexName,
14744                searchClient: searchClientParam,
14745                insights: {
14746                    insightsInitParams: {
14747                        userToken: userToken
14748                    }
14749                },
14750                searchFunction: function(helper) {
14751                    inputSearchQuery = decodeURIComponent(helper.getQuery().query);
14752                    // Prevent the searches on page load
14753                    // Only search after user has interacted with the search bar in the header
14754                    if(afterFirstFocusOnSearchBar) {
14755                        helper.search();
14756                    }
14757                }
14758            });
14759
14760        const renderProductDropdownStats = (renderOptions, isFirstRender) => {
14761            if(renderOptions.nbHits > 1){
14762                renderOptions.widgetParams.container.innerHTML = `<a href="#" aria-label="See all product results">View ${renderOptions.nbHits} product results</a>`;
14763                if(pageType.indexOf("ift") > -1 && language === 'de') {
14764                    renderOptions.widgetParams.container.innerHTML = `<a href="#" aria-label="Alle Produktergebnisse anzeigen">Sehen Sie sich ${renderOptions.nbHits} Produktergebnisse an</a>`;
14765                }
14766            } else {
14767                renderOptions.widgetParams.container.innerHTML = '';
14768            }
14769        };
14770
14771        const renderPopularPagesDropdownStats = (renderOptions, isFirstRender) => {
14772            if(renderOptions.nbHits > 1){
14773                renderOptions.widgetParams.container.innerHTML = `<a href="#" aria-label="See all page results">View ${renderOptions.nbHits} page results</a>`;
14774            } else {
14775                renderOptions.widgetParams.container.innerHTML = '';
14776            }
14777        };
14778
14779        const renderSearchBox = (renderOptions, isFirstRender) => {
14780            const clear = renderOptions;
14781            const container = renderOptions.widgetParams.container;
14782
14783            if(isFirstRender) {
14784                const input = document.createElement('input');
14785                input.className = 'input-box';
14786                input.setAttribute('type', 'text');
14787                input.setAttribute('enterkeyhint', 'done');
14788                input.setAttribute('aria-label', 'Search');
14789                input.placeholder = 'Search';
14790
14791                input.addEventListener('input', (event) => {
14792                    renderOptions.refine(event.target.value);
14793                });
14794
14795                renderOptions.refine(inputSearchQuery);
14796
14797                // Create reset button
14798                const removeBtn = document.createElement('button');
14799                removeBtn.className = 'ais-SearchBox-reset';
14800                removeBtn.textContent = 'X';
14801                removeBtn.setAttribute('aria-label', 'Clear search');
14802                removeBtn.style.display = 'none';
14803
14804                // Show/hide reset button based on input value
14805                input.addEventListener('input', () => {
14806                    removeBtn.style.display = input.value ? 'block' : 'none';
14807                });
14808
14809                // Reset button click handler
14810                removeBtn.addEventListener('click', () => {
14811                    renderOptions.clear();
14812                    input.value = '';
14813                    removeBtn.style.display = 'none';
14814                    input.focus();
14815                });
14816
14817                container.appendChild(input);
14818                container.appendChild(removeBtn);
14819            }
14820            if(!afterFirstFocusOnSearchBar) {
14821                container.querySelector('input').addEventListener('focus', firstFocusHandler);
14822            }
14823        };
14824
14825        const renderSearchBoxMobile = (renderOptions, isFirstRender) => {
14826            const container = renderOptions.widgetParams.container;
14827
14828            if(isFirstRender) {
14829                const inputMobile = document.createElement('input');
14830                inputMobile.className = 'input-box';
14831                inputMobile.setAttribute('type', 'text');
14832                inputMobile.setAttribute('enterkeyhint', 'done');
14833                inputMobile.setAttribute('aria-label', 'Search');
14834                inputMobile.placeholder = 'Search';
14835
14836                inputMobile.addEventListener('input', (event) => {
14837                    renderOptions.refine(event.target.value);
14838                });
14839
14840                renderOptions.refine(inputSearchQuery);
14841
14842                // Create reset button for mobile
14843                const removeBtnMobile = document.createElement('button');
14844                removeBtnMobile.className = 'ais-SearchBox-reset';
14845                removeBtnMobile.textContent = 'X';
14846                removeBtnMobile.setAttribute('aria-label', 'Clear search');
14847                removeBtnMobile.style.display = 'none';
14848
14849                // Show/hide reset button based on input value
14850                inputMobile.addEventListener('input', () => {
14851                    removeBtnMobile.style.display = inputMobile.value ? 'block' : 'none';
14852                });
14853
14854                // Reset button click handler
14855                removeBtnMobile.addEventListener('click', () => {
14856                    renderOptions.clear();
14857                    inputMobile.value = '';
14858                    removeBtnMobile.style.display = 'none';
14859                    inputMobile.focus();
14860                });
14861
14862                container.appendChild(inputMobile);
14863                container.appendChild(removeBtnMobile);
14864            }
14865            if(!afterFirstFocusOnSearchBar) {
14866                container.querySelector('input').addEventListener('focus', firstFocusHandler);
14867            }
14868        };
14869
14870        /**
14871         * Handles the first focus event on the search bar.
14872         * Starts the searches in the dropdown and removes the handler.
14873         * @param event focus event
14874         */
14875        function firstFocusHandler(event) {
14876            afterFirstFocusOnSearchBar = true;
14877            dropdownSearchObjects.helper.search();
14878            event.currentTarget.removeEventListener('focus', firstFocusHandler);
14879        }
14880
14881        const customSearchBox = instantsearch.connectors.connectSearchBox(
14882            renderSearchBox
14883        );
14884        const customSearchBoxMobile = instantsearch.connectors.connectSearchBox(
14885            renderSearchBoxMobile
14886        );
14887
14888
14889        const productDropdownStats = instantsearch.connectors.connectStats(
14890            renderProductDropdownStats
14891        );
14892        const currentPagePath = window.location.pathname;
14893        let algoliaRuleContexts = [];
14894        if(currentPagePath.includes('/en-us/water-softening-filtration')) {
14895            algoliaRuleContexts.push('_en-us_water-softening-filtration');
14896        } else if(currentPagePath.includes('/en-us/home-water-treatment')) {
14897            algoliaRuleContexts.push('_en-us_home-water-treatment');
14898        }
14899
14900        const config = {
14901            analyticsTags: [getPlatform()],
14902            hitsPerPage: 4,
14903            filters:getBUFilter(),
14904            ruleContexts: algoliaRuleContexts
14905        };
14906
14907        const language = document.head.querySelector('meta[name="pageLocale"]')?.content || 'en';
14908        const pageType = document.head.querySelector('meta[name="pageType"]')?.content || '';
14909
14910        if(pageType.indexOf("ift") > -1) {
14911            config.facetFilters = [`pageLocale:${language}`];
14912        }
14913
14914        // Search suggestion dropdown hit templates
14915        const dropdownProductHitTemplate = (hit, { html, components, sendEvent }) => {
14916            const imgSrc = hit.productThumbnail
14917                ? `${hit.productThumbnail}.thumb.319.319.png`
14918                : '/content/dam/extranet/product-related/product-photo/Placeholder Image.png.thumb.319.319.png';
14919            return html`
14920                <div class="flex-container">
14921                    <div class="image-container">
14922                        <img src="${imgSrc}" alt="Product Image"/>
14923                    </div>
14924                    <div class="link-container">
14925                        <a href="${hit.url}"
14926                            aria-label="Link to ${hit.productName}"
14927                            data-object-id="${hit.objectID}"
14928                            data-query-id="${hit.__queryID}"
14929                            data-position="${hit.__position}"
14930                            onClick="${() => sendEvent('click', hit, 'Search Bar: Dropdown Product Click')}">
14931                            ${components.Highlight({ hit, attribute: 'productName', highlightedTagName: 'mark' })}
14932                        </a>
14933                    </div>
14934                </div>`;
14935        }
14936        const dropdownPagesHitTemplate = (hit, { html, components, sendEvent }) => {
14937            hasPopularPages = true;
14938            updateContainerVisibility();
14939            return html`<a href="${hit.url}"
14940                aria-label="Search for Popular Page ${hit.title}"
14941                data-query="${hit.title}"
14942                data-object-id="${hit.objectID}"
14943                data-query-id="${hit.__queryID}"
14944                data-position="${hit.__position}"
14945                onClick="${() => sendEvent('click', hit, 'Search Bar: Dropdown Popular Pages Click')}">
14946                ${components.Highlight({ hit, attribute: 'title' })}
14947            </a>`;
14948        }
14949        const dropdownSuggestionsHitTemplate = (hit, { html, components , sendEvent}) => {
14950            hasSuggestions = true;
14951            updateContainerVisibility();
14952            return html`<a href="#"
14953                class="suggested-searches"
14954                aria-label="Search for Suggested Query"
14955                data-query="${hit.query}"
14956                data-query-id="${hit.__queryID}"
14957                data-position="${hit.__position}"
14958                onClick="${() => sendEvent('click', hit, 'Search Bar: Dropdown Query Suggestion Click')}">
14959                ${components.Highlight({ hit, attribute: 'query' })}
14960            </a>`;
14961        }
14962
14963        // Build widgets array
14964        const widgets = [];
14965
14966        // Add search boxes
14967        addSearchBoxWidgets(widgets, containerElem, customSearchBox, customSearchBoxMobile);
14968
14969        // Always add configure widget
14970        widgets.push(instantsearch.widgets.configure(config));
14971
14972        // Add products widgets
14973        addProductWidgets(widgets, containerElem, dropdownProductHitTemplate, productDropdownStats);
14974
14975        // Add suggestions widgets
14976        addSuggestionWidgets(widgets, containerElem, dropdownSuggestionsHitTemplate, getPlatform, getBUSuggestedFilter);
14977
14978        // Add popular pages widgets
14979        addPopularPagesWidgets(widgets, containerElem, dropdownPagesHitTemplate, renderPopularPagesDropdownStats, getPlatform);
14980
14981        // Keep optional sections hidden until we have hits.
14982        updateContainerVisibility();
14983
14984        dropdownSearchObjects.addWidgets(widgets);
14985
14986        dropdownSearchObjects.start();
14987    }
14988
14989    // -------------------------------------------------------------------------
14990    // HELPER FUNCTIONS
14991    // -------------------------------------------------------------------------
14992
14993    function getParams() {
14994        return Object.fromEntries(
14995            location.search.slice(1).split('&')
14996                .filter(Boolean)
14997                .map(item => item.split('='))
14998        );
14999    }
15000
15001    /**
15002     * Sets up event listeners for dropdown and search interactions
15003     */
15004    function setupEventListeners() {
15005        const DROPDOWN_DELAY = 100;
15006
15007        // Dropdown click event delegation
15008
15009        const dropdownContainers = componentElement.querySelectorAll('.dropdown-container');
15010        dropdownContainers.forEach(container => {
15011            container.addEventListener('click', (event) => {
15012                const target = event.target.closest('a');
15013                if(!target) return;
15014
15015                // Popular Pages clicks
15016                if(target.closest('.popular-pages')) {
15017                    dropdownSearchPopularPagesClick(event);
15018                    return;
15019                }
15020
15021                // Popular Pages count clicks
15022                if(target.closest('.popular-pages-count')) {
15023                    dropdownSearchPopularPagesCountClick(event);
15024                    return;
15025                }
15026
15027                // Product clicks
15028                if(target.closest('.products') && !target.closest('.products-count')) {
15029                    dropdownSearchProductClick(event);
15030                    return;
15031                }
15032
15033                // Product count clicks
15034                if(target.closest('.products-count')) {
15035                    dropdownSearchProductCountClick(event);
15036                    return;
15037                }
15038
15039                // Suggestion clicks
15040                if(target.closest('.suggested-searches')) {
15041                    dropdownSuggestionClick(event);
15042                    return;
15043                }
15044            });
15045
15046            // Suggestion dropdown focus listener
15047            container.addEventListener('focusin', () => {
15048                clearTimeout(searchBlurTimer);
15049                searchBoxFocus = true;
15050            });
15051            container.addEventListener('focusout', () => {
15052                searchBlurTimer = setTimeout(() => {
15053                    searchBoxFocus = false;
15054                    updateDropdownVisibility();
15055                }, DROPDOWN_DELAY);
15056            });
15057        });
15058
15059        // Search input event listeners
15060        // Shared timer prevents blur from closing dropdown when focus moves between search elements
15061        let searchBlurTimer = null;
15062        const searchInputs = componentElement.querySelectorAll('.search-box input');
15063        searchInputs.forEach(input => {
15064            input.addEventListener('keypress', inputEnter);
15065
15066            // Track focus for dropdown visibility
15067            input.addEventListener('focus', () => {
15068                clearTimeout(searchBlurTimer);
15069                searchBoxFocus = true;
15070                updateDropdownVisibility();
15071            });
15072
15073            input.addEventListener('blur', () => {
15074                // Delay to allow focus events to fire
15075                searchBlurTimer = setTimeout(() => {
15076                    searchBoxFocus = false;
15077                    updateDropdownVisibility();
15078                }, DROPDOWN_DELAY);
15079            });
15080        });
15081
15082
15083        // Search button clicks
15084        const searchButtons = componentElement.querySelectorAll('.header-search-form button[type="button"], .header-search-form .search-icon');
15085        searchButtons.forEach(button => {
15086            button.addEventListener('click', doSearch);
15087
15088            // Maintain focus state when interacting with search button/icon
15089            button.addEventListener('mousedown', (event) => {
15090                // Prevent blur from firing on the input
15091                event.preventDefault();
15092                searchBoxFocus = true;
15093            });
15094
15095            button.addEventListener('focus', () => {
15096                clearTimeout(searchBlurTimer);
15097                searchBoxFocus = true;
15098                updateDropdownVisibility();
15099            });
15100
15101            button.addEventListener('blur', () => {
15102                // Delay to allow focus events to fire
15103                searchBlurTimer = setTimeout(() => {
15104                    searchBoxFocus = false;
15105                    updateDropdownVisibility();
15106                }, DROPDOWN_DELAY);
15107            });
15108        });
15109
15110        // Close dropdown when clicking outside
15111        document.addEventListener('click', (event) => {
15112            if(!componentElement.contains(event.target)) {
15113                searchBoxFocus = false;
15114                updateDropdownVisibility();
15115            }
15116        });
15117    }
15118
15119    // -------------------------------------------------------------------------
15120    // INITIALIZATION
15121    // -------------------------------------------------------------------------
15122    const searchFieldContainers = componentElement.querySelectorAll('.search-field-container');
15123    if(searchClient && window.instantsearch && searchFieldContainers && searchFieldContainers[0]?.dataset.index) {
15124        initAlgoliaSearchBox(searchClient, searchFieldContainers[0].dataset.index, searchFieldContainers);
15125    }
15126
15127    // Set up all event listeners
15128    setupEventListeners();
15129}
15130
15131// =========================================================================
15132// ANALYTICS HELPER FUNCTIONS
15133// =========================================================================
15134
15135/**
15136 * Tracks the suggested search term/result click event payload.
15137 * @param {string} searchTerm - Term typed in the search box
15138 * @param {string} suggestedSearchText - Term or result text in suggested area clicked on
15139 * @param {string} queryID - Algolia query ID
15140 * @param {boolean} isDirectResult - True ifthe link clicked on was a suggested result linking directly to a page or product
15141 */
15142function trackSuggestedSearchClickPayload(searchTerm, suggestedSearchText, queryID, isDirectResult) {
15143    const eventSearchSuggestedTermClickPayload = {
15144        eventName: isDirectResult ? 'search suggested result clicked' : 'search suggested term clicked',
15145        eventType: 'event',
15146        attributes: {
15147            search: {
15148                searchTerm: processSearchTerm(searchTerm),
15149                algoliaQueryID: queryID,
15150                searchType: "suggested search",
15151            },
15152            visitor: {
15153                pentairCustomerID: getPentairCustomerID(), //if this is available
15154                dealerID: getDealerID() //if this is available
15155            },
15156            page: {
15157                pageCanonical: getPageViewPageAttribute("pageCanonical"),
15158                pageName: getPageViewPageAttribute("pageName"),
15159                pagePath: getPageViewPageAttribute("pagePath"),
15160                pageType: getPageViewPageAttribute("pageType"),
15161                pageURL: getPageViewPageAttribute("pageURL"),
15162                language: getPageViewPageAttribute("language")
15163            }
15164        }
15165    }
15166    // Only add one of the keys; suggestedSearchTerm or suggestedSearchResult
15167    // This is done after inital creation of the object bc ternary operators can't be done with property id names
15168    const searchTextAttrName = isDirectResult ? 'suggestedSearchResult' : 'suggestedSearchTerm';
15169    eventSearchSuggestedTermClickPayload.attributes.search[searchTextAttrName] = suggestedSearchText;
15170    trackEventWithQueue(eventSearchSuggestedTermClickPayload);
15171}
15172
15173// =========================================================================
15174// MOBILE NAVIGATION HELPER FUNCTIONS
15175// =========================================================================
15176
15177/**
15178 * Opens the my account hamburger menu on mobile and tablet viewports
15179 * Checks if its open before trying to open, and hides the main mobile nav menu if its open already
15180 * @param {HTMLElement} headerComponent - The header element
15181 * @param {HTMLElement} mobileHamburgerMenuButton - The mobile hamburger menu button element
15182 * @param {Function} mobileHamburgerMenuToggleHandler - Function handler used to toggle the main mobile nav opening logic
15183 */
15184function openMyAccountMobileNavDropdown(headerComponent, mobileHamburgerMenuButton, mobileHamburgerMenuToggleHandler) {
15185    const myAccountMobileNavMenu = document.querySelector(".mobile-menu .my-account__nav-menu");
15186    const isMyAccountNavDropdownOpen = myAccountMobileNavMenu?.classList.contains("my-account__nav-menu--active");
15187
15188    if(isMyAccountNavDropdownOpen) {
15189        return;
15190    }
15191
15192    const isMobileHamburgerMenuOpen = mobileHamburgerMenuButton.classList.contains("icon-close");
15193    if(isMobileHamburgerMenuOpen) {
15194        mobileHamburgerMenuToggleHandler();
15195    }
15196
15197    mobileHamburgerMenuButton.classList.remove("icon-menu");
15198    mobileHamburgerMenuButton.classList.add("icon-close");
15199    document.body.classList.add("menu-open");
15200    myAccountMobileNavMenu?.classList.add('my-account__nav-menu--active');
15201
15202    mobileHamburgerMenuButton.removeEventListener("click", mobileHamburgerMenuToggleHandler);
15203    const closeHandler = function() {
15204        closeMyAccountMobileNavDropdown(headerComponent, mobileHamburgerMenuButton, mobileHamburgerMenuToggleHandler);
15205        mobileHamburgerMenuButton.removeEventListener("click", closeHandler);
15206    };
15207    mobileHamburgerMenuButton.addEventListener("click", closeHandler);
15208}
15209
15210/**
15211 * Closes the my account mobile hamburger menu and restores the hamburger button to open the mobile nav menu
15212 * @param {HTMLElement} headerComponent - The header element
15213 * @param {HTMLElement} mobileHamburgerMenuButton - The mobile hamburger menu button element
15214 * @param {Function} mobileHamburgerMenuToggleHandler - Function handler used to toggle the main mobile nav opening logic
15215 */
15216function closeMyAccountMobileNavDropdown(headerComponent, mobileHamburgerMenuButton, mobileHamburgerMenuToggleHandler) {
15217    mobileHamburgerMenuButton.classList.remove("icon-close");
15218    mobileHamburgerMenuButton.classList.add("icon-menu");
15219    document.body.classList.remove("menu-open");
15220    const myAccountMenu = document.querySelector(".mobile-menu .my-account__nav-menu");
15221    myAccountMenu?.classList.remove('my-account__nav-menu--active');
15222
15223    mobileHamburgerMenuButton.addEventListener("click", mobileHamburgerMenuToggleHandler);
15224}
15225
15226/**
15227 * Toggles the main header navigation menu for mobile and tablet devices
15228 * @param {HTMLElement} mobileHamburgerMenuButton - The hamburger button element
15229 */
15230function toggleMobileHamburgerMenu(mobileHamburgerMenuButton) {
15231    mobileHamburgerMenuButton.classList.toggle("icon-menu");
15232    mobileHamburgerMenuButton.classList.toggle("icon-close");
15233    const mobileWrap = mobileHamburgerMenuButton.closest(".mobile-wrap");
15234    mobileWrap?.classList.toggle("active");
15235    document.body.classList.toggle("menu-open");
15236    const menuWrap = mobileWrap?.querySelector(".menu-wrap");
15237    menuWrap?.classList.remove("slid");
15238    const mobileSlider = mobileWrap?.querySelector(".mobile-slider");
15239    mobileSlider?.classList.remove("slide");
15240}
15241
15242/**
15243 * Makes parent-only top-level header items open their child dropdown without navigating.
15244 * @param {HTMLElement} headerComponent - The header component element
15245 */
15246function setupParentNavLinkInteractions(headerComponent) {
15247    const parentNavLinks = headerComponent?.querySelectorAll('.top-level-links > li.top-level-link > a');
15248
15249    parentNavLinks?.forEach((anchor) => {
15250        if(anchor.dataset.handlerAttached === 'true') {
15251            return;
15252        }
15253
15254        anchor.dataset.handlerAttached = 'true';
15255
15256        const toggleParentNav = (event) => {
15257            if(anchor.dataset.hasLink === 'true') {
15258                return;
15259            }
15260
15261            event.preventDefault();
15262            event.stopPropagation();
15263
15264            const listItem = anchor.closest('li.top-level-link');
15265            const parentList = listItem?.closest('.top-level-links');
15266            if(!listItem) {
15267                return;
15268            }
15269
15270            const isOpen = listItem.classList.contains('active');
15271            parentList?.querySelectorAll(':scope > li.top-level-link.active').forEach((activeItem) => {
15272                activeItem.classList.remove('active');
15273            });
15274
15275            if(isOpen) {
15276                listItem.classList.remove('active');
15277                anchor.setAttribute('aria-expanded', 'false');
15278            } else {
15279                listItem.classList.add('active');
15280                anchor.setAttribute('aria-expanded', 'true');
15281            }
15282        };
15283
15284        anchor.addEventListener('click', toggleParentNav);
15285        anchor.addEventListener('keydown', (event) => {
15286            if(event.key === 'Enter' || event.key === ' ') {
15287                event.preventDefault();
15288                toggleParentNav(event);
15289            }
15290        });
15291    });
15292}
15293
15294// =========================================================================
15295// TAB NAVIGATION HELPER FUNCTIONS
15296// =========================================================================
15297
15298/**
15299 * Sets the active state on a tab if current page is a child of the tab link
15300 * @param {HTMLElement} tab - The tab element to check and potentially mark as active
15301 */
15302function setActiveTabNav(tab) {
15303    const tabLink = tab.querySelector('.tab-nav__tab--link');
15304    const truncatedTabPath = tabLink?.getAttribute('href')?.replace('/content/pentair/', '').replace('.html', '');
15305    const currentPath = window.location.pathname;
15306    if(truncatedTabPath && currentPath.includes(truncatedTabPath)) {
15307        tab.classList.add('active');
15308    }
15309}
15310
15311/**
15312 * Tracks the menu click event payload for Adobe Analytics
15313 * @param {string} menuText - The text content of the clicked menu item
15314 * @param {string} menuType - The type of menu (e.g., 'main menu', 'sub-nav menu')
15315 */
15316function trackMenuClick(menuText, menuType) {
15317    let eventMenuClickClickPayload = {
15318        eventName: 'click',
15319        eventType: 'event',
15320        attributes: {
15321            linktype: menuType,
15322            linkName: menuText
15323        }
15324    };
15325    trackEventWithQueue(eventMenuClickClickPayload);
15326}
15327
15328// =========================================================================
15329// DOM EVENT SETUP AND COMPONENT INITIALIZATION
15330// =========================================================================
15331
15332function initHeader() {
15333    // Don't wrap in DOMContentLoaded - we're already inside initHeader which runs after DOM is ready
15334    const mobileWrapToggle = document.querySelector(".mobile-wrap button");
15335    if(mobileWrapToggle) {
15336        mobileWrapToggle.addEventListener('click', function() {
15337            const searchForm = document.querySelector('div.header-search-form');
15338            searchForm?.classList.toggle('hideSearchBar');
15339        });
15340    }
15341
15342    const headerComponent = document.querySelector(".header.component");
15343    let isNavStyleSimpleDropdown = false;
15344    if(headerComponent) {
15345        isNavStyleSimpleDropdown = headerComponent.classList.contains('nav-style-simple-dropdown');
15346        document.body.classList.add("header-v2");
15347        setupParentNavLinkInteractions(headerComponent);
15348    }
15349
15350    if(document.querySelector('main.content.generic-interior-page.hide-nav')) {
15351        const mobileWrap = document.querySelector('.mobile-wrap');
15352        mobileWrap?.classList.add('hide-nav');
15353    }
15354
15355    const mobileHamburgerMenuButton = headerComponent?.querySelector(".mobile-menu .icon-menu");
15356    const mobileHamburgerMenuToggleHandler = function() {
15357        toggleMobileHamburgerMenu(mobileHamburgerMenuButton);
15358    }
15359    mobileHamburgerMenuButton?.addEventListener("click", mobileHamburgerMenuToggleHandler);
15360
15361    const mobileMenuWrap = document.querySelector(".mobile-menu .menu-wrap");
15362
15363    //mobile nav sliding
15364    const angleRightIcons = document.querySelectorAll('.mobile-menu .main-nav .icon-angle-right');
15365    angleRightIcons.forEach(icon => {
15366        icon.addEventListener('click', function(e){
15367            e.preventDefault();
15368            const listItemName = this.previousElementSibling?.textContent?.trim();
15369            const dropdown = this.nextElementSibling;
15370            const backButton = dropdown?.querySelector(".back");
15371            if(backButton && listItemName) {
15372                backButton.textContent = listItemName;
15373            }
15374            mobileMenuWrap?.classList.add('slid');
15375            const mobileSlider = this.closest('li')?.querySelector('.mobile-slider:first-child');
15376            mobileSlider?.classList.add('slide');
15377            if(mobileMenuWrap) mobileMenuWrap.scrollTop = 0;
15378        });
15379    });
15380
15381    //mobile back slide
15382    const backButtons = document.querySelectorAll('.mobile-menu .main-nav .back');
15383    backButtons.forEach(button => {
15384        button.addEventListener('click', function(e){
15385            e.preventDefault();
15386            const mobileSlider = this.closest('.mobile-slider');
15387            mobileSlider?.classList.remove('slide');
15388            if(this.nextElementSibling?.classList.contains('tier-2')){
15389                mobileMenuWrap?.classList.remove('slid');
15390            }
15391        });
15392    });
15393
15394    // check for main navigation component and adjust height of menu
15395    const mainNavComponents = headerComponent?.querySelectorAll(".desktop-menu .main-navigation.component");
15396    mainNavComponents?.forEach(function(el){
15397        const tier3List = el.querySelectorAll(".tier-3");
15398        let maxTier3Height = 0;
15399        tier3List.forEach(function(elem) {
15400            const current = elem.offsetHeight;
15401            if(current > maxTier3Height) {
15402                maxTier3Height = current;
15403            }
15404        });
15405
15406        const tier4List = el.querySelectorAll(".tier-4");
15407        let maxTier4Height = 0;
15408        tier4List.forEach(function(elem) {
15409            // need to check if there's more than 8 list items
15410            // if so add class 'greater' to split into 2 columns per designs
15411            const listItems = elem.querySelectorAll(":scope > li");
15412            if(listItems.length > 8) {
15413                elem.classList.add("greater");
15414            }
15415
15416            const current = elem.offsetHeight;
15417            if(current > maxTier4Height) {
15418                maxTier4Height = current;
15419            }
15420        });
15421
15422        // do not adjust height for .nav-style-simple-dropdown
15423        if(!isNavStyleSimpleDropdown) {
15424            const heightToSet = Math.max(maxTier4Height, maxTier3Height);
15425            el.querySelectorAll(".tier-2").forEach(tier => tier.style.height = `${heightToSet}px`);
15426            el.querySelectorAll(".tier-3").forEach(tier => tier.style.height = `${heightToSet}px`);
15427            el.querySelectorAll(".tier-4").forEach(tier => tier.style.height = `${heightToSet}px`);
15428        }
15429    });
15430
15431    document.querySelectorAll('.header.component').forEach((component) => {
15432        checkMenuState(component);
15433        const topLevelLinks = component.querySelector(".top-level-links");
15434
15435        if(topLevelLinks?.children.length) {
15436            setupHeaderSearchAndDropdown(component);
15437        }
15438    });
15439
15440    // Tab Navigation
15441    const tabNav = document.querySelectorAll('.tab-nav__tab');
15442    tabNav.forEach((tab) => {
15443        setActiveTabNav(tab);
15444    });
15445
15446    // Add menu click adobe analytics
15447    const topLevelLinksAll = document.querySelectorAll('header .top-level-link');
15448    topLevelLinksAll.forEach((el) => {
15449        const mainManuItem = el.querySelector(':scope > a');
15450        const mainNavText = mainManuItem?.textContent;
15451        mainManuItem?.addEventListener('click', () => {
15452            trackMenuClick(mainNavText, 'main menu');
15453        });
15454
15455        const subNavLinks = el.querySelectorAll('nav a');
15456        subNavLinks.forEach((elNav) => {
15457            const subNavText = elNav.textContent;
15458            elNav.addEventListener('click', () => {
15459                trackMenuClick(mainNavText + ":" + subNavText, 'sub-nav menu');
15460            });
15461        });
15462    });
15463}
15464
15465// =============================================================================
15466// INITIALIZATION
15467// =============================================================================
15468
15469// Execute immediately if DOM is already ready
15470if(document.readyState === 'loading') {
15471    document.addEventListener('DOMContentLoaded', initHeader);
15472} else {
15473    initHeader();
15474}
15475
15476(function() {
15477    'use strict';
15478    window.HeaderUtil = window.HeaderUtil || function () {
15479
15480        this.getCloudVisitorId = function() {
15481            if(window._satellite && window._satellite.getVisitorId()){
15482                return window._satellite.getVisitorId().getMarketingCloudVisitorID();
15483            }
15484            return null;
15485        };
15486    };
15487    window.HeaderUtil = new window.HeaderUtil();
15488}) ();
15489
15490$(document).ready(function(event) {
15491    const formRefresh = $('.form-refresh')
15492        if (!!formRefresh) {
15493        formRefresh.click(function(){
15494            location.reload();
15495        }); 
15496    }
15497});
15498
15499
15500
15501$(document).ready(function() {
15502    $("select:not(.no-chosen)").chosen({
15503        disable_search_threshold: 10,
15504        width: '100%',
15505        placeholder_text_single: 'Please Select'
15506    });
15507});
15508
15509function setTwoDecimalplaces(elem) {
15510    if ($(elem).attr('data-decimal') ==='true'){
15511        elem.value = parseFloat(elem.value).toFixed(2);
15512    }
15513}
15514
15515
15516(function(){
15517    
15518    function handleInput(instance, input, values) {
15519        
15520        $(input).on("input change", function(e) {
15521
15522            const fcfContent = instance.find(".fcf-content");
15523            const inputs = instance.find("input");
15524
15525            //Add active class and toggle on required inputs for shown form
15526            function setActiveInputs(){
15527                fcfContent.addClass("active");
15528                inputs.each(function(index, elem) {
15529                    const status = $(elem).attr("data-required-status");
15530                    if (status === "required") {
15531                        $(elem).attr("data-parsley-required", "true");
15532                        $(elem).attr("required", "yes");
15533                      }
15534                });
15535            }
15536
15537            //Remove active class and toggle off required inputs for hidden forms
15538            function removeActiveInputs() {
15539                fcfContent.removeClass("active");
15540                inputs.each(function(index, elem) {
15541                    $(elem).attr("data-parsley-required", false);
15542                    $(elem).attr("required", false);
15543                });
15544            }
15545            
15546            if (e.target.tagName === "INPUT") {
15547                if (e.target.type === "text" || e.target.type === "number") {
15548                    if (values.indexOf(e.target.value) !== -1) {
15549                        setActiveInputs();
15550                    } else {
15551                        removeActiveInputs();
15552                    }
15553                } else {
15554                    if ($(this).is(":checked") && values.indexOf(e.target.value) !== -1) {
15555                        setActiveInputs();
15556                    } else {
15557                        removeActiveInputs();
15558                    }
15559                }
15560            } else {                
15561                if (values.indexOf(e.target.value) !== -1) {
15562                    setActiveInputs();
15563                                        
15564                } else {
15565                    removeActiveInputs();
15566                }
15567            }
15568        });
15569    }
15570
15571    function initFormConditionalField(component) {
15572        var currComponent = $(component);
15573
15574        /* grab the values from the Form Conditional Field component and store */
15575        var storage = {};
15576        var fields = currComponent.find(".fcf-field");
15577        for (var i = 0; i < fields.length; i++) {
15578            var fieldProp = $(fields[i]),
15579            fieldPropName = fieldProp.attr("data-field"),
15580            fieldPropValue = fieldProp.val(),
15581            values = [];
15582
15583            if (!storage.hasOwnProperty(fieldPropName)) {
15584                values.push(fieldPropValue);
15585                storage[fieldPropName] = values;
15586            } else {
15587                storage[fieldPropName].push(fieldPropValue);
15588            }
15589        }
15590
15591        /* grab the closest form and its inputs */
15592        var form = currComponent.closest("form");
15593        var formElements = [].slice.call(form[0].elements);
15594        var inputs = formElements.filter(function(item, index) {
15595            return item.type !== "hidden" && item.type !== "submit";
15596        });
15597
15598        /* loop through storage for key and loop through form inputs for specified key */
15599        for (var key in storage) {
15600            for (var i = 0; i < inputs.length; i++) {
15601                var current = $(inputs[i]);
15602                if (current.attr("name") === key) {
15603                    handleInput(currComponent, current, storage[key]);
15604                }
15605            }
15606        }
15607    }
15608
15609    $(document).ready(function() {
15610        var formConditionalField = $(".form-conditional-field.component");
15611        if (formConditionalField.length) {
15612            formConditionalField.each(function(index, elem) {
15613                initFormConditionalField(elem);
15614            });
15615        }
15616    });
15617})();
15618$(window).load(function() {
15619    // Honey pot detection
15620    var spambot = false;
15621    var h0neyp0t = $('.in-left-field');
15622    const hiddenForm=$('.form-multi-hidden');
15623
15624    function getFreeHoney() {
15625        /**
15626         *  getFreeHoney() ensures that hidden fields have not been filled out.
15627         *  when spambot is true the submission breaks and redirects to "/"
15628         *
15629         *  */
15630        if (h0neyp0t.length) {
15631            h0neyp0t.find('input').each(function(index, element) {
15632                if (element.type === 'text' && element.value !== '') {
15633                    spambot = true;
15634                }
15635                if (element.type === 'checkbox' && element.checked) {
15636                    spambot = true;
15637                }
15638            });
15639        }
15640    }
15641
15642    function setHiddenParameters(){
15643             if (typeof _satellite !== undefined && _satellite !== null) {
15644                 var gclidParam=_satellite.getVar('gclid') ;
15645                 var fbclidParam=_satellite.getVar('fbclid');
15646                 if(gclidParam !== 'null') {
15647    				hiddenForm.find('.hidden-marketingclid').val(gclidParam);
15648                 } else {
15649    				hiddenForm.find('.hidden-marketingclid').val(fbclidParam);
15650                 }
15651                 hiddenForm.find('.hidden-utmCampaign').val(_satellite.getVar('UTMCampaign') || null);
15652                 hiddenForm.find('.hidden-cipher').val(_satellite.getVar('campaignCode_PID') || null);
15653                }
15654
15655        }
15656 //call method only when  form multi-hidden component is found
15657    if(hiddenForm.length>0){
15658        setHiddenParameters();
15659    }
15660
15661 //datepicker
15662    $('.datepicker').datepicker({
15663        autoclose: true
15664    }).on('hide', function() {
15665        $(this).parsley().validate();
15666    });
15667
15668    //$("select:not(.no-chosen)").chosen();
15669
15670    /**
15671     * Sets form element to required if form field matching selector (data-parsley-required-if-target) has value of
15672     * one of the items in array (data-parsley-required-if-target-equals).
15673     * Put the following data attributes on a form item to use:
15674     * data-parsley-validate-if-empty="true"                          // Required for checking empty fields.
15675     * data-parsley-required-if-target-equals='["Parts", "Service"]'  // Example select drop down values.
15676     * data-parsley-required-if-target-name="type"                    // Name of other field to check.
15677     */
15678    window.Parsley.addValidator("requiredIfTargetName", {
15679        validateString: function(value, targetName) {
15680            var targetMatches = arguments[2].$element.data('parsley-required-if-target-equals');
15681            var targetValue = arguments[2].$element.parents('form').find('[name=' + targetName + ']').val();
15682            var isString = Object.prototype.toString.call(targetMatches).indexOf('String') !== -1;
15683            var isArray = Object.prototype.toString.call(targetMatches).indexOf('Array') !== -1;
15684
15685            if (isString) {
15686                targetMatches = [targetMatches];
15687                isArray = true;
15688            }
15689
15690            targetMatches = targetMatches.map(function(elem) {
15691                return elem.value;
15692            });
15693
15694            if (isArray && targetMatches.indexOf(targetValue) !== -1) {
15695                return !!value; // Must have value.
15696            }
15697
15698            return true;
15699        },
15700        priority: 33
15701    });
15702
15703    window.Parsley.addValidator("fileType", {
15704        validateString: function(value, targetName) {
15705            var acceptedTypes = ["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document"];
15706            var acceptedExtensions = ["pdf","doc","docx"];
15707            var files = arguments[2].element.files;
15708            var contentTypeValid = false;
15709            var extensionValid = false;
15710            if(value && files && files[0] && targetName === 'documents'){
15711                var contentTypeValid = acceptedTypes.indexOf(files[0].type) != -1;
15712                var extensionValid = acceptedExtensions.indexOf(value.split('.')[1]) != -1;
15713                return contentTypeValid && extensionValid;
15714            }
15715            return true;
15716        },
15717        priority: 34
15718    });
15719
15720    //Note: maxFileSize is in MB
15721    window.Parsley.addValidator("maxFileSize", {
15722        validateString: function(value, targetName) {
15723            var files = arguments[2].element.attachments;
15724            if(value && files && files.length > 0){
15725                var filesArray = [];
15726                var accumulatedSize = _(files).reduce(function(arr, elem){
15727                   return arr + elem.size;
15728                }, 0);
15729                var fileSizeCheck = (accumulatedSize / 1000000) <= parseInt(targetName, 10);
15730                return fileSizeCheck;
15731            }
15732            return true;
15733        },
15734        priority: 35,
15735        messages: {
15736            en: 'File exceeds maximum size of %s MB'
15737        }
15738    });
15739
15740    window.Parsley.on('field:error', function() {
15741        var field = this.$element[0].id;
15742        // This global callback will be called for any field that fails validation.
15743        $('#' + field).parent().addClass('label-error');
15744        $('#' + field).closest('div.checkbox-wrap').addClass('display-error-message');
15745        $('#' + field).closest('div.radio-wrap').addClass('display-error-message');
15746    });
15747    window.Parsley.on('field:success', function() {
15748        var field = this.$element[0].id;
15749        // This global callback will be called for any field that fails validation.
15750        $('#' + field).parent().removeClass('label-error');
15751        $('#' + field).closest('div.checkbox-wrap').removeClass('display-error-message');
15752        $('#' + field).closest('div.radio-wrap').removeClass('display-error-message');
15753    });
15754
15755    if($('form.sfdc').length > 0){
15756    	if($('form.sfdc').find('.hidden-skuid').length > 0 && $('form.sfdc').find('.hidden-skuid').val() == '<SKUID>'){
15757    		var skuid = localStorage.getItem("SKUID");
15758    		if(skuid != '' && skuid != null && skuid != 'undefined'){
15759    			$('form.sfdc').find('.hidden-skuid').val(skuid);
15760    		}
15761    	}
15762    }
15763
15764    $('.form-submit .btn-submit').on('click',function(e) {
15765
15766        getFreeHoney();
15767        if (spambot) {
15768            window.location = '/';
15769            return false;
15770        }
15771
15772        if (!checkRecaptcha($(this))) {
15773            $(".captcha-error").slideToggle(250);
15774            $(".captcha-error").attr("aria-hidden", false);
15775            return false;
15776        }
15777
15778        //get the closest form
15779        var form = $(this).closest("form");
15780        var formid = form.attr("id");
15781        var redirectUrl = form.find('input[name=redirect]').val();
15782
15783        // Custom field population
15784        if (typeof _satellite !== undefined && _satellite != null) {
15785            form.find('.hidden-ecid').attr('value', _satellite.getVisitorId().getMarketingCloudVisitorID());
15786            form.find('input[name=VisitorID]').attr('value', _satellite.getVisitorId().getMarketingCloudVisitorID());
15787        }
15788
15789        var ga = ga || [];
15790        if (typeof ga !== undefined && ga != null && ga.length > 0) {
15791            form.find('.hidden-gacid').attr('value', ga.getAll()[0].get('clientId'));
15792        }
15793
15794        var gclidValue = readCookie('gclid');
15795        if (gclidValue !== undefined && gclidValue != null && gclidValue.length > 0) {
15796            form.find('.hidden-gclid').attr('value', gclidValue);
15797        } else {
15798            form.find('.hidden-gclid').attr('disabled', 'disabled');
15799        }
15800
15801        // Push value from user 'phone' input into hashednumber field for tracking; including hashCode string function
15802        String.prototype.hashCode = function() {
15803          var hash = 0, i, chr;
15804          if (this.length === 0) return hash;
15805          for (i = 0; i < this.length; i++) {
15806            chr   = this.charCodeAt(i);
15807            hash  = ((hash << 5) - hash) + chr;
15808            hash |= 0; // Convert to 32bit integer
15809          }
15810          return hash;
15811        };
15812
15813        var phoneField = form.find("[name*='phone']").val();
15814        if (phoneField !== undefined && phoneField != null && phoneField.length > 0) {
15815            form.find('.hidden-hashednumber').attr('value', phoneField.hashCode());
15816        }
15817
15818
15819        // Custom leadsource and phone override conditions
15820        var leadsource = "In-Home: Pentair";
15821
15822        function getUrlParameter(name) {
15823            name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
15824            var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
15825            var results = regex.exec(location.search);
15826            return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
15827        };
15828        source = getUrlParameter('source');
15829
15830        // TODO: Commented out conditions until business decides on campaign source IDs
15831        if (source == "facebook") {
15832            leadsource = "In-Home: Pentair Facebook";
15833        } else if (source == "google") {
15834            leadsource = "In-Home: Pentair Google";
15835        } else if (source == "programmatic") {
15836            leadsource = "In-Home: Pentair Programmatic";
15837        } else if (source == "criteo") {
15838            leadsource = "In-Home: Pentair Criteo";
15839        }
15840        form.find('.hidden-leadsource').attr('value', leadsource);
15841
15842        parsleyForm = form.parsley();
15843        parsleyForm.validate();
15844        if (parsleyForm.isValid()) {
15845            form.find('.form-submit .btn-submit').prop('disabled', true).text("Sending");
15846            // Pull Services for Analytics
15847            // var services = [];
15848            // var $servicesElements = form.find("[name=services]:checked");
15849            // $servicesElements.each(function() { services.push($(this).val()); });
15850
15851            if (form.hasClass('product-selector')) {
15852                const storyInput = form.find('select.chosen-select').val();
15853                const selectedFootage =$('select[name="squareFootage"]:visible').val() || $('input[name="squareFootage"]:checked:visible').val();
15854                const cfRoot= $('input[name="cfRootPath"]').val()??'';
15855	       	    const servletPath = '/bin/pentair/product/selector';
15856                //create container div
15857                const prodResultsDiv = document.querySelector('.form-submit');
15858                const resultContainer = document.createElement("div");
15859                resultContainer.className = "prod-result-container";
15860                const resultTitleDiv = document.createElement('div');
15861
15862                // helper to create text elements
15863                function buildTextEl(className, text, tagName) {
15864                    const tag = tagName || 'p';
15865                    const el = document.createElement(tag);
15866                    el.className = className;
15867                    el.textContent = text || '';
15868                    return el;
15869                }
15870
15871                //create results section title
15872                const resultsTitle = buildTextEl("prod-rec-title", "Recommended Products");
15873                resultTitleDiv.appendChild(resultsTitle);
15874                resultContainer.appendChild(resultTitleDiv);
15875
15876                //helper to create product card
15877                function createProductCard(product) {
15878                    const resultItem = document.createElement("div");
15879                    resultItem.className = "prod-result-item";
15880
15881                    const productImg = document.createElement("img");
15882                    productImg.className = "prod-result-image";
15883                    productImg.alt = product.imageAlt||" ";
15884                    productImg.src = product.imgSrc;
15885
15886                    const productNumber = buildTextEl("prod-result-number", product.number);
15887                    const productHeader = buildTextEl("prod-result-header", product.header);
15888                    const prodDescription = buildTextEl("prod-result-description", product.description);
15889
15890                    const productLink = document.createElement("a");
15891                    productLink.classList.add('prod-result-link', 'btn', 'btn-primary');
15892                    productLink.href = product.linkSrc;
15893                    productLink.target = "_self";
15894                    productLink.textContent = "Learn More";
15895
15896                    const fragment = document.createDocumentFragment();
15897                    [productImg, productNumber, productHeader, prodDescription, productLink].forEac
15897h(function(node){
15898                        fragment.appendChild(node);
15899                    });
15900                    resultItem.appendChild(fragment);
15901                    return resultItem;
15902                }
15903
15904
15905                const listFragment = document.createDocumentFragment();
15906				fetch(servletPath +'?'+new URLSearchParams({
15907					story: storyInput,
15908					squareFootage:selectedFootage,
15909					cfRoot: cfRoot,
15910				}).toString()).then(response => {
15911				if (!response.ok) {
15912					throw new Error(`HTTP error status: ${response.status}`);
15913				}
15914					return response.json(); // Parse the JSON from the response
15915				})
15916				.then(products => {
15917
15918                     if (!Array.isArray(products)) {  //no results
15919                            const msg = buildTextEl("no-products-msg", products.message || "No products");
15920                            resultContainer.appendChild(msg);
15921                            prodResultsDiv.appendChild(resultContainer);
15922                            return;
15923                     }
15924
15925					products.forEach(function(product){
15926						listFragment.appendChild(createProductCard(product));
15927					});
15928
15929                //append results section to the form
15930                resultContainer.appendChild(listFragment);
15931                prodResultsDiv.appendChild(resultContainer);
15932				})
15933				.catch(error => {
15934					console.error('Error fetching Content Fragment data:', error);
15935				});
15936                e.preventDefault();
15937                return;
15938            } else if (form.hasClass('sfdc')) {
15939                beforeSubmit();
15940                var salesforceForm = form.find('input[name=00N6100000EMJxE]').val();
15941                var backupName = $('form.generic-form').data('form-name');
15942                var eventName = salesforceForm || backupName;
15943                var userHashedNumber = form.find('.hidden-hashednumber').val();
15944                updateFormAnalyticsData(eventName, "submit", "form", userHashedNumber);
15945                // PAAS - Adobe analytics track event payload
15946                trackEventFormSubmitted(eventName);
15947                setTimeout(function() {
15948                    form.submit();
15949                },0);
15950            } else if (form.hasClass('bronto')) {
15951                beforeSubmit();
15952                var brontoForm = form.find('input[name=campaignId]').val();
15953                var eventName = brontoForm;
15954                updateFormAnalyticsData(eventName, "submit", "form", null);
15955                // PAAS - Adobe analytics track event payload
15956                if (!eventName && form.length > 0 && form.get(0) != null) {
15957                    trackEventFormSubmitted(form.get(0).dataset.formName);
15958                } else {
15959                    trackEventFormSubmitted(eventName);
15960                }
15961                setTimeout(function() {
15962                    form.submit();
15963                },0);
15964            } else if (form.hasClass('spectrum')) {
15965                beforeSubmit();
15966
15967                // PAAS - Adobe analytics track event payload
15968                if (form.length > 0 && form.get(0) != null) {
15969                    trackEventFormSubmitted(form.get(0).dataset.formName);
15970                }
15971
15972                // Cannot set form input values to variables as jquery will pass them as objects in url params
15973                updateFormAnalyticsData((form.find('input[name=spectrumCampaignId]').val() || _satellite.getVar('campaign') || ''), "submit", "form", null);
15974
15975                form.attr('action', form.attr('action') + "?Campaign=" + (form.find('input[name=spectrumCampaignId]').val() || _satellite.getVar('campaign') || ''));
15976                form.attr('action', form.attr('action') + "&ParticipantID=" + (form.find('input[name=ParticipantID]').val() || ''));
15977                form.attr('action', form.attr('action') + "&VisitorID=" + (form.find('input[name=VisitorID]').val() || ''));
15978                form.attr('action', form.attr('action') + "&SourceID=" + (form.find('input[name=SourceID]').val() || ''));
15979                form.attr('action', form.attr('action') + "&OptIn=" + (form.find('input[name=OptIn]').val() || '0'));
15980                if (form.find('input[name=OptIn]') != null && form.find('input[name=OptIn]').val() == '1') {
15981                    form.attr('action', form.attr('action') + "&Redirect=0");
15982                } else {
15983                    form.attr('action', form.attr('action') + "&Redirect=1");
15984                }
15985                setTimeout(function() {
15986                    form.submit();
15987                }, 0);
15988            } else if (form.hasClass('pump-calculator')) {
15989                const formType = form.find('select.chosen-select').val();
15990                const calculatedResult = calculateCost(formType, form);
15991                $('.pump-calculator-result').html(`<div class="pump-results"><p>Total Cost of Pump: ${calculatedResult} </br> <span> Reset the form to calculate additional pump costs.</p></div>`);
15992                $('.pump-calculator-result').addClass('display-results');
15993                const calcSelect = form.find('select');
15994                calcSelect.attr("disabled", true);
15995                e.preventDefault();
15996                return;
15997            }
15998
15999            else {
16000                e.preventDefault();
16001
16002                addFileLoader();
16003
16004                var formData = new FormData(form[0]);
16005
16006                $('.inputfile input').each(function() {
16007                    if (this.attachments) {
16008                        $.each(this.attachments, function (index, file) {
16009                            formData.append('attachments[]', file);
16010                        });
16011                    }
16012                });
16013
16014                $.ajax({
16015                    url: form.attr("action"),
16016                    data: formData,
16017                    type: form.attr('method'),
16018                    cache: false,
16019                    contentType: false,
16020                    processData: false
16021                })
16022                    .done(function(resp) {
16023                        console.log(resp);
16024                        form.find("input, textarea, select").val("");
16025                        beforeSubmit();
16026                        ////////////////////////////////////////////////////////
16027                        ////Analytics data layer for form successful submit ///
16028                        //////////////////////////////////////////////////////
16029
16030                        // Adobe analytics track event payload
16031                        if (form.length > 0 && form.get(0) != null) {
16032                            trackEventFormSubmitted(form.get(0).dataset.formName);
16033                        }
16034                        try {
16035                            var eventName = '';
16036                            var customFormVal = form.find('input[name=subject]').val();
16037                            eventName = customFormVal;
16038                            updateFormAnalyticsData(eventName, "submit", "form", null);
16039                        } catch (err) {
16040                            console.log(err);
16041                        }
16042
16043                        ////////////////////////////////////////////////////////
16044                        ////Analytics data layer for form successful submit ///
16045                        //////////////////////////////////////////////////////
16046
16047                        /* Gated Asset Functionality - PENW-3174 */
16048                        if ($("main").hasClass("gated")) {
16049                            var gatedAssets = readCookie('gated_assets');
16050                            var path = window.location.pathname;
16051                            if (gatedAssets !== undefined && gatedAssets != null && gatedAssets.length > 0) {
16052                                // cookie exists
16053                                if (path.indexOf("/content/dam") !== -1) {
16054                                    var cookieStr = gatedAssets.replace(/[\[\]]+/g,'');
16055                                    var cookieArr = cookieStr.split(",");
16056                                    if (cookieArr.indexOf(path) === -1) {
16057                                        cookieArr.push(path);
16058                                        setCookie("gated_assets", "["+ cookieArr.join(",") +"]", 30);
16059                                        var url = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + cookieArr.pop();
16060                                        window.location.replace(url);
16061                                    }
16062                                }
16063                            } else {
16064                                // cookie does not exist
16065                                if (path.indexOf("/content/dam") !== -1) {
16066                                    setCookie("gated_assets", "["+ path +"]", 30);
16067                                    var url = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + path;
16068                                    window.location.replace(url);
16069                                }
16070                            }
16071                        }
16072
16073                        if (redirectUrl.length > 0)
16074                            window.location = redirectUrl;
16075
16076                        // Trigger Analytics Event
16077                        //               form.attr("data-services-selected", services.join(','));
16078                        //               form.triggerNative("FormSuccess");
16079                        form.find('.form-submit .form-loader-wrapper').remove();
16080                    })
16081                    .fail(function(resp) {
16082                        console.log(resp);
16083                        form.find('.hidden-gclid').removeAttr('disabled');
16084                        form.find('.form-submit .btn-submit').prop('disabled', false).text("Submit");
16085                        form.find(".error.text-right").show();
16086                    });
16087            }
16088        } else {
16089            var firstError = $(".parsley-error").eq(0);
16090            $('html, body').animate({
16091                scrollTop: firstError.offset().top - 180
16092            }, 500, function() {
16093                setTimeout(function() {
16094                    firstError.focus();
16095                }, 100);
16096            });
16097        }
16098        /**
16099           * Constructs and tracks the pump-calculator form submitted and returns formulate.
16100           * @param formName name of the form
16101           */
16102        function calculateCost(formType, form) {
16103            var totalCost = 0;
16104            var data;
16105            switch (formType) {
16106                case "cobalt":
16107                    data = {
16108                        pump_model: parseFloat(form.find('input[name=cobaltPumpCost]').val()) || 0,
16109                        fittings: parseFloat(form.find('input[name=cobaltFittingsCouplersCost]').val()) || 0,
16110                        projected_useful_life: parseFloat(form.find('input[name=cobaltProjectedLife]').val()) || 0,
16111                        frequency: parseFloat(form.find('input[name=cobaltSealReplacementFrequency]').val()) || 0,
16112                        cost: parseFloat(form.find('input[name=cobaltSealReplacementCost]').val()) || 0,
16113                    }
16114                    totalCost = eval(data.pump_model + data.fittings + (data.projected_useful_life * (12 / data.frequency) * data.cost));
16115                    break;
16116                case "forcefield":
16117                    data = {
16118                        forcefield_equivalent: parseFloat(form.find('input[name=forceFieldPumpCost]').val()) || 0,
16119                        projected_useful_life: parseFloat(form.find('input[name=forceFieldProjectedLife]').val()) || 0,
16120                        frequency: parseFloat(form.find('input[name=forceFieldSealReplacementFrequency]').val()) || 0,
16121                        material_cost: parseFloat(form.find('input[name=forceFieldSealReplacementCost]').val()) || 0,
16122                        hourly_labor_rate: parseFloat(form.find('input[name=forceFieldSealReplacementLaborRate]').val()) || 0,
16123                        time_to_service: parseFloat(form.find('input[name=forceFieldSealReplacementTimeToService]').val()) || 0,
16124                    }
16125                    totalCost = eval(data.forcefield_equivalent + (data.projected_useful_life * ((12 / data.frequency) * (data.material_cost + (data.hourly_labor_rate * data.time_to_service)))));
16126                    break;
16127                case "centrifugal":
16128                    data = {
16129                        centrifugal_pump_model: parseFloat(form.find('input[name=centrifugalPumpCost]').val()) || 0,
16130                        projected_useful_life: parseFloat(form.find('input[name=centrifugalProjectedLife]').val()) || 0,
16131                        frequency: parseFloat(form.find('input[name=centrifugalSealReplacementFrequency]').val()) || 0,
16132                        material_cost: parseFloat(form.find('input[name=centrifugalSealReplacementCost]').val()) || 0,
16133                        hourly_labor_rate: parseFloat(form.find('input[name=centrifugalSealReplacementLaborRate]').val()) || 0,
16134                        time_to_service: parseFloat(form.find('input[name=centrifugalSealReplacementTimeToService]').val()) || 0,
16135                    }
16136                    totalCost = eval(data.centrifugal_pump_model + (data.projected_useful_life * ((12 / data.frequency) * (data.material_cost + (data.hourly_labor_rate * data.time_to_service)))));
16137                    break;
16138                case "diaphragm":
16139                    data = {
16140                        current_pump_cost: parseFloat(form.find('input[name=diaphragmPumpCost]').val()) || 0,
16141                        motor_adapter_kit: parseFloat(form.find('input[name=diaphragmMotorAdapterCost]').val()) || 0,
16142                        motor_cost: parseFloat(form.find('input[name=diaphgramMotorCost]').val()) || 0,
16143                        installation_labor_cost: parseFloat(form.find('input[name=diaphragmMotorInstallationLaborCost]').val()) || 0,
16144                        projected_useful_life: parseFloat(form.find('input[name=diaphragmProjectedLife]').val()) || 0,
16145                        diaphragm_replacement_cost: parseFloat(form.find('input[name=diaphragmReplacementCost]').val()) || 0,
16146                        diaphragm_replacement_frequency: parseFloat(form.find('input[name=diaphragmReplacementFrequency]').val()) || 0,
16147                        valve_seal_replacement_frequency: parseFloat(form.find('input[name=diaphragmSealReplacementFrequency]').val()) || 0,
16148                        valve_seal_replacement_cost: parseFloat(form.find('input[name=diaphragmSealReplacementCost]').val()) || 0,
16149                        oil_change_frequency: parseFloat(form.find('input[name=diaphragmOilChangeFrequency]').val()) || 0,
16150                        oil_change_cost: parseFloat(form.find('input[name=diaphragmOilChangeCost]').val()) || 0,
16151                        gearbox_oil_change_frequency: parseFloat(form.find('input[name=diaphragmGearboxOilChangeFrequency]').val()) || 0,
16152                        gearbox_oil_change_cost: parseFloat(form.find('input[name=diaphragmGearboxOilChangeCost]').val()) || 0,
16153                        //below two fields are optional and part of installation cost
16154                        relief_valve_plumbing_cost: parseFloat(form.find('input[name=diaphragmReliefValveCost]').val()) || 0,
16155                        fittings_couplers_cost: parseFloat(form.find('input[name=diagphragmFittingsCouplersCost]').val()) || 0,
16156                    }
16157                    totalCost = eval((data.current_pump_cost + data.relief_valve_plumbing_cost + data.fittings_couplers_cost + data.motor_adapter_kit + data.motor_cost + data.installation_labor_cost) + (data.projected_useful_life * ((data.diaphragm_replacement_frequency / 12) * data.diaphragm_replacement_cost) + ((data.valve_seal_replacement_frequency / 12) * data.valve_seal_replacement_cost) + ((12 / data.oil_change_frequency) * data.oil_change_cost) + ((data.gearbox_oil_change_frequency / 12) * data.gearbox_oil_change_cost)));
16158                    break;
16159            }
16160            return totalCost;
16161
16162        }
16163        /**
16164         * Constructs and tracks the form submitted event payload.
16165         * @param formName name of the form
16166         */
16167        function trackEventFormSubmitted(formName) {
16168            var eventFormSubmittedPayload = {
16169                eventName: 'form submitted',
16170                eventType: 'event',
16171                attributes: {
16172                    visitor: {
16173                        pentairCustomerID: getPentairCustomerID(),
16174                        dealerID: getDealerID()
16175                    },
16176                    page: {
16177                        pageCanonical: getPageViewPageAttribute("pageCanonical"),
16178                        pageName: getPageViewPageAttribute("pageName"),
16179                        pagePath: getPageViewPageAttribute("pagePath"),
16180                        pageType: getPageViewPageAttribute("pageType"),
16181                        pageURL: getPageViewPageAttribute("pageURL"),
16182                        pageTitle: getPageViewPageAttribute("pageTitle"),
16183                        pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
16184                        businessUnitID: getPageViewPageAttribute("businessUnitID"),
16185                        subBrand: getPageViewPageAttribute("subBrand"),
16186                        language: getPageViewPageAttribute("language"),
16187                        author: getPageViewPageAttribute("author"),
16188                    },
16189                    form: {
16190                        formName: formName
16191                    }
16192                }
16193            }
16194            trackEventWithQueue(eventFormSubmittedPayload);
16195        }
16196
16197        function beforeSubmit() {
16198            form.find('.form-submit .btn-submit').text("Sent");
16199            $(".form-thanks").slideToggle(250);
16200            $(".form-thanks").attr("aria-hidden", false);
16201            form.find(".captcha-error").hide();
16202            form.find(".error .text-right").hide();
16203
16204            var hideOnSubmit = $('form').closest('.form.component').data('hideonsubmit');
16205            if (hideOnSubmit) {
16206                form.find('button').hide();
16207                form.find("div[class*='form-input']").hide();
16208                $('html, body').animate({
16209                    scrollTop: form.offset().top - 180
16210                }, 500, function() {
16211                });
16212            }
16213        }
16214
16215        function addFileLoader() {
16216            if(form.find('.inputfile').siblings('.message.has-file').length > 0){
16217                var loader = '<div class="form-loader-wrapper loader"><div class="results-loader"><p class="loading-text">Uploading...</p></div></div>';
16218                form.find('.form-submit .btn-submit').after(loader);
16219            }
16220        };
16221
16222    });
16223
16224    function checkRecaptcha(submitButton) {
16225        recaptchaResponse = submitButton.closest('form').find('.g-recaptcha-response').val();
16226        var hasCaptcha = submitButton.closest('form').find('.form-captcha').length > 0;
16227        if (hasCaptcha && (recaptchaResponse == "" || recaptchaResponse == undefined || recaptchaResponse.length == 0)) {
16228            return false;
16229        } else {
16230            return true;
16231        }
16232    }
16233
16234    function overridePhone(number) {
16235        if (number.length > 0) {
16236            $('span#number').each(function() {
16237                if($(this).parent().hasClass('utility-dialogtech') === false) {
16238                    $(this).html(number);
16239                }
16240            });
16241        }
16242    }
16243
16244    $('.inputfile input').each(function(index, inputElem) {
16245        var message    = $(this).parent().siblings('.message'),
16246            label = $(this).parent();
16247        $(inputElem)[0].attachments = [];
16248
16249        $(inputElem).on( 'change', function( e ) {
16250            var fileName = '';
16251            var self = this;
16252
16253            if( this.files && this.files.length > 0 ){
16254
16255                var allowMultiple = $(inputElem).prop('multiple');
16256                $.each(this.files, function(index, elem){
16257                    if(allowMultiple){
16258                        $(inputElem)[0].attachments.push(elem);
16259                    } else {
16260                        $(inputElem)[0].attachments = [elem];
16261                    }
16262                });
16263
16264
16265                $(this).val(null); // clear input after we've saved to variable.
16266
16267                message.find('.form-file-item').remove();
16268                message.addClass('has-file');
16269
16270                $.each($(inputElem)[0].attachments, function(index, file){
16271                    var newFileElem = $('<span class="form-file-item"></span>').text(file.name);
16272                    message.append(newFileElem);
16273                    newFileElem.on('click', function(clickElement){
16274                        var fileIndex = $(clickElement.target).parent().find('.form-file-item').index($(clickElement.target));
16275                        if(fileIndex > -1){
16276                            $(clickElement.target).remove();
16277                            $(inputElem)[0].attachments.splice(fileIndex, 1);
16278                        }
16279                    });
16280                });
16281            }
16282
16283            if( fileName ) {
16284                label.addClass('has-file').html(fileName);
16285            } else {
16286                label.removeClass('has-file');
16287            }
16288
16289        });
16290
16291        $(inputElem).parent().find('button').on('click', function(e){
16292            e.preventDefault();
16293            e.stopImmediatePropagation();
16294            $(this).parent().find('input').click();
16295            return false;
16296        });
16297
16298    });
16299
16300    ////////////////////////////////////////////////////////
16301    /////// Form auto-prefill based on URL params /////////
16302    //////////////////////////////////////////////////////
16303
16304    var queryParams = window.location.href.indexOf("?") !== -1;
16305    if (queryParams) {
16306        var search = window.location.search.substring(1);
16307        var params = JSON.parse('{"' + decodeURI(search).replace(/&/g, '","').replace(/=/g,'":"') + '"}');
16308
16309        // loop through params
16310        for (var key in params) {
16311
16312            // get input fields in form component
16313            var inputs = $(".form.component").find("input,textarea,select");
16314            for (var i = 0; i < inputs.length; i++) {
16315                if ($(inputs[i]).attr("name") === key) {
16316                    var tagName = document.querySelector('[name="'+key+'"]').tagName.toLowerCase();
16317                    if (tagName === "input") {
16318                        if ($(inputs[i]).attr("type") === "text") {
16319                            $(inputs[i]).val(params[key]);
16320                        } else {
16321                            if ($(inputs[i]).val() == params[key]) {
16322                                $(inputs[i]).prop("checked", true);
16323                            }
16324                        }
16325                    } else if (tagName === "select") {
16326                        $(inputs[i]).chosen().val(params[key]);
16327                        $(inputs[i]).trigger("chosen:updated");
16328                    } else if (tagName === "textarea") {
16329                        $(inputs[i]).val(params[key]);
16330                    }
16331                }
16332            }
16333
16334        }
16335    }
16336
16337    ////////////////////////////////////////////////////////
16338    //// building data analytics layer object start ///////
16339    //////////////////////////////////////////////////////
16340
16341    //event for form Field Initiate
16342    $('.form.component form').on('focus', 'input[type=text],textarea', function(e) {
16343        checkAndInitiateForm($(this));
16344        var $element = $(this);
16345        var parentWraper = $element.closest('.section');
16346        var eventName = "";
16347        var label = parentWraper.find('label');
16348        if (label.text() !== undefined) {
16349            eventName = label.text().replace('*', '').trim();
16350        }
16351        updateFormAnalyticsData(eventName, "initiate", "form field", null);
16352    });
16353
16354    //event for form Field complete of text and textarea
16355    $('.form.component form').on('blur', 'input[type=text],textarea', function(e) {
16356        var $element = $(this);
16357        var parentWraper = $element.closest('.section');
16358        var eventName = "";
16359        var label = parentWraper.find('label');
16360        if (label.text() !== undefined) {
16361            eventName = label.text().replace('*', '').trim();
16362        }
16363        updateFormAnalyticsData(eventName, "complete", "form field", null);
16364    });
16365
16366    //event for form Field initiate/complete of radio and checkbox
16367    $('.form.component form').on('change', 'input[type=radio],input[type=checkbox]', function(e) {
16368        checkAndInitiateForm($(this));
16369        var $element = $(this);
16370        //var label = $element.parent().find('label');
16371        var label = $element.closest('.section').find('fieldset legend');
16372        var eventName = label.text().replace('*', '').trim();
16373        updateFormAnalyticsData(eventName, "initiate", "form field", null);
16374        updateFormAnalyticsData(eventName, "complete", "form field", null);
16375    });
16376
16377    $('.form.component form').on('change', 'select', function(e) {
16378        checkAndInitiateForm($(this));
16379        var $element = $(this);
16380        var parentWraper = $element.closest('.section');
16381        var eventName = "";
16382        var label = parentWraper.find('label');
16383        if (label.text() !== undefined) {
16384            eventName = label.text().replace('*', '').trim();
16385        }
16386        updateFormAnalyticsData(eventName, "initiate", "form field", null);
16387        updateFormAnalyticsData(eventName, "complete", "form field", null);
16388    });
16389
16390    function updateFormAnalyticsData(eventName, eventAction, eventType, userHashedNumber) {
16391        //event name should be the subject of the form
16392        //eventAction should be the "submit/complete/initiate"
16393        if (eventAction === 'submit') {
16394            console.info('Form submission -- EventName: ' + eventName + '  EventAction: ' + eventAction + '  EventType: ' + eventType);
16395        }
16396
16397        try {
16398            if (digitalData) {
16399                if (digitalData.form) {
16400                    digitalData.form.eventName = eventName;
16401                    digitalData.form.eventAction = eventAction;
16402                    digitalData.form.type = eventType;
16403                    digitalData.form.timeStamp = new Date();
16404                    if (userHashedNumber != null) {
16405                        digitalData.form.phone = userHashedNumber;
16406                    }
16407                }
16408            }
16409            } catch (err) {
16410                console.log(err);
16411            }
16412        }
16413
16414    function checkAndInitiateForm($element) {
16415        var form = $element.closest("form");
16416        if (!form.attr('data-is-initiated')) {
16417            var eventName = '';
16418            var customFormVal = form.find('input[name=subject]').val();
16419            if (undefined === customFormVal) {
16420                //get the title from the salesforece hidden field
16421                var salesforceForm = form.find('input[name=00N6100000EMJxE]').val();
16422                eventName = salesforceForm;
16423            } else {
16424                eventName = customFormVal;
16425
16426            }
16427            updateFormAnalyticsData(eventName, "initiate", "form", null);
16428            form.attr('data-is-initiated', true);
16429        }
16430    }
16431
16432    ////////////////////////////////////////////////////////
16433    ///// building data analytics layer object end  ///////
16434    //////////////////////////////////////////////////////
16435});
16436
16437function readCookie(name) {
16438    var n = name + "=";
16439    var cookie = document.cookie.split(';');
16440    for (var i = 0; i < cookie.length; i++) {
16441        var c = cookie[i];
16442        while (c.charAt(0) == ' ') {
16443            c = c.substring(1, c.length);
16444        }
16445        if (c.indexOf(n) == 0) {
16446            return c.substring(n.length, c.length);
16447        }
16448    }
16449    return null;
16450}
16451
16452$(function() {
16453
16454    function getPlatform() {
16455        return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'mobile' : 'desktop';
16456    }
16457
16458    function initFooterComponents(instance) {
16459        var component = instance;
16460
16461        var links = component.find(".footer__links > .links");
16462
16463        // on mobile, hide the child pages to look like an accordion
16464        var isMobile = ($(window).width() < 768) || (getPlatform() === "mobile");
16465        if (isMobile) {
16466            links.find("ul").attr("hidden", "hidden");
16467        }
16468
16469        // toggles the list to dropdown on mobile
16470        links.on("click", function(e) {
16471            if (isMobile) {
16472                if (!$(this).hasClass("active")) {
16473                    $(this).find("ul").removeAttr("hidden");
16474                } else {
16475                    $(this).find("ul").attr("hidden", "hidden");
16476                }
16477                $(this).toggleClass("active");
16478            }
16479        });
16480    }
16481
16482
16483
16484    $(document).ready(function() {
16485        var footerComponents = $(".footer.component");
16486        if (footerComponents.length) {
16487            footerComponents.each(function(index, elem) {
16488                initFooterComponents($(elem));
16489            });
16490        }
16491    });
16492});
16493
16494var FADPrefilterFormModel = function(componentElement) {
16495    var self = this;
16496    self.title = componentElement.find(".title").text() || "";
16497    self.zipCodePlaceholderText = componentElement.find("input[name='zipcode']").attr("placeholder") || "";
16498    self.categoryPlaceholderText = componentElement.find("select[name='category']").data("placeholder") || "";
16499    self.ctaText = componentElement.find(".category-btn > span").text() || "";
16500    self.userCoordinates = ko.observableArray([]);
16501    self.userZipCode = ko.observable("");
16502    self.userZipCodeAddress = ko.observable("");
16503    self.showNoGeoLocationMessage = ko.observable(false);
16504    self.geolocate = function geolocate() {
16505        if (navigator.geolocation) {
16506            navigator.geolocation.getCurrentPosition(function(position) {
16507                var geolocation = {
16508                    lat: position.coords.latitude,
16509                    lng: position.coords.longitude
16510                };
16511                self.userCoordinates.push(geolocation);
16512                var point = new google.maps.LatLng(geolocation.lat, geolocation.lng);
16513                var geocoder = new google.maps.Geocoder().geocode(
16514                    {'latLng': point}, function( res, status) {
16515                        var zip = res[0].address_components.filter(function(item) {
16516                            return item.types.indexOf("postal_code") !== -1;
16517                        });
16518                        self.userZipCode(zip[0].short_name);
16519                        componentElement.find(".autocomplete").val(self.userZipCode());
16520                    }
16521                );
16522            }, function(err) {
16523                console.warn("User location is blocked. Manually input zipcode.");
16524            });
16525        }
16526    };
16527    self.inputZipCodeKeyPress = function(context, event) {
16528        var value = $(event.target).val();
16529        self.userZipCode(value);
16530        return true;
16531    }
16532    // RESP-385
16533    // pre-select category if there's only one option available
16534    self.checkSelectNumItems = function() {
16535        var select = componentElement.find("select[name='category']");
16536        var numItems = select.find("option").length - 1;
16537        if (numItems === 1) {
16538            select.val(select.find("option")[1].value);
16539            select.prop('disabled', true);
16540            select.trigger('chosen:updated');
16541            var selected = select.find("option")[1].value;
16542            componentElement.find(".category-btn").attr("href", selected);
16543        }
16544        return true;
16545    }
16546
16547    self.init = function() {
16548        self.geolocate();
16549        self.checkSelectNumItems();
16550    };
16551
16552    self.init();
16553
16554    // set authorable select placeholder text
16555    componentElement.find("select[name='category']").chosen({
16556        disable_search_threshold: 10,
16557        width: '100%',
16558        placeholder_text_single: self.categoryPlaceholderText
16559    });
16560
16561    // set CTA url when an option in selected within the dropdown
16562    componentElement.find("select[name='category']").on("change", function(e) {
16563        var selected = $(this).find("option:selected")[0].value;
16564        componentElement.find(".category-btn").attr("href", selected);
16565    });
16566
16567    componentElement.find(".category-btn").on("click", function(e) {
16568        e.preventDefault();
16569        var path = $(this).attr("href");
16570        var zip = self.userZipCode();
16571        var select = componentElement.find("select[name='category']");
16572        if (zip !== undefined && zip != null && zip.length && select.val()) {
16573            window.location.replace(path + "?zip=" + zip);
16574        } else {
16575            self.showNoGeoLocationMessage(true);
16576            return false;
16577        }
16578
16579        // Find a Dealer Prefilter Form Button Click Analytics - [RESP-155]
16580        if(!_.isUndefined(window._satellite)){
16581            _satellite.track('wtb_prefilter');
16582        }
16583
16584        return true;
16585    });
16586
16587    // adding class to body to show overflow between sections - [RESP-380]
16588    componentElement.find("select[name='category']").on("chosen:showing_dropdown", function() {
16589        $("body").addClass("chosen-is-active");
16590    });
16591
16592    componentElement.find("select[name='category']").on("chosen:hiding_dropdown", function() {
16593        $("body").removeClass("chosen-is-active");
16594    });
16595}
16596
16597$(document).ready(function () {
16598    $(".find-a-dealer-prefilter-form.component").each(function() {
16599        try {
16600            ko.applyBindings(new FADPrefilterFormModel($(this)), this);
16601        }
16602        catch(e) {
16603            console.log(e);
16604        }
16605    });
16606});
16607/************************* GLOBALS ***********************/
16608const DISPLAY_RESULTS = 'display-products';
16609const FILTER_FINDER_MODAL_PRESENT = 'filter-finder-modal-present';
16610const DISPLAY_ERROR_MESSAGE = 'display-error-message';
16611const DISPLAY_PRODUCTS_NONE = 'display-products-none';
16612const MANUFACTURERS = 'manufacturers'
16613const DIAMETER = 'diameter';
16614const LENGTH = 'length';
16615const USA = 'USA';
16616const DIAMETER_USA = 'diameterUSA';
16617const LENGTH_USA = 'lengthUSA';
16618const DIAMETER_METRIC = 'diameterMetric';
16619const LENGTH_METRIC = 'lengthMetric';
16620const URL_IS_PRESENT = 'url-is-present';
16621const FILBER_UNICEL_INACTIVE = 'filbur-unicel-inactive';
16622const DASH_DISCONTINUED = ' - Discontinued';
16623const ICON_SEARCH_LARGE = 'icon-search-large';
16624const SEARCH_ICON = 'search-icon';
16625const FF_COMP_FORM_SUBMIT_BUTTON = 'ff-comp__form--submit-button';
16626const SUBMIT_PART_SEARCH = 'Submit part search';
16627
16628const filterFinderInit = (filterFinderComp) => {
16629  /************************* CONSTANTS ***********************/
16630  // Element consts
16631  const ffComp = filterFinderComp.querySelector('.ff-comp');
16632  const ffModal = filterFinderComp.querySelector('.filter-finder-modal');
16633  const modalHeading = ffModal.querySelector('.modal-title');
16634  const modalTitle = ffModal.querySelector('.title-banner h2');
16635  const productResults = ffModal.querySelector('.product-results');
16636  const resultHits = ffModal.querySelector('.result-hits');
16637  const modalCloseButton = ffModal.querySelector('.custom-close');
16638  const productResultsNone = ffModal.querySelector('.product-results-none');
16639  const part = ffComp.querySelector('.part');
16640  const partError = ffComp.querySelector('.part__error-message');
16641  const manufacturer = ffComp.querySelector('.manufacturer');
16642  const measurement = ffComp.querySelector('.measurement');
16643  const measurementError = ffComp.querySelector('.measurement__error-message');
16644  let units = USA;
16645  let lastFocusedElement; // For returning focus after modal close
16646
16647  // Strings
16648  const INSTANCE = ffComp.dataset.indexenvironment;
16649  const INDEX_NAME = INSTANCE + '_' + ffComp.dataset.index;
16650  const APPLICATION_ID = ffComp.dataset.applicationid;
16651  const SEARCH_API_KEY = ffComp.dataset.searchApiKey;
16652
16653  // Algolia consts
16654  const searchClient = window.algoliasearch.algoliasearch(APPLICATION_ID, SEARCH_API_KEY);
16655  let search;
16656  let modalInstance; // Bootstrap modal instance
16657  const useBootstrap5 = typeof bootstrap !== 'undefined' && bootstrap.Modal;
16658
16659  /************************* FUNCTIONS ***********************/
16660  const restoreNativeSelect = (selectElement) => {
16661    if (!selectElement) return;
16662    const chosenContainer = selectElement.nextElementSibling;
16663    if (chosenContainer?.classList.contains('chosen-container')) {
16664      chosenContainer.remove();
16665    }
16666    selectElement.style.display = 'block';
16667  };
16668
16669  // Modal - Do open
16670  const openFilterModal = (openModalElement) => {
16671    lastFocusedElement = openModalElement;
16672    document.body.classList.add(FILTER_FINDER_MODAL_PRESENT);
16673    productResults.classList.add(DISPLAY_RESULTS);
16674
16675    // Use Bootstrap 5 API if available, otherwise fall back to jQuery Bootstrap 3
16676    if (useBootstrap5) {
16677      if (!modalInstance) {
16678        modalInstance = new bootstrap.Modal(ffModal);
16679      }
16680      modalInstance.show();
16681    } else if (window.$ && $(ffModal).modal) {
16682      $(ffModal).modal('show');
16683    }
16684  };
16685
16686  // Modal - Do close and reset
16687  const closeFilterModal = () => {
16688    search.helper
16689        .clearRefinements(MANUFACTURERS)
16690        .clearRefinements(DIAMETER_USA)
16691        .clearRefinements(LENGTH_USA)
16692        .clearRefinements(DIAMETER_METRIC)
16693        .clearRefinements(LENGTH_METRIC)
16694        .setQuery('')
16695        .search();
16696    partError.classList.remove(DISPLAY_ERROR_MESSAGE);
16697    measurementError.classList.remove(DISPLAY_ERROR_MESSAGE);
16698    modalHeading.innerText = '';
16699    modalTitle.innerText = '';
16700    resultHits.innerHTML = '';
16701    productResultsNone.classList.remove(DISPLAY_PRODUCTS_NONE);
16702    document.body.classList.remove(FILTER_FINDER_MODAL_PRESENT);
16703    productResults.classList.remove(DISPLAY_RESULTS);
16704
16705    // Use Bootstrap 5 API if available, otherwise fall back to jQuery Bootstrap 3
16706    if (useBootstrap5 && modalInstance) {
16707      modalInstance.hide();
16708    } else if (window.$ && $(ffModal).modal) {
16709      $(ffModal).modal('hide');
16710    }
16711
16712    lastFocusedElement?.focus();
16713  };
16714
16715  // Modal - Listeners for close button, ESC and click outside
16716  const initModalClose = () => {
16717    modalCloseButton.addEventListener('click', closeFilterModal);
16718    ffModal.addEventListener('keydown', function (event) {
16719      if (event.key === 'Escape') {
16720        closeFilterModal();
16721      }
16722    });
16723    ffModal.addEventListener('click', function (event) {
16724      const isModalOpen = document.body.classList.contains(
16725        FILTER_FINDER_MODAL_PRESENT
16726      );
16727      if (isModalOpen && !event.target.closest('.modal-content')) {
16728        closeFilterModal();
16729      }
16730    });
16731  };
16732
16733  // Setup the search and results, including results tables
16734  const initSearch = () => {
16735    search = window.instantsearch({
16736      indexName: INDEX_NAME,
16737      searchClient,
16738      insights: true
16739    });
16740
16741    search.addWidgets([
16742      widgets.configure({
16743        facets: [
16744          MANUFACTURERS,
16745          DIAMETER_USA,
16746          LENGTH_USA,
16747          DIAMETER_METRIC,
16748          LENGTH_METRIC
16749        ]
16750      }),
16751      widgets.infiniteHits({
16752        container: resultHits,
16753        templates: {
16754          empty: ({ query }, { html }) => {
16755            modalTitle.innerText = '';
16756            productResultsNone.classList.add(DISPLAY_PRODUCTS_NONE);
16757          },
16758          item(hit, { html, sendEvent }) {
16759            // Check if a value is valid (not null, undefined, or empty string)
16760            const isValidValue = (value) => {
16761                return value !== null && value !== undefined && value !== '' && String(value).trim() !== '';
16762            };
16763
16764            // Create a table row
16765            const createRow = (label, value1, value2 = null, colspan = '') => {
16766                // Dual column scenario (USA/Metric values)
16767                if (value2 !== null) {
16768                    return (isValidValue(value1) || isValidValue(value2)) ?
16769                  `<tr><td class="category">${label}</td><td>${value1}</td><td>${value2}</td></tr>` : '';
16770                }
16771
16772                // Single column scenario
16773                const colspanAttr = colspan ? `colspan="${colspan}"` : '';
16774              return isValidValue(value1) ? `<tr><td class="category">${label}</td><td ${colspanAttr}>${value1}</td></tr>` : '';
16775            };
16776
16777            // Generate table from row configuration array
16778            const generateTableFromConfig = (rowConfigs) => {
16779                const rows = rowConfigs
16780                    .map(config => createRow(config.label, config.value1, config.value2, config.colspan))
16781                    .filter(row => row !== '')
16782                    .join('');
16783                return rows;
16784            };
16785
16786            // Create a complete table with title and optional classes
16787            const createTable = (title, rows, additionalClasses = '') => {
16788                return rows ? `<table class="description ${additionalClasses}" cellpadding="0" cellspacing="0">
16789                    <tbody>
16790                        <tr><th colspan="2">${title}</th></tr>
16791                        ${rows}
16792                    </tbody>
16793                </table>` : '';
16794            };
16795
16796            // Row configs for each table
16797            const distributorRowConfigs = [
16798                { label: 'POOLCORP', value1: hit.poolcorp },
16799                { label: 'POOLCORP (Xtreme Blue)', value1: hit.poolcorpXB },
16800                { label: 'Heritage', value1: hit.heritage },
16801                { label: 'Baystate', value1: hit.baystate }
16802            ];
16803
16804            const specificationRowConfigs = [
16805                { label: 'Description', value1: hit.description, colspan: '2' },
16806                { label: 'Application', value1: hit.application, colspan: '2' },
16807                { label: 'Diameter', value1: hit.diameterUSA, value2: hit.diameterMetric },
16808                { label: 'Length', value1: hit.lengthUSA, value2: hit.lengthMetric },
16809                { label: 'Top Hole', value1: hit.topHoleUSA, value2: hit.topHoleMetric },
16810                { label: 'Bottom Hole', value1: hit.bottomHoleUSA, value2: hit.bottomHoleMetric },
16811                { label: 'Filter Material', value1: hit.category, colspan: '2' },
16812                { label: 'Material Area', value1: hit.materialAreaUSA, value2: hit.materialAreaMetric },
16813                { label: 'Material Weight', value1: hit.materialWeightUSA, value2: hit.materialWeightMetric }
16814            ];
16815
16816            const replacementRowConfigs = [
16817                { label: 'OEM', value1: hit.replacementOEM },
16818                { label: 'Pleatco', value1: hit.replacementPleatco },
16819                { label: 'Unicel', value1: hit.replacementUnicel || (isValidValue(hit.replacementUnicel) ? '-' : null) },
16820                { label: 'Filbur', value1: hit.replacementFilbur || (isValidValue(hit.replacementFilbur) ? '-' : null) }
16821            ];
16822
16823            // Generate table rows using the configs
16824            const distributorRows = generateTableFromConfig(distributorRowConfigs);
16825            const specificationRows = generateTableFromConfig(specificationRowConfigs);
16826            const replacementRows = generateTableFromConfig(replacementRowConfigs);
16827
16828            const urlIsPresent = !!hit.url ? URL_IS_PRESENT : '';
16829            const filburUnicelStatus = (!hit.replacementFilbur && !hit.replacementUnicel) ? FILBER_UNICEL_INACTIVE : '';
16830            const discontinuedItemClass = (hit.discontinued == 'no') ? hit.sku : hit.sku + DASH_DISCONTINUED;
16831            const learnMore = resultHits.dataset.attribute;
16832
16833            return html`
16834                <div class="col-lg-9 col-md-7 col-sm-7 col-xs-12 table-title">
16835                    ${discontinuedItemClass}
16836                </div>
16837                <div class="table-section-wrapper">
16838                    <div class="col-lg-9 col-md-7 col-sm-7 col-xs-12 ff-table">
16839                        ${html([createTable('Distributor Part Numbers', distributorRows)])}
16840                        ${html([createTable('Specifications', specificationRows)])}
16841                        ${html([createTable('Replaced Part Numbers', replacementRows, filburUnicelStatus)])}
16842                    </div>
16843                    <div class="col-lg-3 col-md-5 col-sm-5 col-xs-12 ff-image">
16844                        <div class="product-border">
16845                            <img class="img-responsive"
16846                                src="${hit.image}"
16847                                alt="${hit.sku}.png"
16848                                title="${hit.sku}.png" />
16849                        </div>
16850                        <div class="button hit-learn-more ${urlIsPresent}">
16851                          <a href="${hit.url}" data-trackable="true" aria-label="${hit.sku}" class="btn btn-primary">${learnMore}</a>
16852                        </div>
16853                    </div>
16854                </div>`;
16855          }
16856        }
16857      })
16858    ]);
16859
16860    search.start();
16861  };
16862
16863  /////////////// PARTS ///////////////
16864  // Parts input - Do search based on text or selection, show modal
16865  const displayPartsResults = (searchByText, el, state, inputAutocomplete) => {
16866    let query = el || state?.query; // Input text or selected suggestion
16867    modalHeading.innerText = searchByText;
16868    if (query) {
16869      search.helper
16870        .setQuery(query)
16871        .search();
16872      modalTitle.innerText = query;
16873      openFilterModal(inputAutocomplete);
16874    } else {
16875      partError.classList.add(DISPLAY_ERROR_MESSAGE);
16876    }
16877  };
16878
16879  // Parts input - Populate suggestions
16880  const initPartAutocomplete = () => {
16881    const inputAutocomplete = part.querySelector('.part__select');
16882    autocomplete({
16883      container: inputAutocomplete,
16884      placeholder: 'Search for parts',
16885      detachedMediaQuery: 'none',
16886      onSubmit({ state, setQuery }) {
16887        displayPartsResults(part.querySelector('.ff-comp__form--label').innerText, null, state, inputAutocomplete.querySelector('button'));
16888      },
16889      getSources({ query }) {
16890        return [{
16891          sourceId: 'parts',
16892          getItems() {
16893            return getAlgoliaResults({
16894              searchClient,
16895              insights: true,
16896              queries: [{
16897                  indexName: INDEX_NAME,
16898                  query,
16899                  params: {
16900                    hitsPerPage: 5
16901                  }
16902                }]
16903            });
16904          },
16905          templates: {
16906            item({ item, html }) {
16907              return html`<div class="aa-ItemWrapper">
16908                <div class="aa-ItemIcon">
16909                  <img src="${item.image}" alt="${item.sku}" />
16910                </div>
16911                <div class="aa-ItemContent">${item.sku}</div>
16912              </div>`;
16913            },
16914          },
16915          onSelect({ item }) {
16916            displayPartsResults(part.querySelector('.ff-comp__form--label').innerText, item.sku, null, inputAutocomplete.querySelector('input'));
16917          }
16918        }
16919      ]}
16920    });
16921
16922    part.querySelector('.aa-InputWrapperSuffix').remove();
16923
16924    const iconClasses = [
16925      ICON_SEARCH_LARGE,
16926      SEARCH_ICON,
16927      FF_COMP_FORM_SUBMIT_BUTTON
16928    ];
16929    const submitButton = part.querySelector('.aa-SubmitButton');
16930    submitButton.classList.add(...iconClasses);
16931    submitButton.setAttribute('aria-label', SUBMIT_PART_SEARCH);
16932
16933    const prefix = part.querySelector('.aa-InputWrapperPrefix');
16934    prefix.querySelector('svg').remove();
16935
16936    const inputWrapper = part.querySelector('.aa-InputWrapper');
16937    inputWrapper.after(prefix);
16938  };
16939
16940  // MANUFACTURERS AND MEASUREMENTS HELPER
16941  const retrieveFacetsForSelect = (instSearch, selectElement, attributeName, placeholder) => {
16942    instSearch.addWidgets([
16943      widgets.refinementList({
16944        container: selectElement,
16945        attribute: attributeName,
16946        limit: 200,
16947        showMore: false,
16948        searchable: true,
16949        searchablePlaceholder: placeholder,
16950        searchableIsAlwaysActive: true,
16951        sortBy: ['name:asc'],
16952        templates: {
16953          item(item) {
16954            const { label } = item;
16955            const option = document.createElement('option');
16956            option.value = label;
16957            option.textContent = label;
16958            selectElement.appendChild(option);
16959          }
16960        }
16961      })
16962    ]);
16963  }
16964
16965  /////////////// MANUFACTURERS ///////////////
16966  // Manufacturer - Do search based on facet refinement selection, show modal
16967  const displayManufacturersResults = (searchByText, label, openM
16967odalElement) => {
16968    search.helper
16969        .addFacetRefinement(MANUFACTURERS, label)
16970        .setQuery('')
16971        .search();
16972    modalHeading.innerText = searchByText;
16973    modalTitle.innerText = label;
16974    openFilterModal(openModalElement);
16975  };
16976
16977  // Manufacturer - Populate suggestions
16978  const initManufacturersSelect = () => {
16979    const manufacturerSelect = manufacturer.querySelector('.manufacturer__select');
16980    const manufacturerSearch = window.instantsearch({
16981      indexName: INDEX_NAME,
16982      searchClient,
16983      insights: true
16984    });
16985    manufacturerSearch.start();
16986
16987    retrieveFacetsForSelect(manufacturerSearch, manufacturerSelect, MANUFACTURERS, 'Manufacturers');
16988    restoreNativeSelect(manufacturerSelect);
16989
16990    manufacturerSelect.addEventListener('change', (event) => {
16991      const selectedOption = event.target.value;
16992      if (!selectedOption) return;
16993      displayManufacturersResults(manufacturer.querySelector('.ff-comp__form--label').innerText, selectedOption, manufacturerSelect);
16994    });
16995
16996  };
16997
16998  /////////////// MEASUREMENTS ///////////////
16999  // Measurements - Handle units toggle to display correct inputs
17000  const initMeasurementUnits = () => {
17001    const unitRadios = measurement.querySelectorAll('.units input');
17002    [...unitRadios].forEach((radio) => {
17003      radio.addEventListener('change', () => {
17004        units = measurement.querySelector('.units input:checked').value;
17005        const usaWrapper = ffComp.querySelector('.dimension-usa-wrapper');
17006        const metricWrapper = ffComp.querySelector('.dimension-metric-wrapper');
17007        if (units === USA) {
17008          usaWrapper.classList.remove('hidden');
17009          metricWrapper.classList.add('hidden');
17010        } else {
17011          usaWrapper.classList.add('hidden');
17012          metricWrapper.classList.remove('hidden');
17013        }
17014      });
17015    });
17016  };
17017
17018  // Measurements - Setup search button listener
17019  const initMeasurementSearchButton = () => {
17020    const searchButton = measurement.querySelector('.measurement__button');
17021    searchButton.addEventListener('click', () => {
17022      const dimensionWrapperUnits = (units === USA) ?
17023          measurement.querySelector('.dimension-usa-wrapper') :
17024          measurement.querySelector('.dimension-metric-wrapper');
17025      const diameter = dimensionWrapperUnits.querySelector('.diameter').value;
17026      const length = dimensionWrapperUnits.querySelector('.length').value;
17027      displayMeasurementsResults(measurement.querySelector('.ff-comp__form--label').innerText, diameter, length, searchButton);
17028    });
17029  };
17030
17031  // Measurements - Do search based on facet refinements for at least one dimension, show modal
17032  const displayMeasurementsResults = (searchByText, diameter, length, searchButton) => {
17033    modalHeading.innerText = searchByText;
17034    if (diameter || length) {
17035      let titleText = '';
17036      if (diameter) {
17037        search.helper.addFacetRefinement(DIAMETER + units, diameter);
17038        titleText += 'Diameter: ' + diameter + ' ';
17039      }
17040      if (length) {
17041        search.helper.addFacetRefinement(LENGTH + units, length);
17042        titleText += 'Length: ' + length;
17043      }
17044      search.helper
17045          .setQuery('')
17046          .search();
17047      modalTitle.innerText = titleText;
17048      openFilterModal(searchButton);
17049    } else {
17050      measurementError.classList.add(DISPLAY_ERROR_MESSAGE);
17051    }
17052  };
17053
17054  // Measurements - Populate suggestions for all units
17055  const initMeasurementsSelect = () => {
17056    const dimensionWrapper = measurement.querySelectorAll('.dimension');
17057    dimensionWrapper.forEach((dimension) => {
17058      const measurementSearch = window.instantsearch({
17059        indexName: INDEX_NAME,
17060        searchClient,
17061        insights: true,
17062      });
17063      measurementSearch.start();
17064
17065      dimension.querySelectorAll('.dimension__select').forEach((measurementSelect) => {
17066        const measurementRefinement = measurementSelect.dataset.measurementRefinement;
17067        const measurementType = measurementSelect.dataset.measurementType;
17068
17069        retrieveFacetsForSelect(measurementSearch, measurementSelect, measurementRefinement, measurementType);
17070        restoreNativeSelect(measurementSelect);
17071      });
17072    });
17073  };
17074
17075  /************************* FILTER FINDER INIT EXECUTION ***********************/
17076  initModalClose();
17077  initSearch();
17078  initPartAutocomplete();
17079  initManufacturersSelect();
17080  initMeasurementUnits();
17081  initMeasurementSearchButton();
17082  initMeasurementsSelect();
17083};
17084
17085/************************* ENTRY POINT ***********************/
17086if (document.readyState === 'loading') {
17087  document.addEventListener('DOMContentLoaded', function () {
17088    const filterFinderComp = document.querySelector('.filter-finder');
17088 // Only get first component, assuming there would not be two.
17089    if (filterFinderComp) {
17090      filterFinderInit(filterFinderComp);
17091    }
17092  });
17093} else {
17094  const filterFinderComp = document.querySelector('.filter-finder');
17095  if (filterFinderComp) {
17096    filterFinderInit(filterFinderComp);
17097  }
17098}
17099
17100// =============================================================================
17101// GLOBAL CONSTANTS
17102// =============================================================================
17103
17104/**
17105 * Template text for "Show more/less" button in filter panels
17106 */
17107const showMoreText = ({ isShowingMore }, { html }) => html`${isShowingMore ? Granite.I18n.get('Show less') : Granite.I18n.get('Show more')}`;
17108
17109// =============================================================================
17110// GLOBAL HELPER FUNCTIONS
17111// =============================================================================
17112
17113/**
17114 * Checks if event target is an interactive element that should not trigger panel collapse
17115 * @param {Event} ev - The event object
17116 * @returns {boolean} True if target is interactive, false otherwise
17117 */
17118function isInteractiveTarget(ev) {
17119  const target = ev.target;
17120  if (target.closest('.ais-RefinementList-showMore')) return true;
17121  if (target.matches('input, label, a, button, select, textarea')) return true;
17122  return false;
17123}
17124
17125/**
17126 * Updates aria-expanded attribute based on panel body visibility
17127 * @param {HTMLElement} panel - The panel element
17128 * @param {HTMLElement} body - The panel body element
17129 */
17130function updateExpandedAttr(panel, body) {
17131  if (body) {
17132    const isVisible = body.classList.contains('dcg-panel-expanded');
17133    panel.setAttribute('aria-expanded', isVisible ? 'true' : 'false');
17134  }
17135}
17136
17137/**
17138 * Toggles panel body visibility with accessibility updates
17139 * @param {HTMLElement} panel - The panel element
17140 * @param {HTMLElement} body - The panel body element
17141 */
17142function togglePanel(panel, body) {
17143  if (body) {
17144    const isCurrentlyVisible = body.classList.contains('dcg-panel-expanded');
17145
17146    if (isCurrentlyVisible) {
17147      // Collapse with animation
17148      const height = body.scrollHeight;
17149      body.style.height = height + 'px';
17150      body.offsetHeight; // Force reflow
17151      body.classList.add('dcg-panel-collapsing');
17152      body.style.height = '0';
17153
17154      setTimeout(() => {
17155        body.classList.remove('dcg-panel-collapsing', 'dcg-panel-expanded');
17156        body.classList.add('dcg-panel-collapsed');
17157        body.style.height = '';
17158        updateExpandedAttr(panel, body);
17159      }, 200);
17160    } else {
17161      // Expand with animation
17162      body.classList.remove('dcg-panel-collapsed');
17163      body.classList.add('dcg-panel-expanding', 'dcg-panel-expanded');
17164      const height = body.scrollHeight;
17165      body.style.height = '0';
17166      body.offsetHeight; // Force reflow
17167      body.style.height = height + 'px';
17168
17169      setTimeout(() => {
17170        body.classList.remove('dcg-panel-expanding');
17171        body.style.height = '';
17172        updateExpandedAttr(panel, body);
17173      }, 200);
17174    }
17175  }
17176}
17177
17178/**
17179 * Converts refinement list array to comma-separated string
17180 * @param {Object} obj - The object containing refinement lists
17181 * @param {string} key - The key to access in the object
17182 * @returns {string} Comma-separated string or empty string
17183 */
17184function listRefinement(obj, key) {
17185  if (obj && key) {
17186    const arr = obj[key];
17187    if(arr && arr.length > 0) {
17188      return arr.join();
17189    }
17190  }
17191  return "";
17192}
17193
17194/**
17195 * Detects mobile vs desktop platform
17196 * @returns {string} 'mobile' or 'desktop'
17197 */
17198function getPlatform() {
17199  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'mobile' : 'desktop';
17200}
17201
17202/**
17203 * Creates filter panel configuration for Algolia widgets
17204 * @param {HTMLElement} container - The container element
17205 * @param {string} attribute - The attribute to filter on
17206 * @param {boolean} showMore - Whether to show the "show more" button
17207 * @param {number} showMoreLimit - Maximum items before showing "show more"
17208 * @param {string} sortBy - Sort order for items
17209 * @param {boolean} transformItems - Whether to transform item labels
17210 * @returns {Object} Filter panel configuration object
17211 */
17212function createFilterPanel(container, attribute, showMore, showMoreLimit, sortBy, transformItems) {
17213    const filterPanelConfig = {
17214      container,
17215      attribute,
17216      showMore,
17217      showMoreLimit,
17218      templates: {
17219        showMoreText,
17220        item: (item, { html }) => html`<input class="dc-filter-check" type="checkbox" value="${item.label}" checked=${item.isRefined || null} /><label><span>${item.label}</span><span class="item-count"> (${item.count})</span></label>`,
17221      },
17222      sortBy: sortBy ? [sortBy] : undefined,
17223    }
17224    if (transformItems) {
17225      filterPanelConfig.transformItems = (items) => {
17226        return items.map((item) => {
17227          const formatLabel = item.label.substring(item.label.lastIndexOf('|') + 1, item.length);
17228          item.label = formatLabel;
17229          return item;
17230        });
17231      };
17232    }
17233    return filterPanelConfig;
17234}
17235
17236/**
17237 * Sets up accessibility attributes and event handlers for a single accordion panel
17238 * @param {HTMLElement} panel - The panel element
17239 * @param {HTMLElement} body - The panel body element
17240 */
17241function setupAccordionPanel(panel, body) {
17242  const panelHeader = panel.querySelector('.ais-Panel-header');
17243  if (panelHeader.getAttribute('tabindex') === null) {
17244    panelHeader.setAttribute('tabindex', '0');
17245  }
17246  panelHeader.setAttribute('role', 'button');
17247
17248  // Remove button from tabindex since adding to header instead
17249  const panelButton = panel.querySelector('.ais-Panel-header .ais-Panel-collapseButton');
17250  panelButton.setAttribute('tabindex', '-1');
17251
17252  if (body) {
17253    body.classList.add('.dcg-panel-collapsed');
17254    let bodyId = body.getAttribute('id');
17255    if (!bodyId) {
17256      bodyId = 'dcg-panel-body-' + Math.random().toString(36).slice(2, 10);
17257      body.setAttribute('id', bodyId);
17258    }
17259    panelHeader.setAttribute('aria-controls', bodyId);
17260    const isVisible = body.classList.contains('dcg-panel-expanded');
17261    panelHeader.setAttribute('aria-expanded', isVisible ? 'true' : 'false');
17262  }
17263
17264  panelHeader.addEventListener('click', (e) => {
17265    if (isInteractiveTarget(e)) return;
17266    togglePanel(panelHeader, body);
17267  });
17268
17269  panelHeader.addEventListener('keydown', (e) => {
17270    if (e.key === 'Enter' || e.key === ' ') {
17271      if (isInteractiveTarget(e)) return;
17272      e.preventDefault();
17273      togglePanel(panelHeader, body);
17274    }
17275  });
17276
17277  // Prevents submitting form when using Enter to check filter boxes, but allows it for show more
17278  body.addEventListener('keydown', (e) => {
17279    if (e.key === 'Enter' && !e.target.matches('.ais-RefinementList-showMore')) {
17280      e.preventDefault();
17281    }
17282  });
17283}
17284
17285/**
17286 * Handles mutation observer callback to setup panels when dynamic widgets are added
17287 * @param {HTMLElement} elem - The dynamic widget element
17288 * @param {MutationObserver} observer - The mutation observer instance
17289 */
17290function handleDynamicWidgetMutation(elem, observer) {
17291  // Fired when a mutation occurs. In our case it is addition of dynamic widget content.
17292  // Add keyboard A11y to filter dropdowns
17293  const panels = elem.querySelectorAll('[class*=algolia-accordion-panel]');
17294  panels.forEach((panel) => {
17295    const body = panel.querySelector('div.ais-Panel-body');
17296    setupAccordionPanel(panel, body);
17297  });
17298  observer.disconnect();
17299}
17300
17301/**
17302 * Adds click event handlers to dynamic accordion panel widgets for accessibility
17303 * @param {HTMLElement} filterContainer - Container for the filter widgets
17304 */
17305function initDynamicWidgetAccordianPanelDCG(filterContainer) {
17306  const dynamicWidgets = filterContainer.querySelectorAll('div[class*=ais-DynamicWidgets-widget]');
17307  if (dynamicWidgets.length > 0) {
17308    dynamicWidgets.forEach((elem) => {
17309      let observer = new MutationObserver((mutations, obs) => {
17310        handleDynamicWidgetMutation(elem, obs);
17311      });
17312      observer.observe(elem, {
17313        childList: true
17314      });
17315    });
17316  }
17317}
17318
17319// Gets the title after | from last item in an array with optional lower case.
17320function getTitleForAnalytics(itemArr, doLower = false) {
17321  const length = itemArr?.length;
17322  if (!length) return;
17323
17324  const lastItem = itemArr[length - 1];
17325  const lastItemTitle = lastItem.substring(lastItem.lastIndexOf('|') + 1, lastItem.length);
17326  return doLower ? lastItemTitle.toLowerCase() : lastItemTitle;
17327}
17328
17329/**
17330 * Global function for download analytics tracking
17331 * Must be globally accessible for inline onclick handlers in templates
17332 * @param {number} age - Download age/position
17333 * @param {string} brand - Brand information
17334 * @param {string} language - Language code
17335 * @param {string} type - Document type
17336 * @param {string} name - Document name
17337 */
17338window.downloadAnalytic = function(age, brand, language, type, name) {
17339  try {
17340    if(digitalData){
17341      if(digitalData.event){
17342        const eventArr = {};
17343        eventArr.eventAction = "download resource";
17344        eventArr.eventName = "download center";
17345        eventArr.timeStamp = new Date();
17346        eventArr.type = "download";
17347        digitalData.event.push(eventArr);
17348      }
17349      digitalData.download = digitalData.download || {};
17350      if(digitalData.download){
17351        digitalData.download.downloadAge = age;
17352        digitalData.download.downloadBrand = getTitleForAnalytics(brand);
17353        digitalData.download.downloadLanguage = getTitleForAnalytics(language, true);
17354        digitalData.download.downloadType = getTitleForAnalytics(type);
17355        digitalData.download.downloadName = name;
17356        digitalData.download.filterTypeSelection = getFilterStringForAnalytics();
17357      }
17358    }
17359  } catch (error) {
17360    console.log(error);
17361  }
17362};
17363
17364// =============================================================================
17365// HELPER FUNCTIONS FOR DOWNLOAD CENTER
17366// =============================================================================
17367
17368/**
17369 * Maps AEM metadata schema language codes to Algolia index language values
17370 * @param {string} code - Language code from AEM
17371 * @returns {string} Algolia language name
17372 */
17373function mapLanguageCodeToName(code) {
17374    const languageMap = {
17375      'en_us': 'English',
17376      'en_gb': 'English',
17377      'es': 'Spanish',
17378      'fr_fr': 'French',
17379      'fr_ca': 'French',
17380      'de_de': 'German',
17381      'ar_ye': 'Arabic',
17382      'nl_nl': 'Dutch',
17383      'pt': 'Portuguese',
17384      'it_it': 'Italian',
17385      'zh_cn': 'Chinese',
17386      'da_dk': 'Danish',
17387      'hi': 'Hindi',
17388      'hu': 'Hungarian',
17389      'is': 'Icelandic',
17390      'id': 'Indonesian',
17391      'ja': 'Japanese',
17392      'ko_kr': 'Korean',
17393      'no_no': 'Norwegian',
17394      'pl_pl': 'Polish',
17395      'ru': 'Russian',
17396      'th': 'Thai',
17397      'tr': 'Turkish'
17398    };
17399    return languageMap[code] || code;
17400}
17401
17402/**
17403 * Handler for filter button clicks
17404 * @param {Event} event - The click event
17405 * @returns {boolean} True to allow default behavior
17406 */
17407function handleFilterClick(event) {
17408  const isButtonClick = event.target.matches('button');
17409  if (isButtonClick) {
17410    event.preventDefault();
17411  }
17412  return true;
17413}
17414
17415/**
17416 * Ensures Algolia "Show more" controls do not submit the surrounding form
17417 */
17418function fixShowMoreButtons() {
17419  document.querySelectorAll('.ais-RefinementList-showMore').forEach(btn => btn.type = 'button');
17420}
17421
17422// Creates a String where each item is category:value1,value2,etc for the currently selected filters, and are separated by ^
17423// To be used with Adobe Analytics
17424const getFilterStringForAnalytics = () => {
17425  const currentRefinements = document.querySelectorAll('.download-center-grid .current-refinements li button');
17426  const map = new Map();
17427  currentRefinements.forEach((refinement) => {
17428    const data = refinement.dataset;
17429    const category = data.attribute;
17430    const dataVal = data.value;
17431    const valLabel = dataVal.includes('|') ? dataVal.split('|').pop() : dataVal;
17432    if (!map.get(category)) {
17433      map.set(category, []);
17434    }
17435    map.get(category).push(valLabel);
17436  });
17437
17438  const processedArr = [];
17439  map.forEach((value, key) => {
17440    processedArr.push(key + ':' + value.join(','));
17441  });
17442  return processedArr.join('^');
17443};
17444
17445// Fires an Adobe Analytics event for empty results.
17446const trackRefinementsForEmptyResults = () => {
17447  if (!digitalData) return;
17448  const noResultPayload = {
17449    eventType: 'event',
17450    eventName: 'click',
17451    attributes: [{ linktype: 'download hub filter', linkname: 'download hub zero results' }]
17452  };
17453  trackEventWithQueue(noResultPayload);
17454
17455  digitalData.download = digitalData.download || {};
17456  digitalData.download.filterTypeSelection = getFilterStringForAnalytics();
17457  digitalData.download.filterResultZero = 'true';
17458};
17459
17460// =============================================================================
17461// DOWNLOAD CENTER INITIALIZATION
17462// =============================================================================
17463
17464/**
17465 * Initializes the download center component
17466 * @param {HTMLElement} componentElement - The download center component DOM element
17467 */
17468function initDownloadCenter(componentElement) {
17469  const applicationId = componentElement.dataset.applicationId;
17470  const searchApiKey = componentElement.dataset.searchApiKey;
17471  const index = componentElement.dataset.index;
17472  const mobileFilterModal = document.getElementById('downloadCenterFilterModal');
17473  let searchTerm = componentElement.querySelector('.searchBox')?.dataset.searchterm || "";
17474  let defaultSort = componentElement.querySelector('.sortby')?.dataset.sortby || "dcTitle";
17475  let resultperpage = componentElement.querySelector('.hitsPerPage')?.dataset.resultperpage;
17476  let yearFilterList = componentElement.querySelector('.filter')?.dataset.yearfilter || "";
17477  let languageFilterList = componentElement.querySelector('.filter')?.dataset.languagefilter || "";
17478
17479  /**
17480   * Initializes Algolia search with all widgets and configuration
17481   * @param {string} indexName - The Algolia index name
17482   * @param {HTMLElement} containerElem - The container element for search widgets
17483   */
17484  function initAlgolia(indexName, containerElem) {
17485    const searchClient = window.algoliasearch.algoliasearch(applicationId, searchApiKey);
17486
17487    const initialRefinements = {
17488      searchable: ['true']  // Only show searchable items
17489    };
17490
17491    // Prepare year filter from dialog
17492    if (yearFilterList) {
17493      const yearStr = yearFilterList.toString();
17494      const yearsToFilter = yearStr.split(',').map(item => item.trim()).filter(Boolean);
17495
17496      initialRefinements.year = yearsToFilter;
17497    }
17498
17499    // Prepare language filter from dialog
17500    if (languageFilterList) {
17501      const langStr = languageFilterList.toString();
17502      const languagesToFilter = langStr.split(',').map(item => mapLanguageCodeToName(item.trim())).filter(Boolean);
17503
17504      initialRefinements.language = languagesToFilter;
17505    }
17506
17507    const search = window.instantsearch({
17508      indexName: indexName,
17509      searchClient: searchClient,
17510      insights: true,
17511      initialUiState: {
17512        [indexName]: {
17513          refinementList: initialRefinements
17514        }
17515      },
17516      routing: {
17517        router: window.instantsearch.routers.history({
17518          createURL: ({ qsModule, routeState, location }) => {
17519            const queryParameters = {
17520              q: routeState.q || "",
17521              page: routeState.page || "1",
17522              num: routeState.num,
17523              sort: routeState.sort,
17524              date: routeState.date || "",
17525              brands: routeState.brands || "",
17526              documentType: routeState.documentType || "",
17527              language: routeState.language || "",
17528              applications: routeState.applications || "",
17529              categories: routeState.categories || "",
17530              industrySolutions: routeState.industrySolutions || ""
17531            };
17532
17533            const queryString = qsModule.stringify(queryParameters, {
17534              addQueryPrefix: true
17535            });
17536
17537            return `${location.protocol}//${location.host}${location.pathname}${queryString}`;
17538          },
17539
17540          parseURL: ({ qsModule, location }) => {
17541            const data = qsModule.parse(
17542              location.search.slice(1)
17543            );
17544            yearFilterList = data.date ? data.date : yearFilterList;
17545            defaultSort = data.sort ? data.sort: indexName + "_popular";
17546            resultperpage = data.num ? data.num : resultperpage;
17547            searchTerm = data.q ? decodeURIComponent(data.q) : location.search.slice(1) ? "" : searchTerm;
17548
17549            // Merge URL params with initial refinements from dialog
17550            const yearRefinements = data.date ? data.date.split(',') : (initialRefinements.year || []);
17551            const languageRefinements = data.language ? data.language.split(',') : (initialRefinements.language || []);
17552            const searchableRefinements = data.searchable ? data.searchable.split(',') : (initialRefinements.searchable || []);
17553
17554            return {
17555              query: data.q ? decodeURIComponent(data.q) : searchTerm,
17556              page: data.page ? data.page: '1',
17557              hitsPerPage: data.num ? data.num: resultperpage,
17558              sortBy: data.sort ? data.sort: defaultSort,
17559              refinementList: {
17560                year: yearRefinements,
17561                brands: data.brands ? data.brands.split(','): [],
17562                documentType: data.documentType ? data.documentType.split(',') : [],
17563                language: languageRefinements,
17564                searchable: searchableRefinements,
17565                applications: data.applications ? data.applications.split(',') : [],
17566                categories: data.categories ? data.categories.split(',') : [],
17567                industrySolutions: data.industrySolutions ? data.industrySolutions.split(',') : []
17568              }
17569            };
17570          }
17571        }),
17572
17573        stateMapping: {
17574          stateToRoute: (uiState) => {
17575            const indexUiState = uiState[indexName] || {};
17576            return {
17577              q: indexUiState.query,
17578              page: indexUiState.page || '1',
17579              num: indexUiState.hitsPerPage,
17580              sort: indexUiState.sortBy,
17581              date: listRefinement(indexUiState.refinementList, 'year'),
17582              brands: listRefinement(indexUiState.refinementList, 'brands'),
17583              documentType: listRefinement(indexUiState.refinementList, 'documentType'),
17584              language: listRefinement(indexUiState.refinementList, 'language'),
17585              searchable: listRefinement(indexUiState.refinementList, 'searchable'),
17586              applications: listRefinement(indexUiState.refinementList, 'applications'),
17587              categories: listRefinement(indexUiState.refinementList, 'categories'),
17588              industrySolutions: listRefinement(indexUiState.refinementList, 'industrySolutions')
17589            };
17590          },
17591
17592          routeToState: (routeState) => {
17593            const uiState = {};
17594            uiState[indexName] = routeState;
17595            return uiState;
17596          }
17597        }
17598      }
17599    });
17600
17601    let sortByItems = [];
17602    if (defaultSort === "dcTitle") {
17603      sortByItems = [
17604        { label: Granite.I18n.get('Popularity'), value: indexName + '_popular' },
17605        { label: 'A-Z', value: indexName },
17606        { label: 'Z-A', value: indexName + '1st' },
17607        { label: Granite.I18n.get('Oldest'), value: indexName + '2nd' },
17608        { label:  Granite.I18n.get('Latest'), value: indexName + '3rd' },
17609      ];
17610    } else if (defaultSort === "dcTitleDesc") {
17611      sortByItems = [
17612        { label: Granite.I18n.get('Popularity'), value: indexName + '_popular' },
17613        { label: 'A-Z', value: indexName + '1st' },
17614        { label: 'Z-A', value: indexName },
17615        { label: Granite.I18n.get('Oldest'), value: indexName + '2nd' },
17616        { label:  Granite.I18n.get('Latest'), value: indexName + '3rd' },
17617      ];
17618    }
17619    else if (defaultSort === "dcCreatedDate") {
17620      sortByItems = [
17621        { label: Granite.I18n.get('Popularity'), value: indexName + '_popular' },
17622        { label: 'A-Z', value: indexName + '1st' },
17623        { label: 'Z-A', value: indexName + '2nd' },
17624        { label: Granite.I18n.get('Oldest'), value: indexName },
17625        { label: Granite.I18n.get('Latest'), value: indexName + '3rd' },
17626      ];
17627    } else if (defaultSort === "dcCreatedDateDesc") {
17628      sortByItems = [
17629        { label: Granite.I18n.get('Popularity'), value: indexName + '_popular' },
17630        { label: 'A-Z', value: indexName + '1st' },
17631        { label: 'Z-A', value: indexName + '2nd' },
17632        { label: Granite.I18n.get('Oldest'), value: indexName + '3rd' },
17633        { label: Granite.I18n.get('Latest'), value: indexName },
17634      ];
17635    } else {
17636      sortByItems = [
17637        { label: Granite.I18n.get('Popularity'), value: indexName },
17638        { label: 'A-Z', value: indexName + '1st' },
17639        { label: 'Z-A', value: indexName + '2nd' },
17640        { label: Granite.I18n.get('Oldest'), value: indexName + '3rd' },
17641        { label: Granite.I18n.get('Latest'), value: indexName + '_popular' },
17642      ];
17643    }
17644
17645    // Desktop disjunctive, clear and current refinements
17646    search.addWidgets([
17647      window.instantsearch.widgets.configure({
17648        analyticsTags: [getPlatform()],
17649        disjunctiveFacets: ['year', 'language', 'brands', 'documentType', 'searchable','applications', 'categories', 'industrySolutions', 'description', 'url', 'title', 'createdDate', 'expirationDate', 'lastModifiedDate', 'thumbnail']
17650      }),
17651      PENTAIR.CustomAlgoliaWidgets.clearRefinements(['searchable'])({
17652        container: componentElement.querySelector('.filter .clear-refinements')
17653      }),
17654      PENTAIR.CustomAlgoliaWidgets.currentRefinements([ 'searchable'], true)({
17655        container: componentElement.querySelector('.filter .current-refinements')
17656      }),
17657    ]);
17658    // Mobile clear and current refinements
17659    if (mobileFilterModal) {
17660      search.addWidgets([
17661        PENTAIR.CustomAlgoliaWidgets.clearRefinements(['searchable'])({
17662            container: mobileFilterModal.querySelector('.clear-refinements')
17663        }),
17664        PENTAIR.CustomAlgoliaWidgets.currentRefinements([ 'searchable'], true)({
17665            container: mobileFilterModal.querySelector('.current-refinements')
17666        }),
17667      ]);
17668    }
17669
17670    //Search box
17671    search.addWidgets([
17672      window.instantsearch.widgets.searchBox({
17673        container: containerElem.querySelector('.searchBox'),
17674        placeholder: Granite.I18n.get('Search Download Center'),
17675        cssClasses: {
17676          form: 'input-search',
17677          input: 'search-field mobile-search',
17678          submit: 'search-icon',
17679          submitIcon: 'icon-search',
17680        },
17681        showReset: false,
17682        showLoadingIndicator: false,
17683      }),
17684    ])
17685    //SortBy
17686    search.addWidgets([
17687      window.instantsearch.widgets.sortBy({
17688        container: containerElem.querySelector('.sortby'),
17689        items: sortByItems,
17690      }),
17691    ])
17692    // Mobile sortBy
17693    if (mobileFilterModal) {
17694      search.addWidgets([
17695        window.instantsearch.widgets.sortBy({
17696          container: mobileFilterModal.querySelector('.sort-by.mobile'),
17697          items: sortByItems,
17698        })
17699      ])
17700    }
17701    //Results per page
17702    //Author default
17703    let hitsPerPageItems = [];
17704    if (resultperpage === '24') {
17705      hitsPerPageItems = [
17706        { label: '12', value: 12 },
17707        { label: '24', value: 24, default: true },
17708        { label: '48', value: 48 },
17709      ];
17710    } else if (resultperpage === '48') {
17711      hitsPerPageItems = [
17712        { label: '12', value: 12 },
17713        { label: '24', value: 24 },
17714        { label: '48', value: 48, default: true },
17715      ];
17716    } else {
17717      hitsPerPageItems = [
17718        { label: '12', value: 12, default: true },
17719        { label: '24', value: 24 },
17720        { label: '48', value: 48 },
17721      ];
17722    }
17723    // Hits per page
17724    search.addWidgets([
17725      window.instantsearch.widgets.hitsPerPage({
17726        container: containerElem.querySelector('.hitsPerPage'),
17727        items: hitsPerPageItems,
17728        cssClasses: {
17729          root: 'num-results',
17730          select: 'filters-num-results',
17731        }
17732      }),
17733    ])
17734    // Mobile hits per page
17735    if (mobileFilterModal) {
17736      search.addWidgets([
17737        window.instantsearch.widgets.hitsPerPage({
17738          container: mobileFilterModal.querySelector('.hitsPerPage.mobile'),
17739          items: hitsPerPageItems,
17740          cssClasses: {
17741            root: 'num-results',
17742            select: 'filters-num-results',
17743          }
17744        }),
17745      ])
17746    }
17747
17748    //Results
17749    search.addWidgets([
17750      window.instantsearch.widgets.hits({
17751        container: containerElem.querySelector('.hits'),
17752        cssClasses: {
17753          list: 'resource-results-list'
17754        },
17755        templates: {
17756          item: (hit, { html, sendEvent }) => html`
17757            <a class="resource-link" target="_blank" rel="noopener noreferrer" href="${hit.url}"
17758               onClick="${() => {
17759                 sendEvent('click', hit, 'Download Center Item Click');
17760                 downloadAnalytic(hit.__position, hit.brands, hit.language, hit.documentType, hit.title);
17761               }}"
17762               data-query-id="${hit.__queryID}"
17763               data-object-id="${hit.objectID}"
17764               data-position="${hit.__position}">
17765              <span class="image"><img loading="lazy" src="${hit.thumbnail}" alt="decorative"/></span>
17766              <div class="resource-title">${hit.title}</div>
17767              <p class="revision-data"><span>${hit.literatureNumber || ''}</span><span>${hit.revision || ''}</span><span>${hit.revisionDate || ''}</span></p>
17768            </a>`,
17769        },
17770      })
17771    ])
17772
17773    //Pagination
17774    search.addWidgets([
17775      window.instantsearch.widgets.pagination({
17776        container: containerElem.querySelector('.pagination .paging'),
17777        cssClasses: {
17778          root: 'paginationList'
17779        },
17780        showFirst: false,
17781        showLast: false,
17782        padding: 2,
17783        templates: {
17784          next: '',
17785          previous: ''
17786        },
17787        scrollTo: containerElem
17788      }),
17789    ])
17790    //Count
17791    search.addWidgets([
17792      window.instantsearch.widgets.stats({
17793        container: containerElem.querySelector('.pagination .count'),
17794        templates: {
17795          text: (result) => {
17796            const firstItem = parseInt(result.hitsPerPage, 10) * parseInt(result.page, 10) + 1;
17797            const lastItem = Math.min(parseInt(firstItem, 10) - 1 + parseInt(result.hitsPerPage, 10), result.nbHits);
17798            return (result.nbHits > 1) ? `${Granite.I18n.get("Displaying")} ${firstItem} - ${lastItem}${Granite.I18n.get(" of ")}${result.nbHits}` : '';
17799          },
17800        }
17801      }),
17802    ])
17803
17804    //Filter list
17805    const dcgFilterPanelWidgets = [
17806        container =>
17807            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('By Year', 'year')(createFilterPanel(container, 'year', true, 30, 'name:desc', false)),
17808        container =>
17809            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Brands', 'brands')(createFilterPanel(container, 'brands', true, 30, null, true)),
17810        container =>
17811            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Industry Solutions', 'industrySolutions')(createFilterPanel(container, 'industrySolutions', true, 30, null, true)),
17812        container =>
17813            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Channels', 'channels')(createFilterPanel(container, 'channels', true, 30, null, true)),
17814        container =>
17815            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Categories', 'categories')(createFilterPanel(container, 'categories', true, 30, null, true)),
17816        container =>
17817            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Applications', 'applications')(createFilterPanel(container, 'applications', true, 30, null, true)),
17818        container =>
17819            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel(Granite.I18n.get('Document Type'), 'documentType')(createFilterPanel(container, 'documentType', true, 30, null, true)),
17820        container =>
17821            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Language', 'language')(createFilterPanel(container, 'language', true, 30, null, false)),
17822        container =>
17823            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Description', 'description')(createFilterPanel(container, 'description', true, 30, null, false)),
17824        container =>
17825            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Url', 'url')(createFilterPanel(container, 'Url', true, 30, null, false)),
17826        container =>
17827            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Title', 'title')(createFilterPanel(container, 'title', true, 30, null, false)),
17828        container =>
17829            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Created Date', 'createdDate')(createFilterPanel(container, 'createdDate', true, 30, null, false)),
17830        container =>
17831            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Expiration Date', 'expirationDate')(createFilterPanel(container, 'expirationDate', true, 30, null, false)),
17832        container =>
17833            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Last Modified Date', 'lastModifiedDate')(createFilterPanel(container, 'lastModifiedDate', true, 30, null, false)),
17834        container =>
17835            PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Thumbn
17835ail', 'thumbnail')(createFilterPanel(container, 'thumbnail', true, 30, null, false)),
17836    ];
17837    // Desktop dynamic filters
17838    search.addWidgets([
17839      window.instantsearch.widgets.dynamicWidgets({
17840        container: componentElement.querySelector('#dynamic-widgets'),
17841        widgets: dcgFilterPanelWidgets
17842      }),
17843      window.instantsearch.widgets.refinementList({
17844        container: containerElem.querySelector('.searchable'),
17845        attribute: 'searchable',
17846      })
17847    ]);
17848    // Mobile dynamic filters
17849    if (mobileFilterModal) {
17850      search.addWidgets([
17851        window.instantsearch.widgets.dynamicWidgets({
17852          container: mobileFilterModal.querySelector('#dynamic-widgets-mobile'),
17853          widgets: dcgFilterPanelWidgets
17854        }),
17855      ]);
17856    }
17857
17858    // Sets state for prev refinement list so that when refinements change, there is a comparison of prev and current.
17859    // This check is needed to ignore pagination and sorting since prev and current filters would be the same.
17860    // Excludes the searchable property since that's a default filter and wouldn't be user-facing.
17861    // Generated by AI
17862    let prevRefinementSnapshot = null;
17863    let isRefinementsModified = false;
17864    let prevQuery = null;
17865    let prevResultsRef = null;
17866    search.addWidgets([
17867      instantsearch.connectors.connectCurrentRefinements(function (renderState, isFirstRender) {
17868        const snapshot = JSON.stringify(renderState.items);
17869        if (isFirstRender) {
17870          prevRefinementSnapshot = snapshot;
17871          return;
17872        }
17873        if (snapshot !== prevRefinementSnapshot) {
17874          prevRefinementSnapshot = snapshot;
17875          isRefinementsModified = true;
17876        }
17877      })({ excludedAttributes: ['searchable'] }),
17878      {
17879        render: function ({ results }) {
17880          if (!results || results === prevResultsRef) return; // Checks there is a new results object
17881          prevResultsRef = results;
17882
17883          const currentQuery = results.query;
17884          const queryChanged = currentQuery !== prevQuery;
17885          prevQuery = currentQuery;
17886
17887          if (isRefinementsModified) {
17888            isRefinementsModified = false;
17889            if (!queryChanged && results.nbHits === 0) {
17890              trackRefinementsForEmptyResults();
17891            }
17892          }
17893        }
17894      }
17895    ]);
17896
17897    search.start();
17898
17899    fixShowMoreButtons();
17900
17901    //hide filter if empty
17902    let lastFocusedCheckboxId = null;
17903
17904    /**
17905     * Sets up accessibility for a single checkbox/label pair
17906     * @param {HTMLElement} item - The refinement list item
17907     * @param {Object} idCounts - ID counter object for generating unique IDs
17908     * @returns {boolean} True if setup was successful
17909     */
17910    const setupCheckboxAccessibility = (item, idCounts) => {
17911      const check = item.querySelector('.dc-filter-check');
17912      const label = item.querySelector('label');
17913
17914      if(!check || !label) return false;
17915
17916      // Generate unique ID
17917      const base = check.value || 'checkbox';
17918      const baseId = 'dcf-' + base
17919        .replace(/\s+/g,'-')
17920        .replace(/[^A-Za-z0-9\-_]/g,'')
17921        .toLowerCase();
17922
17923      let uniqueId;
17924      if(idCounts[baseId]) {
17925        idCounts[baseId]++;
17926        uniqueId = baseId + '-' + idCounts[baseId];
17927      } else {
17928        idCounts[baseId] = 1;
17929        uniqueId = baseId;
17930      }
17931
17932      check.id = uniqueId;
17933      label.setAttribute('for', uniqueId);
17934
17935      // Override Algolia's label click handler to prevent double-toggling
17936      label.addEventListener('click', (e) => {
17937        e.preventDefault();
17938        e.stopPropagation();
17939        lastFocusedCheckboxId = check.id;
17940        check.click();
17941      }, true);
17942
17943      // Track focus on keyboard interaction
17944      check.addEventListener('keydown', (e) => {
17945        if(e.key === ' ' || e.key === 'Space' || e.keyCode === 32) {
17946          lastFocusedCheckboxId = check.id;
17947        }
17948      });
17949
17950      // Track focus on direct click
17951      check.addEventListener('click', () => {
17952        lastFocusedCheckboxId = check.id;
17953      });
17954
17955      return true;
17956    };
17957
17958    search.on('render', () => {
17959      fixShowMoreButtons();
17960
17961      // Hide dc-filter-groups with no refinements
17962      document.querySelectorAll('.component.download-center-grid .filter .filter-list .dc-filter-group').forEach(group => {
17963        const hasNoRefinement = group.querySelector('div.ais-RefinementList--noRefinement');
17964        group.style.display = hasNoRefinement ? 'none' : '';
17965      });
17966
17967      // Hide loader and no-results
17968      const loader = document.querySelector('.loader-wrapper.loader');
17969      if (loader) loader.style.display = 'none';
17970      const noResults = document.querySelector('.no-search-results');
17971      if (noResults) noResults.style.display = 'none';
17972
17973      // Assign IDs and associate labels with checkboxes for screen readers
17974      const idCounts = {};
17975      componentElement.querySelectorAll('.ais-RefinementList-item').forEach((item) => {
17976        setupCheckboxAccessibility(item, idCounts);
17977      });
17978
17979      // Restore focus to the checkbox that was just changed
17980      if(lastFocusedCheckboxId) {
17981        setTimeout(() => {
17982          const checkboxToFocus = document.getElementById(lastFocusedCheckboxId);
17983          if(checkboxToFocus) {
17984            checkboxToFocus.focus();
17985          }
17986          lastFocusedCheckboxId = null;
17987        }, 50);
17988      }
17989    });
17990
17991    // Focus change on keyboard pagination
17992    const paginationElem = componentElement.querySelector('.pagination');
17993    if (paginationElem) {
17994      paginationElem.addEventListener('keydown', (e) => {
17995        if (e.target.matches('a.ais-Pagination-link') && e.key === 'Enter') {
17996          // Move focus to the first page result after Algolia re-renders
17997          setTimeout(() => {
17998            const firstResourceLink = componentElement.querySelector('a.resource-link');
17999            if (firstResourceLink) {
18000              firstResourceLink.focus();
18001            }
18002          }, 100);
18003        }
18004      })
18005    }
18006
18007    // Set focus when modal is actually visible, not using bootstrap3 event bc it is jquery
18008    componentElement.querySelector('.btn-filter')?.addEventListener('click', function () {
18009      const waitForModal = () => {
18010        const isVisible = mobileFilterModal.classList.contains('in') && getComputedStyle(mobileFilterModal).display !== 'none';
18011        if (isVisible) {
18012          mobileFilterModal?.querySelector('.icon-close')?.focus();
18013        } else {
18014          requestAnimationFrame(waitForModal);
18015        }
18016      };
18017      waitForModal();
18018    });
18019  };
18020
18021  // Initialize Algolia and dynamic widgets
18022  initAlgolia(index, componentElement);
18023  const dynamicWidgetsContainer = componentElement.querySelector('.filter #dynamic-widgets');
18024  if (dynamicWidgetsContainer) {
18025    initDynamicWidgetAccordianPanelDCG(dynamicWidgetsContainer);
18026  }
18027  const mobileDynamicWidgetsContainer = mobileFilterModal.querySelector('#dynamic-widgets-mobile');
18028  if (mobileDynamicWidgetsContainer) {
18029    initDynamicWidgetAccordianPanelDCG(mobileDynamicWidgetsContainer);
18030  }
18031}
18032
18033// =============================================================================
18034// INITIALIZATION
18035// =============================================================================
18036
18037// Initialize on DOM ready
18038document.addEventListener('DOMContentLoaded', () => {
18039  // Initialize each component instance
18040  document.querySelectorAll('.download-center-grid.component').forEach((component) => {
18041    const loader = document.querySelector('.loader-wrapper.loader');
18042    if (loader) loader.style.display = 'absolute';
18043    const noResults = document.querySelector('.no-search-results');
18044    if (noResults) noResults.style.display = 'absolute';
18045    initDownloadCenter(component);
18046  });
18047});
18048
18049$(document).ready(function(){
18050    if($('.dialogtech').length > 0) {
18051
18052        try {
18053            $('.dialogtech [id^="number"]').each(function (i, el) {
18054                const phoneNumUtility = $(this).attr("data-attribute");
18055                const dialogNumBody = $(this).attr("data-override");
18056
18057                let dialogNumHtml = phoneNumUtility || dialogNumBody;
18058
18059                mrkup = "<a href='tel:" + dialogNumHtml + "' class='number'><span class='icon-nvent-phone'></span><span class='num'>" + dialogNumHtml + "</span></a>";
18060
18061                if($(el).parent().hasClass('utility-dialogtech') === false) {
18062                    mrkup = "<a href='tel:" + dialogNumHtml + "' class='number'><span class='num'>" + dialogNumHtml + "</span></a>";
18063                }
18064                $(el).html(mrkup);
18065                setTimeout(function() {
18066                    // Required because something else is changing the value of this in form.js
18067                    $(el).html(mrkup);
18068                }, 1000);
18069                if($(el).parent().hasClass('utility-dialogtech') === true) {
18070                    $(el).parent().remove();
18071                    $('.utility-nav .utility-nav-links').append("<li class='dialogtech dialogtech-nav'>"+ mrkup +"</li>");
18072                    $('.mobile-menu .mobile-wrap .cart').before(mrkup);
18073                    $('.message-header').addClass('message-header__add-pad');
18074
18075                    if($('.bread-section .share.component').length > 0) {
18076                        $('.bread-section .share.component').addClass('hide-mobile');
18077                    }
18078                }
18079            });
18080        } catch (e) {
18081            console.log('Caught Error: ' + e);
18082        }
18083    }
18084
18085    // Mobile Chat Feature
18086    if ($('[class=message-desktop]').length > 0) {
18087        $('.message-mobi').addClass('message-mobi--50');
18088    }
18089
18090    if ($('.dialogtech-mobi').length > 0) {
18091        $('.message-mobi').addClass('message-mobi--50');
18092    }else{
18093        $('.message-mobi').removeClass('message-mobi--50');
18094    }
18095
18096    if ($('.message-mobi').length > 0) {
18097        $('.dialogtech-mobi').addClass('dialogtech-mobi--50');
18098    }else{
18099        $('.dialogtech-mobi').removeClass('dialogtech-mobi--50');
18100    }
18101
18102
18103    var dialogHeader = $('.message-header');
18104    if (dialogHeader){
18105        dialogHeader.remove;
18106        $('.utility-nav .utility-nav-links').append($('.message-header'));
18107    }
18108
18109    $('.dialogtech.utility-dialogtech').on('click', function (e) {
18110        if(!!window._satellite) {
18111            _satellite.track('dialog_tech_click');
18112        }
18113    });
18114    $('.dialogtech-nav').on('click', function (e) {
18115        if(!!window._satellite) {
18116            _satellite.track('dialog_tech_click');
18117        }
18118    });
18119});
18120
18121$(document).ready(function(){
18122    $('.curator .crt-tag').hide();
18123
18124    $('.curator').each(function() {
18125        var feed = $(this).find('div').attr('data-feed');
18126        var script = document.createElement("script");
18127        script.setAttribute("type", "text/javascript");
18128        script.setAttribute("src", "https://cdn.curator.io/published/" + feed + ".js");
18129        document.body.appendChild(script);
18130    });
18131});
18132$(document).ready(function(){
18133    function getParam(p) {
18134        var match = RegExp('[?&]' + p + '=([^&]*)').exec(window.location.search);
18135        return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
18136    }
18137
18138    // Append source value for MSA CTAs if available
18139    var source = getParam("source");
18140    if (source) {
18141        $(".btn").each(function() {
18142            if ($(this).attr("href") != null && $(this).attr("href").length > 0 && $(this).attr("href").indexOf("source=") == -1) {
18143                if ($(this).attr("href").indexOf("?") > -1) {
18144                    $(this).attr("href", $(this).attr("href") + "&source=" + source);
18145                } else {
18146                    $(this).attr("href", $(this).attr("href") + "?source=" + source);
18147                }
18148            }
18149        });
18150    }
18151    $("a.btn").click(function(e){
18152        var href = $("a.btn").attr("href");
18153        if(href && href.indexOf("/products/") !== -1){
18154            localStorage.setItem("productFindingMethod","PDPRecommendation");
18155            document.cookie="productFindingMethod=PDPRecommendation; domain=.pentair.com; path=/";
18156        }
18157    });
18158});
18159
18160// Adobe analytics, wait for the page to load before adding the listeners.
18161window.addEventListener('load', function () {
18162    var ctas = document.querySelectorAll('a[class~="btn"], button[class~="sku-add-to-cart-btn"]');
18163    for (var i = 0; i < ctas.length; i++) {
18164        ctas[i].addEventListener('click', trackCTAClick);
18165    }
18166
18167    // CTA Click event
18168    function trackCTAClick(clickEvent) {
18169        var ctaText = $(clickEvent.currentTarget).text();
18170        var analyticsEvent = $(clickEvent.currentTarget).attr("data-analytics-event");
18171        ctaText = ctaText ? ctaText.trim() : "";
18172        var eventCTAPayload = {
18173            eventName: 'cta clicked',
18174            eventType: 'event',
18175            attributes: {
18176                visitor: {
18177                    pentairCustomerID: getPentairCustomerID(), //if this is available
18178                    dealerID: getDealerID() //if this is available
18179                },
18180                page: {
18181                    pageCanonical: getPageViewPageAttribute("pageCanonical"),
18182                    pageName: getPageViewPageAttribute("pageName"),
18183                    pagePath: getPageViewPageAttribute("pagePath"),
18184                    pageType: getPageViewPageAttribute("pageType"),
18185                    pageURL: getPageViewPageAttribute("pageURL"),
18186                    pageTitle: getPageViewPageAttribute("pageTitle"),
18187                    pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
18188                    businessUnitID: getPageViewPageAttribute("businessUnitID"),
18189                    subBrand: getPageViewPageAttribute("subBrand"),
18190                    language: getPageViewPageAttribute("language"),
18191                    author: getPageViewPageAttribute("author")
18192                },
18193                cta: {
18194                    cta: ctaText
18195                }
18196            }
18197        }
18198        trackEventWithQueue(eventCTAPayload);
18199
18200        // Dropdown select analytics event
18201        if (analyticsEvent){
18202            eventname = analyticsEvent ? analyticsEvent.trim() : "";
18203            var analyticsEventPayload = {
18204                eventName: eventname,
18205                eventType: 'event',
18206                attributes: {
18207                    visitor: {
18208                        pentairCustomerID: getPentairCustomerID(), //if this is available
18209                        dealerID: getDealerID(), //if this is available
18210                        distributorID: getDistributorID() //if this is available
18211                    },
18212                    page: {
18213                        pageCanonical: getPageViewPageAttribute("pageCanonical"),
18214                        pageName: getPageViewPageAttribute("pageName"),
18215                        pagePath: getPageViewPageAttribute("pagePath"),
18216                        pageType: getPageViewPageAttribute("pageType"),
18217                        pageURL: getPageViewPageAttribute("pageURL"),
18218                        pageTitle: getPageViewPageAttribute("pageTitle"),
18219                        pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
18220                        businessUnitID: getPageViewPageAttribute("businessUnitID"),
18221                        subBrand: getPageViewPageAttribute("subBrand"),
18222                        language: getPageViewPageAttribute("language"),
18223                        author: getPageViewPageAttribute("author"),
18224                    },
18225                    product: {
18226                        skuID: self.productSku,
18227                        productName: getPageViewProductAttribute("productName"),
18228                        type: getPageViewProductAttribute("type")
18229                    }
18230                }
18231            }
18232            trackEventWithQueue(analyticsEventPayload);
18233
18234        }
18235    }
18236});
18237$(document).ready(function(){
18238    function getParam(p) {
18239        var match = RegExp('[?&]' + p + '=([^&]*)').exec(window.location.search);
18240        return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
18241    }
18242
18243    // Append source value for MSA CTAs if available
18244    var source = getParam("source");
18245    if (source) {
18246        $(".btn").each(function() {
18247            if ($(this).attr("href") != null && $(this).attr("href").length > 0 && $(this).attr("href").indexOf("source=") == -1) {
18248                if ($(this).attr("href").indexOf("?") > -1) {
18249                    $(this).attr("href", $(this).attr("href") + "&source=" + source);
18250                } else {
18251                    $(this).attr("href", $(this).attr("href") + "?source=" + source);
18252                }
18253            }
18254        });
18255    }
18256});
18257$(function() {
18258
18259    $(document).ready(function() {
18260
18261        function toggleSelectionContent(option, value) {
18262            var options = $(option).closest("select").find("option");
18263            options.each(function() {
18264                if ($(this).val() !== value) {
18265                    $(this).closest(".wrapper").find(".selection-content[data-control
18265='" + $(this).val() + "']").hide();
18266                } else {
18267                    $(this).closest(".wrapper").find(".selection-content[data-control='" + $(this).val() + "']").show();
18268                }
18269            });
18270        }
18271
18272        function toggleInitialContent(instance) {
18273            // initially show/hide content
18274            var that = instance;
18275            if (!$(that).find(".wrapper").hasClass("in-edit")) {
18276                var options = $(that).find("select > option");
18277                options.each(function() {
18278                    if (typeof $(this).attr("selected") === typeof undefined || $(this).attr("selected") === false) {
18279                        var optionValue = $(this).val();
18280                        $(this).closest(".wrapper").find(".selection-content[data-control='" + optionValue + "']").hide();
18281                    }
18282                });
18283            }
18284        }
18285
18286        function initContentSectionComponent(component) {
18287            var that = component;
18288
18289            toggleInitialContent(that);
18290
18291            // handle selection change
18292            $(that.find("select[name='selection']")).on("change", function() {
18293                toggleSelectionContent($(this), $(this).val());
18294            });
18295
18296            // handle chosen dropdown when active - hides behind page content
18297            var chosen = $(that).find(".chosen-container");
18298            $(chosen).on("mouseenter", function() {
18299                if (!$(this).hasClass("chosen-container-active")) {
18300                    $("body").toggleClass("chosen-is-active");
18301                }
18302            });
18303
18304            $(chosen).on("mouseleave",function() {
18305                if ($("body").hasClass("chosen-is-active")) {
18306                    if (!$(this).hasClass("chosen-container-active")) {
18307                        $("body").removeClass("chosen-is-active");
18308                    }
18309                }
18310            });
18311
18312            //adding select dropdown arrow for mobile/tablet views only
18313            $(that.find(".chosen-select")).each(function() {
18314                $(this).after('<span class="arrow" aria-hidden="true"></span>');
18315            });
18316
18317            $(document).on("click", function(e) {
18318                if (!$(e.target).closest(".chosen-container").length) {
18319                    if ($("body").hasClass("chosen-is-active")) {
18320                        $("body").removeClass("chosen-is-active");
18321                    }
18322                }
18323            });
18324
18325        }
18326
18327        var contentSectionComponents = $(".content-selection-container.component");
18328        if (contentSectionComponents.length) {
18329            contentSectionComponents.each(function(index, elem) {
18330                initContentSectionComponent($(elem));
18331            });
18332        }
18333    });
18334});
18335$(document).ready(function () {
18336
18337    const $tab = $('.component.contact-grid .contact-filter a');
18338    const $headerContainers = $('.component.contact-grid .contact-grid__header-container');
18339    const $gridItems = $('.component.contact-grid .contact-grid__contacts > ul > li');
18340    const $iconClose = $('.component.contact-grid .filter-wrap .icon-close');
18341    const $sortBtn = $('.component.contact-grid .btn.btn-sortby');
18342    const $sortBy = $('.component.contact-grid .filter-wrap');
18343
18344    // Add 'active' class on tab click
18345    $tab.on('click', function (e) {
18346        e.preventDefault();
18347        const $thisTab = $(this).parent();
18348        const $activeTab = $('.component.contact-grid .contact-filter li.active');
18349        const dataSort = $thisTab.attr('data-sort');
18350
18351        if (!$thisTab.hasClass('active')) {
18352            if (dataSort === 'all') {
18353                $activeTab.removeClass('active');
18354                $thisTab.addClass('active');
18355
18356                // Hide all headers...
18357                $headerContainers.hide();
18358
18359                // ... and show only heading related to the active tab
18360                $('.component.contact-grid .contact-grid__header-container[data-type= "' + dataSort + '"]').fadeIn('fast');
18361
18362                // Show All grid items
18363                $gridItems.fadeIn('fast');
18364
18365            } else {
18366                $activeTab.removeClass('active').find('a').blur();
18367                $thisTab.addClass('active');
18368
18369                // hide all headers
18370                $headerContainers.hide();
18371
18372                // Show Heading related to the active tab
18373                $('.component.contact-grid .contact-grid__header-container[data-type= "' + dataSort + '"]').fadeIn('fast');
18374
18375                // Hide all cards
18376                $gridItems.hide();
18377
18378                // Show cards related to the active tab
18379                const activeTabIndustry = $thisTab.data('sort');
18380                $gridItems.each(function () {
18381                    let industries = $(this).find('.contact-card__categories').data('type').split(',');
18382                    if (industries.includes(activeTabIndustry)) {
18383                        $(this).fadeIn('fast');
18384                    }
18385                });
18386            }
18387        }
18388
18389        // Mobile: Close filter modal on category click
18390        if ($sortBy.hasClass('open')) {
18391            closeSortby();
18392        }
18393    });
18394
18395    // Sort By modal
18396    // show/hide sort by filter MOBILE
18397
18398    $sortBtn.on('click', function (e) {
18399        e.preventDefault();
18400        if ($sortBy.hasClass('open')) {
18401            closeSortby();
18402        } else if (!$sortBy.hasClass('open')) {
18403            $sortBy.addClass('open');
18404            ensureOpenFilterZPosition()
18405            $('body').addClass('sortby-open modal-open');
18406        }
18407    });
18408
18409    $iconClose.click(function (e) {
18410        e.preventDefault();
18411        closeSortby();
18412    });
18413
18414    function closeSortby() {
18415        $('body').removeClass('sortby-open modal-open');
18416        $sortBy.removeClass('open');
18417        ensureClosedFilterZPosition()
18418    }
18419});
18420
18421$(document).ready(function(){
18422    //var cstImageCarousel = $('.carousel-side-text.component .image-carousel-wrapper .image-carousel.owl-carousel');
18423    //var cstCaptionCarousel = $('.carousel-side-text.component .caption-carousel.owl-carousel');
18424
18425
18426    function init() {
18427        $('.carousel-side-text.component').each(function(){
18428
18429            var $this = $(this);
18430
18431            $this.find('.image-carousel-wrapper .image-carousel.owl-carousel').owlCarousel({
18432                items: 1,
18433                navText: ['<span class="ico icon-angle-left" aria-hidden="true"></span><span class="sr-only">Previous</span>', '<span class="ico icon-angle-right" aria-hidden="true"></span><span class="sr-only">Next</span>'],
18434                nav: true,
18435                navContainer: $this.find('.cst-nav'),
18436                autoHeight: true,
18437                info: doTheThing(),
18438                dots: false
18439            }).trigger('refresh.owl.carousel');
18440
18441            $this.find('.caption-carousel.owl-carousel').owlCarousel({
18442                items: 1,
18443                nav: false,
18444                autoHeight: true,
18445                mouseDrag: false,
18446                touchDrag: false,
18447                dots: false
18448            }).trigger('refresh.owl.carousel');
18449
18450            $this.find('.caption-nav .cst-nav .cst-prev').click(function () {
18451                $this.find('.image-carousel.owl-carousel').trigger('prev.owl.carousel');
18452            });
18453            $this.find('.caption-nav .cst-nav .cst-next').click(function () {
18454                $this.find('.image-carousel.owl-carousel').trigger('next.owl.carousel');
18455            });
18456
18457            function doTheThing() {
18458                $this.find('.image-carousel.owl-carousel').on('initialized.owl.carousel', function(e) {
18459                    if (e.item.count >= 10) {
18460                        $this.find('.caption-nav .cst-nav .slider-counts .total-slides').text(e.item.count);
18461                    } else {
18462                        $this.find('.caption-nav .cst-nav .slider-counts .total-slides').text('0' + e.item.count);
18463                    }
18464                });
18465                $this.find('.image-carousel.owl-carousel').on('changed.owl.carousel', function(e) {
18466                    var position = e.item.index;
18467                    if (e.item.index >= 9) {
18468                        $this.find('.caption-nav .cst-nav .slider-counts .current-slide').text(position + 1);
18469                    } else {
18470                        $this.find('.caption-nav .cst-nav .slider-counts .current-slide').text('0' + (position + 1));
18471                    }
18472                    $this.find('.caption-carousel.owl-carousel').trigger('to.owl.carousel', position);
18473                });
18474            }
18475        });
18476    }
18477
18478    $(window).on('load', function() {
18479        init();
18480    });
18481
18482});
18483
18484/*******************************************************************************
18485 * Copyright 2018 Adobe
18486 *
18487 * Licensed under the Apache License, Version 2.0 (the "License");
18488 * you may not use this file except in compliance with the License.
18489 * You may obtain a copy of the License at
18490 *
18491 *     http://www.apache.org/licenses/LICENSE-2.0
18492 *
18493 * Unless required by applicable law or agreed to in writing, software
18494 * distributed under the License is distributed on an "AS IS" BASIS,
18495 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18496 * See the License for the specific language governing permissions and
18497 * limitations under the License.
18498 ******************************************************************************/
18499(function() {
18500    "use strict";
18501
18502    var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined;
18503    if (!containerUtils) {
18504        // eslint-disable-next-line no-console
18505        console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page.");
18506    }
18507    var dataLayerEnabled;
18508    var dataLayer;
18509
18510    var NS = "cmp";
18511    var IS = "carousel";
18512
18513    var keyCodes = {
18514        SPACE: 32,
18515        END: 35,
18516        HOME: 36,
18517        ARROW_LEFT: 37,
18518        ARROW_UP: 38,
18519        ARROW_RIGHT: 39,
18520        ARROW_DOWN: 40
18521    };
18522
18523    var selectors = {
18524        self: "[data-" + NS + '-is="' + IS + '"]'
18525    };
18526
18527    var properties = {
18528        /**
18529         * Determines whether the Carousel will automatically transition between slides
18530         *
18531         * @memberof Carousel
18532         * @type {Boolean}
18533         * @default false
18534         */
18535        "autoplay": {
18536            "default": false,
18537            "transform": function(value) {
18538                return !(value === null || typeof value === "undefined");
18539            }
18540        },
18541        /**
18542         * Duration (in milliseconds) before automatically transitioning to the next slide
18543         *
18544         * @memberof Carousel
18545         * @type {Number}
18546         * @default 5000
18547         */
18548        "delay": {
18549            "default": 5000,
18550            "transform": function(value) {
18551                value = parseFloat(value);
18552                return !isNaN(value) ? value : null;
18553            }
18554        },
18555        /**
18556         * Determines whether automatic pause on hovering the carousel is disabled
18557         *
18558         * @memberof Carousel
18559         * @type {Boolean}
18560         * @default false
18561         */
18562        "autopauseDisabled": {
18563            "default": false,
18564            "transform": function(value) {
18565                return !(value === null || typeof value === "undefined");
18566            }
18567        }
18568    };
18569
18570    /**
18571     * Carousel Configuration
18572     *
18573     * @typedef {Object} CarouselConfig Represents a Carousel configuration
18574     * @property {HTMLElement} element The HTMLElement representing the Carousel
18575     * @property {*[]} options The Carousel options
18576     */
18577
18578    /**
18579     * Carousel
18580     *
18581     * @class Carousel
18582     * @classdesc An interactive Carousel component for navigating a list of generic items
18583     * @param {CarouselConfig} config The Carousel configuration
18584     */
18585    function Carousel(config) {
18586        var that = this;
18587
18588        if (config && config.element) {
18589            init(config);
18590        }
18591
18592        /**
18593         * Initializes the Carousel
18594         *
18595         * @private
18596         * @param {CarouselConfig} config The Carousel configuration
18597         */
18598        function init(config) {
18599            that._config = config;
18600
18601            // prevents multiple initialization
18602            config.element.removeAttribute("data-" + NS + "-is");
18603
18604            setupProperties(config.options);
18605            cacheElements(config.element);
18606
18607            that._active = 0;
18608            that._paused = false;
18609
18610            if (that._elements.item) {
18611                initializeActive();
18612                bindEvents();
18613                resetAutoplayInterval();
18614                refreshPlayPauseActions();
18615                scrollToDeepLinkIdInCarousel();
18616            }
18617
18618            // TODO: This section is only relevant in edit mode and should move to the editor clientLib
18619            if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
18620                /*
18621                 * Editor message handling:
18622                 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
18623                 * - check that the message data panel container type is correct and that the id (path) matches this specific Carousel component
18624                 * - if so, route the "navigate" operation to enact a navigation of the Carousel based on index data
18625                 */
18626                window.CQ = window.CQ || {};
18627                window.CQ.CoreComponents = window.CQ.CoreComponents || {};
18628                window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
18629                window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) {
18630                    if (message.data && message.data.type === "cmp-carousel" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) {
18631                        if (message.data.operation === "navigate") {
18632                            navigate(message.data.index);
18633                        }
18634                    }
18635                });
18636            }
18637        }
18638
18639        /**
18640         * Displays the slide containing the element that corresponds to the deep link in the URI fragment
18641         * and scrolls the browser to this element.
18642         */
18643        function scrollToDeepLinkIdInCarousel() {
18644            if (containerUtils) {
18645                var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "item", "item");
18646                if (deepLinkItemIdx > -1) {
18647                    var deepLinkItem = that._elements["item"][deepLinkItemIdx];
18648                    if (deepLinkItem && that._elements["item"][that._active].id !== deepLinkItem.id) {
18649                        navigateAndFocusIndicator(deepLinkItemIdx, true);
18650                        // pause the carousel auto-rotation
18651                        pause();
18652                    }
18653                    var hashId = window.location.hash.substring(1);
18654                    if (hashId) {
18655                        var hashItem = document.querySelector("[id='" + hashId + "']");
18656                        if (hashItem) {
18657                            hashItem.scrollIntoView();
18658                        }
18659                    }
18660                }
18661            }
18662        }
18663
18664        /**
18665         * Caches the Carousel elements as defined via the {@code data-carousel-hook="ELEMENT_NAME"} markup API
18666         *
18667         * @private
18668         * @param {HTMLElement} wrapper The Carousel wrapper element
18669         */
18670        function cacheElements(wrapper) {
18671            that._elements = {};
18672            that._elements.self = wrapper;
18673            var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]");
18674
18675            for (var i = 0; i < hooks.length; i++) {
18676                var hook = hooks[i];
18677                var capitalized = IS;
18678                capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
18679                var key = hook.dataset[NS + "Hook" + capitalized];
18680                if (that._elements[key]) {
18681                    if (!Array.isArray(that._elements[key])) {
18682                        var tmp = that._elements[key];
18683                        that._elements[key] = [tmp];
18684                    }
18685                    that._elements[key].push(hook);
18686                } else {
18687                    that._elements[key] = hook;
18688                }
18689            }
18690        }
18691
18692        /**
18693         * Sets up properties for the Carousel based on the passed options.
18694         *
18695         * @private
18696         * @param {Object} options The Carousel options
18697         */
18698        function setupProperties(options) {
18699            that._properties = {};
18700
18701            for (var key in properties) {
18702                if (Object.prototype.hasOwnProperty.call(properties, key)) {
18703                    var property = properties[key];
18704                    var value = null;
18705
18706                    if (options && options[key] != null) {
18707                        value = options[key];
18708
18709                        // transform the provided option
18710                        if (property && typeof property.transform === "function") {
18711                            value = property.transform(value);
18712                        }
18713                    }
18714
18715                    if (value === null) {
18716                        // value still null, take the property default
18717                        value = properties[key]["default"];
18718                    }
18719
18720                    that._properties[key] = value;
18721                }
18722            }
18723        }
18724
18725        /**
18726         * Binds Carousel event handling
18727         *
18728         * @private
18729         */
18730        function bindEvents() {
18731            window.addEventListener("hashchange", scrollToDeepLinkIdInCarousel, false);
18732            if (that._elements["previous"]) {
18733                that._elements["previous"].addEventListener("click", function() {
18734                    var index = getPreviousIndex();
18735                    navigate(index);
18736                    if (dataLayerEnabled) {
18737                        dataLayer.push({
18738                            event: "cmp:show",
18739                            eventInfo: {
18740                                path: "component." + getDataLayerId(that._elements.item[index])
18741                            }
18742                        });
18743                    }
18744                });
18745            }
18746
18747            if (that._elements["next"]) {
18748                that._elements["next"].addEventListener("click", function() {
18749                    var index = getNextIndex();
18750                    navigate(index);
18751                    if (dataLayerEnabled) {
18752                        dataLayer.push({
18753                            event: "cmp:show",
18754                            eventInfo: {
18755                                path: "component." + getDataLayerId(that._elements.item[index])
18756                            }
18757                        });
18758                    }
18759                });
18760            }
18761
18762            var indicators = that._elements["indicator"];
18763            if (indicators) {
18764                for (var i = 0; i < indicators.length; i++) {
18765                    (function(index) {
18766                        indicators[i].addEventListener("click", function(event) {
18767                            navigateAndFocusIndicator(index);
18768                            // pause the carousel auto-rotation
18769                            pause();
18770                        });
18771                    })(i);
18772                }
18773            }
18774
18775            if (that._elements["pause"]) {
18776                if (that._properties.autoplay) {
18777                    that._elements["pause"].addEventListener("click", onPauseClick);
18778                }
18779            }
18780
18781            if (that._elements["play"]) {
18782                if (that._properties.autoplay) {
18783                    that._elements["play"].addEventListener("click", onPlayClick);
18784                }
18785            }
18786
18787            that._elements.self.addEventListener("keydown", onKeyDown);
18788
18789            if (!that._properties.autopauseDisabled) {
18790                that._elements.self.addEventListener("mouseenter", onMouseEnter);
18791                that._elements.self.addEventListener("mouseleave", onMouseLeave);
18792            }
18793
18794            // for accessibility we pause animation when a element get focused
18795            var items = that._elements["item"];
18796            if (items) {
18797                for (var j = 0; j < items.length; j++) {
18798                    items[j].addEventListener("focusin", onMouseEnter);
18799                    items[j].addEventListener("focusout", onMouseLeave);
18800                }
18801            }
18802        }
18803
18804        /**
18805         * Handles carousel keydown events
18806         *
18807         * @private
18808         * @param {Object} event The keydown event
18809         */
18810        function onKeyDown(event) {
18811            var index = that._active;
18812            var lastIndex = that._elements["indicator"].length - 1;
18813
18814            switch (event.keyCode) {
18815                case keyCodes.ARROW_LEFT:
18816                case keyCodes.ARROW_UP:
18817                    event.preventDefault();
18818                    if (index > 0) {
18819                        navigateAndFocusIndicator(index - 1);
18820                    }
18821                    break;
18822                case keyCodes.ARROW_RIGHT:
18823                case keyCodes.ARROW_DOWN:
18824                    event.preventDefault();
18825                    if (index < lastIndex) {
18826                        navigateAndFocusIndicator(index + 1);
18827                    }
18828                    break;
18829                case keyCodes.HOME:
18830                    event.preventDefault();
18831                    navigateAndFocusIndicator(0);
18832                    break;
18833                case keyCodes.END:
18834                    event.preventDefault();
18835                    navigateAndFocusIndicator(lastIndex);
18836                    break;
18837                case keyCodes.SPACE:
18838                    if (that._properties.autoplay && (event.target !== that._elements["previous"] && event.target !== that._elements["next"])) {
18839                        event.preventDefault();
18840                        if (!that._paused) {
18841                            pause();
18842                        } else {
18843                            play();
18844                        }
18845                    }
18846                    if (event.target === that._elements["pause"]) {
18847                        that._elements["play"].focus();
18848                    }
18849                    if (event.target === that._elements["play"]) {
18850                        that._elements["pause"].focus();
18851                    }
18852                    break;
18853                default:
18854                    return;
18855            }
18856        }
18857
18858        /**
18859         * Handles carousel mouseenter events
18860         *
18861         * @private
18862         * @param {Object} event The mouseenter event
18863         */
18864        function onMouseEnter(event) {
18865            clearAutoplayInterval();
18866        }
18867
18868        /**
18869         * Handles carousel mouseleave events
18870         *
18871         * @private
18872         * @param {Object} event The mouseleave event
18873         */
18874        function onMouseLeave(event) {
18875            resetAutoplayInterval();
18876        }
18877
18878        /**
18879         * Handles pause element click events
18880         *
18881         * @private
18882         * @param {Object} event The click event
18883         */
18884        function onPauseClick(event) {
18885            pause();
18886            that._elements["play"].focus();
18887        }
18888
18889        /**
18890         * Handles play element click events
18891         *
18892         * @private
18893         * @param {Object} event The click event
18894         */
18895        function onPlayClick() {
18896            play();
18897            that._elements["pause"].focus();
18898        }
18899
18900        /**
18901         * Pauses the playing of the Carousel. Sets {@code Carousel#_paused} marker.
18902         * Only relevant when autoplay is enabled
18903         *
18904         * @private
18905         */
18906        function pause() {
18907            that._paused = true;
18908            clearAutoplayInterval();
18909            refreshPlayPauseActions();
18910        }
18911
18912        /**
18913         * Enables the playing of the Carousel. Sets {@code Carousel#_paused} marker.
18914         * Only relevant when autoplay is enabled
18915         *
18916         * @private
18917         */
18918        function play() {
18919            that._paused = false;
18920
18921            // If the Carousel is hovered, don't begin auto transitioning until the next mouse leave event
18922            var hovered = false;
18923            if (that._elements.self.parentElement) {
18924                hovered = that._elements.self.parentElement.querySelector(":hover") === that._elements.self;
18925            }
18926            if (that._properties.autopauseDisabled || !hovered) {
18927                resetAutoplayInterval();
18928            }
18929
18930            refreshPlayPauseActions();
18931        }
18932
18933        /**
18934         * Refreshes the play/pause action markup based on the {@code Carousel#_paused} state
18935         *
18936         * @private
18937         */
18938        function refreshPlayPauseActions() {
18939            setActionDisabled(that._elements["pause"], that._paused);
18940            setActionDisabled(that._elements["play"], !that._paused);
18941        }
18942
18943        /**
18944         * Initialize {@code Carousel#_active} based on the active item of the carousel.
18945         */
18946        function initializeActive() {
18947            var items = that._elements["item"];
18948            if (items && Array.isArray(items)) {
18949                for (var i = 0; i < items.length; i++) {
18950                    if (items[i].classList.contains("cmp-carousel__item--active")) {
18951                        that._active = i;
18952                        break;
18953                    }
18954                }
18955            }
18956        }
18957
18958        /**
18959         * Refreshes the item markup based on the current {@code Carousel#_active} index
18960         *
18961         * @private
18962         */
18963        function refreshActive() {
18964            var items = that._elements["item"];
18965            var indicators = that._elements["indicator"];
18966
18967            if (items) {
18968                if (Array.isArray(items)) {
18969                    for (var i = 0; i < items.length; i++) {
18970                        if (i === parseInt(that._active)) {
18971                            items[i].classList.add("cmp-carousel__item--active");
18972                            items[i].removeAttribute("aria-hidden");
18973                            indicators[i].classList.add("cmp-carousel__indicator--active");
18974                            indicators[i].setAttribute("aria-selected", true);
18975                            indicators[i].setAttribute("tabindex", "0");
18976                        } else {
18977                            items[i].classList.remove("cmp-carousel__item--active");
18978                            items[i].setAttribute("aria-hidden", true);
18979                            indicators[i].classList.remove("cmp-carousel__indicator--active");
18980                            indicators[i].setAttribute("aria-selected", false);
18981                            indicators[i].setAttribute("tabindex", "-1");
18982                        }
18983                    }
18984                } else {
18985                    // only one item
18986                    items.classList.add("cmp-carousel__item--active");
18987                    indicators.classList.add("cmp-carousel__indicator--active");
18988                }
18989            }
18990        }
18991
18992        /**
18993         * Focuses the element and prevents scrolling the element into view
18994         *
18995         * @param {HTMLElement} element Element to focus
18996         */
18997        function focusWithoutScroll(element) {
18998            var x = window.scrollX || window.pageXOffset;
18999            var y = window.scrollY || window.pageYOffset;
19000            element.focus();
19001            window.scrollTo(x, y);
19002        }
19003
19004        /**
19005         * Retrieves the next active index, with looping
19006         *
19007         * @private
19008         * @returns {Number} Index of the next carousel item
19009         */
19010        function getNextIndex() {
19011            return that._active === (that._elements["item"].length - 1) ? 0 : that._active + 1;
19012        }
19013
19014        /**
19015         * Retrieves the previous active index, with looping
19016         *
19017         * @private
19018         * @returns {Number} Index of the previous carousel item
19019         */
19020        function getPreviousIndex() {
19021            return that._active === 0 ? (that._elements["item"].length - 1) : that._active - 1;
19022        }
19023
19024        /**
19025         * Navigates to the item at the provided index
19026         *
19027         * @private
19028         * @param {Number} index The index of the item to navigate to
19029         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
19030         */
19031        function navigate(index, keepHash) {
19032            if (index < 0 || index > (that._elements["item"].length - 1)) {
19033                return;
19034            }
19035
19036            that._active = index;
19037            refreshActive();
19038
19039            keepHash = true;// CUSTOM: Set keepHash to true so that carousel ID doesn't appear in url
19040
19041            if (!keepHash && containerUtils) {
19042                containerUtils.updateUrlHash(that, "item", index);
19043            }
19044
19045            if (dataLayerEnabled) {
19046                var carouselId = that._elements.self.id;
19047                var activeItem = getDataLayerId(that._elements.item[index]);
19048                var updatePayload = { component: {} };
19049                updatePayload.component[carouselId] = { shownItems: [activeItem] };
19050
19051                var removePayload = { component: {} };
19052                removePayload.component[carouselId] = { shownItems: undefined };
19053
19054                dataLayer.push(removePayload);
19055                dataLayer.push(updatePayload);
19056            }
19057
19058            // reset the autoplay transition interval following navigation, if not already hovering the carousel
19059            if (that._elements.self.parentElement) {
19060                if (that._elements.self.parentElement.querySelector(":hover") !== that._elements.self) {
19061                    resetAutoplayInterval();
19062                }
19063            }
19064        }
19065
19066        /**
19067         * Navigates to the item at the provided index and ensures the active indicator gains focus
19068         *
19069         * @private
19070         * @param {Number} index The index of the item to navigate to
19071         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
19072         */
19073        function navigateAndFocusIndicator(index, keepHash) {
19074            navigate(index, keepHash);
19075            focusWithoutScroll(that._elements["indicator"][index]);
19076
19077            if (dataLayerEnabled) {
19078                dataLayer.push({
19079                    event: "cmp:show",
19080                    eventInfo: {
19081                        path: "component." + getDataLayerId(that._elements.item[index])
19082                    }
19083                });
19084            }
19085        }
19086
19087        /**
19088         * Starts/resets automatic slide transition interval
19089         *
19090         * @private
19091         */
19092        function resetAutoplayInterval() {
19093            if (that._paused || !that._properties.autoplay) {
19094                return;
19095            }
19096            clearAutoplayInterval();
19097            that._autoplayIntervalId = window.setInterval(function() {
19098                if (document.visibilityState && document.hidden) {
19099                    return;
19100                }
19101                var indicators = that._elements["indicators"];
19102                if (indicators !== document.activeElement && indicators.contains(document.activeElement)) {
19103                    // if an indicator has focus, ensure we switch focus following navigation
19104                    navigateAndFocusIndicator(getNextIndex(), true);
19105                } else {
19106                    navigate(getNextIndex(), true);
19107                }
19108            }, that._properties.delay);
19109        }
19110
19111        /**
19112         * Clears/pauses automatic slide transition interval
19113         *
19114         * @private
19115         */
19116        function clearAutoplayInterval() {
19117            window.clearInterval(that._autoplayIntervalId);
19118            that._autoplayIntervalId = null;
19119        }
19120
19121        /**
19122         * Sets the disabled state for an action and toggles the appropriate CSS classes
19123         *
19124         * @private
19125         * @param {HTMLElement} action Action to disable
19126         * @param {Boolean} [disable] {@code true} to disable, {@code false} to enable
19127         */
19128        function setActionDisabled(action, disable) {
19129            if (!action) {
19130                return;
19131            }
19132            if (disable !== false) {
19133                action.disabled = true;
19134                action.classList.add("cmp-carousel__action--disabled");
19135            } else {
19136                action.disabled = false;
19137                action.classList.remove("cmp-carousel__action--disabled");
19138            }
19139        }
19140    }
19141
19142    /**
19143     * Parses the dataLayer string and returns the ID
19144     *
19145     * @private
19146     * @param {HTMLElement} item the accordion item
19147     * @returns {String} dataLayerId or undefined
19148     */
19149    function getDataLayerId(item) {
19150        if (item) {
19151            if (item.dataset.cmpDataLayer) {
19152                return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0];
19153            } else {
19154                return item.id;
19155            }
19156        }
19157        return null;
19158    }
19159
19160    /**
19161     * Document ready handler and DOM mutation observers. Initializes Carousel components as necessary.
19162     *
19163     * @private
19164     */
19165    function onDocumentReady() {
19166        dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled");
19167        dataLayer = (dataLayerEnabled) ? window.adobeDataLayer = window.adobeDataLayer || [] : undefined;
19168
19169        var elements = document.querySelectorAll(selectors.self);
19170        for (var i = 0; i < elements.length; i++) {
19171            new Carousel({ element: elements[i], options: CMP.utils.readData(elements[i], IS) });
19172        }
19173
19174        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
19175        var body = document.querySelector("body");
19176        var observer = new MutationObserver(function(mutations) {
19177            mutations.forEach(function(mutation) {
19178                // needed for IE
19179                var nodesArray = [].slice.call(mutation.addedNodes);
19180                if (nodesArray.length > 0) {
19181                    nodesArray.forEach(function(addedNode) {
19182                        if (addedNode.querySelectorAll) {
19183                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
19184                            elementsArray.forEach(function(element) {
19185                                new Carousel({ element: element, options: CMP.utils.readData(element, IS) });
19186                            });
19187                        }
19188                    });
19189                }
19190            });
19191        });
19192
19193        observer.observe(body, {
19194            subtree: true,
19195            childList: true,
19196            characterData: true
19197        });
19198    }
19199
19200    var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) {
19201        document.addEventListener("DOMContentLoaded", resolve);
19202    });
19203    Promise.all([documentReady]).then(onDocumentReady);
19204
19205    if (containerUtils) {
19206        window.addEventListener("load", containerUtils.scrollToAnchor, false);
19207    }
19208
19209}());
19210
19211jQuery(window).on('load', function() {
19212
19213
19214    let touchstartX = 0
19215    let touchendX = 0
19216
19217    function checkDirection() {
19218        if (touchendX < touchstartX) jQuery('.cmp-carousel__action.cmp-carousel__action--next').trigger('click');
19219        if (touchendX > touchstartX) jQuery('.cmp-carousel__action.cmp-carousel__action--previous').trigger('click');
19220    }
19221
19222    document.addEventListener('touchstart', e => {
19223        touchstartX = e.changedTouches[0].screenX
19224    })
19225
19226    document.addEventListener('touchend', e => {
19227        touchendX = e.changedTouches[0].screenX
19228        checkDirection()
19229    })
19230	if (jQuery('.cmp-carousel__item').length < 2) {
19231    	jQuery('.cmp-carousel__actions').hide();
19232     	jQuery('.cmp-carousel__indicators').hide();
19233	}
19234})
19235$(document).ready(function(){
19236
19237    var initImageCarousel = function(carouselComponent){
19238        var carousel = carouselComponent.find('.owl-carousel');
19239        var totalSlides = carousel.find('.image.parbase').length;
19240        var currentSlide = 0;
19241
19242        if(totalSlides < 2){
19243            carouselComponent.find('.owl-custom-nav').hide();
19244        }
19245
19246        var addLeadingZero = function (numString) {
19247            return (parseInt(numString, 10) < 10) ? '0' + numString : numString;
19248        };
19249
19250        var update = function(){
19251            setTimeout(function(){
19252                var activeDot = carousel.find('.owl-dot.active');
19253                currentSlide = carousel.find('.owl-dot').index(activeDot) + 1;
19254                carouselComponent.find('.owl-custom-nav .current').text(addLeadingZero(currentSlide));
19255            }, 10);
19256        };
19257
19258        carouselComponent.find('.owl-custom-nav .total').text(addLeadingZero(totalSlides));
19259
19260        carousel.on('initialized.owl.carousel changed.owl.carousel resized.owl.carousel', function(e) {   
19261            update();
19262        });
19263
19264        carouselComponent.find('.owl-custom-nav .owl-next').on('click', function (e) {
19265            carousel.trigger('next.owl.carousel');
19266        });
19267
19268        carouselComponent.find('.owl-custom-nav .owl-prev').on('click', function (e) {
19269            carousel.trigger('prev.owl.carousel');
19270        });
19271
19272        carousel.owlCarousel({
19273            loop: true,
19274            margin: 10,
19275            center: true,
19276            singleItem: true,
19277            animateIn: 'fadeIn',
19278            animateOut: 'fadeOut',
19279            mouseDrag: false,
19280            dots: true,
19281            responsive:{
19282                0:{
19283                    items: 1
19284                }
19285            }
19286        });
19287
19288        update();
19289    };
19290
19291    var carouselComponents = $('.component.carousel');
19292
19293    if(carouselComponents.length){
19294        var mode = carouselComponents.first().data('isedit');
19295        if (mode === 'noedit') {
19296            $(function(){
19297                carouselComponents.each(function(index, elem){
19298                    initImageCarousel($(elem));
19299                });
19300            });
19301        }
19302    }
19303
19304
19305    //Check statistics
19306    carouselComponents.find('.statistic').each(function(){
19307        var $this = $(this);
19308        var theString = $this.text();
19309        var count = $this.text().replace(/ /g,'').length;
19310
19311        //wrap special characters
19312        if(/^[a-zA-Z0-9- ]*$/.test(theString) == false) {
19313            $this.addClass('symbol-wrap');
19314        }
19315        if ($this.is(':contains("$")')){
19316            //wrap cents, if any
19317            var price = $this.text();
19318            if ($this.is(':contains(".")')){
19319                var priceTokens = price.split('.');
19320                price = priceTokens[0] +
19321                    '<span class="cents">.' + priceTokens[1] + '</span>';
19322                $this.html(price);
19323            }
19324
19325            //wrap symbol
19326            $this.html(function(_, html) {
19327                return html.replace(/(\$)/g, '<span class="symbol">$</span>');
19328            });
19329        //wrap percent
19330        } else if ($this.is(':contains("%")')){
19331            $this.html(function(_, html) {
19332                return html.replace(/(%)/g, '<span class="symbol">%</span>');
19333            });
19334        }
19335
19336        if (count === 2){
19337            $this.addClass('count-2');
19338        } else if (count === 3){
19339            $this.addClass('count-3');
19340        } else if (count === 4){
19341            $this.addClass('count-4');
19342        } else if (count === 5){
19343            $this.addClass('count-5');
19344        } else if (count === 6){
19345            $this.addClass('count-6');
19346        }
19347    });
19348
19349});
19350$(document).ready(function(){
19351
19352    //CATEGORY ICONS
19353    $('.component.brand-grid .categories').each(function(){
19354        var $this = $(this);
19355        var tags = [];
19356        var theTags = $(this).attr('data-type');
19357        if (theTags != null){
19358            theTags = theTags.split(",");
19359            for(var i = 0 , len = theTags.length; i < len; i++){
19360                tags.push(theTags[i]);
19361            }
19362            $.each(tags, function( i, l ){
19363                $this.append('<span class="icon-'+ tags[i] +'"><span class="sr-only">'+ tags[i] +' category</span></span>');
19364            });
19365        }
19366    });
19367
19368
19369    //BRAND MODAL
19370    var theLogo, theImage, theContent;
19371    $('.component.brand-grid .brands .brand-open').on('click', function(e){
19372        var $this = $(this).closest('li');
19373        theLogo = $this.find('.brand-logo').html();
19374        theImage = $this.find('.brand-modal-content .image').html();
19375        theContent = $this.find('.brand-modal-content .content').html();
19376    });
19377    $('#brandModal').on('show.bs.modal', function (e) {
19378        $(this).find('.image').html('').append(theImage);
19379        $(this).find('.brand-logo').html('').append(theLogo);
19380        $(this).find('.details').html('').append(theContent);
19381    })
19382
19383
19384    //SORTING
19385    //gets initial types of sortable items based on the data values on the brand grid items
19386    var types = [];
19387    allSort();
19388    function allSort(){
19389        $('.component.brand-grid .brands .categories').each(function() {
19390            var theType = $(this).attr('data-type');
19391            if (theType != null) {
19392                theType = theType.split(",");
19393                for (var i = 0, len = theType.length; i < len; i++) {
19394                    if ($.inArray(theType[i], types) == -1) {
19395                        types.push(theType[i]);
19396                    }
19397                }
19398            }
19399        });
19400    }
19401
19402    //add Active Class on click
19403    $('.component.brand-grid .brand-filter a').on('click', function(e){
19404        e.preventDefault();
19405        var $this = $(this).parent();
19406        var dataSort = $this.attr('data-sort');
19407        if (dataSort == 'all'){
19408            $('.component.brand-grid .brand-filter li.active').removeClass('active');
19409            $this.addClass('active');
19410            sortGrid(dataSort, true);
19411        } else{
19412            if ($this.hasClass('active')){
19413                $this.removeClass('active').find('a').blur();
19414                sortGrid(dataSort, false);
19415            } else{
19416                $('.component.brand-grid .brand-filter li:first-child').removeClass('active');
19417                $this.addClass('active');
19418                sortGrid(dataSort, true);
19419            }
19420        }
19421    });
19422
19423
19424    var emptied = false;
19425    function sortGrid(sort, adding){
19426        if (adding){
19427            if (sort == 'all'){
19428                allSort();
19429                emptied = false;
19430            } else{
19431                if (!emptied){
19432                    types = [];
19433                    emptied = true;
19434                }
19435                types.push(sort);
19436            }
19437        } else if (!adding){
19438            types.splice($.inArray(sort, types),1);
19439        }
19440
19441        //sort and hide elements not in type array
19442        $('.component.brand-grid .brands .categories').each(function() {
19443            var theType = $(this).attr('data-type');
19444            if (theType != null) {
19445                theType = theType.split(",");
19446                var show = false;
19447                for (var i = 0, len = theType.length; i < len; i++) {
19448                    if ($.inArray(theType[i], types) !== -1) {
19449                        show = true;
19450                    }
19451                }
19452                if (show) {
19453                    $(this).closest('li').fadeIn('fast');
19454                } else {
19455                    $(this).closest('li').fadeOut('fast');
19456                }
19457            }
19458        });
19459    }
19460
19461
19462    //SORT BY MODAL
19463    //show/hide sort by filter MOBILE
19464    var sortBtn = $(".component.brand-grid .btn.btn-sortby");
19465    var sortby = $(".component.brand-grid .filter-wrap");
19466    sortBtn.on('click', function(e){
19467        e.preventDefault();
19468        if (sortby.hasClass('open')){
19469            closeSortby();
19470        } else if (!sortby.hasClass('open')){
19471            sortby.addClass('open');
19472            ensureOpenFilterZPosition()
19473            $('body').addClass('sortby-open modal-open');
19474        }
19475
19476    });
19477    $('.component.brand-grid .filter-wrap .icon-close').click(function(e){
19478        e.preventDefault();
19479        closeSortby();
19480    });
19481
19482    function closeSortby(){
19483        $('body').removeClass('sortby-open modal-open');
19484        sortby.removeClass('open');
19485        ensureClosedFilterZPosition()
19486    }
19487
19488});
19489
19490/**
19491 * Shared factory for Algolia article / news listing components.
19492 * Returns an initializeArticleComponent function for initializing a single component element.
19493 *
19494 * Config:
19495 *   wrapperClass        {string}    CSS class of the component wrapper (used to find .sorting container)
19496 *   emptyHitsText       {string}    Prefix for empty hits message (default 'No results')
19497 *   mobileSortFromModal {boolean}   Source .sorting from #articleListingFilterModal on mobile (default false)
19498 *   buildSortItems      {Function}  (indexName) => [{value, label}]
19499 *   renderHit           {Function}  (indexName, hit, { html, components }) => html
19500 *   sortItemsClientSide {Function}  optional (items, activeSortIndex) => items
19501 *   addFilterWidgets    {Function}  ({ search, indexName, containerElem, areFiltersEnabled,
19502 *                                      isMobileView, preFilters, handleFilterChange }) => void
19503 */
19504/* Start - Article Link Click Analytics */
19505function resultItemAnalyticsHandler(event) {
19506    const item = event.target.closest('.result-item');
19507    if (!item) return;
19508    if (typeof _satellite !== 'undefined' && _satellite != null) {
19509        _satellite.track('articleResultClick', {
19510            articleLinkName: item.querySelector('.title')?.textContent,
19511            articleType: item.closest('.results')?.dataset.type,
19512            articlePosition: item.dataset.position
19513        });
19514    }
19515}
19516/* End - Article Link Click Analytics */
19517
19518function createArticleListing(config) {
19519    const {
19520        wrapperClass,
19521        emptyHitsText = 'No results',
19522        mobileSortFromModal = false,
19523        buildSortItems,
19524        renderHit,
19525        sortItemsClientSide,
19526        addFilterWidgets
19527    } = config;
19528
19529    // Constants
19530    const INITIALIZED_STATE = 'true';
19531    const REFINEMENT_UPDATE_DELAY = 100;
19532    const MIN_ITEMS_FOR_NAV = 2;
19533    const FILTER_PANEL_ANIMATION_MS = 200;
19534
19535    function isMobileView() {
19536        return window.matchMedia?.('(max-width: 767px)').matches;
19537    }
19538
19539    // ====================================
19540    // SHARED EVENT HANDLERS (Factory scope - reused across all component instances)
19541    // ====================================
19542
19543    function togglePanelBody(panelBody, shouldOpen) {
19544        panelBody.getAnimations().forEach(animation => animation.cancel());
19545        panelBody.style.overflow = 'hidden';
19546
19547        if (shouldOpen) {
19548            panelBody.style.display = 'block';
19549            const targetHeight = panelBody.scrollHeight;
19550            panelBody.style.height = '0px';
19551            const animation = panelBody.animate(
19552                [{ height: '0px' }, { height: `${targetHeight}px` }],
19553                { duration: FILTER_PANEL_ANIMATION_MS, easing: 'ease-out' }
19554            );
19555            animation.onfinish = () => {
19556                panelBody.style.height = '';
19557                panelBody.style.overflow = '';
19558            };
19559            return;
19560        }
19561
19562        const currentHeight = panelBody.scrollHeight;
19563        panelBody.style.height = `${currentHeight}px`;
19564        const animation = panelBody.animate(
19565            [{ height: `${currentHeight}px` }, { height: '0px' }],
19566            { duration: FILTER_PANEL_ANIMATION_MS, easing: 'ease-in' }
19567        );
19568        animation.onfinish = () => {
19569            panelBody.style.display = 'none';
19570            panelBody.style.height = '';
19571            panelBody.style.overflow = '';
19572        };
19573    }
19574
19575    function handleOpenFilter(event) {
19576        const headerClick = event.target.closest('.ais-Panel-header');
19577        if (!headerClick) return;
19578        const panel = event.currentTarget.closest('.ais-Panel');
19579        const panelBody = panel.querySelector('.ais-Panel-body');
19580        if (panelBody) {
19581            togglePanelBody(panelBody, panel.classList.contains('ais-Panel--collapsed'));
19582        }
19583    }
19584
19585    function initDynamicWidgetAccordionPanel(filterContainer) {
19586        filterContainer.querySelectorAll('div[class*=ais-DynamicWidgets-widget]').forEach(elem => {
19587            const observer = new MutationObserver(() => {
19588                elem.querySelectorAll('.ais-Panel-header').forEach(panelHeader => {
19589                    panelHeader.addEventListener('click', handleOpenFilter);
19590                });
19591                elem.querySelectorAll('.ais-Panel-body').forEach(panelBody => {
19592                    panelBody.addEventListener('keydown', (e) => {
19593                        if (e.key === 'Enter') {
19594                            e.preventDefault();
19595                        }
19596                    })
19597                });
19598                if (isMobileView()) {
19599                    elem.querySelectorAll('.ais-Panel-body').forEach(el => el.style.display = 'none');
19600                }
19601                observer.disconnect();
19602            });
19603            observer.observe(elem, { childList: true });
19604        });
19605    }
19606
19607    return function initializeArticleComponent(componentElement) {
19608        if (componentElement.dataset.algoliaListingInitialized === INITIALIZED_STATE) {
19609            return;
19610        }
19611        componentElement.dataset.algoliaListingInitialized = INITIALIZED_STATE;
19612
19613        const applicationId = componentElement.dataset.applicationId;
19614        const searchApiKey = componentElement.dataset.searchApiKey;
19615        const index = componentElement.querySelector('.index')?.dataset.index;
19616        const preFilters = componentElement.dataset.preFilters ? JSON.parse(componentElement.dataset.preFilters) : {};
19617        const areFiltersEnabled = !componentElement.querySelector('.articles-container')?.classList.contains('hide-filters');
19618        const isDynamic = componentElement.querySelector('.articles')?.classList.contains('dynamic');
19619
19620        // ====================================
19621        // COMPONENT EVENT HANDLERS
19622        // ====================================
19623
19624        /* Start - Article Filter Click Analytics */
19625        function handleFilterClick(event) {
19626            const articleType = event.target.closest('.articles-container')?.querySelector('.results')?.dataset.type;
19627            const refinementList = event.target.closest('.ais-RefinementList-list');
19628            const refinementsForm = event.target.closest('form');
19629            setTimeout(() => {
19630                const refinementListItems = refinementsForm?.querySelectorAll('.ais-RefinementList-item--selected');
19631                updateArticleFilterAnalytics(articleType, refinementList, refinementListItems);
19632            }, REFINEMENT_UPDATE_DELAY);
19633        }
19634
19635        function handleFilterChange() {
19636            if (!isMobileView()) return true;
19637            const owl = componentElement.querySelector('.owl-carousel');
19638            if (!owl) return false;
19639            const items = componentElement.querySelectorAll('.owl-carousel > .ais-Hits-item');
19640            const owlItems = owl.querySelectorAll('.owl-item');
19641            for (let i = 0; i < items.length; i++) {
19642                if (!items[i].classList.contains('item')) items[i].classList.add('item');
19643                if (owlItems[i]) owlItems[i].appendChild(items[i]);
19644            }
19645            const numItems = items.length - 1;
19646            owlItems.forEach((el, i) => { if (i > numItems) el.remove(); });
19647            owl.querySelectorAll('.owl-dot').forEach((el, i) => {
19648                if (i > numItems) el.remove();
19649            });
19650            if (numItems < MIN_ITEMS_FOR_NAV) owl.querySelector('.owl-nav > .owl-next')?.classList.add('disabled');
19651            return true;
19652        }
19653
19654        function updateArticleFilterAnalytics(articleType, list, listItems) {
19655            if (!listItems) return;
19656            const data = {};
19657            for (const item of listItems) {
19658                const filterTypeEl = item.closest('.filter-container');
19659                const filterTypeSplit = filterTypeEl.className.split(' ');
19660                const filterType = filterTypeSplit[0].charAt(0).toUpperCase() + filterTypeSplit[0].slice(1);
19661                const filterData = item.querySelector('label > span:first-child').textContent;
19662                if (filterType in data) {
19663                    data[filterType].push(filterData);
19664                } else {
19665                    data[filterType] = [filterData];
19666                }
19667            }
19668            try {
19669                if (!digitalData?.event) return;
19670                digitalData.event.eventName = 'article filter';
19671                digitalData.event.eventAction = 'click';
19672                digitalData.event.type = 'filter';
19673                digitalData.event.timeStamp = new Date();
19674                let filterStr = '';
19675                for (const key in data) {
19676                    for (const value of data[key]) {
19677                        filterStr += `By ${key}:${value}|`;
19678                    }
19679                }
19680                componentElement.querySelector('.filters .current-refinements')?.querySelectorAll('button').forEach(btn => {
19681                        if (btn.dataset.attribute === 'eventCategories') {
19682                            filterStr += `By Category:${btn.dataset.value}|`;
19683                        }
19684                    });
19685                digitalData.article = { type: articleType, filterValues: filterStr.slice(0, -1) };
19686            } catch (err) {
19687                console.log(err);
19688            }
19689        }
19690        /* End - Article Filter Click Analytics */
19691
19692        function setupMobileCarousel() {
19693            if (!isMobileView()) return;
19694            const owl = componentElement.querySelector('.articles');
19695            const carousel = owl?.querySelector('.ais-Hits-list');
19696            const results = owl?.querySelector('.results');
19697            const options = owl?.dataset.options;
19698            if (options) {
19699                options['navText'] = [
19700                    "<span class='icon-chevron-left'></span>",
19701                    "<span class='icon-chevron-right'></span>"
19702                ];
19703            }
19704            results?.querySelectorAll('.ais-Hits-item').forEach(item => item.classList.add('item'));
19705            if (!carousel || (owl?.dataset.view !== 'none' && owl?.dataset.view !== 'load-more')) return;
19706            if (!carousel.classList.contains('owl-carousel')) carousel.classList.add('owl-carousel');
19707            if (!options) return;
19708            carousel.owlCarousel(options);
19709        }
19710
19711        function initMobileFilters() {
19712            const modalElement = document.getElementById('articleListingFilterModal');
19713            if (!modalElement) return;
19714
19715            modalElement.querySelectorAll('.ais-DynamicWidgets-widget').forEach(elem => {
19716                const observer = new MutationObserver(() => {
19717                    elem.querySelectorAll('.ais-Panel-header').forEach(panelHeader => {
19718                        panelHeader.addEventListener('click', handleOpenFilter);
19719                    });
19720                    elem.querySelectorAll('.ais-Panel-body').forEach(panelBody => {
19721                        panelBody.addEventListener('keydown', (e) => {
19722                            if (e.key === 'Enter') {
19723                                e.preventDefault();
19724                            }
19725                        })
19726                    });
19727                    observer.disconnect();
19728                });
19729                observer.observe(elem, { childList: true });
19730            });
19731
19732            modalElement.addEventListener('click', event => {
19733                if (!event.target.closest('.algolia-filter-container')) return;
19734                if (event.target.closest('.ais-RefinementList-item')) handleFilterClick(event);
19735            });
19736            modalElement.querySelectorAll('.ais-Panel-body').forEach(el => el.style.display = 'none');
19737        }
19738
19739        if (isDynamic) {
19740            const initAlgolia = function(indexName, containerElem) {
19741                const searchClient = window.algoliasearch.algoliasearch(applicationId, searchApiKey);
19742                const pageLoadFacetFilters = [];
19743                if (preFilters?.bneCategories?.name && preFilters.bneCategories.prefilter) {
19744                    preFilters.bneCategories.name.split(',').forEach(name => pageLoadFacetFilters.push(`categoriesTitles:${name}`));
19745                } else if (preFilters?.categories?.name && preFilters.categories.prefilter) {
19746                    preFilters.categories.name.split(',').forEach(name => pageLoadFacetFilters.push(`categoryTitles:${name}`));
19747                }
19748                const articlesElement = containerElem.querySelector('.articles');
19749                const maxHitsPerPage = articlesElement?.dataset.hitsPerPage;
19750                const defaultSorting = articlesElement?.dataset.defaultSorting || '';
19751                const defaultSortIndex = `${indexName}${defaultSorting}`;
19752                const sortingContainer = (mobileSortFromModal && isMobileView())
19753                    ? document.querySelector('#articleListingFilterModal .sorting')
19754                    : containerElem.closest(`.${wrapperClass}`)?.querySelector('.sorting');
19755                let currentSortIndex = defaultSortIndex;
19756                const instantSearchInstance = window.instantsearch({ indexName, searchClient, insights: true });
19757
19758                instantSearchInstance.addWidgets([
19759                    instantsearch.widgets.hits({
19760                        container: containerElem.querySelector('.results'),
19761                        transformItems: (items) => {
19762                            const activeSortIndex = instantSearchInstance.helper?.state?.index || currentSortIndex;
19763                            if (typeof sortItemsClientSide === 'function') {
19764                                return sortItemsClientSide(items, activeSortIndex);
19765                            }
19766                            return items;
19767                        },
19768                        templates: {
19769                            item: (hit, { html, components }) => renderHit(indexName, hit, { html, components }),
19770                            empty: ({ query }, { html }) => html`${emptyHitsText}${query ? html` for "${query}"` : ''}`
19771                        },
19772                        cssClasses: {
19773                            root: 'owl-wrapper',
19774                            list: ['owl-carousel', 'owl-theme']
19775                        }
19776                    }),
19777                    instantsearch.widgets.pagination({
19778                        container: containerElem.closest('.articles-content')?.querySelector('.pagination .paging'),
19779                        showFirst: false,
19780                        showLast: false,
19781                        padding: 1,
19782                        templates: { next: '', previous: '' },
19783                        cssClasses: {
19784                            selectedItem: 'selected',
19785                            root: 'wrapper-list light-theme',
19786                            list: 'pagination-count',
19787                            item: 'pagination-item'
19788                        },
19789                        scrollTo: '#articleListing'
19790                    }),
19791                    instantsearch.widgets.stats({
19792                        container: containerElem.closest('.articles-content')?.querySelector('.hitsCount'),
19793                        templates: {
19794                            text: (result) => {
19795                                const first = parseInt(result.hitsPerPage, 10) * parseInt(result.page, 10) + 1;
19796                                const last = Math.min(first - 1 + parseInt(result.hitsPerPage, 10), result.nbHits);
19797                                return result.nbHits > 1 ? `Showing ${first}-${last} of ${result.nbHits} results` : '';
19798                            }
19799                        }
19800                    }),
19801                    instantsearch.widgets.sortBy({
19802                        container: sortingContainer,
19803                        items: buildSortItems(indexName)
19804                    }),
19805                    instantsearch.widgets.configure({
19806                        index: defaultSortIndex,
19807                        hitsPerPage: maxHitsPerPage,
19808                        facetFilters: [pageLoadFacetFilters]
19809                    })
19810                ]);
19811
19812                sortingContainer?.addEventListener('change', event => {
19813                    const target = event.target;
19814                    if (target?.classList?.contains('ais-SortBy-select')) {
19815                        const sortIndex = target.value;
19816                        const nextSortIndex = sortIndex || defaultSortIndex;
19817                        currentSortIndex = nextSortIndex;
19818                        if (instantSearchInstance.helper?.state?.index !== nextSortIndex) {
19819                            instantSearchInstance.helper?.setIndex(nextSortIndex).search();
19820                        }
19821                    }
19822                });
19823
19824                addFilterWidgets({ search: instantSearchInstance, indexName, containerElem, areFiltersEnabled, isMobileView, preFilters, handleFilterChange });
19825
19826                // Wire up the "Show More" button without a second configure widget,
19827                // which would conflict with sortBy by overriding the search state on each render.
19828                let currentHitsPerPage = Number.parseInt(maxHitsPerPage, 10);
19829                const infiniteHitsContainer = containerElem.closest('.articles-content')?.querySelector('.infiniteHits');
19830                if (infiniteHitsContainer) {
19831                    const button = document.createElement('button');
19832                    const span = document.createElement('span');
19833                    button.classList.add('btn', 'btn-primary');
19834                    span.textContent = 'Show More Results';
19835                    button.appendChild(span);
19836                    infiniteHitsContainer.appendChild(button);
19837                    button.addEventListener('click', () => {
19838                        currentHitsPerPage += Number.parseInt(maxHitsPerPage, 10);
19839                        instantSearchInstance.helper?.setQueryParameter('hitsPerPage', currentHitsPerPage).search();
19840                    });
19841                }
19842
19843                instantSearchInstance.on('error', ({ error }) => {
19844                    console.error('Algolia article listing search error', {
19845                        index: instantSearchInstance.helper?.state?.index,
19846                        message: error?.message
19847                    });
19848                });
19849
19850                instantSearchInstance.on('render', () => setupMobileCarousel());
19851                instantSearchInstance.start();
19852            };
19853
19854            const setupAlgoliaSearchInstance = function() {
19855                initAlgolia(index, componentElement.querySelector('.articles-container'));
19856                initMobileFilters();
19857                const filterContainer = (mobileSortFromModal && isMobileView())
19858                    ? document.querySelector('#articleListingFilterModal .algolia-filter-container')
19859                    : componentElement.querySelector('.algolia-filter-container');
19860                if (filterContainer) initDynamicWidgetAccordionPanel(filterContainer);
19861
19862                componentElement.addEventListener('click', resultItemAnalyticsHandler);
19863            };
19864
19865            setupAlgoliaSearchInstance();
19866
19867            document.querySelector('#articleListingFilterModal .see-results')
19868                ?.addEventListener('click', event => {
19869                    event.currentTarget.closest('figure')?.querySelector('.icon-close')?.click();
19870                });
19871        } else {
19872            setupMobileCarousel();
19873        }
19874
19875        componentElement.querySelector('.filter-btn')?.addEventListener('click', () => {
19876                document.body.classList.add('article-modal-open');
19877            });
19878
19879        const nextModal = componentElement.nextElementSibling?.matches('.modal')
19880            ? componentElement.nextElementSibling : null;
19881        nextModal?.querySelector('.icon-close')
19882            ?.addEventListener('click', () => {
19883                document.body.classList.remove('article-modal-open');
19884            });
19885    };
19886}
19887
19888(function () {
19889    'use strict';
19890
19891    window.PENTAIR = window.PENTAIR || {};
19892
19893    // ========================================
19894    // SORT ITEMS
19895    // ========================================
19896
19897    function buildSortItems(indexName) {
19898        let items = [
19899            { value: indexName, label: 'Sort by Relevance' },
19900            { value: `${indexName}_sort_date_dsc`, label: 'Newest to Oldest' },
19901            { value: `${indexName}_sort_date_asc`, label: 'Oldest to Newest' },
19902            { value: `${indexName}_sort_alpha_asc`, label: 'A-Z' },
19903            { value: `${indexName}_sort_alpha_dsc`, label: 'Z-A' }
19904        ];
19905        if (indexName.includes('pentair_education')) {
19906            items = items.filter(item => !item.value.includes('_sort_date'));
19907        }
19908        if (indexName.includes('pentair_education') || indexName.includes('pentair_blog')) {
19909            items.push({ value: `${indexName}_sort_pageviews_dsc`, label: 'Most Popular' });
19910        }
19911        return items;
19912    }
19913
19914    // ========================================
19915    // HIT TEMPLATES
19916    // ========================================
19917
19918    function renderHit(indexName, hit, { html, components }) {
19919        if (indexName.includes('mypentair_blog')) {
19920            const blogImage = hit.blogImage ? html`<div class="top-image cover"><img loading="lazy" src="${hit.blogImage}.thumb.319.319.png" alt="${hit.blogImageAltText}"/><span class="triangle"></span></div>` : '';
19921            const authorImg = hit.fileReference ? html`<div class="author-img-wrapper"><img loading="lazy" class="author-img" src="${hit.fileReference}.thumb.48.48.png" alt="Image of Author"/></div>` : '';
19922            const description = hit.description ? html`<div class="content">${components.Snippet({ attribute: 'description', highlightedTagName: 'mark', hit })}</div>` : '';
19923            return html`<a class="result-item" href="${hit.pagePath}" data-position="${hit.__position}">
19924                ${blogImage}
19925                <div class="content-padding">
19926                    <div class="info">
19927                        <div class="category">${hit.categoriesTitles[0] || ''}</div>
19928                        <div class="date">${hit.displayDate || ''}</div>
19929                    </div>
19930                    <div class="title title-text">${components.Highlight({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
19931                    ${description}
19932                    <div class="flex-row left mb-2">${authorImg}<div class="author-name">${hit.authorName}</div></div>
19933                    <span class="arrow"></span>
19934                </div>
19935            </a>`;
19936        } else if (indexName.includes('pentair_blog')) {
19937            const bneImg = hit.bneImgPath ? html`<div class="top-image cover"><img loading="lazy" src="${hit.bneImgPath}.thumb.319.319.png" alt="Article Image"/><span class="triangle"></span></div>` : '';
19938            const authorImg = hit.bneAuthorImage ? html`<div class="author-img-wrapper"><img loading="lazy" class="author-img" src="${hit.bneAuthorImage}.thumb.48.48.png" alt="Image of Author"/></div>` : '';
19939            const bneDesc = hit.bneDesc ? html`<div class="content">${components.Snippet({ attribute: 'bneDesc', highlightedTagName: 'mark', hit })}</div>` : '';
19940            return html`<a class="result-item" href="${hit.bnePagePath}" data-position="${hit.__position}">
19941                ${bneImg}
19942                <div class="content-padding">
19943                    <div class="info">
19944                        <div class="category">${hit.categoriesTitles[0] || ''}</div>
19945                        <div class="date">${hit.bneDate || ''}</div>
19946                    </div>
19947                    <div class="title title-text">${components.Highlight({ attribute: 'bneTitle', highlightedTagName: 'mark', hit })}</div>
19948                    ${bneDesc}
19949                    <div class="flex-row left mb-2">${authorImg}<div class="author-name">${hit.bneAuthorNm}</div></div>
19950                    <span class="arrow"></span>
19951                </div>
19952            </a>`;
19953        } else if (indexName.includes('mypentair_news')) {
19954            const description = hit.description ? html`<div class="content">${components.Snippet({ attribute: 'description', highlightedTagName: 'mark', hit })}</div>` : '';
19955            return html`<a class="result-item" href="${hit.pagePath}.html" data-position="${hit.__position}">
19956                <div class="content-padding">
19957                    <div class="info"><div class="date">${hit.displayDate || ''}</div></div>
19958                    <div class="title title-text">${components.Highlight({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
19959                    ${description}
19960                </div>
19961            </a>`;
19962        } else if (indexName.includes('pentair_news')) {
19963            const description = hit.description ? html`<div class="content">${components.Snippet({ attribute: 'description', highlightedTagName: 'mark', hit })}</div>` : '';
19964            return html`<a class="result-item" href="${hit.pagePath}.html" data-position="${hit.__position}">
19965                <div class="content-padding">
19966                    <div class="info"><div class="date">${hit.displayDate}</div></div>
19967                    <div class="title title-text">${components.Highlight({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
19968                    ${description}
19969                </div>
19970            </a>`;
19971        } else if (indexName.includes('mypentair_external_news') || indexName.includes('pentair_external_news')) {
19972            const description = hit.description ? html`<div class="content">${components.Snippet({ attribute: 'description', highlightedTagName: 'mark', hit })}</div>` : '';
19973            return html`<a class="result-item" href="${hit.externalSourceUrl}.html" data-position="${hit.__position}" target="_blank" rel="noopener noreferrer">
19974                <div class="content-padding">
19975                    <div class="info"><div class="date">${hit.displayDate || ''}</div></div>
19976                    <div class="title title-text">${components.Highlight({ attribute: 'jcrTitle', highlightedTagName: 'mark', hit })}</div>
19977                    ${description}
19978                </div>
19979            </a>`;
19980        } else if (indexName.includes('pentair_events')) {
19981            const eventDescription = hit.eventDescription ? html`<div class="content">${components.Snippet({ attribute: 'eventDescription', highlightedTagName: 'mark', hit })}</div>` : '';
19982            return html`<a class="result-item" href="${hit.eventPagePath}" data-position="${hit.__position}">
19983                <div class="content-padding">
19984                    <div class="top">
19985                        <div class="date title-text">${hit.prettyDateRange || ''}</div>
19986                        <div class="info"><div>${hit.eventLocation}</div></div>
19987                    </div>
19988                    <div class="bottom">
19989                        <div class="title title-text">${components.Highlight({ attribute: 'eventTitle', highlightedTagName: 'mark', hit })}</div>
19990                        ${eventDescription}
19991                    </div>
19992                </div>
19993            </a>`;
19994        } else if (indexName.includes('press')) {
19995            const shortDescription = hit.shortDescription ? html`<div class="content">${components.Snippet({ attribute: 'shortDescription', highlightedTagName: 'mark', hit })}</div>` : '';
19996            return html`<a class="result-item" href="${hit.investorLink}" data-position="${hit.__position}">
19997                <div class="content-padding">
19998                    <div class="top"><div class="date title-text">${hit.date || ''}</div></div>
19999                    <div class="bottom">
20000                        <div class="title title-text">${components.Highlight({ attribute: 'title', highlightedTagName: 'mark', hit })}</div>
20001                        ${shortDescription}
20002                    </div>
20003                </div>
20004            </a>`;
20005        } else if (indexName.includes('pentair_education')) {
20006            const articleImage = hit.articleImage ? html`<div class="top-image cover"><img loading="lazy" src="${hit.articleImage}.thumb.319.319.png" alt="Article Image"/><span class="triangle"></span></div>` : '';
20007            const description = hit.description ? html`<div class="content">${components.Snippet({ attribute: 'description', highlightedTagName: 'mark', hit })}</div>` : '';
20008            const title = hit.educationTitle
20009                ? components.Highlight({ attribute: 'educationTitle', highlightedTagName: 'mark', hit })
20010                : components.Highlight({ attribute: 'jcrTitle', highlightedTagName: 'mark', hit });
20011            return html`<a class="result-item" href="${hit.pagePath}.html" data-position="${hit.__position}">
20012                ${articleImage}
20013                <div class="content-padding">
20014                    <div class="title title-text">${title}</div>
20015                    ${description}
20016                    <span class="arrow"></span>
20017                </div>
20018            </a>`;
20019        }
20020    }
20021
20022    // ========================================
20023    // FILTER WIDGETS
20024    // ========================================
20025
20026    function addFilterWidgets({ search, indexName, containerElem, areFiltersEnabled, isMobileView, preFilters, handleFilterChange }) {
20027        if (!areFiltersEnabled) return;
20028        const modalFilter = document.getElementById('articleListingFilterModal');
20029
20030        const triggerHandleFilterChangeForRefinedItems = items => {
20031            if (items.some(item => item.isRefined)) {
20032                handleFilterChange();
20033            }
20034            return items;
20035        };
20036
20037        const splitPipeLabel = label => {
20038            const labelText = String(label || '');
20039            const splitLabel = labelText.split('|')[1];
20040            return splitLabel || labelText;
20041        };
20042
20043        const splitPipeLabelsAndHandleRefinedItems = items => {
20044            const transformedItems = items.map(item => {
20045                const splitLabel = splitPipeLabel(item.label);
20046                return { ...item, label: splitLabel, highlighted: splitLabel }; // default refinementList template renders `highlighted`, keep it in sync with `label`
20047            });
20048            return triggerHandleFilterChangeForRefinedItems(transformedItems);
20049        };
20050
20051        if (indexName.includes('mypentair_blog')) {
20052            search.addWidgets([
20053                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Authors', 'authorName')({
20054                    container: isMobileView() ? modalFilter?.querySelector('.filter-container.author') : containerElem.querySelector('.filter-container.author'),
20055                    attribute: 'authorName',
20056                    transformItems: triggerHandleFilterChangeForRefinedItems
20057                }),
20058                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'dateFilter')({
20059                    container: isMobileView() ? modalFilter?.querySelector('.filter-container.date') : containerElem.querySelector('.filter-container.date'),
20060                    attribute: 'dateFilter',
20061                    transformItems: triggerHandleFilterChangeForRefinedItems
20062                }),
20063                instantsearch.widgets.clearRefinements({
20064                    container: modalFilter?.querySelector('.clear-refinements'),
20065                    templates: { resetLabel: 'Clear Filters' }
20066                })
20067            ]);
20068        } else if (indexName.includes('mypentair_news') || indexName.includes('mypentair_external_news') || indexName.includes('pentair_external_news')) {
20069            search.addWidgets([
20070                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'dateFilter')({
20071                    container: isMobileView() ? modalFilter?.querySelector('.filter-container.date') : containerElem.querySelector('.filter-container.date'),
20072                    attribute: 'dateFilter',
20073                    transformItems: triggerHandleFilterChangeForRefinedItems
20074                }),
20075                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Type', 'type')({
20076                    container: isMobileView() ? modalFilter?.querySelector('.filter-container.type') : containerElem.querySelector('.filter-container.type'),
20077                    attribute: 'type',
20078                    transformItems: splitPipeLabelsAndHandleRefinedItems
20079                })
20080            ]);
20081        } else if (indexName.includes('pentair_blog')) {
20082            const customWidgets = [
20083                container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Authors', 'bneAuthorNm')({ container, attribute: 'bneAuthorNm', transformItems: triggerHandleFilterChangeForRefinedItems }),
20084                container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Date', 'filterDate')({ container, attribute: 'filterDate', transformItems: triggerHandleFilterChangeForRefinedItems })
20085            ];
20086            if (!(preFilters['bneCategories'] && preFilters['bneCategories'].name && preFilters['bneCategories'].prefilter)) {
20087                customWidgets.push(container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Categories', 'categoriesTitles')({ container, attribute: 'categoriesTitles', transformItems: triggerHandleFilterChangeForRefinedItems }));
20088            }
20089            search.addWidgets([
20090                instantsearch.widgets.dynamicWidgets({
20091                    container: isMobileView() ? modalFilter?.querySelector('.filter-container') : containerElem.querySelector('.filter-container'),
20092                    widgets: customWidgets
20093                }),
20094                instantsearch.widgets.clearRefinements({
20095                    container: modalFilter?.querySelector('.clear-refinements'),
20096                    templates: { resetLabel: 'Clear Filters' }
20097                })
20098            ]);
20099        } else if (indexName.includes('pentair_events')) {
20100            search.addWidgets([
20101                PENTAIR.CustomAlgoliaWidgets.clearRefinements()({ container: containerElem.querySelector('.filters .clear-refinements') }),
20102                PENTAIR.CustomAlgoliaWidgets.currentRefinements()({ container: containerElem.querySelector('.filters .current-refinements') }),
20103                PENTAIR.CustomAlgoliaWidgets.hierarchicalMenu()({
20104                    container: containerElem.querySelector('.filters .categories'),
20105                    limit: 5,
20106                    sortBy: ['count:desc'],
20107                    attributes: ['eventCategories']
20108                }),
20109                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Date', 'bneDateFacet')({
20110                    container: containerElem.querySelector('.filters .date'),
20111                    attribute: 'bneDateFacet',
20112                    transformItems: triggerHandleFilterChangeForRefinedItems
20113                }),
20114                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Region', 'region')({
20115                    container: containerElem.querySelector('.filters .region'),
20116                    attribute: 'region',
20117                    transformItems: splitPipeLabelsAndHandleRefinedItems
20118                }),
20119                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Brands', 'brands')({
20120                    container: containerElem.querySelector('.filters .brand'),
20121                    attribute: 'brands',
20122                    transformItems: splitPipeLabelsAndHandleRefinedItems
20123                }),
20124                PENTAIR.CustomAlgoliaWidgets.accordionFilterPanel('Event Type', 'type')({
20125                    container: containerElem.querySelector('.filters .event-type'),
20126                    attribute: 'type',
20127                    transformItems: splitPipeLabelsAndHandleRefinedItems
20128                })
20129            ]);
20130        } else if (indexName.includes('pentair_education')) {
20131            const customWidgets = [
20132                container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Audience', 'audience')({ container, attribute: 'audie
20132nce', transformItems: splitPipeLabelsAndHandleRefinedItems }),
20133                container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Channel', 'channel')({ container, attribute: 'channel', transformItems: splitPipeLabelsAndHandleRefinedItems }),
20134                container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Type', 'type')({ container, attribute: 'type', transformItems: splitPipeLabelsAndHandleRefinedItems })
20135            ];
20136            if (!(preFilters['categories'] && preFilters['categories'].name && preFilters['categories'].prefilter)) {
20137                customWidgets.push(container => PENTAIR.CustomAlgoliaWidgets.dynamicAccordionFilterPanel('Categories', 'categoryTitles')({
20138                    container,
20139                    attribute: 'categoryTitles',
20140                    transformItems: triggerHandleFilterChangeForRefinedItems
20141                }));
20142            }
20143            search.addWidgets([
20144                instantsearch.widgets.dynamicWidgets({
20145                    container: isMobileView() ? modalFilter?.querySelector('.algolia-filter-container.dynamic-widgets') : containerElem.querySelector('.algolia-filter-container.dynamic-widgets'),
20146                    widgets: customWidgets
20147                }),
20148                instantsearch.widgets.clearRefinements({
20149                    container: modalFilter?.querySelector('.clear-refinements'),
20150                    templates: { resetLabel: 'Clear Filters' }
20151                })
20152            ]);
20153        }
20154    }
20155
20156    // ========================================
20157    // INITIALIZATION
20158    // ========================================
20159
20160    // Expose factory for use by other components (e.g., IFT news-article-listing)
20161    window.PENTAIR.createArticleListing = createArticleListing;
20162
20163    const defaultArticleListingInitializer = createArticleListing({
20164        wrapperClass: 'article-listing-algolia',
20165        emptyHitsText: 'No blog results',
20166        mobileSortFromModal: true,
20167        buildSortItems,
20168        renderHit,
20169        addFilterWidgets
20170    });
20171
20172    document.addEventListener('DOMContentLoaded', () => {
20173        document.querySelectorAll('.article-listing.component').forEach(elem => {
20174            try {
20175                defaultArticleListingInitializer(elem);
20176            } catch (e) {
20177                console.log(e);
20178            }
20179        });
20180    });
20181
20182})();
20183
20184$(document).ready(function(){
20185
20186    var NewsListingPagination = function(elem, setEqualHeight) {
20187        var self = this,
20188            $newsListingContainer = $(elem),
20189            $newsContainer = $(elem).find('.news-container'),
20190            $pagination = $newsListingContainer.find('.pagination .wrapper-list'),
20191            $newsList = $newsListingContainer.find('.news-list'),
20192            $loadMoreBtn = $newsListingContainer.find('.load-more-btn > a'),
20193            urlToFecthFrom = $newsContainer.attr('data-current-resource') + '.pagination.',
20194            maxPagDiplay = 3,
20195            showPerPage = +$newsContainer.attr('data-news-records-per-page'),
20196            totalResultCount = +$newsContainer.attr('data-news-total-count'),
20197            $fromIndex = $newsListingContainer.find('.current-list .from'),
20198            $toIndex = $newsListingContainer.find('.current-list .to'),
20199            $loadMoreBtn = $newsListingContainer.find('.load-more-btn a'),
20200            isMobile = window.matchMedia('(max-width: 767px)').matches,
20201            currentPage = 0,
20202            tempPageIndex = 0,
20203            totalPages = Math.ceil(totalResultCount/showPerPage);
20204
20205        self.getNewPageNews = function(pageInd, loop) {
20206            if ( !$newsList.length ) {
20207                return;
20208            }
20209
20210            $.ajax({
20211                type: 'GET',
20212                async: false,
20213                url: urlToFecthFrom + ( pageInd || 0 ) +'.html',
20214                success: function(data) {
20215                    console.log("URL: " + urlToFecthFrom + ( pageInd || 0 ) +'.html');
20216                    if ( isMobile ) {
20217                        $newsContainer.find('.news-list-wrapper').append($('<div />').html(data).find('.news-list')[0].innerHTML);
20218                    } else {
20219                        $newsList.html(data);
20220                        if ( $pagination.pagination('getCurrentPage') != currentPage + 1 ) {
20221                            $pagination.pagination('drawPage', currentPage + 1);
20222                            self.setPageAck(currentPage + 1);
20223                        }
20224                    }
20225
20226                    if ( setEqualHeight ) {
20227                        $(document).trigger('adjustInternalNewsHeights');
20228                    }
20229                },
20230                error: function(err) {
20231                    // failed from some reason.
20232                },
20233                complete: function(){
20234                    if ( loop && currentPage > 0 && tempPageIndex !== currentPage ) {
20235                        tempPageIndex += 1;
20236                        self.getNewPageNews(tempPageIndex, true);
20237                    } else {
20238                        tempPageIndex = 0;
20239                        if ( currentPage == totalPages - 1 ) {
20240                            $loadMoreBtn.hide();
20241                        }
20242                    }
20243                }
20244            });
20245        }
20246
20247        self.bindPagination = function(){
20248            if ( !$pagination.length ) {
20249                return;
20250            }
20251
20252            $pagination.pagination({
20253                items: totalResultCount,
20254                displayedPages: maxPagDiplay,
20255                itemsOnPage: showPerPage,
20256                edges: 0,
20257                ellipsePageSet: false,
20258                hrefTextPrefix: '#',
20259                onPageClick: function(pageInd){
20260                    currentPage = pageInd - 1
20261                    self.getNewPageNews(currentPage);
20262                    self.setPageAck(pageInd);
20263                    $('html, body').stop().animate({
20264                        scrollTop: $newsListingContainer.offset().top - 70
20265                    }, 500);
20266                }
20267            });
20268        }
20269
20270        self.setPageAck = function( pageNum ){
20271            var start = pageNum ? ( ( pageNum - 1 )* showPerPage ) : 0,
20272                count = totalResultCount,
20273                end = Math.min(start + showPerPage, count);
20274
20275            $fromIndex.text(start + 1);
20276            $toIndex.text( end );
20277        }
20278
20279        self.bindEvents = function(){
20280            $loadMoreBtn.on('click', function(e){
20281                e.preventDefault();
20282                $(this).blur();
20283                currentPage += 1;
20284                self.getNewPageNews(currentPage);
20285
20286                if ( currentPage == totalPages - 1 ) {
20287                    $loadMoreBtn.hide();
20288                }
20289            });
20290
20291            $(window).on('resize', function(){
20292                var newIsMobile = window.matchMedia('(max-width: 767px)').matches;
20293                $newsList.html('');
20294
20295                if ( isMobile === false && newIsMobile ) {
20296                    isMobile = newIsMobile;
20297                    self.getNewPageNews(0, true);
20298                } else {
20299                    isMobile = newIsMobile;
20300                    self.getNewPageNews(currentPage);
20301                }
20302            });
20303        }
20304
20305        self.init = function(){
20306            self.bindPagination();
20307            self.setPageAck();
20308            self.bindEvents();
20309        }
20310
20311        self.init();
20312    }
20313
20314
20315    $('.news-listing').each(function(){
20316        new NewsListingPagination(this, true);
20317    });
20318});
20319var PENTAIR = PENTAIR || {};
20320
20321PENTAIR.InitAccordion = function() {
20322    $('.accordion.section .accordion dt.active').next('dd').stop().slideDown('fast');
20323
20324    var addLeadingZero = function(numString) {
20325        return (parseInt(numString, 10) < 10) ? '0' + numString : numString;
20326    };
20327
20328    // Accessibility helpers
20329    const setAriaState = ($headerEl, expanded) => {
20330        const $panelEl = $headerEl.next('dd');
20331        $headerEl.attr('aria-expanded', !!expanded);
20332        $panelEl.attr('aria-hidden', !expanded);
20333    };
20334
20335    var accordionGroupIndex = 1;
20336
20337    $('.accordion.section').each(function(index, elem) {
20338        accordionGroupIndex = $(elem).prev().is('.accordion.section') ? accordionGroupIndex + 1 : 1;
20339        $(elem).find('.number').text(addLeadingZero(accordionGroupIndex));
20340    });
20341
20342    // Keyboard Accessibility
20343    (function initA11y() {
20344        let idCounter = 0;
20345        var $headers = $('.accordion.section .accordion dt');
20346
20347        $headers.each(function() {
20348            idCounter += 1;
20349            const $headerEl = $(this);
20350            const $panelEl = $headerEl.next('dd');
20351
20352            // Make header focusable
20353            $headerEl.attr('role', 'button').attr('tabindex', '0');
20354
20355            if (!$headerEl.attr('id')) $headerEl.attr('id', 'acc-header-' + idCounter);
20356            if (!$panelEl.attr('id')) $panelEl.attr('id', 'acc-panel-' + idCounter);
20357
20358            $headerEl.attr('aria-controls', $panelEl.attr('id'));
20359            $panelEl.attr('role', 'region').attr('aria-labelledby', $headerEl.attr('id'));
20360
20361            const isExpanded = $headerEl.hasClass('active');
20362            setAriaState($headerEl, isExpanded);
20363        });
20364
20365        // Keyboard interactions
20366        $headers.on('keydown', function(e) {
20367            const $current = $(this);
20368
20369            const keyHandlers = {
20370                Enter: () => { e.preventDefault(); $current.trigger('click'); },
20371                Space: () => { e.preventDefault(); $current.trigger('click'); }
20372            };
20373
20374            // Normalize key across browsers
20375            const normalizeKey = (evt) => {
20376                if (typeof evt.key === 'string') {
20377                    if (evt.key === ' ' || evt.key === 'Spacebar') return 'Space';
20378                    if (evt.key === 'Enter') return 'Enter';
20379                    return undefined;
20380                }
20381            };
20382
20383            const evnt = normalizeKey(e);
20384            if (evnt && keyHandlers[evnt]) return keyHandlers[evnt]();
20385        });
20386    })();
20387
20388    $('.accordion.section .accordion dt').on('click', function() {
20389        var $this = $(this);
20390        var siblingAccordions = $this.parents('.accordion.section').first().nextUntil(':not(.accordion.section)'); // Used to clear all immediate sibling accordions.
20391        var jumpNav = $('.sticky-jump-nav');
20392        var jumpNavHeight = jumpNav.length ? jumpNav.outerHeight() : 0;
20393
20394        siblingAccordions = siblingAccordions.add($this.parents('.accordion.section').first().prevUntil(':not(.accordion.section)'));
20395
20396        if ($this.hasClass('active')) {
20397            $this.removeClass('active').next('dd').stop().slideUp('fast', function() {
20398                $('.owl-carousel').trigger('refresh.owl.carousel'); //fires to correct heights of tabs when accordion is embedded within
20399            });
20400            setAriaState($this, false);
20401        } else {
20402            $this.addClass('active').next('dd').stop().slideDown('fast', function() {
20403                $('.owl-carousel').trigger('refresh.owl.carousel'); //fires to correct heights of tabs when accordion is embedded within
20404            });
20405            setAriaState($this, true);
20406            // Close siblings and update ARIA
20407            siblingAccordions.find('dt').each(function() {
20408                var $hdr = $(this);
20409                $hdr.removeClass('active').next('dd').stop().slideUp('fast');
20410                setAriaState($hdr, false);
20411            });
20412        }
20413        setTimeout(function() {
20414            $('html, body').animate({
20415                scrollTop: Number($this.offset().top - $('header').outerHeight() - jumpNavHeight) + "px"
20416            }, 250);
20417        }, 250);
20418    });
20419};
20420
20421$(document).ready(function() {
20422    PENTAIR.InitAccordion();
20423});
20424
20425$(document).ready(function(){
20426    function getParam(p) {
20427        var match = RegExp('[?&]' + p + '=([^&]*)').exec(window.location.search);
20428        return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
20429    }
20430
20431    // Append source value for MSA CTAs if available
20432    var source = getParam("source");
20433    if (source) {
20434        $(".btn").each(function() {
20435            if ($(this).attr("href") != null && $(this).attr("href").length > 0 && $(this).attr("href").indexOf("source=") == -1) {
20436                if ($(this).attr("href").indexOf("?") > -1) {
20437                    $(this).attr("href", $(this).attr("href") + "&source=" + source);
20438                } else {
20439                    $(this).attr("href", $(this).attr("href") + "?source=" + source);
20440                }
20441            }
20442        });
20443    }
20444});
20445$(document).ready(function () {
20446  $('.pnt-part-number').each(function (index, element) {
20447    let inputContainer = $(element).find('.pnt-part-number__input');
20448    let searchResultContainer = $(element).find('.pnt-part-number__search-results');
20449    let noresultContainer = $(element).find('.pnt-part-number__input-noresult');
20450    let inputSection = inputContainer.find('.pnt-part-number__input-section');
20451    let inputbutton = inputSection.find('#partnumber');
20452    let submitbutton = inputSection.find('.part-number-submit');
20453    let inputCloseIcon = inputSection.find('.icon-close');
20454    let captionId = searchResultContainer.find('#pnt-part-number__search-results-id');
20455
20456    inputbutton.on('keypress', function (e) {
20457      if (e.keyCode === 13) {
20458        submitbutton.click();
20459      }
20460    });
20461    inputbutton.on('keyup', function () {
20462      if (this.value.length > 0) {
20463        inputCloseIcon.show();
20464      } else {
20465        inputCloseIcon.hide();
20466      }
20467    });
20468
20469    inputCloseIcon.click(function (e) {
20470      inputbutton.val('');
20471      inputCloseIcon.hide();
20472      noresultContainer.hide();
20473      searchResultContainer.hide();
20474      noresultContainer.hide();
20475    });
20476
20477    submitbutton.click(function (e) {
20478      const apiUrl = '/content/ift/partNumber.xmlParse.json';
20479      $.ajax({
20480        type: 'GET',
20481        url: '/content/ift/partNumber.xmlParse.json',
20482        dataType: 'json',
20483        success: function (data) {
20484          const jsonaData = data.products;
20485          let filterRes = jsonaData.filter(function (item) {
20486            return ((item.oldPn == inputbutton.val()) || (item.newPn == inputbutton.val()));
20487          });
20488
20489          if (filterRes.length > 0) {
20490            const tableValues = filterRes[0];
20491            $('#oldPartNumber').html(tableValues.oldPn);
20492            $('#newPartNumber').html(tableValues.newPn);
20493            $('#description').html(tableValues.description);
20494            captionId.html(inputbutton.val());
20495            noresultContainer.hide();
20496            searchResultContainer.show();
20497
20498          } else {
20499            noresultContainer.show();
20500            searchResultContainer.hide();
20501          }
20502        },
20503        error: function (data) {
20504          noresultContainer.find('.partnumber-not-found-text').html('Error requesting Part Number Data. Please try after some time.');
20505          noresultContainer.show();
20506        }
20507      });
20508    });
20509  });
20510});
20511$(function(){
20512	$("#distributorlocatormodal").on('show.bs.modal', function(event){
20513		//where-to-buy-new-distributor.js adds access to isloading and init for lazy loading.
20514		var targetWhereToBuy = $(this).find('.where-to-buy-new-distributor')[0];
20515		if(targetWhereToBuy.isLoading && targetWhereToBuy.isLoading()){ // "isLoading = true" means it hasn't been init yet
20516			targetWhereToBuy.init();
20517		}
20518	});
20519});
20520(function() {
20521
20522    var distDisplayHelpers = function(self, brandsVerticalsAllowedFromTags) {
20523        return {
20524            distance: function(data) {
20525                return Math.round(data.distance * 10) / 10;
20526            },
20527            address: function(data) {
20528                var addressParts = [data.Dealer_Locator_Street_Address_1__c, data.Dealer_Locator_City__c, data.Dealer_Locator_State_Province__c, data.Dealer_Locator_Zip_Postal_Code__c, data.Dealer_Locator_Country__c].filter(function(elem) { return !!elem });
20529                var fullAddress = "";
20530                addressParts.forEach(function(addressElem, addressIndex) {
20531                    var addComma = addressIndex < (addressParts.length - 1);
20532                    fullAddress += addressElem + (addComma ? ', ' : '');
20533                });
20534                return fullAddress;
20535            },
20536            showDirections: function(data) {
20537                return data.Do_Not_Show_Address_on_Dealer_Locator__c === false;
20538            },
20539            phone: function(data) {
20540                return data.Dealer_Locator_Phone__c ? data.Dealer_Locator_Phone__c : '';
20541            },
20542            phonehref: function(data) {
20543                return data.Dealer_Locator_Phone__c ? 'tel:'+ data.Dealer_Locator_Phone__c  : '';
20544            },
20545            email: function(data) {
20546                return data.Dealer_Locator_Email__c ?  data.Dealer_Locator_Email__c : '';
20547            },
20548            emailhref: function(data) {
20549                return data.Dealer_Locator_Email__c ? 'mailto:'+ data.Dealer_Locator_Email__c : '';
20550            },
20551            website: function(data) {
20552                var website = data.Dealer_Locator_Website__c;
20553                var websiteExp = /(https:\/\/|http:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/;
20554                var normalUrlCheck = website && website.match(websiteExp);
20555                if (normalUrlCheck && website.indexOf('//') > -1) {
20556                    return website;
20557                } else if (normalUrlCheck && website.indexOf('//') === -1) {
20558                    return website ? '//' + website : '';
20559                } else {
20560                    return '';
20561                }
20562            },
20563            googleDirectionsLink: function(data) {
20564                return "https://www.google.com/maps/dir/?api=1&destination=" + this.address(data);
20565            },
20566            showNoResultsMessage: function() {
20567                return self.distributorList().length === 0 && !self.isLoading() && self.errorMessage() === 'noDistributors';
20568            },
20569            showNoGeoLocationMessage: function() {
20570                return !self.isLoading() && self.errorMessage() === 'noGeo';
20571            },
20572            showGeo: function() {
20573                return self.userLatLong() && self.userLatLong().lat && self.userLatLong().lng;
20574            },
20575            brandsVerticals: function(data) { // Returns array of all records' brand by vertical strings
20576                var allBrandsVerticals = new Set();
20577                var records = data.Account_Territories__r.records;
20578                $(records).each(function(index, record) {
20579                    var split = record.Brand_by_Vertical__c.split(';');
20580                    split.forEach(function(item) {
20581                        allBrandsVerticals.add(item);
20582                    });
20583                });
20584                return [...allBrandsVerticals];
20585            },
20586            // brands: function(data) {
20587            //     var brands = new Set();
20588            //     var brandsVerticalsString = '';
20589            //     var records = data.Account_Territories__r.records;
20590            //     $(records).each(function(index, record) {
20591            //         brandsVerticalsString += record.Brand_by_Vertical__c + ';';
20592            //     })
20593            //     var brandsVerticalsSet = new Set(brandsVerticalsString.split(';'));
20594            //     brandsVerticalsSet.forEach(function(index, item) {
20595            //         if (item.indexOf(' - ') >= 0) {
20596            //             var itemArr = item.split(' - ');
20597            //             if (itemArr[0] !== null || itemArr[1] !== "0" || itemArr[0] !== undefined) {
20598            //                 brands.add(itemArr[0]);
20599            //             }
20600            //         }
20601            //     });
20602            //     return "Brands: " + Array.from(brands).join(', ');
20603            // },
20604            markets: function(data) {
20605                var markets = new Set();
20606                var brandsVerticalsString = '';
20607                var records = data.Account_Territories__r.records;
20608                $(records).each(function(index, record) {
20609                    brandsVerticalsString += record.Brand_by_Vertical__c + ';';
20610                })
20611                var brandsVerticalsSet = new Set(brandsVerticalsString.split(';'));
20612                brandsVerticalsSet.forEach(function(index, item) {
20613                    if (brandsVerticalsAllowedFromTags.includes(item) && item.indexOf(' - ') >= 0) {
20614                        var itemArr = item.split(' - ');
20615                        if (itemArr[1] !== null || itemArr[1] !== "" || itemArr[1] !== undefined) {
20616                            markets.add(itemArr[1]);
20617                        }
20618                    }
20619                });
20620                return "Markets: " + Array.from(markets).join(', ');
20621            }
20622        }
20623    };
20624
20625    var WhereToBuyViewModel = function(distributorComponentElement) {
20626        var self = this;
20627
20628        self.distributorList = ko.observableArray(); // Populated by ajax call.
20629
20630        self.mapHelper = new PENTAIR.Water.MapHelper(distributorComponentElement.find('.map-container'));
20631        self.googleMapsData = ko.observableArray();
20632        self.filterModel = new GenericFilterViewModel();
20633
20634        var filterRules = {
20635            // 'Distance': function(distributorItem, currentFilter) {
20636            //     return currentFilter.value() >= distributorItem.distance;
20637            // },
20638            'Distributor Name': function(distributorItem, currentFilter) {
20639                return currentFilter.value() === distributorItem.name;
20640            },
20641            'Brand By Market': function(distributorItem, currentFilter) {
20642                var brandsVerticalsForItem = self.distDisplayHelpers.brandsVerticals(distributorItem);
20643                return brandsVerticalsForItem.includes(currentFilter.value());
20644            }
20645            // 'Brand Name': function(distributorItem, currentFilter) {
20646            //     var brandString = self.distDisplayHelpers.brands(distributorItem);
20647            //     return brandString.indexOf(currentFilter.value()) >= 0;
20648            // },
20649            // 'Market': function(distributorItem, currentFilter) {
20650            //     var marketString = self.distDisplayHelpers.markets(distributorItem);
20651            //     return marketString.indexOf(currentFilter.value()) >= 0;
20652            // }
20653        };
20654
20655        self.searchInput = ko.observable().extend({ throttle: 200 });
20656
20657        self.userPostalCode = ko.observable();
20658        self.userLatLong = ko.observable();
20659        self.userAddress = ko.observable();
20660        self.userCity = ko.observable('');
20661        self.userState = ko.observable('');
20662        self.userPostalCode = ko.observable('No Zip');
20663        var userCountry = '';
20664        var userState = '';
20665        var userCounty = '';
20666
20667        self.zipQueryParam = ko.observable(getParams().zip ? decodeURIComponent(getParams().zip).replace(/\+/g, ' ') : '');
20668        self.zipcodeLat = ko.observable('');
20669        self.zipcodeLong = ko.observable('');
20670        self.zipcodeAddress = ko.observable('');
20671
20672        self.filterModal = ko.observable('closed'); // closed or open
20673        self.errorMessage = ko.observable('noDistributors'); // 'noDistributors' or 'noGeo'
20674
20675        // Brands and verticals are populated with TAGS from aem.
20676        var brands = distributorComponentElement.data('brands') ? distributorComponentElement.data('brands').split(',') : '';
20677        self.brands = ko.observableArray(brands);
20678        var verticals = distributorComponentElement.data('verticals') ? distributorComponentElement.data('verticals').split(',') : '';
20679        self.verticals = ko.observableArray(verticals);
20680        var brandsVerticalsAllowedFromTags = getAllowedTags();
20681        var resultsBrandsVerticals = new Set();
20682
20683        // Get list of valid brands by verticals based on tag combinations
20684        function getAllowedTags() {
20685            var allowedTags = [];
20686            if (self.brands().length <= 0 || self.verticals().length <= 0) {
20687                console.log('Authored brands or verticals missing');
20688                return [];
20689            }
20690            self.brands().forEach(function(brandTag) {
20691                self.verticals().forEach(function(verticalTag) {
20692                    allowedTags.push(brandTag + ' - ' + verticalTag);
20693                })
20694            })
20695            return allowedTags;
20696        }
20697
20698        function setCountryStateCounty(addressComponents) {
20699            userCountry = ''; // Reset values so not retained between searches
20700            userCounty = '';
20701            userState = '';
20702            var userCity = '';
20703            $(addressComponents).each(function(index, elem) {
20704                if (elem.types.includes('country')) {
20705                    userCountry = elem.short_name; // Get abbreviated country first
20706                }
20707            });
20708            $(addressComponents).each(function(index, elem) {
20709                if (userCountry === "US" && elem.types.includes("administrative_area_level_1")) {
20710                    userState = elem.short_name; // Abbreviated state name
20711                }
20712                if (userCountry === "US" && elem.types.includes("administrative_area_level_2")) {
20713                    userCounty = elem.long_name.replace(' County', ''); // Do not include the word county in the set value
20714                }
20715                if (userCountry === "US" && elem.types.includes("locality")) {
20716                    userCity = elem.long_name;
20717                }
20718            });
20719            if (userCountry === "US" && userCounty === '') {
20720                userCounty = userCity; // Set county to city to handle case where county doesn't exist
20721            }
20722        }
20723
20724        self.userLatLong.subscribe(function(newValue) {
20725            if (!google || google === undefined) { return;}
20726            var geocoder = new google.maps.Geocoder();
20727            if (newValue) {
20728                geocoder.geocode({ 'latLng': newValue }, function(results, status) {
20729                    if (status == google.maps.GeocoderStatus.OK) {
20730                        self.userAddress(results[0].formatted_address);
20731
20732                        var addressData = getCityStateZip(results);
20733                        self.userCity(addressData.city);
20734                        self.userState(addressData.state);
20735                        self.userPostalCode(addressData.zip);
20736
20737                        setCountryStateCounty(results[0].address_components);
20738                    }
20739                });
20740            }
20741        });
20742
20743        var getCityStateZip = function(results){
20744            var outputData = {city: '', state: '', zip: ''};
20745
20746            if(results[0] && results[0]['address_components']){
20747                var cityNameArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('locality') !== -1});
20748                var stateNameArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('administrative_area_level_1') !== -1});
20749                var postalCodeArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('postal_code') !== -1});
20750                outputData['city'] = (cityNameArray && cityNameArray.length > 0) ? cityNameArray[0]['long_name'] : "";
20751                outputData['state']  = (stateNameArray && stateNameArray.length > 0) ? stateNameArray[0]['short_name'] : "";
20752                outputData['zip'] = (postalCodeArray && postalCodeArray.length > 0) ? postalCodeArray[0]['long_name'] : "";
20753            }
20754
20755            return outputData;
20756        };
20757
20758        self.isLoading = ko.observable(true);
20759        self.activeIndex = ko.observable(null);
20760
20761        //Check if active filter is still visible when filter updates.
20762        function updateActiveFilter(filteredData) {
20763            var visibleIndexes = filteredData.map(function(elem) { return elem.index });
20764            if (!self.activeIndex() || (self.activeIndex() && visibleIndexes.indexOf(self.activeIndex()) == -1)) {
20765                self.activeIndex(null);
20766                self.mapHelper.closeMarker();
20767            }
20768        }
20769
20770
20771        // Hide or show pins when filter changes.
20772        self.filterModel.filteredDataList.subscribe(function(newValue) {
20773            var visiblePinIndexes = newValue.map(function(elem) { return elem.index });
20774            self.mapHelper.showPins(visiblePinIndexes);
20775            updateActiveFilter(newValue);
20776        });
20777
20778        self.locationClick = function() {
20779            if (self.userLatLong() && self.userLatLong().latitude && self.userLatLong().longitude) {
20780                var pos = { lat: self.userLatLong().latitude, lng: self.userLatLong().longitude };
20781                self.runLatLongSearch(pos);
20782            }
20783        };
20784
20785        self.isActive = function(data) {
20786            return (self.activeIndex() !== null) && (self.activeIndex() === data.index);
20787        };
20788
20789        // workaround for preventing bubbling (and preventDefault) when an anchor tag is inside a div with a click event.
20790        self.innerClick = function(selection, event) {
20791            /* Analytics Model Update*/
20792            if ((selection && selection.name) && (event && event.target && event.target.dataset && event.target.dataset.eventName)) {
20793                updateDataLayerObj(selection.name, 'Result Link', event.target.dataset.eventName, undefined, undefined, undefined, false);
20794            }
20795            // Adobe analytics
20796            trackWTBClickEvent('WTB Distributor list get directions click', selection.id, selection.index, 'get directions');
20797            return true;
20798        };
20799
20800        self.distributorClick = function(data) {
20801            self.mapHelper.closeMarker();
20802            self.activeIndex(data.index);
20803            if (!data.hideAddress) {
20804                self.mapHelper.openMarker(data.index);
20805            }
20806            // Adobe analytics
20807            const business = [{name: data.Dealer_Locator_Name__c, zip: data.Dealer_Locator_Zip_Postal_Code__c}];
20808            trackWTBClickEvent('WTB Distributor search result list click', data.id, data.index, 'list result', business);
20809        };
20810
20811        self.activePanel = ko.observable('list');
20812
20813        self.mapPanelActive = function() { return self.activePanel() === 'map' };
20814
20815        self.listPanelActive = function() { return self.activePanel() === 'list' };
20816
20817        self.setListPanel = function() {
20818            self.activePanel('list');
20819            self.reInitJscroll(true);
20820        };
20821
20822        self.setMapPanel = function() {
20823            self.activePanel('map');
20824            self.mapHelper.updateZoom();
20825        };
20826
20827        self.openFilterModal = function() {
20828            self.filterModal('open');
20829            $('body').addClass('filter-open modal-open');
20830            ensureOpenFilterZPosition()
20831        };
20832
20833        self.closeFilterModal = function() {
20834            self.filterModal('closed');
20835            $('body').removeClass('filter-open modal-open');
20836            ensureClosedFilterZPosition()
20837        };
20838
20839        self.isFilterModalOpen = function() {
20840            return self.filterModal() === 'open';
20841        };
20842
20843        // Used for hiding/showing sections. No hash means show all sections.
20844        var hashes = window.location.hash.replace("#", "");
20845        var hashArray = hashes ? hashes.split(",") : [];
20846        self.urlHashes = ko.observableArray(hashArray);
20847
20848        // Jscroll handling.
20849        self.filterModel.setFilterRules(filterRules);
20850
20851        self.reInitJscroll = ko.observable(false).extend({ rateLimit: 100, notify: 'always' });
20852
20853        self.filterModel.activeFilters.subscribe(function(newValue) {
20854            self.reInitJscroll(true);
20855        });
20856
20857        self.distDisplayHelpers = distDisplayHelpers(self, brandsVerticalsAllowedFromTags);
20858
20859        self.reInitJscroll.subscribe(function(newValue) {
20860            if (newValue) {
20861                self.reInitJscroll(false);
20862                reInitJscroll();
20863            }
20864        });
20865
20866        function reInitJscroll() {
20867            if (distributorComponentElement.find('.scroll-list').jScrollPane) {
20868                distributorComponentElement.find('.scroll-list').jScrollPane({
20869                    contentWidth: '0px',
20870                    autoReinitialize: true
20871                });
20872
20873            }
20874        }
20875
20876        $(window).on('resize', function(e) {
20877            self.reInitJscroll(true);
20878        });
20879
20880        function getVisiblePins() {
20881            var indexArray = [];
20882
20883            return indexArray;
20884        }
20885
20886        self.afterRender = function() {
20887            self.reInitJscroll(true);
20888        };
20889
20890        /**
20891         * Uses a set of values to populate a filter
20892         */
20893        function getSimpleFilterValues(values) {
20894            var valuesArr = []
20895            values.forEach(function(item) {
20896                valuesArr.push({'value': item, 'title': item});
20897            });
20898            return valuesArr;
20899        }
20900
20901
20902        // Populate Filters:
20903        self.distributorList.subscribe(function(newValue) {
20904            // var distanceValues = [{ value: 10, title: 10 }, { value: 20, title: 20 }, { value: 30, title: 30 }, { value: 50, title: 50 }, { value: 100, title: 100 }, { value: 150, title: 150 }, { value: 200, title: 200 }];
20905            var recordFilters = getRecordFilters();
20906            var filterCategories = [
20907                // { name: "Distance", type: "static", values: distanceValues, inputType: "radio" },
20908                { name: "Distributor Name", type: "dynamic", fromField: "name", inputType: "checkbox" },
20909                { name: "Brand By Market", type: "static", values: getSimpleFilterValues(resultsBrandsVerticals), inputType: "checkbox" },
20910                // { name: "Brand Name", type: "static", values: getSimpleFilterValues(self.brands()), inputType: "checkbox" },
20911                // { name: "Market", type: "static", values: getSimpleFilterValues(self.verticals()), inputType: "checkbox" }
20912            ];
20913
20914            // if (self.brands().size <= 1) {
20915            //     filterCategories = filterCategories.filter(function(elem) { return elem.name !== "Brand Name" });
20916            // }
20917            // if (self.verticals().size <= 1) {
20918            //     filterCategories = filterCategories.filter(function(elem) { return elem.name !== "Market" });
20919            // }
20920            // if (resultsBrandsVerticals.size <= 1) {
20921            //     filterCategories = filterCategories.filter(function(elem) { return elem.name !== "Brand By Market" });
20922            // }
20923
20924            self.filterModel.filters([]);
20925            self.filterModel.populateCategories(filterCategories, newValue);
20926            // initFilterSelection(newValue);
20927        });
20928
20929        // function initFilterSelection(distributorList) {
20930        //     var distanceCategory = self.filterModel.filters().filter(function(categoryFilter) { return categoryFilter.name() === "Distance" });
20931        //     var distanceFiltersWithResults;
20932        //     if (distanceCategory.length && distanceCategory[0].values()) {
20933        //         distanceFiltersWithResults = distanceCategory[0].values().filter(function(filterModel) { return (filterModel.count() > 0) && (filterModel.value() >= 50) });
20934        //         if (distanceFiltersWithResults.length > 0) {
20935        //             distanceFiltersWithResults[0].toggleSelection();
20936        //             setInitialRadius();
20937        //         }
20938        //     }
20939        // }
20940
20941        // If a user hits the 'x' when the location requests pops up in IE, the error section is not hit,
20942        // and the service fails silently.
20943        function geoLocationIETimeout() {
20944            var isIE = /*@cc_on!@*/ false || !!document.documentMode; // Internet Explorer 6-11
20945            self.geoLocationStatus = ko.observable('waiting');
20946            if (isIE) {
20947                setTimeout(function() {
20948                    if (self.geoLocationStatus() === 'waiting') {
20949                        self.errorMessage('noGeo');
20950                        self.firstSearch.dispose();
20951                        self.isLoading(false);
20952                    }
20953                }, 8000);
20954            }
20955        };
20956
20957        function initUserLatLong() {
20958            if (navigator.geolocation) {
20959                geoLocationIETimeout();
20960                navigator.geolocation.getCurrentPosition(function(position) {
20961                    var pos = { lat: position.coords.latitude, lng: position.coords.longitude };
20962                    self.userLatLong(pos);
20963                    self.geoLocationStatus('complete');
20964                }, function(e) { // error
20965                    self.errorMessage('noGeo');
20966                    self.firstSearch.dispose();
20967                    self.geoLocationStatus('complete');
20968                    self.isLoading(false);
20969                });
20970            }
20971        }
20972
20973        function getParams() {
20974            return _.chain(location.search.slice(1).split('&'))
20975                .map(function (item) { if (item) { return item.split('='); } })
20976                .compact()
20977                .object()
20978                .value();
20979        }
20980
20981        self.runLatLongSearch = function(latLongData) {
20982            if (latLongData && latLongData.lat && latLongData.lng) {
20983                var pos = { latitude: latLongData.lat, longitude: latLongData.lng };
20984
20985                // Reset user location
20986                if (latLongData) {
20987                    var geocoder = new google.maps.Geocoder();
20988                    if (!self.zipQueryParam()) {
20989
20990                        geocoder.geocode({ 'latLng': latLongData }, function(results, status) {
20991                            if (status == google.maps.GeocoderStatus.OK) {
20992                                self.userAddress(results[0].formatted_address);
20993
20994                                var addressData = getCityStateZip(results);
20995                                self.userCity(addressData.city);
20996                                self.userState(addressData.state);
20997                                self.userPostalCode(addressData.zip);
20998                                self.searchInput(self.userAddress());
20999                                setCountryStateCounty(results[0].address_components)
21000                            }
21001                            loadMapData(pos);
21002                        });
21003                    } else {
21004                        var address = self.zipQueryParam();
21005                        geocoder.geocode({ 'address': 'zipcode '+address }, function (results, status) {
21006                            if (status == google.maps.GeocoderStatus.OK) {
21007                                var latitude = results[0].geometry.location.lat();
21008                                var longitude = results[0].geometry.location.lng();
21009                                var address = results[0].formatted_address;
21010                                self.zipcodeLat(latitude);
21011                                self.zipcodeLong(longitude);
21012                                self.zipcodeAddress(address);
21013                                self.searchInput(address);
21014                                var zipPos = { latitude: latitude, longitude: longitude };
21015                                setCountryStateCounty(results[0].address_components)
21016                                loadMapData(zipPos);
21017                            }
21018                        });
21019                    }
21020                }
21021
21022                self.activeIndex(null);
21023                self.reInitMap();
21024            }
21025        };
21026
21027        self.runAddressSearch = function(address) {
21028            var geocoder = new google.maps.Geocoder();
21029            if (address) {
21030                geocoder.geocode({ 'address': address }, function(results, status) {
21031                    setCountryStateCounty(results[0].address_components)
21032                    if (status == google.maps.GeocoderStatus.OK) {
21033                        var pos = { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng() };
21034                        self.runLatLongSearch(pos);
21035                    }
21036                });
21037            }
21038        };
21039
21040        self.locationSearchClick = function() {
21041            if (self.userLatLong() && self.userLatLong().lat && self.userLatLong().lng) {
21042                self.runLatLongSearch(self.userLatLong());
21043                self.searchInput(self.userAddress());
21044            } else {
21045                self.init(); // asks for location data again.
21046            }
21047        };
21048
21049        self.searchUserInputClick = function() {
21050            self.runAddressSearch(self.searchInput());
21051        }
21052
21053        self.searchInputKeypress = function(scope, event) {
21054            initAutocomplete();
21055            return true;
21056        };
21057
21058        // Bias the autocomplete object to the user's geographical location,
21059        // as supplied by the browser's 'navigator.geolocation' object.
21060        self.geolocate = function geolocate() {
21061            if (navigator.geolocation && autocomplete) {
21062                navigator.geolocation.getCurrentPosition(function(position) {
21063                    var geolocation = {
21064                        lat: position.coords.latitude,
21065                        lng: position.coords.longitude
21066                    };
21067                    var circle = new google.maps.Circle({ center: geolocation, radius: position.coords.accuracy });
21068                    autocomplete.setBounds(circle.getBounds());
21069                });
21070            }
21071        };
21072
21073        self.showContactDistributor = function(data) {
21074            return data.Dealer_Locator_Phone__c || data.Dealer_Locator_Website__c || data.Dealer_Locator_Email__c;
21075        };
21076
21077        self.showDistContactCallback = function(event, selection) {
21078            /* Analytics Model Update*/
21079            if ((selection && selection.Dealer_Locator_Name__c) && (event && event.target && event.target.dataset && event.target.dataset.eventName)) {
21080                updateDataLayerObj(selection.Dealer_Locator_Name__c, 'Result Link', event.target.dataset.eventName, undefined, undefined, undefined, false);
21081            }
21082            if ($(event.target).is($('a.contact-distributor'))) {
21083                event.preventDefault();
21084                if ($(event.target).parents('.marker').length) { // in map infowindow
21085                    $(event.target).parents('.show-contact').siblings('.contact').show();
21086                    $(event.target).parents('.show-contact').hide();
21087                    // Adobe analytics
21088                    var markerElem = event.target.closest('.marker');
21089                    trackWTBClickEvent('WTB map contact distributor click', markerElem.dataset.distributorId, markerElem.dataset.distributorIndex, 'map contact distributor');
21090                } else { // in distributor list
21091                    $(event.target).siblings('.contact').show();
21092                    $(event.target).hide();
21093                    reInitJscroll();
21094                    // Adobe analytics
21095                    trackWTBClickEvent('WTB list contact distributor click', selection.id, selection.index, 'contact distributor');
21096                }
21097            }
21098        };
21099
21100        self.reInitMap = function() {
21101            var initMap = self.distributorList.subscribe(function() {
21102                updateDataLayerList(); // analytics wants a list of results
21103                self.googleMapsData(getGoogleMapsModel());
21104                self.mapHelper.setMarkerHtmlCallback(markerHtmlCallback);
21105                self.mapHelper.initMap(self.googleMapsData());
21106                self.mapHelper.addInfoWindowEvent('click', self.showDistContactCallback);
21107                initMap.dispose();
21108            });
21109        };
21110
21111        var total;
21112
21113        function updateDataLayerList() {
21114            var userAddress = self.searchInput();
21115            if (self.distributorList().length !== total) { // don't bother if results haven't changed
21116                total = self.distributorList().length;
21117                var distributorListNames = [];
21118                self.distributorList().forEach(function(elem) {
21119                    distributorListNames.push(elem.name);
21120                });
21121                distributorListNames = distributorListNames.join('|');
21122                updateDataLayerObj(undefined, 'Results Found', 'Distributors Impression', distributorListNames, undefined, undefined, userAddress, false);
21123            } else {
21124                var distributorListNames = [];
21125                self.distributorList().forEach(function(elem) {
21126                    distributorListNames.push(elem.name);
21127                });
21128                distributorListNames = distributorListNames.join('|');
21129                updateDataLayerObj(undefined, 'Results Found', 'Distributors Impression', distributorListNames, undefined, undefined, userAddress, false);
21130            }
21131        }
21132
21133        function clearDigitalDataProperty(prop, propVal) {
21134            // clears out optional/circumstantial analytics properties
21135            if (propVal) {
21136                digitalData.findDistributor[prop] = propVal;
21137            } else {
21138                if (digitalData.findDistributor[prop]) {
21139                    delete digitalData.findDistributor[prop];
21140                }
21141            }
21142        }
21143
21144        self.updateAnalytics = function updateAnalytics(scopedItem) {
21145            if (scopedItem && scopedItem.selected()) {
21146                var filterType = scopedItem.parent && scopedItem.parent.name() ? scopedItem.parent.name() : undefined;
21147                var filterValue = scopedItem.value();
21148                updateDataLayerObj(undefined, "Refine Search", "Apply Filter", undefined, filterType, filterValue, undefined, true);
21149            }
21150            return true;
21151        };
21152
21153        // strictly for updating Data Layer Object with user location data
21154        function getUserLocationData(res) {
21155            var city, state, zip, formattedAddress;
21156
21157            city = self.userCity();
21158            state = self.userState();
21159            zip = /\d{5}/.test(res) ? self.userPostalCode() : "No Zip";
21160            formattedAddress = city + "|" + state + "|" + zip;
21161
21162            return formattedAddress;
21163        }
21164
21165        function updateDataLayerObj(name, eventAction, eventName, distributorList, filterType, filterValue, address, fireInputTracking) {
21166            try {
21167                if (digitalData) {
21168                    if (digitalData.findDistributor) {
21169                        var TYPE = 'Find A Distributor';
21170                        clearDigitalDataProperty('name', name);
21171                        clearDigitalDataProperty('distributorsFound', distributorList);
21172                        clearDigitalDataProperty('filterType', filterType);
21173                        clearDigitalDataProperty('filterValue', filterValue);
21174                        digitalData.findDistributor.eventName = eventName;
21175                        digitalData.findDistributor.type = TYPE;
21176                        digitalData.findDistributor.eventAction = eventAction;
21177                        digitalData.findDistributor.timeStamp = new Date();
21178                        digitalData.findDistributor.distributorFormInput = getUserLocationData(address);
21179                        if (!_.isUndefined(window._satellite) && fireInputTracking) {
21180                            window._satellite.track("wtb_input");
21181                        }
21182
21183                    }
21184                }
21185            } catch (err) {
21186                console.log(err);
21187            }
21188        }
21189
21190        /**
21191         * Constructs the payload for the click event analytics tracking and sends the payload to be tracked.
21192         * @param eventName analytics event name
21193         * @param wtbDistributorIDClicked ID of the distributor clicked
21194         * @param wtbSearchResultIndex index of the clicked distributor in the list
21195         * @param wtbClickType click type: list result, contact distributor, get directions, map pin, map contact distributor
21196         */
21197        function trackWTBClickEvent(eventName, wtbDistributorIDClicked, wtbSearchResultIndex, wtbClickType, businesses = []) {
21198            var eventWTBClickPayload = {
21199                eventName: eventName,
21200                eventType: 'event',
21201                attributes: {
21202                    visitor: {
21203                        pentairCustomerID: getPentairCustomerID(), //if this is available
21204                        distributorID: getDistributorID() //if this is available
21205                    },
21206                    wtbSearch: {
21207                        wtbBrands: self.brands().join(),
21208                        wtbVerticals: self.verticals().join(),
21209                        wtbSearchZip: self.userPostalCode(),
21210                        wtbDistributorIDClicked: wtbDistributorIDClicked,
21211                        wtbSearchResultIndex: wtbSearchResultIndex + 1, // index start at 1
21212                        wtbClickType: wtbClickType
21213                    },
21214                    ...(businesses.length > 0 && {wtbBusinessInfo: businesses.splice(0, 10)})
21215                }
21216            }
21217            trackEventWithQueue(eventWTBClickPayload);
21218        }
21219
21220        function markerHtmlCallback(item) {
21221            var infoHtml;
21222            if (item && !isNaN(item.index)) {
21223                infoHtml = $('<div>').addClass('marker')
21224                                    .attr('data-distributor-index', item.index)
21225                                    .attr('data-distributor-id', item.id);
21226            }
21227            if (item && item.name) {
21228                infoHtml.append($('<p>').addClass('location-name').html(item.name));
21229            }
21230            if (item && item.distance) {
21231                infoHtml.append($('<p>').addClass('distance').html(item.distance + ' miles away'));
21232            }
21233            if (item && item.address) {
21234                infoHtml.append($('<p>')
21235                    .html(item.address.split(',')[0] + '<br>' + item.address.split(',').slice(1).join(', ')));
21236            }
21237
21238            if(item && (item.phone || item.website || item.email)){
21239              var contact = $('<span>').addClass('contact').hide();
21240
21241              if(item && item.phone){
21242                contact.append(
21243                    $('<p>')
21244                        .addClass('phone-one')
21245                        .append('<span class="icon-phone" aria-hidden="true"></span>')
21246                        .append($('<a>').attr('href', 'tel:' + item.phone).html(item.phone))
21247                );
21248              }
21249              if(item && item.email){
21250                contact.append(
21251                    $('<p>')
21252                        .addClass('email')
21253                        .append('<span class="icon-pentair-email" aria-hidden="true"></span>')
21254                        .append(
21255                            $('<a>')
21256                                .attr('href', 'mailto:' + item.email)
21257                                .attr('target', '_blank')
21258                                .attr('rel', 'noopener noreferrer')
21259                                .html(item.email)
21260                        )
21261                );
21262              }
21263              if(item && item.website){
21264                contact.append(
21265                    $('<p>')
21266                        .addClass('website')
21267                        .append('<span class="icon-external-link-square" aria-hidden="true"></span>')
21268                        .append($('<a>').attr({'href': item.website, 'target': '_blank'}).html(' Website'))
21269                );
21270              }
21271
21272              infoHtml.append(contact);
21273              infoHtml.append($('<p>').addClass('show-contact').append('<span class="icon-address-book" aria-hidden="true"></span>').append($('<a>').addClass('contact-distributor').attr('href', '#').html(' Contact Distributor')));
21274            }
21275
21276            // If the callback came from clicking on a map pin, fire adobe analytics event for tracking map pin click
21277            if (item && event.target.closest('.map-container')) {
21278                const business = [{name: item.name, zip: item.zip}];
21279                trackWTBClickEvent('WTB Distributor map pin click', item.id, item.index, 'map pin', business);
21280            }
21281
21282            return infoHtml[0].outerHTML;
21283        }
21284
21285        self.init = function() {
21286            initUserLatLong();
21287            self.firstSearch = self.userLatLong.subscribe(function(newValue) {
21288                if (newValue) {
21289                    self.runLatLongSearch(newValue);
21290                }
21291                self.firstSearch.dispose();
21292            });
21293        };
21294
21295        function setInitialRadius() {
21296            var component = distributorComponentElement;
21297            var distance = component.find(".filter .Distance");
21298            var distanceFilters = distance.next("ul").find("li");
21299            for (var i = 0; i < distanceFilters.length; i++) {
21300                var currentFilter = $(distanceFilters[i]);
21301                var count = currentFilter.find(".item-count");
21302                var num = count.text().replace(/[()]/g, '');
21303                if (num > 0) {
21304                    currentFilter.find("input").click();
21305                    break;
21306                }
21307            }
21308        }
21309
21310        function loadMapData(locationData) {
21311            // Leave distance: 200 here because Salesforce will handle it on their side
21312            var extendLocationData = { distance: 200, country: userCountry, brands: self.brands().join(','), verticals: self.verticals().join(',') };
21313            if (userState.length > 0) {
21314                extendLocationData.stateProvince = userState;
21315            }
21316            if (userCounty.length > 0) {
21317                extendLocationData.county = userCounty;
21318            }
21319            locationData = locationData;
21320            $.extend(locationData, extendLocationData);
21321            self.isLoading(true);
21322            self.errorMessage('noDistributors');
21323
21324            let businesses = [];
21325
21326            $.ajax({
21327                type: 'GET',
21328                data: locationData,
21329                url: '/bin/pentair/sfdc/distributor',
21330                beforeSend: function() {},
21331                success: function(data) {
21332                    if (data) {
21333                        jsonData = JSON.parse(data);
21334                        var sortedDistributorResults = processDistData(jsonData.acctList);
21335                        self.distributorList(sortedDistributorResults);
21336                        if (self.distributorList().length === 0 && (locationData.latitude && locationData.longitude)) {
21337                            var pos = { "lat": locationData.latitude, "lng": locationData.longitude };
21338                            self.mapHelper.setCenter(pos);
21339                        } else {
21340                            businesses = self.distributorList().map((item) => {
21341                                return {name: item.Dealer_Locator_Name__c, zip: item.Dealer_Locator_Zip_Postal_Code__c}
21342                            });
21343                        }
21344                    } else {
21345                        console.error('No distributors found. -> ', data.length);
21346                    }
21347                    self.isLoading(false);
21348                    var pageViewDistributorListLoaded = new CustomEvent("pageViewDistributorListLoaded", {
21349                        detail: {
21350                            wtbSearch: {
21351                                wtbBrands: self.brands().join(),
21352                                wtbVerticals: self.verticals().join(),
21353                                wtbDistributorID: getFilteredDistributorIDs(),
21354                                wtbNumberResults: self.filterModel.filteredDataList().length,
21355                                wtbSearchZip: self.userPostalCode()
21356                            },
21357                            ...(businesses.length > 0 && {wtbBusinessInfo: businesses.splice(0, 10)})
21358                        }
21359                    });
21360                    // Dispatch the event to be handled in clientlib-site/js/analytics/pageView.js
21361                    var whereToBuyComponent = document.querySelector('.where-to-buy-new-distributor.component');
21362                    whereToBuyComponent.dispatchEvent(pageViewDistributorListLoaded);
21363                },
21364                error: function(data) {
21365                    console.error('Error retrieving Distributor List ->', data);
21366                    self.isLoading(false);
21367                }
21368            });
21369        }
21370
21371        // PENW-3184 - resetting focus state of Search button when clicked?
21372        $(".where-to-buy-new-distributor.component .wtb-search").on("click", function(e) {
21373            e.preventDefault();
21374            $(this).blur();
21375        });
21376
21377        /**
21378         * Gets the filtered Distributor IDs that were returned in the search.
21379         * @returns comma separated string list of distributor IDs
21380         */
21381        function getFilteredDistributorIDs() {
21382            var distributorIDs = [];
21383            self.filterModel.filteredDataList().forEach(function(distributor) {
21384                distributorIDs.push(distributor["id"]);
21385            });
21386            return distributorIDs.join();
21387        }
21388
21389        function getRecordFilters() {
21390            var allBrandNames = [];
21391            var allVerticals = [];
21392
21393            self.distributorList().forEach(function(distributorElem) {
21394                allBrandNames = allBrandNames.concat(distributorElem["brands"]);
21395                allVerticals = allVerticals.concat(distributorElem["verticals"]);
21396            });
21397
21398            var brandNameFilters = ko.utils.arrayGetDistinctValues(allBrandNames).sort().map(function(elem) { return { value: elem, title: elem } });
21399            var verticalsFilters = ko.utils.arrayGetDistinctValues(allVerticals).sort().map(function(elem) { return { value: elem, title: elem } });
21400            return { brandNameFilters: brandNameFilters, verticalsFilters: verticalsFilters };
21401        }
21402
21403        function getGoogleMapsModel() {
21404            var mapData = self.distributorList()
21405                .map(function(elem, index) {
21406                    var mapElem = {};
21407                    mapElem.id = elem.iD;
21408                    mapElem.name = elem.Dealer_Locator_Name__c;
21409                    mapElem.phone = elem.Dealer_Locator_Phone__c;
21410                    mapElem.email = elem.email;
21411                    mapElem.address = self.distDisplayHelpers.address(elem);
21412                    mapElem.zip = elem.Dealer_Locator_Zip_Postal_Code__c;
21413                    mapElem.website = self.distDisplayHelpers.website(elem);
21414                    mapElem.index = index;
21415                    mapElem.latitude = elem.Dealer_Locator_Location__Latitude__s;
21416                    mapElem.longitude = elem.Dealer_Locator_Location__Longitude__s;
21417                    mapElem.distance = self.distDisplayHelpers.distance(elem);
21418                    mapElem.hideAddress = elem.Do_Not_Show_Address_on_Dealer_Locator__c;
21419                    return mapElem
21420                });
21421            return mapData;
21422        }
21423
21424        // Add indexes, retrieve sets for brands and verticals
21425        function processDistData(data) {
21426            var sortedAndFiltered = data.filter(function(elem) {
21427                return (elem.Do_Not_Show_Address_on_Dealer_Locator__c == false) ||
21428                        (elem.Do_Not_Show_Address_on_Dealer_Locator__c && self.showContactDistributor(elem));
21429            });
21430
21431            // Create full string of all brands by verticals results
21432            var brandsVerticalsString = '';
21433            $(sortedAndFiltered).each(function(index, elem) {
21434                var records = elem.Account_Territories__r.records;
21435                $(records).each(function(index, record) {
21436                    brandsVerticalsString += record.Brand_by_Vertical__c + ';';
21437                })
21438                elem.index = index;
21439            });
21440
21441            // Use string to create set, then add to results set if result matches an allowed tag
21442            var brandsVerticalsSet = new Set(brandsVerticalsString.split(';'));
21443            brandsVerticalsSet.forEach(function(index, item) {
21444                if (brandsVerticalsAllowedFromTags.includes(item)) {
21445                    resultsBrandsVerticals.add(item);
21446                }
21447            });
21448
21449            return sortedAndFiltered;
21450        }
21451
21452        /*  Start of autocomplete changes
21453            Autocomplete requires the Places library, e.g.,
21454            src="//maps.googleapis.com/maps/api/js?key=${config.googleMapsKey}&libraries=places   */
21455        var autocomplete;
21456
21457        function initAutocomplete() {
21458            // Create the autocomplete object, restricting the search predictions to
21459            // geographical location types.
21460            if (!autocomplete) {
21461                autocomplete = new google.maps.places.Autocomplete(distributorComponentElement.find('.autocomplete')[0], { types: ['geocode'] });
21462                // Avoid paying for data that you don't need by restricting the set of
21463                // place fields that are returned to just the address components.
21464                autocomplete.setFields(['address_component', 'formatted_address']);
21465                autocomplete.addListener('place_changed', function() {
21466                    //
21467                    result = autocomplete.getPlace();
21468                    if (typeof result.address_components == 'undefined') {
21469                        // The user pressed enter in the input
21470                        // without selecting a result from the list
21471                        // Let's get the list from the Google API so that
21472                        // we can retrieve the details about the first result
21473                        // and use it (just as if the user had actually selected it)
21474                        autocompleteService = new google.maps.places.AutocompleteService();
21475                        autocompleteService.getPlacePredictions({
21476                                'input': result.name,
21477                                'types': ['geocode']
21478                            },
21479                            function listentoresult(list, status) {
21480                                if (list == null || list.length == 0) {
21481                                    // There are no suggestions available.
21482                                    // The user saw an empty list and hit enter.
21483                                    //console.log("No results");
21484                                } else {
21485                                    // Here's the first result that the user saw
21486                                    // in the list. We can use it and it'll be just
21487                                    // as if the user actually selected it
21488                                    // themselves. But first we need to get its details
21489                                    // to receive the result on the same format as we
21490                                    // do in the AutoComplete.
21491                                    placesService = new google.maps.places.PlacesService(distributorComponentElement.find('.autocomplete')[0]);
21492                                    placesService.getDetails({ 'reference': list[0].reference },
21493                                        function detailsresult(detailsResult, placesServiceStatus) {
21494                                            // Here's the first result in the AutoComplete with the exact
21495                                            // same data format as you get from the AutoComplete.
21496                                            self.searchInput(detailsResult.formatted_address);
21497                                            self.runAddressSearch(detail
21497sResult.formatted_address);
21498                                        }
21499                                    );
21500                                }
21501                            }
21502                        );
21503                    } else {
21504                        // The user selected a result from the list, we can
21505                        // proceed and use it right away
21506                        var place = autocomplete.getPlace();
21507                        var address = place.formatted_address;
21508                        self.searchInput(address);
21509                        self.runAddressSearch(address);
21510                    }
21511                });
21512            }
21513        }
21514        /*END of autocomplete */
21515
21516        // lazy load if modal:
21517
21518        var parentModal = distributorComponentElement.parents('#storelocatormodal');
21519        var isInModal = !!parentModal.length;
21520        if (isInModal) {
21521            self = this;
21522            distributorComponentElement[0].init = self.init;
21523            distributorComponentElement[0].isLoading = self.isLoading;
21524        } else {
21525            self.init();
21526        }
21527    };
21528    var showParams;
21529    try {
21530    var regex = /(%22)+/g;
21531    var queryString = location.search.substring(1);
21532    queryString = queryString.replace(regex, '_');
21533    var urlParams = queryString ? JSON.parse('{"' + decodeURIComponent(queryString).replace(/=&/g, "\":\"\",\"").replace(/&/g, "\",\"").replace(/=/g, "\":\"") + '"}') : {};
21534    showParam = urlParams["show"] || "";
21535    }catch(message){
21536        var params = new URLSearchParams(window.location.search);
21537        showParam = params.get("show") || "";
21538    }
21539
21540    $(document).ready(function() {
21541        $('.where-to-buy-new-distributor.component').each(function() {
21542            if (showParam) {
21543                $(document).find('section.toolbar').hide();
21544            }
21545            if (!showParam || showParam === "localDistributors") {
21546                try {
21547                    ko.applyBindings(new WhereToBuyViewModel($(this)), this);
21548                } catch (e) {
21549                    console.log(e);
21550                }
21551            } else {
21552                $('.where-to-buy-new-distributor.component').hide();
21553            }
21554        });
21555    });
21556})();
21557
21558$(function(){
21559	$("#storelocatormodal").on('show.bs.modal', function(event){
21560		//where-to-buy-new.js adds access to isloading and init for lazy loading.
21561		var targetWhereToBuy = $(this).find('.where-to-buy-new')[0];
21562		if(targetWhereToBuy.isLoading && targetWhereToBuy.isLoading()){ // "isLoading = true" means it hasn't been init yet
21563			targetWhereToBuy.init();
21564		}
21565	});
21566});
21567(function () {
21568    var WhereToBuyButton = function (componentElement) {
21569        let isShowDistributorsLocator = componentElement.attr("data-show-local-distributors-locator") !== undefined;
21570        let isShowDealersLocator = !isShowDistributorsLocator;
21571
21572        // 'supplier' = dealer or distributor
21573        let NO_SUPPLIERS_AVAILABLE;
21574        let NO_SUPPLIERS_ERROR_MESSAGE;
21575        let SFDC_URL
21576        if (isShowDistributorsLocator) {
21577            NO_SUPPLIERS_AVAILABLE = "NO DISTRIBUTORS AVAILABLE";
21578            NO_SUPPLIERS_ERROR_MESSAGE = "noDistributors";
21579            SFDC_URL = '/bin/pentair/sfdc/distributor';
21580        } else if (isShowDealersLocator) {
21581            NO_SUPPLIERS_AVAILABLE = "NO DEALERS AVAILABLE";
21582            NO_SUPPLIERS_ERROR_MESSAGE = "noDealers";
21583            SFDC_URL = '/bin/pentair/sfdc/dealers';
21584        } else {
21585            console.error("isShowDistributorsLocator or isShowDealersLocator  should be 'true', but both 'false'");
21586        }
21587
21588        // Brands and categories are populated with TAGS from aem.
21589        var brands = componentElement.data('brands') ? componentElement.data('brands').split(',') : '';
21590        self.brands = ko.observableArray(brands);
21591
21592        var categories = componentElement.data('categories') ? componentElement.data('categories').split(',') : '';
21593        self.categories = ko.observableArray(categories);
21594
21595        self.isLoading = ko.observable(true);
21596        self.userLatLong = ko.observable();
21597        self.errorMessage = ko.observable();
21598        self.pageType = ko.observable(componentElement.attr('data-resource').split('/').pop()); // product or sku-page
21599
21600        var skus = componentElement.attr('data-wtb-sku') ? componentElement.attr('data-wtb-sku').split(',') : [];
21601        self.skus = ko.observableArray(skus);
21602        self.productSku = componentElement.attr('data-product-sku');
21603        self.hasSalesforceResults = ko.observable(false);								// should we display find local section or not
21604        self.hasChannelAdvisor = ko.observable(componentElement.attr('data-wtb-in-sku-list') == 'true'); 	// should we display channeladvisor (find online section) or not
21605
21606        var productPageUrl = componentElement.attr("data-product-page-url") ? componentElement.attr("data-product-page-url") : ""
21607        var editMode = window.location.search.includes("wcmmode=disabled") ? 'edit' : 'publish'; // TODO remove this once full solution is found
21608        self.productPageUrl = ko.observable(productPageUrl);
21609
21610        self.pageUrl = ko.observable(window.location.pathname);
21611
21612        self.geoLocationFailed = ko.computed(function () {
21613            return !self.userLatLong() && !self.isLoading();
21614        });
21615
21616        self.runLatLongSearch = function (latLongData) {
21617            if (latLongData && latLongData.lat && latLongData.lng) {
21618                var pos = {latitude: latLongData.lat, longitude: latLongData.lng};
21619                loadMapData(pos);
21620            }
21621        };
21622
21623        self.linkUrl = ko.computed(function () {
21624            var link = self.pageType() === 'product' ? self.productPageUrl() : self.pageUrl().replace(".html", "");
21625
21626            // Adding conditional class to show non-commpdp if available
21627            $('.buttons.none-ecommpdp').addClass("has-child");
21628
21629            var skuSection = (self.skus().length >= 1) ? ('/sku/' + self.skus()[0]) : '';
21630            link += self.pageType() === 'product' ? skuSection + '/where-to-buy.html' : '';
21631            link += self.pageType() !== 'product' ? '/where-to-buy.html' : '';
21632
21633            if (!self.hasChannelAdvisor()) {
21634                if (isShowDealersLocator) {
21635                    link += '?show=local';
21636                } else if (isShowDistributorsLocator) {
21637                    link += '?show=localDistributors';
21638                }
21639            } else {
21640                link += '?show=online'
21641            }
21642
21643            var prefix = link.indexOf('?') == -1 ? '?' : '&';
21644            link += prefix + 'from=' + self.pageType();
21645
21646            return editMode === "publish" ? link.replace("/content/pentair", "") : link;
21647        });
21648
21649        self.init = function () {
21650            initUserLatLong();
21651            self.initSearch = self.userLatLong.subscribe(function (newValue) {
21652                if (newValue) {
21653                    self.runLatLongSearch(newValue);
21654                }
21655                self.initSearch.dispose();
21656            });
21657        };
21658
21659        // If a user hits the 'x' when the location requests pops up in IE, the error section is not hit,
21660        // and the service fails silently.
21661        function geoLocationIETimeout() {
21662            var isIE = /*@cc_on!@*/false || !!document.documentMode; // Internet Explorer 6-11
21663            self.geoLocationStatus = ko.observable('waiting');
21664            if (isIE) {
21665                setTimeout(function () {
21666                    if (self.geoLocationStatus() === 'waiting') {
21667                        self.errorMessage('noGeo');
21668                        self.initSearch.dispose();
21669                        self.isLoading(false);
21670                    }
21671                }, 3000);
21672            }
21673        };
21674
21675        function initUserLatLong() {
21676            if (navigator.geolocation) {
21677                geoLocationIETimeout();
21678                navigator.geolocation.getCurrentPosition(function (position) {
21679                    var pos = {lat: position.coords.latitude, lng: position.coords.longitude}
21680                    self.userLatLong(pos);
21681                    self.geoLocationStatus('complete');
21682                }, function (e) { // error
21683                    self.errorMessage('noGeo');
21684                    self.initSearch.dispose();
21685                    self.isLoading(false);
21686                    self.geoLocationStatus('complete');
21687                });
21688            }
21689        };
21690
21691        function loadMapData(locationData) {
21692            var extendLocationData = {
21693                distance: 200,
21694                brands: self.brands().join(','),
21695                categories: self.categories().join(',')
21696            };
21697            locationData = locationData;
21698            $.extend(locationData, extendLocationData);
21699            self.isLoading(true);
21700            self.errorMessage(NO_SUPPLIERS_ERROR_MESSAGE);
21701
21702            $.ajax({
21703                type: 'GET',
21704                data: locationData,
21705                url: SFDC_URL,
21706                beforeSend: function () {
21707                },
21708                success: function (data) {
21709                    jsonData = JSON.parse(data);
21710                    var filteredResults = jsonData.results.filter(function (elem) {
21711                        return elem.hideAddress == false;
21712                    });
21713                    self.hasSalesforceResults(filteredResults.length > 0);
21714                    self.isLoading(false);
21715                },
21716                error: function (data) {
21717                    self.isLoading(false);
21718                }
21719            });
21720        };
21721
21722        // Fire all 'on click' event analytics tracking methods
21723        self.wtbAnalyticsEvents = function () {
21724            trackWTBClickEvent();
21725            constructAlgoliaAnalyticsWTBObject();
21726            return true;
21727        }
21728
21729        // [SEAP-145] - Algolia WTB Conversion Tracking
21730        function constructAlgoliaAnalyticsWTBObject() {
21731            var queryParams = window.location.href.indexOf("?") !== -1;
21732            if (queryParams) {
21733                var search = window.location.search.substring(1);
21734                var params = JSON.parse('{"' + decodeURI(search).replace(/&/g, '","').replace(/=/g, '":"') + '"}');
21735                if (params.hasOwnProperty("queryID") && params.hasOwnProperty("objectID") && params.hasOwnProperty("indexName")) {
21736                    var userToken = "";
21737                    if (typeof _satellite !== undefined && _satellite != null) {
21738                        userToken = _satellite.getVisitorId().getMarketingCloudVisitorID();
21739                    }
21740                    // attach to window object with conversion tracking details
21741                    aa('convertedObjectIDsAfterSearch', {
21742                        userToken: userToken,
21743                        eventName: 'Where_To_Buy',
21744                        index: params.indexName,
21745                        queryID: params.queryID,
21746                        objectIDs: [params.objectID]
21747                    });
21748                }
21749            }
21750            return true;
21751        }
21752
21753        // Abode Analytics
21754        // Tracks the WTB button click event
21755        function trackWTBClickEvent() {
21756            var eventWTBPayload = {
21757                eventName: 'WTB click',
21758                eventType: 'event',
21759                attributes: {
21760                    visitor: {
21761                        pentairCustomerID: getPentairCustomerID(), //if this is available
21762                        dealerID: getDealerID(), //if this is available
21763                        distributorID: getDistributorID() //if this is available
21764                    },
21765                    page: {
21766                        pageCanonical: getPageViewPageAttribute("pageCanonical"),
21767                        pageName: getPageViewPageAttribute("pageName"),
21768                        pagePath: getPageViewPageAttribute("pagePath"),
21769                        pageType: getPageViewPageAttribute("pageType"),
21770                        pageURL: getPageViewPageAttribute("pageURL"),
21771                        pageTitle: getPageViewPageAttribute("pageTitle"),
21772                        pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
21773                        businessUnitID: getPageViewPageAttribute("businessUnitID"),
21774                        subBrand: getPageViewPageAttribute("subBrand"),
21775                        language: getPageViewPageAttribute("language"),
21776                        author: getPageViewPageAttribute("author"),
21777                    },
21778                    product: {
21779                        skuID: self.productSku,
21780                        productName: getPageViewProductAttribute("productName"),
21781                        type: getPageViewProductAttribute("type")
21782                    }
21783                }
21784            }
21785            trackEventWithQueue(eventWTBPayload);
21786        }
21787
21788        self.init();
21789    };
21790
21791    $(document).ready(function () {
21792        $('.wtb-button.component').each(function () {
21793            try {
21794                ko.applyBindings(new WhereToBuyButton($(this)), this);
21795            } catch (e) {
21796                console.log(e);
21797            }
21798        });
21799    });
21800})();
21801
21802(function() {
21803    var displayHelpers = function(self) {
21804        return {
21805            distance: function(data) {
21806                return Math.round(data.distance * 10) / 10;
21807            },
21808            address: function(data) {
21809                var addressParts = [data.address1, data.address2, data.city, data.state, data.postal_code, data.country].filter(function(elem) { return !!elem });
21810                var fullAddress = "";
21811                addressParts.forEach(function(addressElem, addressIndex) {
21812                    var addComma = addressIndex < (addressParts.length - 1);
21813                    fullAddress += addressElem + (addComma ? ', ' : '');
21814                });
21815                return fullAddress;
21816            },
21817            showDirections: function(data) {
21818                return data.hideAddress === false;
21819            },
21820            phone: function(data) {
21821                return data.phone ? ('tel: ' + data.phone) : '';
21822            },
21823            email: function(data) {
21824                return data.email ? ('mailto:' + data.email) : '';
21825            },
21826            googleDirectionsLink: function(data) {
21827                return "https://www.google.com/maps/dir/?api=1&destination=" + this.address(data);
21828            },
21829            showTrueBlue: function(data) {
21830                return data.status === "True Blue";
21831            },
21832            website: function(data) {
21833                var websiteExp = /(https:\/\/|http:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/;
21834                var normalUrlCheck = data.website && data.website.match(websiteExp);
21835                if (normalUrlCheck && data.website.indexOf('//') > -1) {
21836                    return data.website;
21837                } else if (normalUrlCheck && data.website.indexOf('//') === -1) {
21838                    return data.website ? '//' + data.website : '';
21839                } else {
21840                    return '';
21841                }
21842            },
21843            showNoResultsMessage: function() {
21844                return self.dealerList().length === 0 && !self.isLoading() && self.errorMessage() === 'noDealers';
21845            },
21846            showNoGeoLocationMessage: function() {
21847                return !self.isLoading() && self.errorMessage() === 'noGeo';
21848            },
21849            showGeo: function() {
21850                return self.userLatLong() && self.userLatLong().lat && self.userLatLong().lng;
21851            }
21852        }
21853    };
21854
21855    var WhereToBuyViewModel = function(componentElement) {
21856        var self = this;
21857
21858        self.dealerList = ko.observableArray(); // Populated by ajax call.
21859
21860        self.mapHelper = new PENTAIR.Water.MapHelper(componentElement.find('.map-container'));
21861        self.googleMapsData = ko.observableArray();
21862        self.filterModel = new GenericFilterViewModel();
21863
21864        var filterRules = {
21865            'Distance': function(dealerItem, currentFilter) {
21866                return currentFilter.value() >= dealerItem.distance;
21867            },
21868            'Dealer Name': function(dealerItem, currentFilter) {
21869                return currentFilter.value() === dealerItem.name;
21870            },
21871            'Store Type': function(dealerItem, currentFilter) {
21872                // if brand name is selected, check against only that brand, else look for any.
21873                // var activeBrandFilters = currentFilter.parent.parent.activeFilters().filter(function(activeFilter){
21874                //     return activeFilter.parent.name() === "Brand Name";
21875                // });
21876
21877                // var activeBrandNames = activeBrandFilters.map(function(activeBrandFilter){return activeBrandFilter.value()});
21878
21879                var valueBasedRules = {
21880                    "Service Only": function(record) { return !record["Retail__c"] && record["Service__c"] },
21881                    "Retail Only": function(record) { return record["Retail__c"] && !record["Service__c"] },
21882                    "Retail & Service": function(record) { return record["Retail__c"] && record["Service__c"] },
21883                };
21884
21885                // var recordsMatchingBrandName = dealerItem.details.records.filter(function(elem){return activeBrandNames.indexOf(elem["Brand_Name__c"]) > -1}) // If ANY of the brand names you have selected?
21886                return dealerItem.details.records.reduce(function(acc, record) {
21887                    return acc || valueBasedRules[currentFilter.value()](record)
21888                }, false)
21889            },
21890            'Brand Name': function(dealerItem, currentFilter) {
21891                return dealerItem.brands.indexOf(currentFilter.value()) > -1;
21892            },
21893            'Product Category': function(dealerItem, currentFilter) {
21894                return dealerItem.categories.indexOf(currentFilter.value()) > -1;
21895            },
21896            'Partner Level': function(dealerItem, currentFilter) {
21897                return currentFilter.value() === dealerItem.status;
21898            }
21899        };
21900
21901        self.searchInput = ko.observable().extend({ throttle: 200 });
21902
21903        self.userPostalCode = ko.observable();
21904        self.userLatLong = ko.observable();
21905        self.userAddress = ko.observable();
21906        self.userCity = ko.observable('');
21907        self.userState = ko.observable('');
21908        self.userPostalCode = ko.observable('No Zip');
21909
21910        self.zipQueryParam = ko.observable(getParams().zip ? decodeURIComponent(getParams().zip).replace(/\+/g, ' ') : '');
21911        self.zipcodeLat = ko.observable('');
21912        self.zipcodeLong = ko.observable('');
21913        self.zipcodeAddress = ko.observable('');
21914
21915        self.filterModal = ko.observable('closed'); // closed or open
21916        self.errorMessage = ko.observable('noDealers'); // 'noDealers' or 'noGeo'
21917
21918        // Brands and categories are populated with TAGS from aem.
21919        var brands = componentElement.data('brands') ? componentElement.data('brands').split(',') : '';
21920        self.brands = ko.observableArray(brands);
21921
21922        var categories = componentElement.data('categories') ? componentElement.data('categories').split(',') : '';
21923        self.categories = ko.observableArray(categories);
21924
21925        self.userLatLong.subscribe(function(newValue) {
21926            var geocoder = new google.maps.Geocoder();
21927            if (newValue) {
21928                geocoder.geocode({ 'latLng': newValue }, function(results, status) {
21929                    if (status == google.maps.GeocoderStatus.OK) {
21930                        self.userAddress(results[0].formatted_address);
21931
21932                        var addressData = getCityStateZip(results);
21933                        self.userCity(addressData.city);
21934                        self.userState(addressData.state);
21935                        self.userPostalCode(addressData.zip);
21936                    }
21937                });
21938            }
21939        });
21940
21941        var getCityStateZip = function(results){
21942            var outputData = {city: '', state: '', zip: ''};
21943
21944            if(results[0] && results[0]['address_components']){
21945                var cityNameArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('locality') !== -1});
21946                var stateNameArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('administrative_area_level_1') !== -1});
21947                var postalCodeArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('postal_code') !== -1});
21948                outputData['city'] = (cityNameArray && cityNameArray.length > 0) ? cityNameArray[0]['long_name'] : "";
21949                outputData['state']  = (stateNameArray && stateNameArray.length > 0) ? stateNameArray[0]['short_name'] : "";
21950                outputData['zip'] = (postalCodeArray && postalCodeArray.length > 0) ? postalCodeArray[0]['long_name'] : "";
21951
21952            }
21953
21954            return outputData;
21955        };
21956
21957        self.isLoading = ko.observable(true);
21958        self.activeIndex = ko.observable(null);
21959
21960        //Check if active filter is still visible when filter updates.
21961        function updateActiveFilter(filteredData) {
21962            var visibleIndexes = filteredData.map(function(elem) { return elem.index });
21963            if (!self.activeIndex() || (self.activeIndex() && visibleIndexes.indexOf(self.activeIndex()) == -1)) {
21964                self.activeIndex(null);
21965                self.mapHelper.closeMarker();
21966            }
21967        }
21968
21969        // Hide or show pins when filter changes.
21970        self.filterModel.filteredDataList.subscribe(function(newValue) {
21971            var visiblePinIndexes = newValue.map(function(elem) { return elem.index });
21972            self.mapHelper.showPins(visiblePinIndexes);
21973            updateActiveFilter(newValue);
21974        });
21975
21976        self.locationClick = function() {
21977            if (self.userLatLong() && self.userLatLong().latitude && self.userLatLong().longitude) {
21978                var pos = { lat: self.userLatLong().latitude, lng: self.userLatLong().longitude };
21979                self.runLatLongSearch(pos);
21980            }
21981        };
21982
21983        self.isActive = function(data) {
21984            return (self.activeIndex() !== null) && (self.activeIndex() === data.index);
21985        };
21986
21987        // workaround for preventing bubbling (and preventDefault) when an anchor tag is
21988        // inside a div with a click event.
21989        self.innerClick = function(selection, event) {
21990            /* Analytics Model Update*/
21991            if ((selection && selection.name) && (event && event.target && event.target.dataset && event.target.dataset.eventName)) {
21992                updateDataLayerObj(selection.name, 'Result Link', event.target.dataset.eventName, undefined, undefined, undefined, false);
21993            }
21994            // Adobe analytics
21995            trackWTBClickEvent('WTB list get directions click', selection.id, selection.index, 'get directions');
21996            return true;
21997        };
21998
21999        self.dealerClick = function(data) {
22000            self.mapHelper.closeMarker();
22001            self.activeIndex(data.index);
22002            if (!data.hideAddress) {
22003                self.mapHelper.openMarker(data.index);
22004            }
22005            // Adobe analytics
22006            const business = [{name: data.name, zip: data.postal_code}];
22007            trackWTBClickEvent('WTB search result list click', data.id, data.index, 'list result', business);
22008        };
22009
22010        self.activePanel = ko.observable('list');
22011
22012        self.mapPanelActive = function() { return self.activePanel() === 'map' };
22013
22014        self.listPanelActive = function() { return self.activePanel() === 'list' };
22015
22016        self.setListPanel = function() {
22017            self.activePanel('list');
22018            self.reInitJscroll(true);
22019        };
22020
22021        self.setMapPanel = function() {
22022            self.activePanel('map');
22023            self.mapHelper.updateZoom();
22024        };
22025
22026        self.openFilterModal = function() {
22027            self.filterModal('open');
22028            $('body').addClass('filter-open modal-open');
22029            ensureOpenFilterZPosition()
22030        };
22031
22032        self.closeFilterModal = function() {
22033            self.filterModal('closed');
22034            $('body').removeClass('filter-open modal-open');
22035            ensureClosedFilterZPosition()
22036        };
22037
22038        self.isFilterModalOpen = function() {
22039            return self.filterModal() === 'open';
22040        };
22041
22042        // Used for hiding/showing sections. No hash means show all sections.
22043        var hashes = window.location.hash.replace("#", "");
22044        var hashArray = hashes ? hashes.split(",") : [];
22045        self.urlHashes = ko.observableArray(hashArray);
22046
22047        // Jscroll handling.
22048        self.filterModel.setFilterRules(filterRules);
22049
22050        self.reInitJscroll = ko.observable(false).extend({ rateLimit: 100, notify: 'always' });
22051
22052        self.filterModel.activeFilters.subscribe(function(newValue) {
22053            self.reInitJscroll(true);
22054        });
22055
22056        self.displayHelpers = displayHelpers(self);
22057
22058        self.reInitJscroll.subscribe(function(newValue) {
22059            if (newValue) {
22060                self.reInitJscroll(false);
22061                reInitJscroll();
22062            }
22063        });
22064
22065        function reInitJscroll() {
22066            if (componentElement.find('.scroll-list').jScrollPane) {
22067                componentElement.find('.scroll-list').jScrollPane({
22068                    contentWidth: '0px',
22069                    autoReinitialize: true
22070                });
22071
22072            }
22073        }
22074
22075        $(window).on('resize', function(e) {
22076            self.reInitJscroll(true);
22077        });
22078
22079        function getVisiblePins() {
22080            var indexArray = [];
22081
22082            return indexArray;
22083        }
22084
22085        self.afterRender = function() {
22086            self.reInitJscroll(true);
22087        };
22088
22089        // Populate Filters:
22090        self.dealerList.subscribe(function(newValue) {
22091            var distanceValues = [{ value: 10, title: 10 }, { value: 20, title: 20 }, { value: 30, title: 30 }, { value: 50, title: 50 }, { value: 100, title: 100 }, { value: 150, title: 150 }, { value: 200, title: 200 }];
22092            var storeTypeValues = [{ value: "Service Only", title: "Service Only" }, { value: "Retail Only", title: "Retail Only" }, { value: "Retail & Service", title: "Retail & Service" }];
22093            var recordFilters = getRecordFilters();
22094            var filterCategories = [
22095                { name: "Distance", type: "static", values: distanceValues, inputType: "radio" },
22096                { name: "Dealer Name", type: "dynamic", fromField: "name", inputType: "checkbox" },
22097                //{name: "Store Type", type: "static", values: storeTypeValues, inputType: "radio"},
22098                { name: "Brand Name", type: "static", values: recordFilters.brandNameFilters, inputType: "checkbox" },
22099                // {name: "Product Category", type: "static", values: recordFilters.categoryFilters, inputType: "checkbox"}, waiting on new API/backend field 'product line'
22100                { name: "Partner Level", type: "dynamic", fromField: "status", inputType: "checkbox" }
22101            ];
22102
22103            if (self.brands().length == 1) {
22104                filterCategories = filterCategories.filter(function(elem) { return elem.name !== "Brand Name" });
22105            }
22106
22107            self.filterModel.filters([]);
22108            self.filterModel.populateCategories(filterCategories, newValue);
22109            initFilterSelection(newValue);
22110        });
22111
22112        function initFilterSelection(dealerList) {
22113            var distanceCategory = self.filterModel.filters().filter(function(categoryFilter) { return categoryFilter.name() === "Distance" });
22114            var distanceFiltersWithResults;
22115            if (distanceCategory.length && distanceCategory[0].values()) {
22116                distanceFiltersWithResults = distanceCategory[0].values().filter(function(filterModel) { return (filterModel.count() > 0) && (filterModel.value() >= 50) });
22117                if (distanceFiltersWithResults.length > 0) {
22118                    distanceFiltersWithResults[0].toggleSelection();
22119                    setInitialRadius();
22120                }
22121            }
22122        }
22123
22124        // If a user hits the 'x' when the location requests pops up in IE, the error section is not hit,
22125        // and the service fails silently.
22126        function geoLocationIETimeout() {
22127            var isIE = /*@cc_on!@*/ false || !!document.documentMode; // Internet Explorer 6-11
22128            self.geoLocationStatus = ko.observable('waiting');
22129            if (isIE) {
22130                setTimeout(function() {
22131                    if (self.geoLocationStatus() === 'waiting') {
22132                        self.errorMessage('noGeo');
22133                        self.firstSearch.dispose();
22134                        self.isLoading(false);
22135                    }
22136                }, 8000);
22137            }
22138        };
22139
22140        function initUserLatLong() {
22141            if (navigator.geolocation) {
22142                geoLocationIETimeout();
22143                navigator.geolocation.getCurrentPosition(function(position) {
22144                    var pos = { lat: position.coords.latitude, lng: position.coords.longitude };
22145                    self.userLatLong(pos);
22146                    self.geoLocationStatus('complete');
22147                }, function(e) { // error
22148                    self.errorMessage('noGeo');
22149                    self.firstSearch.dispose();
22150                    self.geoLocationStatus('complete');
22151                    self.isLoading(false);
22152                });
22153            }
22154        }
22155
22156        function getParams() {
22157            return _.chain(location.search.slice(1).split('&'))
22158                .map(function (item) { if (item) { return item.split('='); } })
22159                .compact()
22160                .object()
22161                .value();
22162        }
22163
22164        self.runLatLongSearch = function(latLongData) {
22165            if (latLongData && latLongData.lat && latLongData.lng) {
22166                var pos = { latitude: latLongData.lat, longitude: latLongData.lng };
22167
22168                // Reset user location
22169                if (latLongData) {
22170                    var geocoder = new google.maps.Geocoder();
22171                    if (!self.zipQueryParam()) {
22172                        geocoder.geocode({ 'latLng': latLongData }, function(results, status) {
22173                            if (status == google.maps.GeocoderStatus.OK) {
22174                                self.userAddress(results[0].formatted_address);
22175
22176                                var addressData = getCityStateZip(results);
22177                                self.userCity(addressData.city);
22178                                self.userState(addressData.state);
22179                                self.userPostalCode(addressData.zip);
22180
22181                                self.searchInput(self.userAddress());
22182                            }
22183                        });
22184                        loadMapData(pos);
22185                    } else {
22186                          var address = self.zipQueryParam();
22187                          geocoder.geocode({ 'address': 'zipcode '+address }, function (results, status) {
22188                              if (status == google.maps.GeocoderStatus.OK) {
22189                                  var latitude = results[0].geometry.location.lat();
22190                                  var longitude = results[0].geometry.location.lng();
22191                                  var address = results[0].formatted_address;
22192                                  self.zipcodeLat(latitude);
22193                                  self.zipcodeLong(longitude);
22194                                  self.zipcodeAddress(address);
22195                                  self.searchInput(address);
22196                                  var zipPos = { latitude: latitude, longitude: longitude };
22197                                  loadMapData(zipPos);
22198                              }
22199                          });
22200                    }
22201                }
22202
22203                self.activeIndex(null);
22204                self.reInitMap();
22205            }
22206        };
22207
22208        self.runAddressSearch = function(address) {
22209            var geocoder = new google.maps.Geocoder();
22210            if (address) {
22211                geocoder.geocode({ 'address': address }, function(results, status) {
22212                    if (status == google.maps.GeocoderStatus.OK) {
22213                        var pos = { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng() };
22214                        self.runLatLongSearch(pos);
22215                    }
22216                });
22217            }
22218        };
22219
22220        self.locationSearchClick = function() {
22221            if (self.userLatLong() && self.userLatLong().lat && self.userLatLong().lng) {
22222                self.runLatLongSearch(self.userLatLong());
22223                self.searchInput(self.userAddress());
22224            } else {
22225                self.init(); // asks for location data again.
22226            }
22227        };
22228
22229        self.searchUserInputClick = function() {
22230            self.runAddressSearch(self.searchInput());
22231        }
22232
22233        self.searchInputKeypress = function(scope, event) {
22234            initAutocomplete();
22235            return true;
22236        };
22237
22238        // Bias the autocomplete object to the user's geographical location,
22239        // as supplied by the browser's 'navigator.geolocation' object.
22240        self.geolocate = function geolocate() {
22241            if (navigator.geolocation && autocomplete) {
22242                navigator.geolocation.getCurrentPosition(function(position) {
22243                    var geolocation = {
22244                        lat: position.coords.latitude,
22245                        lng: position.coords.longitude
22246                    };
22247                    var circle = new google.maps.Circle({ center: geolocation, radius: position.coords.accuracy });
22248                    autocomplete.setBounds(circle.getBounds());
22249                });
22250            }
22251        };
22252
22253        self.showContactDealer = function(data) {
22254            return data.phone || data.website || data.email;
22255        };
22256
22257        self.showContactCallback = function(event, selection) {
22258            /* Analytics Model Update*/
22259            if ((selection && selection.name) && (event && event.target && event.target.dataset && event.target.dataset.eventName)) {
22260                updateDataLayerObj(selection.name, 'Result Link', event.target.dataset.eventName, undefined, undefined, undefined, false);
22261            }
22262            if ($(event.target).is($('a.contact-dealer'))) {
22263                event.preventDefault();
22264                if ($(event.target).parents('.marker').length) { // in map infowindow
22265                    $(event.target).parents('.show-contact').siblings('.contact').show();
22266                    $(event.target).parents('.show-contact').hide();
22267                    // Adobe analytics
22268                    var markerElem = event.target.closest('.marker');
22269                    trackWTBClickEvent('WTB map contact dealer click', markerElem.dataset.dealerId, markerElem.dataset.dealerIndex, 'map contact dealer');
22270                } else { // in dealer list
22271                    $(event.target).siblings('.contact').show();
22272                    $(event.target).hide();
22273                    reInitJscroll();
22274                    // Adobe analytics
22275                    trackWTBClickEvent('WTB list contact dealer click', selection.id, selection.index, 'contact dealer');
22276                }
22277            }
22278        };
22279
22280        self.reInitMap = function() {
22281            var initMap = self.dealerList.subscribe(function() {
22282                updateDataLayerList(); // analytics wants a list of results
22283                self.googleMapsData(getGoogleMapsModel());
22284                self.mapHelper.setMarkerHtmlCallback(markerHtmlCallback);
22285                self.mapHelper.initMap(self.googleMapsData());
22286                self.mapHelper.addInfoWindowEvent('click', self.showContactCallback);
22287                initMap.dispose();
22288            });
22289        };
22290
22291        var total;
22292
22293        function updateDataLayerList() {
22294            var userAddress = self.searchInput();
22295            if (self.dealerList().length !== total) { // don't bother if results haven't changed
22296                total = self.dealerList().length;
22297                var dealerListNames = [];
22298                self.dealerList().forEach(function(elem) {
22299                    dealerListNames.push(elem.name);
22300                });
22301                dealerListNames = dealerListNames.join('|');
22302                updateDataLayerObj(undefined, 'Results Found', 'Dealers Impression', dealerListNames, undefined, undefined, userAddress, false);
22303            } else {
22304                var dealerListNames = [];
22305                self.dealerList().forEach(function(elem) {
22306                    dealerListNames.push(elem.name);
22307                });
22308                dealerListNames = dealerListNames.join('|');
22309                updateDataLayerObj(undefined, 'Results Found', 'Dealers Impression', dealerListNames, undefined, undefined, userAddress, false);
22310            }
22311        }
22312
22313        function clearDigitalDataProperty(prop, propVal) {
22314            // clears out optional/circumstantial analytics properties
22315            if (propVal) {
22316                digitalData.findDealer[prop] = propVal;
22317            } else {
22318                if (digitalData.findDealer[prop]) {
22319                    delete digitalData.findDealer[prop];
22320                }
22321            }
22322        }
22323
22324        self.updateAnalytics = function updateAnalytics(scopedItem) {
22325            if (scopedItem && scopedItem.selected()) {
22326                var filterType = scopedItem.parent && scopedItem.parent.name() ? scopedItem.parent.name() : undefined;
22327                var filterValue = scopedItem.value();
22328                updateDataLayerObj(undefined, "Refine Search", "Apply Filter", undefined, filterType, filterValue, undefined, true);
22329            }
22330            return true;
22331        };
22332
22333        // strictly for updating Data Layer Object with user location data
22334        function getUserLocationData(res) {
22335            var city, state, zip, formattedAddress;
22336
22337            city = self.userCity();
22338            state = self.userState();
22339            zip = /\d{5}/.test(res) ? self.userPostalCode() : "No Zip";
22340            formattedAddress = city + "|" + state + "|" + zip;
22341
22342            return formattedAddress;
22343        }
22344
22345        function updateDataLayerObj(name, eventAction, eventName, dealerList, filterType, filterValue, address, fireInputTracking) {
22346            try {
22347                if (digitalData) {
22348                    if (digitalData.findDealer) {
22349                        var TYPE = 'Find A Dealer';
22350                        clearDigitalDataProperty('name', name);
22351                        clearDigitalDataProperty('dealersFound', dealerList);
22352                        clearDigitalDataProperty('filterType', filterType);
22353                        clearDigitalDataProperty('filterValue', filterValue);
22354                        digitalData.findDealer.eventName = eventName;
22355                        digitalData.findDealer.type = TYPE;
22356                        digitalData.findDealer.eventAction = eventAction;
22357                        digitalData.findDealer.timeStamp = new Date();
22358                        digitalData.findDealer.dealerFormInput = getUserLocationData(address);
22359                        if (!_.isUndefined(window._satellite) && fireInputTracking) {
22360                            window._satellite.track("wtb_input");
22361                        }
22362
22363                    }
22364                }
22365            } catch (err) {
22366                console.log(err);
22367            }
22368        }
22369
22370        /**
22371         * Constructs the payload for the click event analytics tracking and sends the payload to be tracked.
22372         * @param eventName analytics event name
22373         * @param wtbDealerIDClicked ID of the dealer clicked
22374         * @param wtbSearchResultIndex index of the clicked dealer in the list
22375         * @param wtbClickType click type: list result, contact dealer, get directions, map pin, map contact dealer
22376         * @param businesses a list of objects for businesses and their zip codes
22377         */
22378        function trackWTBClickEvent(eventName, wtbDealerIDClicked, wtbSearchResultIndex, wtbClickType, businesses = []) {
22379            var eventWTBClickPayload = {
22380                eventName: eventName,
22381                eventType: 'event',
22382                attributes: {
22383                    visitor: {
22384                        pentairCustomerID: getPentairCustomerID(), //if this is available
22385                        dealerID: getDealerID() //if this is available
22386                    },
22387                    wtbSearch: {
22388                        wtbBrands: self.brands().join(),
22389                        wtbCategories: self.categories().join(),
22390                        wtbSearchZip: self.userPostalCode(),
22391                        wtbDealerIDClicked: wtbDealerIDClicked,
22392                        wtbSearchResultIndex: wtbSearchResultIndex + 1, // index start at 1
22393                        wtbClickType: wtbClickType
22394                    },
22395                    ...(businesses.length > 0 && {wtbBusinessInfo: businesses.splice(0, 10)})
22396                }
22397            }
22398            trackEventWithQueue(eventWTBClickPayload);
22399        }
22400
22401        function markerHtmlCallback(item) {
22402            var infoHtml;
22403            if (item && !isNaN(item.index)) {
22404                infoHtml = $('<div>').addClass('marker')
22405                                    .attr('data-dealer-index', item.index)
22406                                    .attr('data-dealer-id', item.id);
22407            }
22408            if (item && item.name) {
22409                infoHtml.append($('<p>').addClass('location-name').html(item.name));
22410            }
22411            if (item && item.distance) {
22412                infoHtml.append($('<p>').addClass('distance').html(item.distance + ' miles away'));
22413            }
22414            if (item && item.address) {
22415                infoHtml.append($('<p>')
22416                    .html(item.address.split(',')[0] + '<br>' + item.address.split(',').slice(1).join(', ')));
22417            }
22418
22419            if(item && (item.phone || item.website || item.email)){
22420              var contact = $('<span>').addClass('contact').hide();
22421
22422              if(item && item.phone){
22423                contact.append(
22424                    $('<p>')
22425                        .addClass('phone-one')
22426                        .append('<span class="icon-phone" aria-hidden="true"></span>')
22427                        .append($('<a>').attr('href', 'tel:' + item.phone).html(item.phone))
22428                );
22429              }
22430              if(item && item.email){
22431                contact.append(
22432                    $('<p>')
22433                        .addClass('email')
22434                        .append('<span class="icon-pentair-email" aria-hidden="true"></span>')
22435                        .append(
22436                            $('<a>')
22437                                .attr('href', 'mailto:' + item.email)
22438                                .attr('target', '_blank')
22439                                .attr('rel', 'noopener noreferrer')
22440                                .html(item.email)
22441                        )
22442                );
22443              }
22444              if(item && item.website){
22445                contact.append(
22446                    $('<p>')
22447                        .addClass('website')
22448                        .append('<span class="icon-external-link-square" aria-hidden="true"></span>')
22449                        .append($('<a>').attr({'href': item.website, 'target': '_blank'}).html(' Website'))
22450                );
22451              }
22452
22453              infoHtml.append(contact);
22454              infoHtml.append($('<p>').addClass('show-contact').append('<span class="icon-address-book" aria-hidden="true"></span>').append($('<a>').addClass('contact-dealer').attr('href', '#').html(' Contact Dealer')));
22455            }
22456
22457            // If the callback came from clicking on a map pin, fire adobe analytics event for tracking map pin click
22458            if (item && event.target.closest('.map-container')) {
22459                const business = [{name: item.name, zip: item.zip}];
22460                trackWTBClickEvent('WTB map pin click', item.id, item.index, 'map pin', business);
22461            }
22462
22463            return infoHtml[0].outerHTML;
22464        }
22465
22466        self.init = function() {
22467            initUserLatLong();
22468            self.firstSearch = self.userLatLong.subscribe(function(newValue) {
22469                if (newValue) {
22470                    self.runLatLongSearch(newValue);
22471                }
22472                self.firstSearch.dispose();
22473            });
22474        };
22475
22476        function setInitialRadius() {
22477            var component = componentElement;
22478            var distance = component.find(".filter .Distance");
22479            var distanceFilters = distance.next("ul").find("li");
22480            for (var i = 0; i < distanceFilters.length; i++) {
22481                var currentFilter = $(distanceFilters[i]);
22482                var count = currentFilter.find(".item-count");
22483                var num = count.text().replace(/[()]/g, '');
22484                if (num > 0) {
22485                    currentFilter.find("input").click();
22486                    break;
22487                }
22488            }
22489        }
22490
22491        function loadMapData(locationData) {
22492            var extendLocationData = { distance: 200, brands: self.brands().join(','), categories: self.categories().join(',') };
22493            locationData = locationData;
22494            $.extend(locationData, extendLocationData);
22495            self.isLoading(true);
22496            self.errorMessage('noDealers');
22497            let businesses = [];
22498
22499            $.ajax({
22500                type: 'GET',
22501                data: locationData,
22502                url: '/bin/pentair/sfdc/dealers',
22503                beforeSend: function() {},
22504                success: function(data) {
22505                    if (data) {
22506                        jsonData = JSON.parse(data);
22507                        var sortedDealerResults = flattenBrandAndCategory(processData(jsonData.results));
22508                        self.dealerList(sortedDealerResults);
22509                        if (self.dealerList().length === 0 && (locationData.latitude && locationData.longitude)) {
22510                            var pos = { "lat": locationData.latitude, "lng": locationData.longitude };
22511                            self.mapHelper.setCenter(pos);
22512                        } else {
22513                            businesses = self.dealerList().map((item) => {
22514                                return {name: item.name, zip: item.postal_code}
22515                            });
22516                        }
22517                    } else {
22518                        console.error('No dealers found. -> ', data.length);
22519                    }
22520                    self.isLoading(false);
22521                    var pageViewDealerListLoaded = new CustomEvent("pageViewDealerListLoaded", {
22522                        detail: {
22523                            wtbSearch: {
22524                                wtbBrands: self.brands().join(),
22525                                wtbCategories: self.categories().join(),
22526                                wtbDealerID: getFilteredDealerIDs(),
22527                                wtbNumberResults: self.filterModel.filteredDataList().length,
22528                                wtbSearchZip: self.userPostalCode()
22529                            },
22530                            ...(businesses.length > 0 && {wtbBusinessInfo: businesses.splice(0, 10)})
22531                        }
22532                    });
22533                    // Dispatch the event to be handled in clientlib-site/js/analytics/pageView.js
22534                    var whereToBuyComponent = document.querySelector('.where-to-buy-new.component');
22535                    whereToBuyComponent.dispatchEvent(pageViewDealerListLoaded);
22536                },
22537                error: function(data) {
22538                    console.error('Error retrieving Dealer List ->', data);
22539                    self.isLoading(false);
22540                }
22541            });
22542        }
22543
22544        // PENW-3184 - resetting focus state of Search button when clicked?
22545        $(".where-to-buy-new.component .wtb-search").on("click", function(e) {
22546            e.preventDefault();
22547            $(this).blur();
22548        });
22549
22550        /**
22551         * Gets the filtered Dealer IDs that were returned in the search.
22552         * @returns comma separated string list of dealer IDs
22553         */
22554        function getFilteredDealerIDs() {
22555            var dealerIDs = [];
22556            self.filterModel.filteredDataList().forEach(function(dealer) {
22557                dealerIDs.push(dealer["id"]);
22558            });
22559            return dealerIDs.join();
22560        }
22561
22562        function flattenBrandAndCategory(data) {
22563
22564            data.forEach(function(dealerElem) {
22565                var brandNames = [];
22566                var categories = [];
22567
22568                dealerElem.details.records.forEach(function(recordElem) {
22569                    brandNames = brandNames.concat(recordElem["Brand_Name__c"]);
22570                    categories = categories.concat(recordElem["Category_Name__c"]);
22571                });
22572
22573                if (self.brands().length === 1) {
22574                    dealerElem['brands'] = self.brands();
22575                } else {
22576                    dealerElem['brands'] = ko.utils.arrayGetDistinctValues(brandNames).sort();
22577                }
22578
22579                dealerElem['categories'] = ko.utils.arrayGetDistinctValues(categories).sort();
22580            });
22581
22582            return data;
22583        }
22584
22585        function getRecordFilters() {
22586            var allBrandNames = [];
22587            var allCategories = [];
22588
22589            self.dealerList().forEach(function(dealerElem) {
22590                allBrandNames = allBrandNames.concat(dealerElem["brands"]);
22591                allCategories = allCategories.concat(dealerElem["categories"]);
22592            });
22593
22594            var brandNameFilters = ko.utils.arrayGetDistinctValues(allBrandNames).sort().map(function(elem) { return { value: elem, title: elem } });
22595            var categoryFilters = ko.utils.arrayGetDistinctValues(allCategories).sort().map(function(elem) { return { value: elem, title: elem } });
22596            return { brandNameFilters: brandNameFilters, categoryFilters: categoryFilters };
22597        }
22598
22599        function getGoogleMapsModel() {
22600            var mapData = self.dealerList()
22601                .map(function(elem, index) {
22602                    var mapElem = {};
22603                    mapElem.id = elem.id;
22604                    mapElem.name = elem.name;
22605                    mapElem.phone = elem.phone;
22606                    mapElem.email = elem.email;
22607                    mapElem.address = self.displayHelpers.address(elem);
22608                    mapElem.zip = elem.postal_code;
22609                    mapElem.website = self.displayHelpers.website(elem);
22610                    mapElem.index = index;
22611                    mapElem.latitude = elem.latitude;
22612                    mapElem.longitude = elem.longitude;
22613                    mapElem.distance = self.displayHelpers.distance(elem);
22614                    mapElem.hideAddress = elem.hideAddress;
22615                    return mapElem
22616                });
22617            return mapData;
22618        }
22619
22620        // Add indexes, and remove invalid results.
22621        function processData(data) {
22622            var sortedAndFiltered = data.filter(function(elem) {
22623                var validContact = (elem.hideAddress == false) || (elem.hideAddress && self.showContactDealer(elem));
22624                return elem.details && elem.details.records && validContact;
22625            });
22626
22627            $(sortedAndFiltered).each(function(index, elem) {
22628                elem.index = index;
22629            });
22630
22631            return sortedAndFiltered;
22632        }
22633
22634        /*  Start of autocomplete changes
22635            Autocomplete requires the Places library, e.g.,
22636            src="//maps.googleapis.com/maps/api/js?key=${config.googleMapsKey}&libraries=places   */
22637        var autocomplete;
22638
22639        function initAutocomplete() {
22640            // Create the autocomplete object, restricting the search predictions to
22641            // geographical location types.
22642            if (!autocomplete) {
22643                autocomplete = new google.maps.places.Autocomplete(componentElement.find('.autocomplete')[0], { types: ['geocode'] });
22644                // Avoid paying for data that you don't need by restricting the set of
22645                // place fields that are returned to just the address components.
22646                autocomplete.setFields(['address_component', 'formatted_address']);
22647                autocomplete.addListener('place_changed', function() {
22648                    //
22649                    result = autocomplete.getPlace();
22650                    if (typeof result.address_components == 'undefined') {
22651                        // The user pressed enter in the input
22652                        // without selecting a result from the list
22653                        // Let's get the list from the Google API so that
22654                        // we can retrieve the details about the first result
22655                        // and use it (just as if the user had actually selected it)
22656                        autocompleteService = new google.maps.places.AutocompleteService();
22657                        autocompleteService.getPlacePredictions({
22658                                'input': result.name,
22659                                'types': ['geocode']
22660                            },
22661                            function listentoresult(list, status) {
22662                                if (list == null || list.length == 0) {
22663                                    // There are no suggestions available.
22664                                    // The user saw an empty list and hit enter.
22665                                    //console.log("No results");
22666                                } else {
22667                                    // Here's the first result that the user saw
22668                                    // in the list. We can use it and it'll be just
22669                                    // as if the user actually selected it
22670                                    // themselves. But first we need to get its details
22671                                    // to receive the result on the same format as we
22672                                    // do in the AutoComplete.
22673                                    placesService = new google.maps.places.PlacesService(componentElement.find('.autocomplete')[0]);
22674                                    placesService.getDetails({ 'reference': list[0].reference },
22675                                        function detailsresult(detailsResult, placesServiceStatus) {
22676                                            // Here's the first result in the AutoComplete with the exact
22677                                            // same data format as you get from the AutoComplete.
22678                                            self.searchInput(detailsResult.formatted_address);
22679                                            self.runAddressSearch(detail
22679sResult.formatted_address);
22680                                        }
22681                                    );
22682                                }
22683                            }
22684                        );
22685                    } else {
22686                        // The user selected a result from the list, we can
22687                        // proceed and use it right away
22688                        var place = autocomplete.getPlace();
22689                        var address = place.formatted_address;
22690                        self.searchInput(address);
22691                        self.runAddressSearch(address);
22692                    }
22693                });
22694            }
22695        }
22696        /*END of autocomplete */
22697
22698        // lazy load if modal:
22699
22700        var parentModal = componentElement.parents('#storelocatormodal');
22701        var isInModal = !!parentModal.length;
22702        if (isInModal) {
22703            self = this;
22704            componentElement[0].init = self.init;
22705            componentElement[0].isLoading = self.isLoading;
22706        } else {
22707            self.init();
22708        }
22709    };
22710
22711    var regex = /(%22)+/g;
22712    var showParam;
22713    try {
22714        var queryString = location.search.substring(1);
22715        queryString = queryString.replace(regex, '_');
22716        var urlParams = queryString ? JSON.parse('{"' + decodeURIComponent(queryString).replace(/=&/g, "\":\"\",\"").replace(/&/g, "\",\"").replace(/=/g, "\":\"") + '"}') : {};
22717        showParam = urlParams["show"] || "";
22718    } catch (message) {
22719        var params = new URLSearchParams(window.location.search);
22720        showParam = params.get("show") || "";
22721    }
22722    $(document).ready(function () {
22723        $('.where-to-buy-new.component').each(function () {
22724            if (showParam) {
22725                $(document).find('section.toolbar').hide();
22726            }
22727            if (!showParam || showParam === "local") {
22728                try {
22729                    ko.applyBindings(new WhereToBuyViewModel($(this)), this);
22730                } catch (e) {
22731                    console.log(e);
22732                }
22733            } else {
22734                $('.where-to-buy-new.component').hide();
22735            }
22736        });
22737    });
22738})();
22739
22740window.Pentair = window.Pentair || {};
22741window.Pentair.updateFAD = function updateFAD() {
22742    var storelocator = $('#storelocatorwidget');
22743    storelocator.find('.storelocator-btn').each(function() {
22744        $(this).find('span.fa').remove();
22745        $(this)
22746            .removeClass('storelocator-btn-danger')
22747            .removeClass('storelocator-btn-primary')
22748            .removeClass('storelocator-btn')
22749            .addClass('btn')
22750            .addClass('btn-primary')
22751            .wrapInner('<span></span>');
22752    });
22753    storelocator.find('iframe').attr('title', 'Find A Dealer Map');
22754};
22755
22756$(function() {
22757    var where2Buy = $('.where-to-buy.component');
22758    if(where2Buy.length) {
22759        where2Buy.closest('section').find('div.bg-image').css('background-position', 'center bottom');
22760
22761        ////////////////////////////////////////////////////////
22762        //// building data analytics layer object start ///////
22763        //////////////////////////////////////////////////////
22764
22765        where2Buy.on('click', 'button.btn.btn-secondary', function(e) {
22766
22767            try {
22768                if(digitalData) {
22769                    var dataFilters = $('#storelocatorscript').attr('data-filters');
22770                    var brand = "";
22771                    if(dataFilters && dataFilters !== "") {
22772                        var brands = dataFilters.split(',');
22773                        if(brands.length > 0) {
22774                            brand = brands[0];
22775                        }
22776                    }
22777                    console.log("brand", brand);
22778                    if(digitalData.product) {
22779                        digitalData.product.productBrand = brand;
22780                    }
22781                    if(digitalData.event) {
22782                        var eventData = {};
22783                        eventData.eventName = "where to buy";
22784                        eventData.eventAction = "where to buy click";
22785                        eventData.type = "where to buy";
22786                        eventData.timeStamp = new Date();
22787                        digitalData.event.push(eventData);
22788                    }
22789
22790                }
22791
22792            } catch(err) {
22793                console.log(err);
22794            }
22795        });
22796        ////////////////////////////////////////////////////////
22797        ///// building data analytics layer object end  ///////
22798        //////////////////////////////////////////////////////
22799    }
22800
22801});
22802
22803$(window).load(function() {
22804    $('#storelocatormodal').on('show.bs.modal', function(e) {
22805        if(window.Pentair && !!window.Pentair.updateFAD) {
22806            window.Pentair.updateFAD();
22807        }
22808    });
22809});
22810
22811
22812$(document).ready(function(){
22813    var $table = $(".table.component");
22814    var $tableModal = $(".table.component .table-modal");
22815    var modal = document.querySelector('.table-modal');
22816
22817    if ($(".table.component tbody").hasClass("has-image")){
22818        $table.find("img.cq-image-placeholder").remove();
22819        if ($table.find("td").has("img")){
22820            $table.find("img").closest("td").addClass("add-icon");
22821            $table.find("img").wrap("<a href='#' data-toggle='table-modal' class='table-anchor'></a>");
22822        }
22823    }
22824    
22825    function killTheModal() {
22826        $("body").removeClass("table-modal-open");
22827        $tableModal.css("display", "");
22828        $tableModal.removeClass("active");
22829        $table.find(".table-modal img").attr("src", "");
22830        $table.find(".table-modal img").attr("alt", "");
22831        $table.find(".table-modal .product-info a").attr("href", "#");
22832        $table.find(".table-modal .product-info a").text("");
22833    }
22834
22835    $(".table.component tbody.has-image tr td img").on("click", function(e){
22836        e.preventDefault();
22837        $("body").addClass("table-modal-open");
22838        $(this).closest(".table.component").find(".table-modal").css("display", "block");
22839        $(this).closest(".table.component").find(".table-modal").addClass("active");
22840        $table.find(".table-modal img").attr("src", $(this).attr("src"));
22841        $table.find(".table-modal img").attr("alt", $(this).closest("td").next().find("a").text());
22842        $table.find(".table-modal .product-info a").attr("href", $(this).closest("td").next().find("a").attr("href"));
22843        $table.find(".table-modal .product-info a").text($(this).closest("td").next().find("a").text());
22844
22845    });
22846    
22847    if(modal) {
22848        modal.addEventListener('click', function(e) {
22849            if(e.target.classList.contains('table-modal')) {
22850                killTheModal();
22851            }
22852        });
22853    }
22854
22855    $(".table.component .table-modal button.close-modal").on("click", function(e){
22856        killTheModal()
22857    });
22858
22859    //cell text count for table formatting
22860    $('.table.component table td').each(function(){
22861        var textCount = $(this).text().trim().length;
22862        var thisIndex = $(this).index();
22863        var thisTable = $(this).closest('table');
22864        if (textCount <= 24) {
22865            thisTable.find('thead th:eq(' + thisIndex + ')').addClass('small-width');
22866        } else if (textCount > 25 && textCount < 75){
22867            thisTable.find('thead th:eq(' + thisIndex + ')').addClass('medium-width');
22868        } else if (textCount >= 75){
22869            thisTable.find('thead th:eq(' + thisIndex + ')').addClass('large-width');
22870        }
22871    });
22872});
22873
22874function mobileSlide(e) {
22875    var ths = $(e.currentTarget),
22876        rent = ths.parent().parent();
22877
22878    if(!(rent.hasClass('inactive') === true)) {
22879        rent.addClass('inactive');
22880        rent.find('td').each(function(i, el) {
22881            if(i > 0) {
22882                $(el).slideUp(250);
22883            }
22884        });
22885    } else {
22886        rent.removeClass('inactive');
22887        rent.find('td').each(function(i, el) {
22888            if(i > 0) {
22889                $(el).slideDown(250);
22890            }
22891        });
22892    }
22893};
22894
22895function mobileCleanUp(w, tbl) {
22896    if(w >= 768) {
22897        tbl.each(function(i, el) {
22898            $(el).removeAttr('class');
22899            $(el).find('td').removeAttr('class style');
22900        });
22901    } else {
22902        tbl.each(function(i, el) {
22903            $(el).addClass('inactive');
22904            $(el).find('td').not(":nth-child(1)").hide();
22905        });
22906
22907    }
22908}
22909
22910function hideTableView(showFullSku) {
22911
22912    if (showFullSku) {
22913        $(".data-tables .partial-sku-view").addClass("hidden");
22914        $(".data-tables .full-sku-view .less-skus").addClass("hidden");
22915    } else {
22916        $(".data-tables .full-sku-view").addClass("hidden");
22917    }
22918}
22919
22920var document_width;
22921$(function() {
22922	document_width=$(document).width();
22923    let showFullSku = $('.show-full-skus')?.data('showFullSkus');
22924    $(document).click(function(event) {
22925        var $target = $(event.target);
22926
22927        if ($target.closest(".less-skus").length > 0) {
22928            $(".full-sku-view").addClass("hidden");
22929            $(".partial-sku-view").removeClass("hidden");
22930        } else if ($target.closest(".more-skus").length > 0) {
22931            $(".full-sku-view").removeClass("hidden");
22932            $(".partial-sku-view").addClass("hidden");
22933        } else if($target.hasClass("sku-link")){
22934            event.preventDefault();
22935            localStorage.setItem("productFindingMethod","Navigation");
22936            document.cookie="productFindingMethod=Navigation; domain=.pentair.com; path=/";
22937            location.href = $target.attr("href");
22938        }
22939    });
22940
22941    $(".more-skus-link,.less-skus-link").attr("href","javascript:void(0);");
22942    hideTableView(showFullSku);
22943
22944    //cell text count
22945    $('.specs-tables table td').each(function(){
22946        var textCount = $(this).text().length;
22947        var thisIndex = $(this).index();
22948        var thisTable = $(this).closest('table');
22949        if (textCount > 25 && textCount < 75){
22950            thisTable.find('thead th:eq(' + thisIndex + ')').addClass('medium-width');
22951            $.fn.matchHeight._update()
22952        } else if (textCount >= 75){
22953            thisTable.find('thead th:eq(' + thisIndex + ')').addClass('large-width');
22954            $.fn.matchHeight._update()
22955        }
22956    });
22957
22958    // Makes table responsive
22959    $('.specs-table table tbody tr').each(function(i,el){
22960        var table = $(el).closest('table');
22961        var thead = table.find('thead th');
22962
22963        for (j = 0; j < $(el).find('td').length; j++) {
22964            $(this).find('td:eq('+j+')').wrapInner('<div class="content"></div>').prepend('<div class="header">'+thead.eq(j).text()+'</div>');
22965            if(j === 0) {
22966                $(this).find('td:eq('+j+')').append('<button class="toggle"></div>');
22967                $(this).find('td:eq('+j+') button.toggle').on('click', function(e) {
22968                    mobileSlide(e);
22969                });
22970            }
22971        }
22972    });
22973    //print the tables nicely
22974    $('.specs-table.component .print-only table tr').each(function(i,e){
22975        var table = $(this).closest('table');
22976        var thead = table.find('thead th');
22977
22978        for (j = 0; j < $(this).find('td').length; j++){
22979            $(this).find('td:eq('+j+')').attr('data-title',thead.eq(j).text());
22980        }
22981    });
22982    $(window).on('resize', function(e) {
22983        if(document_width!=$(document).width()) {
22984            document_width=$(document).width();
22985            mobileCleanUp($(window).outerWidth(), $('.specs-table table tbody tr'));
22986        }
22987    });
22988
22989    mobileCleanUp($(window).outerWidth(), $('.specs-table table tbody tr'));
22990    setTimeout(hideFull, 1000);
22991    function hideFull(){
22992        hideTableView(showFullSku);
22993    }
22994
22995    // E-Commerce Specs Table has missing data - counter by adding empty table cells for styling purposes
22996    var specsTableComponent = $(".specs-table.component");
22997    var table = specsTableComponent.find("table");
22998    for (var m = 0; m < table.length; m++) {
22999        var currTable = $(table[m]);
23000        var tableHeaders = currTable.find("th");
23001        var numHeaders = tableHeaders.length;
23002        var tableRows = currTable.find("tbody > tr");
23003        for (var i = 0; i < tableRows.length; i++) {
23004            var currRow = $(tableRows[i]);
23005            var numCells = currRow.find("td").length;
23006            if (numCells < numHeaders) {
23007                var diff = numHeaders - numCells;
23008                for (var j = 0; j < diff; j++) {
23009                    var emptyCell = "<td><span class='sr-only'>Empty Cell</span></td>";
23010                    currRow.append(emptyCell);
23011                }
23012            }
23013        }
23014    }
23015});
23016
23017(function() {
23018
23019    var displayHelpers = function(self) {
23020        return {
23021            kValue: function(data) {
23022                return data > 1000 ? data / 1000 + 'k' : data;
23023            },
23024            addCommas: function(data) {
23025                return data.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
23026            },
23027            saltTickLabel: function(index) {
23028                var label = self.isFirst(index) ? this.addCommas(self.minSalt) : '';
23029                label = label || (self.isLast(self.saltTickMarks(), index) ? this.addCommas(self.maxSalt) : '');
23030                return label;
23031            },
23032            gallonTickLabel: function(data, min, max) {
23033                var label = data % 4 === 0 ? min * (data / 4 + 1) : "";
23034                var kVal = self.displayHelpers.kValue(label);
23035                return label ? self.displayHelpers.addCommas(kVal) : "";
23036            }
23037        }
23038    };
23039
23040    var calculationHelper = function(self) {
23041        return {
23042            ppmNeeded: function(salinity) { return 3600 - salinity; },
23043            liters: function(gallons) { return gallons * 3.7854; }, //--- Gives you liters from Gallons
23044            glNeeded: function(ppmNeeded) { return ppmNeeded * 0.001; }, //--- Gives g/L needed
23045            gSaltNeeded: function(liters, glNeeded) { return liters * glNeeded; },
23046            lbsSaltNeeded: function(gSaltNeeded) { return Math.ceil(gSaltNeeded / 453.5923); } //--- Gives you lbs of salt needed.
23047        }
23048    };
23049
23050    var SalinityCalculatorViewModel = function(componentElement) {
23051        var self = this;
23052        self.displayHelpers = displayHelpers(self);
23053        self.calculationHelper = calculationHelper(self);
23054
23055        self.maxGallons = 40000;
23056        self.minGallons = self.maxGallons / 4;
23057        self.startingGallons = ((self.maxGallons - self.minGallons) / 2) + self.minGallons;
23058        self.gallonsOfWater = ko.observable(self.startingGallons);
23059        self.minSalt = 0;
23060        self.maxSalt = 3600;
23061        self.currentSaltLevel = ko.observable(self.maxSalt / 2);
23062        self.sliderHasChanged = ko.observable(false);
23063
23064        self.calculatedDemand = ko.computed(function() {
23065            if (!self.sliderHasChanged()) {
23066                return 0
23067            } else {
23068                var ppmNeeded = self.calculationHelper.ppmNeeded(self.currentSaltLevel());
23069                var liters = self.calculationHelper.liters(self.gallonsOfWater());
23070                var glNeeded = self.calculationHelper.glNeeded(ppmNeeded);
23071                var gSaltNeeded = self.calculationHelper.gSaltNeeded(liters, glNeeded);
23072                var lbsSaltNeeded = self.calculationHelper.lbsSaltNeeded(gSaltNeeded);
23073                return lbsSaltNeeded;
23074            }
23075        });
23076
23077        self.gallonsSub = self.gallonsOfWater.subscribe(function() {
23078            self.sliderHasChanged(true);
23079            self.gallonsSub.dispose();
23080            self.saltSub.dispose();
23081        });
23082
23083        self.saltSub = self.currentSaltLevel.subscribe(function() {
23084            self.sliderHasChanged(true);
23085            self.gallonsSub.dispose();
23086            self.saltSub.dispose();
23087        });
23088
23089        self.gallonSelected = ko.computed(function() {
23090            return (self.gallonsOfWater() - self.minGallons) / (self.maxGallons - self.minGallons) * 100 + '%';
23091        });
23092
23093        self.gallonUnselected = ko.computed(function() {
23094            return 100 - (self.gallonsOfWater() - self.minGallons) / (self.maxGallons - self.minGallons) * 100 + '%';
23095        });
23096
23097        self.saltSelected = ko.computed(function() {
23098            return (self.currentSaltLevel() - self.minSalt) / (self.maxSalt - self.minSalt) * 100 + '%';
23099        });
23100
23101        self.saltUnselected = ko.computed(function() {
23102            return 100 - (self.currentSaltLevel() - self.minSalt) / (self.maxSalt - self.minSalt) * 100 + '%';
23103        });
23104
23105        self.isOdd = function(data) {
23106            return data % 2 === 1;
23107        };
23108
23109        self.isEven = function(data) {
23110            return data % 2 === 0;
23111        };
23112
23113        self.isFirst = function(index) {
23114            return index === 0;
23115        };
23116
23117        self.isLast = function(array, index) {
23118            return index === (array.length - 1);
23119        };
23120
23121        self.isFirstOrLast = function(array, index) {
23122            return self.isFirst(index) || self.isLast(array, index);
23123        }
23124
23125        // These depend on some helper methods defined above.
23126        var gallonTickArray = (new Array(14)).join('0').split(''); // results in array of 13
23127        self.gallonTickMarks = ko.observableArray(gallonTickArray.map(function(elem, index) { return self.isOdd(index) ? 'small-tick' : 'large-tick' }));
23128        var saltTickArray = (new Array(13).join('0').split('')); // results in array of 12
23129        self.saltTickMarks = ko.observableArray(saltTickArray.map(function(elem, index) { return self.isFirstOrLast(saltTickArray, index) ? 'large-tick' : 'small-tick' }));
23130
23131        var initParams = function() {
23132            var queryString = location.search.substring(1);
23133            var urlParams = queryString ? JSON.parse('{"' + decodeURIComponent(queryString).replace(/=&/g, "\",\"").replace(/&/g, "\",\"").replace(/=/g, "\":\"") + '"}') : {};
23134            var saltParam = urlParams["salt"] || "";
23135            var gallonParam = urlParams["gallons"] || "";
23136
23137            if (saltParam || gallonParam) {
23138                self.gallonsOfWater(gallonParam);
23139                self.currentSaltLevel(saltParam);
23140            }
23141        };
23142
23143        initParams();
23144    };
23145
23146    $(document).ready(function() {
23147        $('.salinity-calculator.component .ko-container').each(function() {
23148            ko.applyBindings(new SalinityCalculatorViewModel($(this)), this);
23149        });
23150    });
23151
23152})();
23153
23154$(function() {
23155    if($('.related-products.component').length) {
23156        objectFitImages('img.product-image');
23157    }
23158    $('a.product-link').click(function(event) {
23159        localStorage.setItem("productFindingMethod", "Navigation");
23160        document.cookie="productFindingMethod=Navigation; domain=.pentair.com; path=/";
23161    });
23162    $( "a.product-link" ).contextmenu(function(event) {
23163        localStorage.setItem("productFindingMethod", "Navigation");
23164        document.cookie="productFindingMethod=Navigation; domain=.pentair.com; path=/";
23165      });
23166});
23167
23168// From tutorial https://hidde.blog/using-javascript-to-trap-focus-in-an-element/
23169function tabListener(e) {
23170    const focusableEls = e.currentTarget.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled]), .
23170iframe-helper-button');
23171    const firstFocusableEl = focusableEls[0];
23172    const lastFocusableEl = focusableEls[focusableEls.length - 1];
23173    const KEYCODE_TAB = 9;
23174    const isTabPressed = (e.key === 'Tab' || e.keyCode === KEYCODE_TAB)
23175    if (!isTabPressed) {
23176        return;
23177    }
23178
23179    if (e.shiftKey) {
23180        if (document.activeElement === firstFocusableEl) {
23181            lastFocusableEl.focus();
23182            e.preventDefault();
23183        }
23184    } else {
23185        if (document.activeElement === lastFocusableEl) {
23186            firstFocusableEl.focus();
23187            e.preventDefault();
23188        }
23189    }
23190}
23191
23192// If the modal ends with an iframe, insert a tabbable div so that we can detect last tabbable element in trapFocus()
23193function setIframeTabHelper(element) {
23194    const modalBody = element.querySelector('.modal__body');
23195    const bodyChildren = modalBody.getElementsByTagName('*');
23196    const lastBodyChild = bodyChildren[bodyChildren.length - 1];
23197
23198    if (lastBodyChild.tagName === "IFRAME") {
23199        const iframeTabHelper = document.createElement("div");
23200        iframeTabHelper.setAttribute("tabindex", "0");
23201        iframeTabHelper.classList.add("iframe-helper-button");
23202        modalBody.insertBefore(iframeTabHelper, lastBodyChild.nextSibling);
23203    }
23204}
23205
23206$(document).ready(function() {
23207    const wrapper = document.querySelector('.promobar-xpf .modal__wrapper');
23208    const overlay = document.querySelector('.promobar-xpf .modal__overlay');
23209    const closeBtn = document.querySelector('.promobar-xpf .modal__wrapper .btn-close');
23210
23211    if (!wrapper) {
23212        return;
23213    }
23214
23215    const openModal = (e) => {
23216        e.stopImmediatePropagation();
23217        e.preventDefault();
23218        fadeIn(wrapper);
23219        fadeIn(overlay);
23220        document.body.style.overflow = 'hidden';
23221        overlay.textContent = "Modal Open";
23222        closeBtn.focus();
23223        wrapper.addEventListener('keydown', tabListener);
23224    }
23225
23226    const closeModal = (e) => {
23227        e.stopImmediatePropagation();
23228        e.preventDefault();
23229        wrapper.removeEventListener('keydown', tabListener);
23230        document.querySelector('#skipLink').focus(); // Skip to Main Content link since unknown what link opened the modal
23231        overlay.textContent = "Modal Closed";
23232        document.body.style.overflow = '';
23233        fadeOut(overlay);
23234        fadeOut(wrapper);
23235    }
23236
23237    setIframeTabHelper(wrapper);
23238
23239    closeBtn.addEventListener('click', closeModal);
23240    overlay.addEventListener('click',closeModal);
23241
23242    // Setup links to open modal
23243    const modalHref = wrapper.getAttribute('data-target');
23244    const modalLinks = document.querySelectorAll("a[href='#" + modalHref + "']");
23245    const modalLinksArr = [...modalLinks];
23246    modalLinksArr.forEach(modalLink => {
23247        modalLink.addEventListener('click', openModal);
23248        modalLink.setAttribute('aria-label', 'Open Modal')
23249    });
23250});
23251
23252(function() {
23253    /* From original header.js for sticky jump nav */
23254    function doOriginalCode(isMobile) {
23255        // If both promobar and sticky jump nav are present, add a class for styling.
23256        let iparPromoBar = $('.promobar-xpf');
23257        let $stickyJumpNav = $('.sticky-jump-nav');
23258        if ((iparPromoBar.length) && ($stickyJumpNav.length)) {
23259            $(".promobar-xpf").addClass("promobar-xpf__sticky-nav");
23260        }
23261    }
23262
23263    /**
23264     * Hide promo bar when close button is used. Promo bar under hero, all other promo bars
23265     */
23266    function handlePromoClose() {
23267        $('.promo-bar-exp-frag .bar-close').on('click', function(e) {
23268            e.preventDefault();
23269            $('.promo-bar-exp-frag').addClass('bar-hide');
23270        });
23271
23272        $('.promo-bar-xpf .bar-close').on('click', function(e) {
23273            e.preventDefault();
23274            $('.promo-bar-xpf').addClass('bar-hide');
23275            if ($('.promobar-xpf').find('.promo-bar-xpf').attr('class').includes('sticky')) {
23276                $('section.hero.component').css({
23277                    marginTop: 0
23278                });
23279            }
23280        });
23281    }
23282
23283    /**
23284     * Calculate where promo bar should be for all use cases, ensure styling
23285     * If already processed, only add css for sizes that might change like header height and promo height
23286     * Sticky promo bar gets moved in the DOM, which may cause subsequent calls on resize to not pick up the correct if case since parent has changed
23287     */
23288    function updatePromoBarPosition() {
23289        // for iparsys, inherited, body
23290        $('.promobar-xpf').each(function(idx, el) {
23291            const isBodyPromo = $(el).attr('class').includes('body-promo');
23292            const isIparsysPromo = $(el).attr('class').includes('iparsys-promo');
23293            const isInheritedPromo = $(el).attr('class').includes('inherited-promo');
23294
23295            const promoChildDiv = $(el).find('.promo-bar-xpf');
23296            const isStickyPromo = $(promoChildDiv).attr('class').includes('sticky');
23297            const isMobile = window.matchMedia('(max-width: 767px)').matches;
23298            const isProcessed = $(el).attr('class').includes('processed');
23299            const hasStickyJumpNavMobile = $('.sticky-jump-nav.mobile').length > 0;
23300            const headerHeight = $('header').outerHeight() - 1;
23301            const promoHeight = $(promoChildDiv).outerHeight();
23302
23303
23304
23305            if (isBodyPromo || isStickyPromo || isIparsysPromo) {
23306                $(el).css({
23307                    marginTop: 0
23308                });
23309            } else {
23310                $(el).css({
23311                    marginTop: headerHeight
23312                });
23313            }
23314
23315            if (hasStickyJumpNavMobile) {
23316                const jumpNavHeight = $('.sticky-jump-nav.mobile button').outerHeight();
23317                const currentPromoTopMargin = parseInt($(el).css('margin-top').replace('px', ''));
23318
23319                $('.sticky-jump-nav.mobile').css({
23320                    zIndex: 51
23321                })
23322
23323                if (isStickyPromo) {
23324                    $(el).css({
23325                        marginTop: jumpNavHeight
23326                    });
23327                    $('section.hero.component').css({
23328                        marginTop: promoHeight + jumpNavHeight
23329                    })
23330
23331                }
23332                if (isInheritedPromo && !isStickyPromo) {
23333                    $(el).css({
23334                        marginTop: jumpNavHeight + currentPromoTopMargin
23335                    });
23336                }
23337
23338            }
23339
23340            if (isBodyPromo && isStickyPromo && !isProcessed) {
23341                $(el).css({
23342                    top: 'unset'
23343                });
23344            }
23345
23346            if (isInheritedPromo && !isStickyPromo) {
23347                doOriginalCode(isMobile);
23348            }
23349
23350            if (isStickyPromo) {
23351                // Move sticky promo out of main-content to below header
23352                if (!isProcessed) {
23353                    $(el).detach();
23354                    $('#bypassHeader').before(el);
23355                }
23356
23357                if (!isMobile) {
23358                    $('section.hero.component').css({
23359                        marginTop: promoHeight
23360                    })
23361                }
23362            }
23363
23364            $(el).addClass('processed')
23365        });
23366
23367        // for below hero
23368        $('.promo-bar-exp-frag').each(function(idx, el) {
23369            const isMobile = window.matchMedia('(max-width: 767px)').matches;
23370            doOriginalCode(isMobile);
23371        });
23372    }
23373
23374    /** Add classes to indicate which kind of promobar-xpf since there are three dom locations it might be in
23375     * Need to do this since the other code may move promo bar in the DOM, so class is the only way to know what it originally was
23376     */
23377    function initPromoBar() {
23378        $('.promobar-xpf').each(function(idx, el) {
23379            const isBodyPromo = $(el).parent().attr('class') === 'main-content';
23380            const isIparsysPromo = $(el).parent().parent().attr('role') === 'main';
23381            const isInheritedPromo = $(el).parent().attr('class') === 'promoBarIpar iparsys parsys';
23382
23383            if (isBodyPromo) {
23384                $(el).addClass('body-promo');
23385            } else if (isIparsysPromo) {
23386                $(el).addClass('iparsys-promo');
23387            } else if (isInheritedPromo) {
23388                $(el).addClass('inherited-promo');
23389            }
23390        });
23391    }
23392
23393    $(document).ready(function () {
23394        initPromoBar();
23395        updatePromoBarPosition();
23396        handlePromoClose();
23397
23398        $(window).on('resize', function() {
23399            updatePromoBarPosition();
23400        });
23401    })
23402})()
23403
23404const COOKIE_NAME = 'pnt_pb_pop';
23405const COOKIE_VALUE = 'closed'; // Not closed = no cookie stored
23406const FADE_INCREMENT = .05;
23407const FULL_OPACITY = 1;
23408const FADE_DURATION = 20;
23409
23410// Calculates how far down from top of page the pop up should be, uses root css var
23411function setTopOffset() {
23412    const promoBarXpf = document.querySelector('.promobar-xpf');
23413    const desktopMenuHeight = parseInt(window.getComputedStyle(document.querySelector('.desktop-menu'), null).getPropertyValue('height').replace('px',''))
23414    const mobileMenuHeight = parseInt(window.getComputedStyle(document.querySelector('.mobile-wrap'), null).getPropertyValue('height').replace('px',''))
23415    const headerHeight = isNaN(desktopMenuHeight) ? mobileMenuHeight : desktopMenuHeight;
23416    const promoHeight = parseInt(window.getComputedStyle(promoBarXpf.querySelector('.wrap'), null).getPropertyValue('height').replace('px',''));
23417    let r = document.querySelector(':root');
23418    r.style.setProperty('--popup-top-offset', headerHeight + promoHeight + 'px');
23419}
23420
23421function fadeIn(element) {
23422    return new Promise(resolve => {
23423        element.style.opacity = 0;
23424        element.style.display = "flex";
23425        let opacity = 0;
23426        const timer = setInterval(() => {
23427            opacity += FADE_INCREMENT;
23428            element.style.opacity = opacity;
23429            if (opacity >= FULL_OPACITY) {
23430                clearInterval(timer);
23431                resolve(); // Resolve the promise when fade-in is complete
23432            }
23433        }, FADE_DURATION);
23434    });
23435}
23436
23437function fadeOut(element) {
23438    return new Promise(resolve => {
23439        let opacity = FULL_OPACITY;
23440        const timer = setInterval(() => {
23441        opacity -= FADE_INCREMENT;
23442        element.style.opacity = opacity;
23443        if (opacity <= 0) {
23444            clearInterval(timer);
23445            element.style.display = "none";
23446            resolve();
23447        }
23448        }, FADE_DURATION);
23449    });
23450}
23451
23452// Show and add listeners if pop up exists
23453function setupPopup() {
23454    const popupDiv = document.querySelector('.promo-bar_popup');
23455    if (popupDiv == null) {
23456        return;
23457    }
23458    if (readCookie(COOKIE_NAME)) {
23459        popupDiv.classList.add('hidden');
23460        return;
23461    }
23462
23463    const popupCta = popupDiv.querySelector(".popup-cta");
23464    const fadeOutTimer = parseInt(popupDiv.getAttribute('data-display-time'));
23465    const delayTimer = parseInt(popupDiv.getAttribute('data-delay-time')) || 0;
23466    const cookieDuration = parseInt(popupDiv.getAttribute('data-cookie-duration'));
23467    const xButton = popupDiv.querySelector(".btn-close");
23468    const promoBarXpfClose = popupDiv.parentElement.querySelector('.bar-close');
23469
23470    // Hide the pop up, remove listeners, set cookie
23471    function closePopUp(popupDiv, timeoutId, resetTimeout, doSetCookie) {
23472        popupDiv.style.display = "none"; // hide immediately on click
23473        if (timeoutId) {
23474            clearTimeout(timeoutId);
23475            popupDiv.removeEventListener('mouseover', resetTimeout);
23476            popupDiv.removeEventListener('mouseout', resetTimeout);
23477        }
23478        if (cookieDuration && doSetCookie) {
23479            setCookie(COOKIE_NAME, COOKIE_VALUE, cookieDuration);
23480        }
23481    }
23482    // Fade out pop up after time, reset time on hover and maouseout
23483    async function doPopupFade(fadeIn, fadeOut) {
23484        await fadeIn(popupDiv);
23485        let timeoutId;
23486        let resetTimeout;
23487
23488        if (fadeOutTimer) {
23489            resetTimeout = () => {
23490                clearTimeout(timeoutId);
23491                timeoutId = setTimeout(() => {
23492                fadeOut(popupDiv);
23493                }, fadeOutTimer);
23494            };
23495
23496            popupDiv.addEventListener('mouseover', resetTimeout);
23497            popupDiv.addEventListener('mouseout', resetTimeout);
23498
23499            resetTimeout(); //Initial timeout
23500
23501        }
23502
23503        // Remove event timeout listener when the pop up is closed
23504        const closeElements = [xButton, popupCta, promoBarXpfClose];
23505        closeElements.forEach(function(elem) {
23506            if (!elem) {
23507                return; // skip null elements
23508            }
23509            elem.addEventListener('click', () => {
23510                closePopUp(popupDiv, timeoutId, resetTimeout, true);
23511            });
23512        })
23513
23514        const skipToContent = document.querySelector('#skipLink');
23515        const handleClickOutsidePopup = (event) => {
23516            if (!popupDiv.contains(event.target) && !skipToContent.contains(event.target)) {
23517                closePopUp(popupDiv, timeoutId, resetTimeout, false);
23518                document.removeEventListener('click', handleClickOutsidePopup);
23519            }
23520        };
23521        document.addEventListener('click', handleClickOutsidePopup);
23522    }
23523
23524    window.onresize = setTopOffset;
23525    setTopOffset();
23526
23527    // Delay showing the popup if delayTimer > 0
23528    if (delayTimer > 0) {
23529        popupDiv.style.display = "none";
23530        setTimeout(() => {
23531            doPopupFade(fadeIn, fadeOut);
23532        }, delayTimer);
23533    } else {
23534        doPopupFade(fadeIn, fadeOut);
23535    }
23536}
23537
23538$(document).ready(function() {
23539    setupPopup();
23540});
23541
23542$(function(){
23543    //svg conversion
23544    $('.product-support-cards img[src$=".svg"]').each(function() {
23545        var $img = jQuery(this);
23546        var imgURL = $img.attr('src');
23547        var attributes = $img.prop("attributes");
23548
23549        $.get(imgURL, function(data) {
23550            // Get the SVG tag, ignore the rest
23551            var $svg = $(data).find('svg');
23552
23553            // Remove any invalid XML tags
23554            $svg = $svg.removeAttr('xmlns:a');
23555
23556            // Loop through IMG attributes and apply on SVG
23557            $.each(attributes, function() {
23558                $svg.attr(this.name, this.value);
23559            });
23560
23561            // Replace IMG with SVG
23562            $img.replaceWith($svg);
23563            $svg.get(0).setAttribute('preserveAspectRatio','xMidYMin meet');
23564        }, 'xml');
23565    });
23566
23567});
23568$(function() {
23569    var fromParam;
23570    try {
23571        var regex = /(%22)+/g;
23572        var queryString = location.search.substring(1);
23573        queryString = queryString.replace(regex, '_');
23574        var urlParams = queryString ? JSON.parse('{"' + decodeURIComponent(queryString).replace(/=&/g, "\":\"\",\"").replace(/&/g, "\",\"").replace(/=/g, "\":\"") + '"}') : {};
23575         fromParam = urlParams["from"] || "";
23576    }catch(message){
23577        var params = new URLSearchParams(window.location.search);
23578        fromParam = params.get("from") || "";
23579    }
23580    var titleDiv = $('.product-sku-hero.component .wtb-title');
23581    var skuTitle = titleDiv.data('skuTitle');
23582    var productTitle = titleDiv.data('productTitle');
23583    $(titleDiv).text(fromParam === 'product' ? productTitle : skuTitle);
23584    $(titleDiv).parent().show();
23585});
23586$(function() {
23587
23588    var $BODY = $('body');
23589    var $CAROUSELCOMP = $('.product-key-features-carousel.component');
23590
23591    function initCarousel(component) {
23592        var pkfCarousel = $(component);
23593        var featuredPKGallery, featuredPKGalleryOptions;
23594        var slides = true;
23595        var NAVIGATION = ['<span class="sr-only">Previous</span>', '<span class="sr-only">Next</span>'];
23596        var bodyWidth = Math.floor($BODY.width());
23597        var totalSlides = 0;
23598        var currentSlide = 0;
23599
23600        var update = function() {
23601            setTimeout(function() {
23602                totalSlides = pkfCarousel.find('.owl-dot').length;
23603                pkfCarousel.find('.owl-custom-nav .total').text(addLeadingZero(totalSlides));
23604                var activeDot = pkfCarousel.find('.owl-dot.active');
23605                currentSlide = pkfCarousel.find('.owl-dot').index(activeDot) + 1;
23606                pkfCarousel.find('.owl-custom-nav .current').text(addLeadingZero(currentSlide));
23607            }, 10);
23608        };
23609
23610        var addLeadingZero = function(numString) {
23611            return (parseInt(numString, 10) < 10) ? '0' + numString : numString;
23612        };
23613
23614        function updateBodyWidthValue() {
23615            bodyWidth = Math.floor($BODY.width());
23616        }
23617
23618        featuredPKGallery = pkfCarousel.find('.owl-carousel.product-key-features');
23619        featuredPKGalleryOptions = {
23620            loop: function() {
23621                return slides;
23622            },
23623            dots: true,
23624            nav: function() {
23625                return slides;
23626            },
23627            navText: function() {
23628                return slides;
23629            } ? NAVIGATION : false,
23630            //navContainer: "#featuredPKNav",
23631            autoHeight: true,
23632            // Auto rotation
23633            autoplay: false,
23634            mouseDrag: false,
23635            responsiveClass: true,
23636            center: true,
23637            responsive: {
23638                0: {
23639                    autoWidth: false,
23640                    items: 1,
23641                    margin: 0,
23642                    stagePadding: 0
23643                },
23644                768: {
23645                    autoWidth: true,
23646                    items: 1,
23647                    margin: 15,
23648                    stagePadding: 150
23649                },
23650                992: {
23651                    autoWidth: true,
23652                    items: 1,
23653                    margin: 30,
23654                    stagePadding: 330
23655                }
23656            },
23657            onInitialized: function() {
23658                update();
23659
23660            },
23661            onResize: function() {
23662                updateBodyWidthValue();
23663                update();
23664            },
23665            onChanged: function() {
23666                update();
23667            }
23668        };
23669
23670        pkfCarousel.find('.owl-custom-nav .owl-next').on('click', function() {
23671            featuredPKGallery.trigger('next.owl.carousel');
23672        });
23673
23674        pkfCarousel.find('.owl-custom-nav .owl-prev').on('click', function() {
23675            featuredPKGallery.trigger('prev.owl.carousel');
23676        });
23677
23678        update();
23679
23680        featuredPKGallery.owlCarousel(featuredPKGalleryOptions);
23681    }
23682
23683    if ($CAROUSELCOMP.length) {
23684        $CAROUSELCOMP.each(function(index, element) {
23685            initCarousel(element);
23686        });
23687    }
23688});
23689
23690
23691    ////////////////////////////////////////////////////////////////////
23692    //// building where to buy data analytics layer object start ///////
23693    ////////////////////////////////////////////////////////////////////
23694
23695    // Image Engagements data layer changes
23696    //function to capture data when item is on screen
23697    var isOnScreen = function (el) {
23698        var $el = $(el);
23699        var height = $el.outerHeight();
23700        var width = $el.outerWidth();
23701
23702        if (!width || !height) {
23703            return false;
23704        }
23705
23706        var win = $(window);
23707
23708        var viewport = {
23709            top: win.scrollTop(),
23710            left: win.scrollLeft()
23711        };
23712        viewport.right = viewport.left + win.width();
23713        viewport.bottom = viewport.top + win.height();
23714
23715        var bounds = $el.offset();
23716        bounds.right = bounds.left + width;
23717        bounds.bottom = bounds.top + height;
23718
23719        var deltas = {
23720            top: viewport.bottom - bounds.top,
23721            left: viewport.right - bounds.left,
23722            bottom: bounds.bottom - viewport.top,
23723            right: bounds.right - viewport.left
23724        };
23725
23726        return deltas.top>0
23727            && deltas.left>0
23728            && deltas.right>0
23729            && deltas.bottom>0;
23730    };
23731
23732    $(window).on('load.produceInfoDL scroll.produceInfoDL', function () {
23733        try {
23734            if (isOnScreen(sync1)) {
23735                $(window).off('.produceInfoDL');
23736                addImageEngagementsData(sync1, true);
23737            }
23738        } catch (error) {
23739            // Intentionally blank
23740        }
23741    });
23742
23743
23744    //where to buy data layer
23745    var $prodcutDetails = $('.prod-details');
23746    $prodcutDetails.on('click', 'button.btn.btn-primary', function () {
23747
23748        try {
23749            if (digitalData) {
23750                var dataFilters = $('#storelocatorscript').attr('data-filters');
23751                var brand = "";
23752                if (dataFilters && dataFilters!==undefined && dataFilters!=="") {
23753                    var brands = dataFilters.split(',');
23754                    if (brands.length>0) {
23755                        brand = brands[0];
23756                    }
23757                }
23758                if (digitalData.product) {
23759                    digitalData.product.productBrand = brand;
23760                }
23761                if (digitalData.event) {
23762                    var eventData = {};
23763                    eventData.eventName = "where to buy";
23764                    eventData.eventAction = "where to buy click";
23765                    eventData.type = "where to buy";
23766                    eventData.timeStamp = new Date();
23767                    digitalData.event.push(eventData);
23768                }
23769
23770            }
23771
23772        } catch (err) {
23773            console.log(err)
23774        }
23775    });
23776
23777    function addImageEngagementsData($element, onloadItem) {
23778        try {
23779            var $curItems;
23780            if (onloadItem) {
23781                $curItems =sync2 ? $(sync2).find('.owl-item').eq(0) : $();
23782            } else {
23783                $curItems = sync1? $(sync1).find('.owl-item').eq($element.item.index):$();
23784            }
23785            var imagePath = $curItems ? $curItems.find('.image img').attr('src') : "";
23786            var altText = $curItems ? $curItems.find('.image img').attr('alt') : "";
23787
23788            if (digitalData) {
23789                if (digitalData.product) {
23790                    digitalData.product.productName = $('h1').text();
23791                    digitalData.product.galleryImageName = imagePath;
23792                }
23793                if (digitalData.event) {
23794                    var eventData = {};
23795                    eventData.eventName = "image engagement";
23796                    eventData.eventAction = "image";
23797                    eventData.type = "shopping";
23798                    eventData.timeStamp = new Date();
23799                    digitalData.event.push(eventData);
23800                }
23801
23802            }
23803
23804        } catch (err) {
23805            console.log(err)
23806        }
23807    }
23808
23809    function syncPosition(el) {
23810        addImageEngagementsData(el);
23811        currentSlide  = el.item.index;
23812        if (sync2.length > 0){
23813            sync2.trigger('to.owl.carousel',[currentSlide, 100, true]);
23814            sync2.find(".owl-item").removeClass("current").eq(currentSlide).addClass("current");
23815        }
23816    }
23817// });
23818
23819var ProductInfomationV2 = function (componentElement) {
23820    var self = this;
23821    self.sku = $(componentElement).data('productSku');
23822    self.productName = $(componentElement).data('productName');
23823    self.productId = $(componentElement).data('productId');
23824    self.brandTags = $(componentElement).data('brandTags');
23825    self.categories = $(componentElement).data('categories');
23826    self.channel = $(componentElement).data('channel');
23827    self.pageType = $(componentElement).data('pageType');
23828    self.stock = getStock($(componentElement).data("stock"));
23829    assignStockClass();
23830    self.init = function () {
23831        updateDataLayerObj();
23832    }
23833    function getStock(value){
23834        if(value == "IN_STOCK"){
23835            return "In Stock";
23836        }
23837        if(value == "OUT_OF_STOCK"){
23838            return "Out of Stock";
23839        }
23840
23841        return "Discontinued"
23842    }
23843    function assignStockClass(){
23844        if($(".stock").text() === "IN STOCK"){
23845            $(".stock").addClass("in-stock");
23846        }
23847}
23848
23849    function getProductFindingMethod() {
23850        var result = "Direct"
23851        var productFindingMethod = localStorage.getItem("productFindingMethod");
23852        if (productFindingMethod && productFindingMethod.trim() !== "") {
23853            result = productFindingMethod;
23854            localStorage.removeItem("productFindingMethod");
23855        } else {
23856            var prvUrl = document.referrer;
23857            if (prvUrl){
23858                if (prvUrl.indexOf('search.html?') !== -1) {
23859                    result =  "Search";
23860                } else if (prvUrl.indexOf('products') !== -1){
23861                    result = "Navigation";
23862                }
23863            }
23864        }
23865        localStorage.setItem("productFindingMethodTemp", result);
23866        document.cookie="productFindingMethod=" + result +"; domain=.pentair.com; path=/";
23867
23868        return result;
23869    }
23870    function updateDataLayerObj() {
23871        try {
23872            if (digitalData) {
23873                if (!digitalData.page) {
23874                    digitalData.page = {
23875                        attributes: {
23876                            analytics: {}
23877                        }
23878                    }
23879                }
23880                if (digitalData.page.attributes.analytics) {
23881                    digitalData.page.attributes.analytics.pageType = self.pageType;
23882                }
23883                if (!digitalData.productItem) {
23884                    digitalData.productItem = [];
23885                }
23886                var index = -1;
23887                for (var i = 0; i < digitalData.productItem.length; i++) {
23888                    if (digitalData.productItem[i] && digitalData.productItem[i].productInfo && digitalData.productItem[i].productInfo.productID === self.productId) {
23889                        index = i;
23890                        break;
23891                    }
23892                }
23893                var productInfoData = {
23894                    productName: self.productName,
23895                    productID: self.productId,
23896                    skuID: self.sku,
23897                    brand: self.brandTags,
23898                    category: self.categories,
23899                    type: self.channel,
23900                    productFindingMethod: getProductFindingMethod(),
23901                    Stock: self.stock
23902                }
23903
23904                if (index === -1) {
23905                    digitalData.productItem.push({ productInfo: productInfoData })
23906                } else {
23907                    digitalData.productItem[index] = { productInfo: productInfoData };
23908                }
23909            }
23910        } catch (err) {
23911            console.log(err);
23912        }
23913    }
23914
23915    self.init();
23916}
23917
23918$(document).ready(function() {
23919    $('.component.product-information-v2').each(function () {
23920        new ProductInfomationV2(this);
23921    });
23922});
23923
23924
23925// Mobile Dropdown behavior
23926var mobileSku = {
23927    init:function($elem, index) {
23928        var skuBtn = $elem.find('button'),
23929            skuBtnInner = $elem.find('button .inner-btn'),
23930            skuMenu = $elem.parent().find('.sku-wrap'),
23931            selected = $elem.parent().find('.sku-wrap .values .keyname-selected');
23932        var $skuBtn = $(skuBtn),
23933            $skuBtnInner = $(skuBtnInner),
23934            $skuMenu = $(skuMenu),
23935            $selected = $(selected);
23936        if($selected){
23937            $skuBtnInner.html($selected.html());
23938        }
23939        var isConfigurable = $('.component.product-information').attr("data-product-configurable");
23940        if(isConfigurable == "true"){
23941            $skuBtnInner .html("Select SKU");
23942        }
23943
23944        $skuBtn.on('click touch', function(e) {
23945            if($("body #skuOverlay").length == 0){
23946                $("body .mobile-sku-selection").remove();
23947                $("body").append("<div id='skuOverlay' class='overlay'></div><div class='mobile-sku-selection'></div>");
23948            }
23949            $("body #skuOverlay").show();
23950            $("body #skuOverlay").on('click touch',function(e){
23951                var $div =  $("body .mobile-sku-selection");
23952                $div.css("height","0");
23953                $("body").css('overflow-y','auto');
23954                e.target.remove();
23955            })
23956            $("body").css('overflow-y','hidden');
23957            mobileSku.toggleMenu(e);
23958        });
23959
23960        $(window).on('resize', function() {
23961            mobileSku.resizeCheck($(window).outerWidth(), $skuBtn, $skuMenu);
23962        })
23963    },
23964    toggleMenu:function(e) {
23965        var $ths = $(e.currentTarget),
23966            $mnu = $ths.parent().parent().find('.sku-wrap');
23967        var $div =  $("body .mobile-sku-selection");
23968        $div.html($mnu.html());
23969        if($('.mobile-sku-selection .values.selected').length > 0){
23970            $('.mobile-sku-selection .values.selected')[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
23971        }
23972        $div.css("height","300px");
23973        $div.on('click touch', 'div.values', function () {
23974            var keyname = $(this).attr("data-keyname");
23975            $div.css("height","0");
23976            selectSku(keyname);
23977        });
23978    },
23979
23980    resizeCheck:function(w, btn, mnu) {
23981        if(w >= 768) {
23982            mnu.removeClass('open');
23983            mnu.removeAttr('style');
23984            btn.removeClass('open');
23985        }
23986    }
23987}
23988
23989$(window).load(function(){
23990    if($('.mobile-sku').length > 0) {
23991        $('.mobile-sku').each(function(index, elem){
23992            mobileSku.init($(elem), index);
23993        });
23994    }
23995    if ($('.product-information.component').length) {
23996        //product details carousel
23997        var sync1 = $(".product-information.component #sync1");
23998        var sync2 = $(".product-information.component #sync2");
23999
24000        var numItems = sync2.find('.image').length;
24001
24002        var syncedSecondary = true;
24003
24004        var currentSlide = 0;
24005        var callback = function(e) {
24006             var hasDots = e.item.count > 1;
24007            if(!hasDots){
24008                $('.owl-dots').hide();
24009            }
24010        }
24011
24012        sync1.owlCarousel({
24013            items: 1,
24014            mouseDrag: false,
24015            nav: true,
24016            navText: ['<div><span class="icon-angle-left" aria-hidden="true"></span><span class="sr-only">Previous</span></div>', '<div><span class="icon-angle-right" aria-hidden="true"></span><span class="sr-only">Next</span></div>'],
24017            dots: true,
24018            animateOut: 'fadeOut',
24019            loop: false,
24020            responsive: {
24021                0: {
24022                    autoHeight: true
24023                },
24024                768: {
24025                    autoHeight: false
24026                }
24027            },
24028            onInitialized: callback
24029        }).on('changed.owl.carousel', syncPosition);
24030        //Reset the size of the Larger carousel window when the carousel initializes
24031        //There are known weird issues with Owl carousel and height calculations. If this has problems in future,
24032        //Look https://github.com/OwlCarousel2/OwlCarousel2/issues/842 for other options.
24033        sync1.trigger('refresh.owl.carousel');
24034
24035        sync2.on('initialized.owl.carousel', function () {
24036            sync2.find(".owl-item").eq(0).addClass("current");
24037            sync2.siblings('.thumbnav').detach().appendTo(sync2);
24038            }).owlCarousel({
24039                slideBy: 1,
24040                loop:false,
24041                stagePadding: 0,
24042                mouseDrag: false,
24043                dots: true,
24044                nav: false,
24045                smartSpeed: 200,
24046                responsiveClass: true,
24047                margin: 10,
24048                autoWidth: true,
24049                responsive: {
24050                    0: {
24051                        items: (numItems > 3 ? 4 : numItems)
24052                    },
24053                    768: {
24054                        items: Math.min(3, numItems)
24055                    },
24056                    992: {
24057                        items: Math.min(4, numItems)
24058                    }
24059                }
24060            });
24061
24062        sync2.on("click", ".owl-item", function (e) {
24063            e.preventDefault();
24064            var number = $(this).index();
24065            sync1.trigger('to.owl.carousel',[number, 100]);
24066        });
24067
24068        $('.product-information.component .thumbnav .icon-angle-right').on('click', function (e) {
24069            e.preventDefault();
24070            currentSlide = currentSlide + 1 > numItems ? 0 : currentSlide + 1;
24071            sync1.trigger('to.owl.carousel',[currentSlide, 100]);
24072        });
24073        $('.product-information.component .thumbnav .icon-angle-left').on('click', function (e) {
24074            e.preventDefault();
24075            currentSlide = currentSlide <= 0 ? numItems - 1 : currentSlide - 1;
24076            sync1.trigger('to.owl.carousel',[currentSlide, 100]);
24077        });
24078
24079        //this fixes a resize issue for the initial load of the main image
24080        setTimeout(function () {
24081            $(window).resize();
24082        }, 1000);
24083    }
24084
24085    ////////////////////////////////////////////////////////////////////
24086    //// building where to buy data analytics layer object start ///////
24087    ////////////////////////////////////////////////////////////////////
24088
24089    // Image Engagements data layer changes
24090    //function to capture data when item is on screen
24091    var isOnScreen = function (el) {
24092        var $el = $(el);
24093        var height = $el.outerHeight();
24094        var width = $el.outerWidth();
24095
24096        if (!width || !height) {
24097            return false;
24098        }
24099
24100        var win = $(window);
24101
24102        var viewport = {
24103            top: win.scrollTop(),
24104            left: win.scrollLeft()
24105        };
24106        viewport.right = viewport.left + win.width();
24107        viewport.bottom = viewport.top + win.height();
24108
24109        var bounds = $el.offset();
24110        bounds.right = bounds.left + width;
24111        bounds.bottom = bounds.top + height;
24112
24113        var deltas = {
24114            top: viewport.bottom - bounds.top,
24115            left: viewport.right - bounds.left,
24116            bottom: bounds.bottom - viewport.top,
24117            right: bounds.right - viewport.left
24118        };
24119
24120        return deltas.top>0
24121            && deltas.left>0
24122            && deltas.right>0
24123            && deltas.bottom>0;
24124    };
24125
24126    $(window).on('load.produceInfoDL scroll.produceInfoDL', function () {
24127        try {
24128            if (isOnScreen(sync1)) {
24129                $(window).off('.produceInfoDL');
24130                addImageEngagementsData(sync1, true);
24131            }
24132        } catch (error) {
24133            // Intentionally blank
24134        }
24135    });
24136
24137
24138    //where to buy data layer
24139    var $prodcutDetails = $('.prod-details');
24140    $prodcutDetails.on('click', 'button.btn.btn-primary', function () {
24141
24142        try {
24143            if (digitalData) {
24144                var dataFilters = $('#storelocatorscript').attr('data-filters');
24145                var brand = "";
24146                if (dataFilters && dataFilters!==undefined && dataFilters!=="") {
24147                    var brands = dataFilters.split(',');
24148                    if (brands.length>0) {
24149                        brand = brands[0];
24150                    }
24151                }
24152                if (digitalData.product) {
24153                    digitalData.product.productBrand = brand;
24154                }
24155                if (digitalData.event) {
24156                    var eventData = {};
24157                    eventData.eventName = "where to buy";
24158                    eventData.eventAction = "where to buy click";
24159                    eventData.type = "where to buy";
24160                    eventData.timeStamp = new Date();
24161                    digitalData.event.push(eventData);
24162                }
24163
24164            }
24165
24166        } catch (err) {
24167            console.log(err)
24168        }
24169    });
24170
24171    function addImageEngagementsData($element, onloadItem) {
24172        try {
24173            var $curItems;
24174            if (onloadItem) {
24175                $curItems = sync2 ? $(sync2).find('.owl-item').eq(0) : $();
24176            } else {
24177                $curItems = sync1? $(sync1).find('.owl-item').eq($element.item.index):$();
24178            }
24179            var imagePath = $curItems ? $curItems.find('.image img').attr('src') : "";
24180            var altText = $curItems ? $curItems.find('.image img').attr('alt') : "";
24181
24182            if (digitalData) {
24183                if (digitalData.product) {
24184                    digitalData.product.productName = $('h1').text();
24185                    digitalData.product.galleryImageName = imagePath;
24186                }
24187                if (digitalData.event) {
24188                    var eventData = {};
24189                    eventData.eventName = "image engagement";
24190                    eventData.eventAction = "image";
24191                    eventData.type = "shopping";
24192                    eventData.timeStamp = new Date();
24193                    digitalData.event.push(eventData);
24194                }
24195
24196            }
24197
24198        } catch (err) {
24199            console.log(err)
24200        }
24201    }
24202
24203    function syncPosition(el) {
24204        addImageEngagementsData(el);
24205        currentSlide  = el.item.index;
24206        if (sync2.length > 0){
24207            sync2.trigger('to.owl.carousel',[currentSlide, 100, true]);
24208            sync2.find(".owl-item").removeClass("current").eq(currentSlide).addClass("current");
24209        }
24210    }
24211});
24212
24213var ProductInfomation = function (componentElement) {
24214    var self = this;
24215    self.sku = $(componentElement).data('productSku');
24216    self.productName = $(componentElement).data('productName');
24217    self.productId = $(componentElement).data('productId');
24218    self.brandTags = $(componentElement).data('brandTags');
24219    self.categories = $(componentElement).data('categories');
24220    self.channel = $(componentElement).data('channel');
24221    self.pageType = $(componentElement).data('pageType');
24222    self.stock = getStock($(componentElement).data("stock"));
24223    self.init = function () {
24224        updateDataLayerObj();
24225    }
24226    function getStock(value){
24227        if(value == "IN_STOCK"){
24228            return "In Stock";
24229        }
24230        if(value == "OUT_OF_STOCK"){
24231            return "Out of Stock";
24232        }
24233
24234        return "Discontinued"
24235    }
24236
24237    if($(".stock").html() === "IN STOCK"){
24238        $(".stock").addClass("in-stock");
24239    }
24240
24241    function getProductFindingMethod() {
24242        var result = "Direct"
24243        var productFindingMethod = localStorage.getItem("productFindingMethod");
24244        if (productFindingMethod && productFindingMethod.trim() !== "") {
24245            result = productFindingMethod;
24246            localStorage.removeItem("productFindingMethod");
24247        } else {
24248            var prvUrl = document.referrer;
24249            if (prvUrl){
24250                if (prvUrl.indexOf('search.html?') !== -1) {
24251                    result =  "Search";
24252                } else if (prvUrl.indexOf('products') !== -1){
24253                    result = "Navigation";
24254                }
24255            }
24256        }
24257        localStorage.setItem("productFindingMethodTemp", result);
24258        document.cookie="productFindingMethod=" + result +"; domain=.pentair.com; path=/";
24259
24260        return result;
24261    }
24262    function updateDataLayerObj() {
24263        try {
24264            if (digitalData) {
24265                if (!digitalData.page) {
24266                    digitalData.page = {
24267                        attributes: {
24268                            analytics: {}
24269                        }
24270                    }
24271                }
24272                if (digitalData.page.attributes.analytics) {
24273                    digitalData.page.attributes.analytics.pageType = self.pageType;
24274                }
24275                if (!digitalData.productItem) {
24276                    digitalData.productItem = [];
24277                }
24278                var index = -1;
24279                for (var i = 0; i < digitalData.productItem.length; i++) {
24280                    if (digitalData.productItem[i] && digitalData.productItem[i].productInfo && digitalData.productItem[i].productInfo.productID === self.productId) {
24281                        index = i;
24282                        break;
24283                    }
24284                }
24285                var productInfoData = {
24286                    productName: self.productName,
24287                    productID: self.productId,
24288                    skuID: self.sku,
24289                    brand: self.brandTags,
24290                    category: self.categories,
24291                    type: self.channel,
24292                    productFindingMethod: getProductFindingMethod(),
24293                    Stock: self.stock
24294                }
24295
24296                if (index === -1) {
24297                    digitalData.productItem.push({ productInfo: productInfoData })
24298                } else {
24299                    digitalData.productItem[index] = { productInfo: productInfoData };
24300                }
24301            }
24302        } catch (err) {
24303            console.log(err);
24304        }
24305    }
24306
24307    self.init();
24308}
24309
24310var selectSku = function(keyname){
24311    if(keyname != '' && keyname != 'undefined'){
24312        var url = window.location.href;
24313        var keyArr = keyname.split("#");
24314        if(keyArr.length == 2){
24315            var skuid = keyArr[1];
24316            var isConfigurable = $('.component.product-information').attr("data-product-configurable");
24317            var urlArr = '';
24318            var productFindingMethod = localStorage.getItem("productFindingMethodTemp");
24319
24320            // Set productFindingMethod for Analytics
24321            localStorage.setItem("productFindingMethod", productFindingMethod);
24322            document.cookie="productFindingMethod=" + productFindingMethod +"; domain=.pentair.com; path=/";
24323
24324            if (isConfigurable == 'true') {
24325                urlArr = url.indexOf('.html') > 0 ? url.replace('.html', '.' + skuid + '.html') : url.concat('.', skuid + '.html');
24326            }
24327            else{
24328                var urlSkuId = $('.component.product-information').attr("data-product-sku");
24329                urlArr = url.replace(urlSkuId, skuid );
24330            }
24331
24332            if(urlArr.indexOf("#productbuycard") != -1){
24333                window.location.href = urlArr;
24334            }
24335            else{
24336                //window.location.href = urlArr + "#productbuycard";
24337                window.location.href = urlArr ;
24338            }
24339
24340
24341        }
24342    }
24343}
24344
24345$(document).ready(function() {
24346    if ($('.component.product-information-v2') <=0){
24347        $('.component.product-information').each(function () {
24348            new ProductInfomation(this);
24349        });
24350        var $skuSelector = $('.skuselector');
24351        $skuSelector.on('click', 'div.values', function () {
24352            var keyname = $(this).attr("data-keyname");
24353            selectSku(keyname);
24354        });
24355
24356        $(".skuselector div.values").hover(function(e) {
24357            if(e.type == "mouseenter") {
24358                var keyname = $(this).attr("data-keyname");
24359                if(keyname != '' && keyname != 'undefined'){
24360                    var keyArr = keyname.split("#");
24361                    if(keyArr.length == 2){
24362                        var skuid = keyArr[1];
24363                        var variantAttributes = keyArr[0];
24364
24365                        // Set Sku Selector Attributes for Sku
24366                        $('.skuselector .options').html(variantAttributes);
24367                    }
24368
24369                }
24370            }
24371            /*if(e.type == "mouseleave") {
24372                $('.skuselector .options').html('&nbsp;');
24373            }*/
24374
24375        });
24376        $('.skuselector').each(function( index ) {
24377            if($(this).find('.keyname-selected').length > 0 ){
24378                var keyname = $(this).find('.keyname-selected').closest('.values').attr("data-keyname");
24379                var keyArr = keyname.split("#");
24380                if(keyArr.length == 2){
24381                    var variantAttributes = keyArr[0];
24382                    $(this).find('.options').html(variantAttributes);
24383                }
24384            }
24385        });
24386
24387        if($('.buttons.none-ecommpdp').find('.btn').length > 0){
24388            $('.buttons.none-ecommpdp').addClass("has-child");
24389        }
24390    }
24391});
24392
24393// adds 'has-child' class for custom cta if present
24394$(document).ready(function() {
24395    if($('.buttons.none-ecommpdp').find('.custom-cta-active').length > 0){
24396        $('.buttons.none-ecommpdp').addClass("has-child");
24397    }
24398});
24399
24400$(document).ready(function() {
24401    var isConfigurableFamily = $('.component.product-information-v2').attr("data-product-configurable");
24402    var currentHref = window.location.href;
24403    var urlSkuId = $('.component.product-buy-card-v2').attr("data-product-sku");
24404    var currentSkuDropdown;
24405
24406    // Retrieve the dropdown list element for the current sku
24407    $('.sku-num').each(function(idx, skuNum) {
24408        if ($(skuNum).text() === urlSkuId) {
24409            currentSkuDropdown = $(skuNum).parents('li');
24410        }
24411    });
24412
24413    $('.selectsku__dropdown-values').each(function(idx, dropdownOption) {
24414        // Set the hrefs for dropdowns
24415        var dropdownHref = '';
24416        var dropdownSkuId = $(dropdownOption).find('.sku-num').html();
24417
24418        if (isConfigurableFamily === 'true') {
24419            dropdownHref = currentHref.indexOf('.html') > 0 ?
24420                    currentHref.replace('.html', '.' + dropdownSkuId + '.html') : currentHref.concat('.', dropdownSkuId + '.html');
24421        } else {
24422            dropdownHref = currentHref.replace(urlSkuId, dropdownSkuId);
24423        }
24424
24425        var dropdownAnchor = $(dropdownOption).find('a');
24426        $(dropdownAnchor).attr('href', dropdownHref);
24427
24428        // Set current sku as "selected", then remove the dropdown option for current sku
24429        if (urlSkuId === dropdownSkuId) {
24430            var skuDropdownElem = $(currentSkuDropdown.find('a')[0]).clone()[0];
24431            var innerSkuDropdown = $(skuDropdownElem).html();
24432            $('#options').html('<div class="options-content"></div>');
24433            $("#options .options-content").html(innerSkuDropdown);
24434            $(currentSkuDropdown).remove();
24435        }
24436    });
24437});
24438
24439(function () {
24440    'use strict';
24441
24442    function initProductBuyCard(componentElement) {
24443        const zipcodeErr = '[Unable get your zipcode]';
24444        const sku = componentElement.dataset.productSku;
24445
24446        const consultationBtn = componentElement.querySelector('.consultation-btn');
24447        const changeZipcodeLink = componentElement.querySelector('.change-zipcode-link');
24448        const zipcodeView = componentElement.querySelector('.zipcode-view');
24449        const zipcodeEdit = componentElement.querySelector('.zipcode-edit');
24450        const zipcodeInput = componentElement.querySelector('.zipcode-input');
24451        const zipcodeOk = componentElement.querySelector('.zipcode-ok');
24452        const zipcodeCancel = componentElement.querySelector('.zipcode-cancel');
24453        const cardLoading = componentElement.querySelector('.cart-loading');
24454        const serviceError = componentElement.querySelector('.service-error');
24455        const installation = componentElement.querySelector('.installation');
24456        const installationInputs = componentElement.querySelectorAll("input[name='install-service']");
24457
24458        installationInputs.forEach(function (input) {
24459            input.addEventListener('change', function (event) {
24460                if (event.target.value === 'White glove') {
24461                    trackZipcode(true, zipcodeView ? zipcodeView.innerHTML : '');
24462                }
24463            });
24464        });
24465
24466        if (consultationBtn) {
24467            consultationBtn.addEventListener('click', function () {
24468                if (serviceError) serviceError.style.display = 'none';
24469                if (!sku) return;
24470                localStorage.setItem('SKUID', sku);
24471                const consultationpageurl = consultationBtn.dataset.consultationpageurl;
24472                window.location.href = consultationpageurl;
24473            });
24474        }
24475
24476        if (changeZipcodeLink) {
24477            changeZipcodeLink.addEventListener('click', function () {
24478                showZipcode(zipcodeView ? zipcodeView.innerHTML : '', true);
24479            });
24480        }
24481
24482        if (zipcodeOk) {
24483            zipcodeOk.addEventListener('click', function () {
24484                const zipcode = zipcodeInput ? zipcodeInput.value : '';
24485                if (zipcode && zipcode.trim()) {
24486                    showZipcode(zipcode, false);
24487                } else {
24488                    zipcodeInput && (zipcodeInput.style.borderColor = 'red');
24489                }
24490            });
24491        }
24492
24493        if (zipcodeCancel) {
24494            zipcodeCancel.addEventListener('click', function () {
24495                showZipcode(null, false);
24496            });
24497        }
24498
24499        function loading(isLoading) {
24500            const isHidden = cardLoading.classList.contains("hide");
24501            if (isLoading && isHidden) {
24502                cardLoading.classList.remove("hide");
24503            }
24504            if (!isLoading && !isHidden) {
24505                setTimeout(function () {
24506                    cardLoading.classList.add("hide");
24507                }, 1000);
24508            }
24509        }
24510
24511        function showZipcode(zipcode, edit) {
24512            if (!installation) return;
24513            if (zipcode) {
24514                if (zipcode === zipcodeErr) {
24515                    if (zipcodeView) zipcodeView.classList.add('error-zipcode-message');
24516                } else {
24517                    if (zipcodeView) zipcodeView.classList.remove('error-zipcode-message');
24518                    localStorage.setItem('zipcode', zipcode);
24519                }
24520                if (zipcodeView) zipcodeView.innerHTML = zipcode;
24521                if (zipcodeInput) zipcodeInput.value = zipcode;
24522                if (zipcodeInput) zipcodeInput.style.borderColor = '#eee';
24523            }
24524            if (edit) {
24525                if (changeZipcodeLink) changeZipcodeLink.style.display = 'none';
24526                if (zipcodeEdit) zipcodeEdit.style.display = 'flex';
24527            } else {
24528                if (changeZipcodeLink) changeZipcodeLink.style.display = '';
24529                if (zipcodeEdit) zipcodeEdit.style.display = 'none';
24530            }
24531        }
24532
24533        function localZipcode() {
24534            return localStorage.getItem('zipcode') || zipcodeErr;
24535        }
24536
24537        function trackZipcode(isEligible, zipcode) {
24538            if (zipcode && zipcode !== zipcodeErr) {
24539                if (window._satellite !== undefined) {
24540                    const whiteGlove = isEligible ? 'whiteglove_zip_available' : 'whiteglove_zip_unavailable';
24541                    window._satellite.track(whiteGlove, { whiteglove_zip: zipcode });
24542                }
24543            }
24544        }
24545
24546        // Initialize zipcode from localStorage on page load
24547        if (installation) {
24548            const zipcode = localZipcode();
24549            showZipcode(zipcode, false);
24550        }
24551
24552        loading(false);
24553    }
24554
24555    document.addEventListener('DOMContentLoaded', function () {
24556        document.querySelectorAll('.product-buy-card.component').forEach(function (element) {
24557            initProductBuyCard(element);
24558        });
24559    });
24560}());
24561
24562$(function () {
24563    // var $pageListItem = $('.page-list-item > p');
24564    //
24565    // if ($pageListItem.length) {
24566    //     $pageListItem.succinct({size: 100});
24567    // } else {
24568    //     console.info('No items found to succinctify.');
24569    // }
24570});
24571
24572$(document).ready(function(){
24573
24574    var $mbSpotList = $('.hero-carousel .hero-interactive-hotspot .spots .mobile-list'),
24575        $spotList = $('.hero-carousel .hero-interactive-hotspot .spots .spot-list'),
24576        $mbSpots = $('.hero-carousel .hero-interactive-hotspot .mobile-spots');
24577
24578    $('.hero-carousel .hero-interactive-hotspot .spots .mobile-list, .hero-carousel .hero-interactive-hotspot .mobile-spots, .hero-carousel .hero-interactive-hotspot .spots .spot-list').find('li').on('click',function(){
24579        var index = $(this).index();
24580        if ($(this).hasClass('active') === false){
24581            $spotList.slideUp('fast', function(){
24582                $mbSpotList.find('.active').removeClass('active');
24583                $mbSpots.find('.active').removeClass('active');
24584                $spotList.find('.active').removeClass('active').hide();
24585
24586                $spotList.find('li').eq(index).addClass('active').show();
24587                $mbSpots.find('li').eq(index).addClass('active');
24588                $mbSpotList.find('li').eq(index).addClass('active');
24589
24590                $spotList.slideDown('fast');
24591            });
24592        } else{
24593            $mbSpots.find('li').removeClass('active');
24594            $mbSpotList.find('li').removeClass('active');
24595            $spotList.find('li').removeClass('active').slideUp('fast');
24596        }
24597    });
24598
24599
24600    $spotList.find('a').on('click',function(e){
24601        if (!$(this).closest('li').hasClass('active') && ($('body').hasClass('tablet') || $('body').hasClass('mobile') || $('body').hasClass('tablet-desktop'))){
24602            e.preventDefault();
24603        }
24604    });
24605
24606
24607    $(document).mouseup(function(e) {
24608        var container = $('.hero-carousel .hero-interactive-hotspot .spots .spot-list, .hero-carousel .hero-interactive-hotspot .spots .mobile-list');
24609        if (!container.is(e.target) && container.has(e.target).length === 0) {
24610            $mbSpots.find('li').removeClass('active');
24611            $mbSpotList.find('li').removeClass('active');
24612            $spotList.find('li').removeClass('active').slideUp('fast');
24613        }
24614    });
24615});
24616$(function () {
24617
24618    var log = function(input) {
24619        return console.log(input);
24620    }
24621
24622    // RESP-156
24623    function updateChannelHeroAnalytics(anchor) {
24624        var linkDetails = "";
24625
24626        if (anchor.hasClass("main-link")) {
24627            linkDetails += "Main link" + "|";
24628        } else {
24629            linkDetails += "Sub link" + "|";
24630        }
24631
24632        if (anchor.closest(".hcs__section").hasClass("residential")) {
24633            linkDetails += "Residential" + "|" + anchor.attr("aria-label");
24634        } else {
24635            linkDetails += "Business and Industry" + "|" + anchor.attr("aria-label");
24636        }
24637
24638        if(!!window._satellite){
24639            _satellite.track('heroBannerClick', {heroLinkDetails: linkDetails} );
24640        }
24641
24642    }
24643
24644    function initHeroChannelSelector(component) {
24645        // need to override hero component styles
24646        if (!$("body").hasClass("hcs-active")) {
24647            $("body").addClass("hcs-active");
24648        }
24649
24650        var imgWrap = component.find(".img-wrap");
24651        imgWrap.hover(function(){
24652            if ($(this).closest(".hcs__section").hasClass("residential")) {
24653                $(this).closest(".hcs__bottom").find(".hcs__section.business-industry").addClass("inactive");
24654            } else {
24655                $(this).closest(".hcs__bottom").find(".hcs__section.residential").addClass("inactive");
24656            }
24657        }, function() {
24658            component.find(".hcs__section.inactive").removeClass("inactive");
24659        });
24660
24661        // set cookie based on what link was clicked
24662        $(component).find("a").on("click", function(e) {
24663            if (component.find("input[name='residential']").length || component.find("input[name='business-industry']").length) {
24664                var section = $(this).closest(".hcs__section");
24665                var identifier = section.hasClass("residential") ? "residential" : "business-industry";
24666                var channelUrl = component.find("input[name='"+ identifier +"']").val();
24667                var date = new Date();
24668                date.setTime(date.getTime() + (30 * 24 * 60 * 60 * 1000));
24669                var expires = "; expires=" + date.toGMTString();
24670                document.cookie = "channel=" + identifier + expires + ";path=/";
24671                document.cookie = "channelUrl=" + channelUrl + expires + ";path=/";
24672            }
24673
24674            if ($(this).hasClass("main-link") || $(this).hasClass("sublink")) {
24675                updateChannelHeroAnalytics($(this));
24676            }
24677
24678            return true;
24679        });
24680
24681        // channel redirect is enabled - redirect on page load
24682        /*if (component.find("input[name='residential']").length || component.find("input[name='business-industry']").length) {
24683            var channelIdentifier = readCookie("channel");
24684            if (channelIdentifier !== undefined && channelIdentifier != null && channelIdentifier.length > 0) {
24685                var url = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + component.find("input[name='"+ channelIdentifier +"']").val() + ".html";
24686                window.location.replace(url);
24687            }
24688        }*/
24689    }
24690
24691    $(document).ready(function() {
24692        var heroChannelSelector = $(".hero-channel-selector.component");
24693        if (heroChannelSelector.length) {
24694            heroChannelSelector.each(function(index, elem) {
24695                initHeroChannelSelector($(elem));
24696            });
24697        }
24698    });
24699});
24700
24701$(function () {
24702    // adds class for height selected from hero-interior, removes classes an author might accidentally select
24703    $(".hero.component").each(function(index, element) {
24704        const pntInterior = $(this).find(".pnt-hero-interior");
24705        const heroInterior = $(this).find(".hero-interior");
24706
24707        if (heroInterior.first().children(".pnt-hero-interior.desktop-height-small").first().length) {
24708            $(this).addClass('desktop-height-small');
24709            pntInterior.removeClass("desktop-height-large");
24710        }
24711        if (heroInterior.first().children(".pnt-hero-interior.desktop-height-default").first().length) {
24712            $(this).addClass('desktop-height-medium');
24713            pntInterior.removeClass("desktop-height-small");
24714            pntInterior.removeClass("desktop-height-large");
24715        }
24716        if (heroInterior.first().children(".pnt-hero-interior.desktop-height-large").first().length) {
24717            $(this).addClass('desktop-height-large');
24718            pntInterior.removeClass("desktop-height-small");
24719        }
24720        if (heroInterior.first().children(".pnt-hero-interior.mobile-height-default").first().length) {
24721            $(this).addClass('mobile-height-default');
24722            pntInterior.removeClass("mobile-height-fit");
24723        }
24724        if (heroInterior.first().children(".pnt-hero-interior.mobile-height-fit").first().length) {
24725            $(this).addClass('mobile-height-fit');
24726            pntInterior.removeClass("mobile-height-default");
24727        }
24728    });
24729
24730    // Check screen size after resizing, then for mobile only,
24731    // if mobile is set to fit, add 55px to content height instead of using the desktop height
24732    const EXTRA_HEIGHT = 55;
24733    const TIMEOUT_DELAY = 400;
24734    function doResize(){
24735        $(".hero.component").each(function(index, element) {
24736            const heroInteriorMobileFit = $(this).find(".pnt-hero-interior.mobile-height-fit");
24737            if (window.matchMedia('(max-width: 767px)').matches) {
24738                const heroContentDetails = $(this).find(".owl-item.active").find(".pnt-hero-interior.mobile-height-fit").children(".pnt-hero-interior__content").children(".pnt-hero-interior__content--details");
24739                const heroContentHeight = heroContentDetails.height();
24740                if (heroInteriorMobileFit.length) {
24741                    const mobileHeight = heroContentHeight + EXTRA_HEIGHT;
24742                    $(heroInteriorMobileFit).css('height', mobileHeight);
24743                }
24744            } else {
24745                $(heroInteriorMobileFit).css('height', '');
24746            }
24747        });
24748    }
24749    $(window).load(function() {
24750        doResize();
24751
24752        let timer;
24753        window.onresize = function(){
24754          clearTimeout(timer);
24755          timer = setTimeout(doResize, TIMEOUT_DELAY);
24756        };
24757
24758    });
24759
24760    /*
24761    * hero.js
24762    *
24763    * watches for changes in edit/preview mode and alters the presentation of the component in response.
24764    *
24765    * initializes owl.carousel functionality and options
24766    *
24767    * */
24768
24769    var delay, heroComponent, heroGallery, heroGalleryOptions;
24770    var singleSlide;
24771    var $HTML = $('html');
24772    var $BODY = $('body');
24773    var $HERO = $BODY.find('.hero.component');
24774    var isEditMode = !!$HTML.hasClass('aem-AuthorLayer-Edit');
24775    var NAVIGATION = ['<span class="sr-only">Previous</span>', '<span class="sr-only">Next</span>'];
24776    var videoIndexes = [];
24777    var carouselItems;
24778    var packOfVids = [];
24779    var videoAutoplay = $HERO.data('videoAutoplay') || false;
24780    var carouselAutoplay = $HERO.data('carouselAutoplay') || false;
24781    var lastTranslateTime;
24782
24783    function getDelayInteger() {
24784        // this function corrects original dialog input of miliseconds (6000)
24785        // the current dialog is in seconds and will throw a validation error if the delay is > 30
24786        var num = parseInt(delay);
24787        var isNum = typeof(num) === 'number';
24788
24789        if (isNum && num % 1000 === 0 ) {
24790            return num;
24791        } else if (isNum) {
24792            return num * 1000;
24793        } else {
24794            return 6000;
24795        }
24796    }
24797
24798    function initCarousel(component) {
24799        heroGallery = component.find('.owl-carousel.hero-carousel');
24800        heroGalleryOptions = {
24801            // autoplay: false,
24802            center: true,
24803            items: 1,
24804            rewind: true,
24805            margin: 10,
24806            nav: true,
24807            navText: true,
24808            animateOut: 'fadeOut',
24809            animateIn: 'fadeIn',
24810            onTranslate: eventRegistered,
24811            changed: eventRegistered,
24812            drag: eventRegistered,
24813            change: eventRegistered,
24814            resize: eventRegistered,
24815            onInitialize: eventRegistered,
24816            onInitialized: eventRegistered
24817        }
24818    }
24819
24820    function eventRegistered(event) {
24821
24822        /* for autoplay enabled videos we need to control the slide translations manually based on the
24823        * video length and the carousel delay settings.  For this to work the owl carousel option:
24824        * autoplay must be false */
24825
24826        var isVideo = false;
24827        var item      = event.item;     // Position of the current item
24828
24829        if (event.type === 'initialized') {
24830            findVideos();
24831            if (videoAutoplay  && videoIndexes.length) {
24832                isVideo = playVideo(0);
24833            }
24834            if (!isVideo) {
24835                if(carouselAutoplay) {
24836                    lastTranslateTime = Date.now();
24837                    setTimeout(function() {
24838                            heroGallery.trigger('next.owl.carousel');
24839                    },delay * 1000);
24840                }
24841            }
24842        }
24843
24844        if (event.type === 'translate') {
24845            if (videoAutoplay  && videoIndexes.length) {
24846                isVideo = playVideo(item.index);
24847            }
24848            if (!isVideo) {
24849                lastTranslateTime = Date.now();
24850                if(carouselAutoplay) {
24851                    setTimeout(function() {
24852                        if (isTimeToChangeSlide()) {
24853                            heroGallery.trigger('next.owl.carousel');
24854                        }
24855                    },delay * 1000);
24856                }
24857            }
24858        }
24859
24860        checkForHeroChannelSelector();
24861    }
24862
24863    function isTimeToChangeSlide() {
24864        return Date.now() - lastTranslateTime  >= delay * 1000;
24865    }
24866
24867    function playVideo(ind) {
24868        /* check if there is a video at that index and execute play */
24869        // debugger;
24870        var thisVideo = videoIndexes.indexOf(ind);
24871        if (thisVideo >= 0) {
24872            var videoElem = carouselItems[ind];
24873            var videoElement = $(videoElem).find('video')[0];
24874            $(videoElement).trigger('play');
24875            return true;
24876        }
24877
24878        return false;
24879    }
24880
24881    function transitionSlideOnVideoCompletion() {
24882        packOfVids.forEach(function iterateEachVideo(video) {
24883            video[0].addEventListener('ended', function triggerOwlTransition() {
24884                heroGallery.trigger('next.owl.carousel');
24885            });
24886        })
24887    }
24888
24889    function findVideos() {
24890
24891        /* use this to get the index numbers of video slides */
24892        carouselItems = singleSlide ? heroGallery.find('.video-holder') : heroGallery.find('.owl-item');
24893
24894        for (var i = 0; i < carouselItems.length; i += 1) {
24895
24896            var video = $(carouselItems[i]).find('video');
24897
24898            if (video.length > 0) {
24899                videoIndexes.push(i);
24900                packOfVids.push(video);
24901            }
24902        }
24903
24904        if (packOfVids.length > 0) {
24905            // use this to add ended listeners?
24906            transitionSlideOnVideoCompletion();
24907        }
24908    }
24909
24910    /*
24911    * Need to check for the Hero Channel Selector component to override default hero styles
24912    */
24913    function checkForHeroChannelSelector() {
24914        var heroCarousel = $HERO.find(".hero-carousel");
24915        if (heroCarousel.find(".item").length < 2) {
24916            if (items.find(".hero-channel-selector.component").length) {
24917                $BODY.addClass("hcs-active");
24918            }
24919        } else {
24920            setTimeout(function(){
24921                var activeItem = heroCarousel.find(".owl-item.active");
24922                if (activeItem.length) {
24923                    if (activeItem.find(".hero-channel-selector.component").length) {
24924                        $BODY.addClass("hcs-active");
24925                    } else {
24926                        if ($BODY.hasClass("hcs-active")) {
24927                            $BODY.removeClass("hcs-active");
24928                        }
24929                    }
24930                }
24931            }, 0);
24932        }
24933    }
24934
24935    $BODY.on('pentair.init', function (event) {
24936        if (event) {
24937            heroComponent = $(event.target).find('.hero');
24938        } else {
24939            heroComponent = $HERO;
24940        }
24941        // Authored delay
24942        delay = heroComponent.find('.owl-carousel.hero-carousel').data('carouselDelay');
24943
24944        if (heroComponent.length) {
24945            singleSlide = heroComponent.find('.item').length < 2;
24946            if (singleSlide){
24947                heroGallery = heroComponent.find('.owl-carousel.hero-carousel');
24948                findVideos();
24949                playVideo(0);
24950            } else {
24951                initCarousel(heroComponent);
24952                heroComponent.addClass('owl-carousel-active');
24953                if (heroGallery && heroGallery.length) {
24954                    heroGallery.owlCarousel(heroGalleryOptions);
24955                }
24956            }
24957        }
24958    });
24959
24960    $HTML.watch({
24961        properties: "attr_class",
24962        watchChildren: false,
24963        interval: 100,
24964        callback: function (data, i) {
24965            var newValue = data.vals[i].replace(/(^\s+|\s+$)/g, '');
24966            if (newValue === 'aem-AuthorLayer-Edit') {
24967                isEditMode = true;
24968                $BODY.trigger('pentair.init');
24969                $HERO.addClass('hero-edit');
24970            } else if (newValue === 'aem-AuthorLayer-Preview') {
24971                isEditMode = false;
24972                $BODY.trigger('pentair.init');
24973            } else {
24974                isEditMode = false;
24975            }
24976        }
24977    });
24978
24979});
24980
24981$(function() {
24982
24983    setSVG();
24984
24985    var featuredComponent, featuredGallery, featuredGalleryOptions;
24986    var slides = true;
24987    var $HTML = $('html');
24988    var $BODY = $('body');
24989    var $GALLERY = $BODY.find('.featured-carousel.owl-carousel');
24990    var isEditMode = !!$HTML.hasClass('aem-AuthorLayer-Edit');
24991    var NAVIGATION = ['<span class="sr-only">Previous</span>', '<span class="sr-only">Next</span>'];
24992
24993    function setSVG() {
24994        $('.featured-carousel.component img[src$=".svg"]').each(function() {
24995            var $img = jQuery(this);
24996            var imgURL = $img.attr('src');
24997            var attributes = $img.prop("attributes");
24998
24999            $.get(imgURL, function(data) {
25000                // Get the SVG tag, ignore the rest
25001                var $svg = $(data).find('svg');
25002
25003                // Remove any invalid XML tags
25004                $svg = $svg.removeAttr('xmlns:a');
25005
25006                // Loop through IMG attributes and apply on SVG
25007                $.each(attributes, function() {
25008                    $svg.attr(this.name, this.value);
25009                });
25010
25011                // Replace IMG with SVG
25012                $img.replaceWith($svg);
25013                $svg.get(0).setAttribute('preserveAspectRatio', 'xMidYMin meet');
25014            }, 'xml');
25015        });
25016    }
25017
25018    function initCarousel(component) {
25019        featuredGallery = component.find('.owl-carousel.featured-carousel');
25020        featuredGalleryOptions = {
25021            loop: function() {
25022                return slides;
25023            },
25024            dots: false,
25025            nav: function() {
25026                return slides;
25027            },
25028            navText: function() {
25029                return slides;
25030            } ? NAVIGATION : false,
25031            navContainer: "#featuredNav",
25032            autoHeight: true,
25033            // Auto rotation
25034            autoplay: false,
25035            mouseDrag: false,
25036            responsiveClass: true,
25037            center: true,
25038            margin: 15,
25039            autoWidth: true,
25040            responsive: {
25041                0: {
25042                    stagePadding: 20,
25043                    items: 1
25044                },
25045                768: {
25046                    stagePadding: 150,
25047                    items: 1
25048                },
25049                992: {
25050                    stagePadding: 230,
25051                    items: 1
25052                }
25053            },
25054            onInitialized: function() {
25055                setSVG();
25056            },
25057            onResize: function() {
25058            }
25059        };
25060    }
25061
25062    $BODY.on('pentair.init', function(event) {
25063
25064        if(event) {
25065            featuredComponent = $(event.target).find('.featured-carousel.component');
25066        } else {
25067            featuredComponent = $GALLERY;
25068        }
25069
25070        if(featuredComponent.length) {
25071
25072            slides = featuredComponent.find('.item').length >= 2;
25073            if(slides) {
25074                initCarousel(featuredComponent);
25075                featuredComponent.addClass('owl-carousel-active');
25076            } else {
25077                featuredComponent.find('.item').addClass('active');
25078            }
25079
25080            if(featuredGallery && featuredGallery.length) {
25081                featuredGallery.owlCarousel(featuredGalleryOptions);
25082
25083                ////////////////////////////////////////////////////
25084                ////////Analytics datalayer chagnes start//////////
25085                //////////////////////////////////////////////////
25086                featuredGallery.on('changed.owl.carousel', function(e) {
25087                    if(featuredGallery.find('.owl-item').eq(e.item.index).length) {
25088                        // var currentOwlItem = featuredGallery.find('.owl-item').eq(e.item.index); // unused variable 1/17/19
25089                        var prodName = featuredGallery.find('.owl-item').eq(e.item.index).find('.images h4').text();
25090                        updateDataLayerObj(prodName, "impression");
25091                    }
25092                });
25093                ////////////////////////////////////////////////////
25094                ////////Analytics datalayer chagnes end////////////
25095                //////////////////////////////////////////////////
25096
25097            } else {
25098                //console.warn('The hero carousel is on the page, however it has not been authored.')
25099            }
25100        }
25101    });
25102
25103    ////////////////////////////////////////////////////////
25104    //// building data analytics layer object start ///////
25105    //////////////////////////////////////////////////////
25106
25107    $GALLERY.on('click', '.owl-item .buttons .btn-primary', function(event) {
25108        var prdtName = $(this).closest('.item').find('.images h4').text();
25109        updateDataLayerObj(prdtName, "click");
25110    });
25111
25112    function updateDataLayerObj(productName, eventAction) {
25113        try {
25114            if(digitalData) {
25115
25116                if(digitalData.internalCampaign) {
25117                    digitalData.internalCampaign.featuredProductName = productName;
25118                }
25119                if(digitalData.event) {
25120                    var eventData = {};
25121                    eventData.eventName = "featured product";
25122                    eventData.eventAction = eventAction;
25123                    eventData.type = "internal campaign";
25124                    eventData.timeStamp = new Date();
25125                    digitalData.event.push(eventData);
25126                }
25127
25128            }
25129
25130        } catch(err) {
25131            console.log(err);
25132        }
25133    }
25134
25135    ////////////////////////////////////////////////////////
25136    ///// building data analytics layer object end  ///////
25137    //////////////////////////////////////////////////////
25138
25139    $HTML.watch({
25140        properties: "attr_class",
25141        watchChildren: false,
25142        interval: 100,
25143        callback: function(data, i) {
25144            var newValue = data.vals[i].replace(/(^\s+|\s+$)/g, '');
25145            if(newValue === 'aem-AuthorLayer-Edit') {
25146                isEditMode = true;
25147                $BODY.trigger('pentair.init');
25148                $GALLERY.addClass('gallery-edit');
25149            } else if(newValue === 'aem-AuthorLayer-Preview') {
25150                isEditMode = false;
25151                $BODY.trigger('pentair.init');
25152            } else {
25153                isEditMode = false;
25154            }
25155        }
25156    });
25157
25158});
25159
25160////////////////////////////////////////////////////////////////
25161///////////////building data layer oject////////////////////////
25162////////////////////////////////////////////////////////////////
25163
25164$(document).ready(function(){
25165    try{
25166        if(digitalData.resource){
25167            var eventData = {};
25168            $('.item .downloads .downloads-resources .pdf').on('click',function(e) {
25169                var timeStamp = new Date();
25170                digitalData.resource.resourceName = $(this).text();
25171                eventData.eventName = "resource";
25172                eventData.eventAction = "click";
25173                eventData.type = "resource library";
25174                eventData.timeStamp = timeStamp;
25175                digitalData.event.push(eventData);
25176            });
25177        }
25178    }catch(err){
25179        console.log(err);
25180    }
25181
25182    // Adobe analytics
25183    var downloadsElement = document.querySelector("[class='downloads-resources']");
25184    if (downloadsElement) {
25185        var downloadLinks = downloadsElement.querySelectorAll("a[href*='.pdf']");
25186        for (var i = 0; i < downloadLinks.length; i++) {
25187            downloadLinks[i].addEventListener('click', trackDownloadsLinkClick);
25188        }
25189    }
25190
25191    function trackDownloadsLinkClick() {
25192        var eventProductInfoDownloadPayload = {
25193            eventName: 'click for product download',
25194            eventType: 'event',
25195            visitor: {
25196                pentairCustomerID: getPentairCustomerID(),
25197                dealerID: getDealerID()
25198            },
25199            page: {
25200                pageCanonical: getPageViewPageAttribute('pageCanonical'),
25201                pageName: getPageViewPageAttribute('pageName'),
25202                pagePath: getPageViewPageAttribute('pagePath'),
25203                pageType: getPageViewPageAttribute('pageType'),
25204                pageURL: getPageViewPageAttribute('pageURL'),
25205                pageTitle: getPageViewPageAttribute('pageTitle'),
25206                pageSEOTags: getPageViewPageAttribute('pageSEOTags'),
25207                businessUnitID: getPageViewPageAttribute('businessUnitID'),
25208                subBrand: getPageViewPageAttribute('subBrand'),
25209                language: getPageViewPageAttribute('language'),
25210                author: getPageViewPageAttribute('author'),
25211            },
25212            product: {
25213                productName: getPageViewProductAttribute('productName'),
25214                skuID: getPageViewProductAttribute('skuID'),
25215                type: getPageViewProductAttribute('type')
25216            }
25217        }
25218        trackEventWithQueue(eventProductInfoDownloadPayload);
25219    }
25220});
25221
25222////////////////////////////////////////////////////////////////
25223///////////////building data layer oject////////////////////////
25224////////////////////////////////////////////////////////////////
25225
25226// CTA Buy Online — logic consolidated into cta-buy-locally clientlib (cta-buy-locally.js).
25227// Both buy-locally and buy-online selectors are handled there via a shared initCtaButton().
25228(function () {
25229    'use strict';
25230
25231    const getPentairCustomerID = (...a) => typeof window.getPentairCustomerID === 'function' ? window.getPentairCustomerID(...a) : '';
25232    const getDealerID = (...a) => typeof window.getDealerID === 'function' ? window.getDealerID(...a) : '';
25233    const getDistributorID = (...a) => typeof window.getDistributorID === 'function' ? window.getDistributorID(...a) : '';
25234    const getPageViewPageAttribute = (...a) => typeof window.getPageViewPageAttribute === 'function' ? window.getPageViewPageAttribute(...a) : '';
25235    const getPageViewProductAttribute = (...a) => typeof window.getPageViewProductAttribute === 'function' ? window.getPageViewProductAttribute(...a) : '';
25236    const trackEventWithQueue = (...a) => { if (typeof window.trackEventWithQueue === 'function') window.trackEventWithQueue(...a); };
25237
25238    // ========================================
25239    // CTA BUY LOCALLY / BUY ONLINE
25240    // Both components share identical behaviour; only the DOM selector differs.
25241    // ========================================
25242
25243    /**
25244     * Initialises a single WTB CTA element.
25245     * @param {HTMLElement} componentElement
25246     */
25247    function initCtaButton(componentElement) {
25248
25249        // Adobe Analytics - Tracks the WTB button click event
25250        function trackWTBClickEvent() {
25251            const eventWTBPayload = {
25252                eventName: 'WTB click',
25253                eventType: 'event',
25254                attributes: {
25255                    visitor: {
25256                        pentairCustomerID: getPentairCustomerID(),
25257                        dealerID: getDealerID(),
25258                        distributorID: getDistributorID()
25259                    },
25260                    page: {
25261                        pageCanonical: getPageViewPageAttribute('pageCanonical'),
25262                        pageName: getPageViewPageAttribute('pageName'),
25263                        pagePath: getPageViewPageAttribute('pagePath'),
25264                        pageType: getPageViewPageAttribute('pageType'),
25265                        pageURL: getPageViewPageAttribute('pageURL'),
25266                        pageTitle: getPageViewPageAttribute('pageTitle'),
25267                        pageSEOTags: getPageViewPageAttribute('pageSEOTags'),
25268                        businessUnitID: getPageViewPageAttribute('businessUnitID'),
25269                        subBrand: getPageViewPageAttribute('subBrand'),
25270                        language: getPageViewPageAttribute('language'),
25271                        author: getPageViewPageAttribute('author'),
25272                    },
25273                    product: {
25274                        skuID: componentElement.dataset.productSku || null,
25275                        productName: getPageViewProductAttribute('productName'),
25276                        type: getPageViewProductAttribute('type')
25277                    }
25278                }
25279            };
25280            trackEventWithQueue(eventWTBPayload);
25281        }
25282
25283        componentElement.addEventListener('click', () => {
25284            trackWTBClickEvent();
25285            constructAlgoliaAnalyticsWTBObject();
25286        });
25287    }
25288
25289    document.addEventListener('DOMContentLoaded', () => {
25290        ['.buy-locally-cta', '.buy-online-cta'].forEach((selector) => {
25291            document.querySelectorAll(selector).forEach((element) => {
25292                try {
25293                    initCtaButton(element);
25294                } catch (e) {
25295                    console.log(e);
25296                }
25297            });
25298        });
25299    });
25300
25301})();
25302
25303
25304$(function () {
25305    var cookieCta;
25306    var cookieElem = $(".cookie-cta");
25307
25308    // Element below footer has same height as cookie-cta, footer is not covered when at bottom of page.
25309    var updateHeight = function () {
25310        $('.cookie-cta-placeholder').css('height', cookieElem.outerHeight());
25311    };
25312
25313    var updateVisibility = function () {
25314        cookieCta = Cookies.get('cookieCta');
25315
25316        if (!cookieCta || cookieCta!=='hide') {
25317            cookieElem.css('display', 'flex');
25318            $('body').append('<div class="cookie-cta-placeholder"></div>');
25319            updateHeight();
25320
25321        } else if (cookieCta==='hide') {
25322            $('.cookie-cta-placeholder').css('height', 0);
25323            cookieElem.hide();
25324        }
25325    };
25326
25327    $('.cookie-cta a.icon-close').click(function (e) {
25328        e.preventDefault();
25329        if (!cookieCta) {
25330            Cookies.set('cookieCta', 'hide', {expires: 90});
25331        }
25332        updateVisibility();
25333    });
25334
25335    $(window).resize($.throttle(updateHeight, 100));
25336
25337    updateVisibility();
25338});
25339
25340$(document).ready(function() {
25341
25342    var regex = /(%22)+/g;
25343    var showParam;
25344    try {
25345        var queryString = location.search.substring(1);
25346        queryString = queryString.replace(regex, '_');
25347        var urlParams = queryString ? JSON.parse('{"' + decodeURI(queryString.replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}') : {};
25348        showParam = urlParams["show"] || "";
25349    } catch (message) {
25350        var params = new URLSearchParams(window.location.search);
25351        showParam = params.get("show") || "";
25352    }
25353    if (showParam == "local") {
25354        $('#channelAdvisor').hide();
25355        $(document).find('section.toolbar').hide();
25356    } else {
25357        var backgroundColor = $('#channelAdvisor iframe').closest('section').css('background-color');
25358        //$('#channelAdvisor iframe').iFrameResize({bodyBackground: backgroundColor});
25359    }
25360});
25361$(function () {
25362    var $categoryComponent = $('.category-selection.component');
25363    if (!$categoryComponent.length) {
25364        return;
25365    }
25366
25367    var $categoryChosen = $categoryComponent.find('select'),
25368        $newContent = $('.swap-area .new-content'),
25369        $noContent = $('.swap-area .no-content'),
25370        $swapArea = $('.swap-area, .sticky-category-container'),
25371        $choice;
25372
25373    function testForValueMatch(element, category) {
25374        if (category===$choice) {
25375            element.style.display = 'block';
25376        } else {
25377            element.style.display = 'none';
25378        }
25379    }
25380
25381    function displaySelection() {
25382        /*$articleContents.length*/
25383        if ($newContent.children('div').length) {
25384            $.each($newContent.children('div'), function (index, element) {
25385                testForValueMatch(element, element.dataset.categoryItem);
25386            });
25387        }
25388    }
25389
25390    function contentReveal() {
25391        displaySelection();
25392        $swapArea.addClass('swapped');
25393        $newContent.slideDown('slow');
25394    }
25395
25396    $categoryChosen.on('input', function () {
25397
25398        $choice = $('#catSelection').val();
25399
25400        if ($choice.length) {
25401
25402            if (!$swapArea.hasClass('swapped')) {
25403                // $swapArea.addClass('swapped');
25404                $noContent.slideUp('slow', function () {
25405                    contentReveal();
25406                });
25407            } else {
25408                // $swapArea.removeClass('swapped');
25409                $newContent.slideUp('slow', function () {
25410                    contentReveal();
25411                });
25412            }
25413        }
25414    });
25415
25416    $button = $('.sticky-category-container > button').on('click', function() {
25417        $('html, body').animate({scrollTop: '0px'}, 800);
25418    });
25419});
25420
25421var FilterViewModel = function(data, filterFields){
25422    var self = this;
25423    self.dataArray = data;
25424    self.Category = ko.observableArray();       // list of all category filters
25425    self.Type = ko.observableArray();           // list of all type filters
25426    self.Audience = ko.observableArray();       // list of all audience filters
25427    self.showMobileFilter = ko.observable(false);
25428    self.selectedList = ko.observableArray();
25429
25430    self.closeMobileFilter = function () {
25431        self.showMobileFilter(false);
25432    };
25433
25434    self.openMobileFilter = function () {
25435        self.showMobileFilter(true);
25436    };
25437
25438    self.selected = ko.computed(function(){
25439        return self.selectedList().reduce(function(selectObject, elem){
25440            selectObject[elem.filterGroup].push(elem.filterName);
25441            return selectObject;
25442        }, { Category : ko.observableArray(), Type : ko.observableArray(), Audience: ko.observableArray() });
25443    });
25444
25445    self.filterGroups = ko.observableArray(filterFields); //['Category', 'Type', 'Audience']
25446
25447    self.filteredEventList = ko.computed(function(){
25448        var filtered = self.dataArray().filter(function(elem){
25449            var categoryArray = elem.categories ? elem.categories.split('|') : [];
25450            var categoryInclude = self.selected().Category().filter(function(category){return categoryArray.indexOf(category) !== -1;}).length > 0;
25451            var typeArray = elem.type ? elem.type.split('|') : [];
25452            var typeInclude = self.selected().Type().filter(function(type){return typeArray.indexOf(type) !== -1;}).length > 0;
25453            var audienceArray = elem.audience ? elem.audience.split('|') : [];
25454            var audienceInclude = self.selected().Audience().filter(function(audience){return audienceArray.indexOf(audience) !== -1;}).length > 0;
25455            if(self.selected().Category().length === 0 && self.selected().Type().length === 0 && self.selected().Audience().length === 0){
25456                return true;
25457            }
25458            return (self.selected().Category().length > 0 ? categoryInclude : false) || (self.selected().Type().length > 0 ? typeInclude : false) || (self.selected().Audience().length > 0 ? audienceInclude : false);
25459        });
25460        return filtered;
25461    }).extend({ throttle: 250 });
25462
25463    var matchIndex = function (filterGroup, filterName) {
25464        var matchIndex = -1;
25465
25466        $(self.selectedList()).each(function(index, elem){
25467            if(elem['filterGroup'] === filterGroup && elem['filterName'] === filterName){ 
25468                matchIndex = index; 
25469                return;
25470            }
25471        });
25472
25473        return matchIndex;
25474    };
25475
25476    self.removeSelected = function(filterGroup, filterName){
25477        var index = matchIndex(filterGroup, filterName);
25478        self.selectedList.splice(index, 1);
25479    };
25480
25481    self.checkboxClick = function (filterGroup, filterName) {
25482        var filterIndex = matchIndex(filterGroup, filterName);
25483        if(filterIndex !== -1){
25484            self.removeSelected(filterGroup, filterName);
25485        } else if(filterIndex === -1){
25486            self.selectedList.push({filterGroup: filterGroup, filterName: filterName});
25487        }
25488    };
25489
25490    self.init = function(){
25491        var category = [];
25492        var type = [];
25493        var audience = [];
25494
25495        var countContainer = {};
25496
25497        var counterHelper = function(filterObj, filterName){
25498            filterObj[filterName] = filterObj[filterName] ? filterObj[filterName] + 1 : 1;
25499            return filterObj;
25500        };
25501
25502        $(self.dataArray()).each(function(index, elem){
25503            if(elem.categories) { 
25504                category = category.concat(elem.categories.split('|')); 
25505            }
25506            if(elem.type) { 
25507                type = type.concat(elem.type.split('|')); 
25508            }
25509            if(elem.audience) {
25510                audience = audience.concat(elem.audience.split('|'));
25511            }
25512        });
25513
25514        // Counts of how many events for each filter.
25515        self.count = {};
25516        self.count['Category'] = category.reduce(counterHelper, {});
25517        self.count['Type'] = type.reduce(counterHelper, {});
25518        self.count['Audience'] = audience.reduce(counterHelper, {});
25519
25520        // Init filter selections
25521        self.selectedList([]);
25522
25523        // All filters, sans repeats.
25524        self.Category(ko.utils.arrayGetDistinctValues(category).sort());
25525        self.Type(ko.utils.arrayGetDistinctValues(type).sort());
25526        self.Audience(ko.utils.arrayGetDistinctValues(audience).sort());
25527    };
25528
25529    self.count = {};
25530
25531    self.displayCount = function(category, filter){
25532        return '(' + self.count[category][filter] + ')';
25533    };
25534
25535    self.showFilters = ko.computed(function(){
25536        return (self.Category().length + self.Type().length + self.Audience().length) > 0;
25537    });
25538
25539    self.showFilter = function (filterName) {
25540        return self[filterName]().length > 0;
25541    }
25542};
25543
25544
25545$(function() {
25546
25547    'use strict';
25548
25549    var CalendarEventsViewModel = function(componentElem) {
25550        var self = this;
25551
25552        var calendarElem = componentElem.find('.calendar-container');
25553
25554        self.specifiedView = 'month';
25555
25556        // Static Params
25557        self.calendarBaseParams = {
25558            header: {
25559                left:   'prev,next today',
25560                center: 'title',
25561                right: 'month, listMonth'
25562            },
25563            titleFormat: 'MMMM YYYY',
25564            columnHeaderFormat: 'dddd',
25565            aspectRatio: 1.38,
25566            eventLimit: true,
25567            eventRender: function (event, element) {
25568                var anchor = element.prop('tagName') === 'A' ? element : element.find('a');
25569                if(event.id && anchor.length > 0){
25570                    anchor.attr('href', '/' + event.id.replace(/_/g,'/') + '.html');
25571                }
25572            }
25573        };
25574
25575        // Observables
25576        self.eventList = ko.observableArray();
25577
25578        self.filters = new FilterViewModel(self.eventList, ['Category', 'Type', 'Audience']);
25579
25580        self.calendarParams = ko.computed(function(){
25581            var events = { events: self.filters.filteredEventList() };
25582            var params = $.extend(true, {}, events, self.calendarBaseParams);
25583            return params;
25584        });
25585
25586        // sample data
25587        //self.eventList([{title: 'All Day Event',start: '2018-07-01', type: 'big', audience: 'cool people', category: 'hockey'},{title: 'Long Event',start: '2018-07-07',end: '2018-03-10', type: 'big', audience: 'cool people', category: 'baseball'},{id: 999,title: 'Repeating Event',start: '2018-07-09T16:00:00'},{id: 999,title: 'Repeating Event',start: '2018-07-16T16:00:00'},{title: 'Conference',start: '2018-03-11',end: '2018-07-13'},{title: 'Meeting',start: '2018-03-12T10:30:00',end: '2018-07-12T12:30:00'},{title: 'Lunch',start: '2018-07-12T12:00:00'},{title: 'Meeting',start: '2018-07-12T14:30:00'},{title: 'Happy Hour',start: '2018-07-12T17:30:00'},{title: 'Dinner',start: '2018-07-12T20:00:00'},{title: 'Birthday Party',start: '2018-07-13T07:00:00'},{title: 'Click for Google',url: 'http://google.com/',start: '2018-07-28'}]);
25588
25589        // Subscriptions
25590        self.filters.filteredEventList.subscribe(function(){
25591            self.specifiedView = calendarElem.fullCalendar('getView').name || 'month';
25592            calendarElem.fullCalendar('destroy');
25593            calendarElem.fullCalendar(self.calendarParams());
25594            checkView();
25595        });
25596
25597        function getView() {
25598            if($('body').hasClass('mobile')) {
25599                return 'listMonth';
25600            } else {
25601                return self.specifiedView;
25602            }
25603        }
25604
25605        //change view depending on current viewpoint size
25606        function checkView(){
25607            calendarElem.fullCalendar('changeView', getView());
25608        }
25609
25610        // Initialization
25611        var initEvents = function () {
25612            var resizeCal;
25613            $(window).on('resize', function(e) {
25614                clearTimeout(resizeCal);
25615                resizeCal = setTimeout(function() {
25616                    checkView();
25617                }, 250);
25618            });
25619            checkView();
25620        };
25621
25622        var init = function(){
25623            initEvents();
25624        };
25625
25626        init();
25627    };
25628
25629    var calendarComponents = $('.calendar-events.component');
25630
25631    calendarComponents.each(function(index, elem){
25632        ko.applyBindings(new CalendarEventsViewModel($(elem)), elem);
25633    });
25634
25635});
25636$(function(){
25637    "use strict";
25638
25639    if($(".pool-volume.component").length > 0) {
25640        var url = window.location.search.substring(1);
25641        // All Pool Volume URLs would have these query params in common if coming from a Share Link
25642        if(url.indexOf("shape=") !== -1 && url.indexOf("&deepEnd=") !== -1 && url.indexOf("&shallowEnd=") !== -1 &&  url.indexOf("&results=") !== -1) {
25643            getShapeUrlParams(url);
25644        } else {
25645            if(window.innerWidth > 767) {
25646                document.getElementsByClassName("pv-tab-container")[0].classList.add("rectangular-active");
25647                document.querySelectorAll("dt.rectangle")[0].classList.add("active");
25648                document.querySelectorAll("dt.rectangle > button")[0].setAttribute("aria-expanded", "true");
25649                document.querySelectorAll("dd#rectangle")[0].removeAttribute("hidden");
25650            } else {
25651                document.querySelectorAll(".tabs")[0].setAttribute("data-allow-toggle", "");
25652            }
25653        }
25654
25655        Array.prototype.slice.call(document.querySelectorAll('.tabs')).forEac
25655h(function (accordion) {
25656
25657            // Allow for multiple accordion sections to be expanded at the same time
25658            var tabsVertical = accordion.hasAttribute('data-tabs-vertical');
25659            // Allow for each toggle to both open and close individually
25660            var allowToggle = accordion.hasAttribute('data-allow-toggle');
25661
25662            // Create the array of toggle elements for the accordion group
25663            var triggers = Array.prototype.slice.call(accordion.querySelectorAll('dt>button'));
25664            var panels = Array.prototype.slice.call(accordion.querySelectorAll('dd'));
25665
25666            accordion.addEventListener('click', function (event) {
25667                var target = event.target;
25668                var targetText = event.target.innerText.trim().toLowerCase();
25669                var tabs = $("dl.tabs");
25670                var activeEl = $(this).find("dt.active");
25671                var tabContainer = document.getElementsByClassName("pv-tab-container")[0];
25672
25673                if (target.tagName === "BUTTON" && target.classList.contains("tab-btn")) {
25674                    // Check if the current toggle is expanded.
25675                    var isExpanded = target.getAttribute('aria-expanded') == 'true';
25676
25677                    var active = accordion.querySelector('[aria-expanded="true"]');
25678
25679                    if(active != null) {
25680                        // without allowMultiple, close the open accordion
25681                        if (active !== target) {
25682                            // Set the expanded state on the triggering element
25683                            active.setAttribute('aria-expanded', 'false');
25684                            // Hide the accordion sections, using aria-controls to specify the desired section
25685                            document.getElementById(active.getAttribute('aria-controls')).setAttribute('hidden', '');
25686                            activeEl.removeClass("active");
25687                            Array.prototype.slice.call(tabContainer.classList).forEach(function(className) {
25688                                if(className.includes("-active")) {
25689                                    tabContainer.classList.remove(className);
25690                                }
25691                            });
25692                            // When toggling is not allowed, clean up disabled state
25693                            if (!allowToggle) {
25694                                active.removeAttribute('aria-disabled');
25695                            }
25696                        }
25697                    }
25698
25699                    if (!isExpanded) {
25700                        // Set the expanded state on the triggering element
25701                        target.setAttribute('aria-expanded', 'true');
25702                        // Hide the accordion sections, using aria-controls to specify the desired section
25703                        document.getElementById(target.getAttribute('aria-controls')).removeAttribute('hidden');
25704
25705                        $(target).closest("dt").addClass("active");
25706                        $(target).closest(".pv-tab-container").addClass(targetText+"-active");
25707
25708                        // If toggling is not allowed, set disabled state on trigger
25709                        if (!allowToggle) {
25710                            target.setAttribute('aria-disabled', 'true');
25711                        }
25712                    } else if (allowToggle && isExpanded) {
25713                        // Set the expanded state on the triggering element
25714                        target.setAttribute('aria-expanded', 'false');
25715                        // Hide the accordion sections, using aria-controls to specify the desired section
25716                        document.getElementById(target.getAttribute('aria-controls')).setAttribute('hidden', '');
25717                        activeEl.removeClass("active");
25718                    }
25719                    event.preventDefault();
25720                }
25721            });
25722
25723            // Minor setup: will set disabled state, via aria-disabled, to an
25724            // expanded/ active accordion which is not allowed to be toggled close
25725            if (!allowToggle) {
25726                // Get the first expanded/ active accordion
25727                var expanded = accordion.querySelector('[aria-expanded="true"]');
25728
25729                // If an expanded/ active accordion is found, disable
25730                if (expanded) {
25731                    expanded.setAttribute('aria-disabled', 'true');
25732                }
25733            }
25734        });
25735
25736        /*
25737            Perform Pool Volume Calculations
25738        */
25739
25740        // Rectangular
25741        var buttonRect = document.getElementById("buttonRectangular");
25742        buttonRect.addEventListener("click", function(e) {
25743            var deepEndVal = document.getElementById("deepEndRectangle");
25744            var shallowEndVal = document.getElementById("shallowEndRectangle");
25745            var lengthVal = document.getElementById("lengthRectangle");
25746            var widthVal = document.getElementById("widthRectangle");
25747
25748            var rectangleShallow = Math.ceil(((parseFloat(lengthVal.value) * parseFloat(widthVal.value)) * parseFloat(shallowEndVal.value)) * 7.48
2574805);
25749            var rectangleDeep = 0;
25750            if (parseFloat(deepEndVal.value) > parseFloat(shallowEndVal.value)) {
25751                rectangleDeep = ((Math.ceil((lengthVal.value*widthVal.value)*deepEndVal.value)*7.4805)-Math.ceil(((lengthVal.value*widthVal.value)*shallowEndVal.value)* 7.4805))/2;
25752            }
25753            var result = Math.ceil(rectangleShallow + rectangleDeep);
25754
25755            if (!isNaN(result)) {
25756                var form = $(this).closest("form");
25757                var tabs = $(this).closest("dl.tabs");
25758                var activeTab = tabs.find("dt.active");
25759                validateForm(form, activeTab, result);
25760            }
25761
25762        });
25763
25764        // Oblong
25765        var buttonOb = document.getElementById("buttonOblong");
25766        buttonOb.addEventListener("click", function(e) {
25767            var deepEndVal = document.getElementById("deepEndOblong");
25768            var shallowEndVal = document.getElementById("shallowEndOblong");
25769            var largeDiameterVal = document.getElementById("largeDiameterOblong");
25770            var smallDiameterVal = document.getElementById("smallDiameterOblong");
25771            var lengthVal = document.getElementById("lengthOblong");
25772
25773            var oblongArea = Math.ceil(((parseFloat(largeDiameterVal.value) + parseFloat(smallDiameterVal.value)) * parseFloat(lengthVal.value)) * 0.45);
25774            var depth = (parseFloat(shallowEndVal.value) + parseFloat(deepEndVal.value)) / 2;
25775
25776            var result = Math.ceil((oblongArea * depth) * 7.4805);
25777
25778            if (!isNaN(result)) {
25779                var form = $(this).closest("form");
25780                var tabs = $(this).closest("dl.tabs");
25781                var activeTab = tabs.find("dt.active");
25782                validateForm(form, activeTab, result);
25783            }
25784
25785        });
25786
25787        // Circular
25788        var buttonCirc = document.getElementById("buttonCircular");
25789        buttonCirc.addEventListener("click", function(e) {
25790            var deepEndVal = document.getElementById("deepEndCircular");
25791            var shallowEndVal = document.getElementById("shallowEndCircular");
25792            var radius = document.getElementById("radiusCircular");
25793
25794            var cylinderShallow = Math.ceil(((Math.PI * Math.pow(radius.value,2))* parseFloat(shallowEndVal.value)) * 7.4805);
25795            var cylinderDeep = 0;
25796            if(parseFloat(deepEndVal.value) > parseFloat(shallowEndVal.value)) {
25797                cylinderDeep = Math.ceil(Math.ceil(((Math.PI * Math.pow(radius.value,2))*parseFloat(deepEndVal.value))*7.4805)-Math.ceil(((Math.PI * Math.pow(radius.value,2))*parseFloat(shallowEndVal.value)))*7.4805)/2;
25798            }
25799
25800            var result = Math.ceil(cylinderShallow + cylinderDeep);
25801
25802            if (!isNaN(result)) {
25803                var form = $(this).closest("form");
25804                var tabs = $(this).closest("dl.tabs");
25805                var activeTab = tabs.find("dt.active");
25806                validateForm(form, activeTab, result);
25807            }
25808        });
25809
25810        // Triangular
25811        var buttonTri = document.getElementById("buttonTriangular");
25812        buttonTri.addEventListener("click", function(e) {
25813            var deepEndVal = document.getElementById("deepEndTriangular");
25814            var shallowEndVal = document.getElementById("shallowEndTriangular");
25815            var triangleBase = document.getElementById("baseTriangular");
25816            var triangleHeight = document.getElementById("heightTriangular");
25817
25818            var triangleShallow = Math.ceil(((parseFloat(triangleBase.value) * parseFloat(triangleHeight.value))*parseFloat(shallowEndVal.value))*7.4805) / 2;
25819            var triangleDeep = 0;
25820            if(parseFloat(deepEndVal.value) > parseFloat(shallowEndVal.value)) {
25821                triangleDeep = Math.ceil((Math.ceil(((triangleBase.value*triangleHeight.value)*parseFloat(deepEndVal.value))*7.4805)-Math.ceil(((triangleBase.value*triangleHeight.value)*parseFloat(shallowEndVal.value))*7.4805))/2)/2;
25822            }
25823
25824            var result = Math.ceil(triangleShallow + triangleDeep);
25825
25826            if (!isNaN(result)) {
25827                var form = $(this).closest("form");
25828                var tabs = $(this).closest("dl.tabs");
25829                var activeTab = tabs.find("dt.active");
25830                validateForm(form, activeTab, result);
25831            }
25832        });
25833
25834        $("#recalcRect, #recalcOb, #recalcCirc, #recalcTri").on("click", function() {
25835            $(this).closest(".tab-content").removeClass("toggle-section");
25836        });
25837
25838        // Prototyping Math Object since IE does not support the trunc prop
25839        Math.trunc = Math.trunc || function(x) {
25840          if (isNaN(x)) {
25841            return NaN;
25842          }
25843          if (x > 0) {
25844            return Math.floor(x);
25845          }
25846          return Math.ceil(x);
25847        };
25848    }
25849});
25850
25851function getShapeUrlParams(url) {
25852    var params = {}, queries, temp, i, l;
25853    // Split into key/value pairs
25854    queries = url.split("&");
25855    // Convert the array of strings into an object
25856    for ( i = 0, l = queries.length; i < l; i++ ) {
25857        temp = queries[i].split('=');
25858        params[temp[0]] = temp[1];
25859    }
25860
25861    return populateValuesFromParams(params);
25862}
25863
25864function populateValuesFromParams(params) {
25865    var tabs = $(".pool-volume.component").find("dt");
25866    var tabContent = $(".pool-volume.component").find("dd");
25867    if(params.shape === "rectangle") {
25868        var rectangleTab = tabs.closest("."+params.shape);
25869        if(!rectangleTab.hasClass("active")) {
25870            rectangleTab.addClass("active");
25871            rectangleTab.find("button.tab-btn").attr("aria-expanded", "true");
25872            tabContent.each(function(index, element) {
25873                if($(element).is("#"+params.shape)) {
25874                    $(element).removeAttr("hidden");
25875                }
25876            });
25877            // input values from ${params} obj
25878            $("#deepEndRectangle").val(params.deepEnd != null ? params.deepEnd : 0);
25879            $("#shallowEndRectangle").val(params.shallowEnd != null ? params.shallowEnd : 0);
25880            $("#lengthRectangle").val(params.length != null ? params.length : 0);
25881            $("#widthRectangle").val(params.width != null ? params.width : 0);
25882            $("#calcResultRectangle").text(params.results != null ? params.results : 0);
25883        }
25884    } else if (params.shape === "oblong") {
25885        var oblongTab = tabs.closest("."+params.shape);
25886        if(!oblongTab.hasClass("active")) {
25887            oblongTab.addClass("active");
25888            oblongTab.find("button.tab-btn").attr("aria-expanded", "true");
25889            tabContent.each(function(index, element) {
25890                if($(element).is("#"+params.shape)) {
25891                    $(element).removeAttr("hidden");
25892                }
25893            });
25894            // input values from ${params} obj
25895            $("#deepEndOblong").val(params.deepEnd != null ? params.deepEnd : 0);
25896            $("#shallowEndOblong").val(params.shallowEnd != null ? params.shallowEnd : 0);
25897            $("#largeDiameterOblong").val(params.largeDiameter != null ? params.largeDiameter : 0);
25898            $("#smallDiameterOblong").val(params.smallDiameter != null ? params.smallDiameter : 0);
25899            $("#lengthOblong").val(params.length != null ? params.length : 0);
25900            $("#calcResultOblong").text(params.results != null ? params.results : 0);
25901        }
25902    } else if (params.shape === "circular") {
25903        var circularTab = tabs.closest("."+params.shape);
25904        if(!circularTab.hasClass("active")) {
25905            circularTab.addClass("active");
25906            circularTab.find("button.tab-btn").attr("aria-expanded", "true");
25907            tabContent.each(function(index, element) {
25908                if($(element).is("#"+params.shape)) {
25909                    $(element).removeAttr("hidden");
25910                }
25911            });
25912            // input values from ${params} obj
25913            $("#deepEndCircular").val(params.deepEnd != null ? params.deepEnd : 0);
25914            $("#shallowEndCircular").val(params.shallowEnd != null ? params.shallowEnd : 0);
25915            $("#radiusCircular").val(params.radius != null ? params.radius : 0);
25916            $("#calcResultCircular").text(params.results != null ? params.results : 0);
25917        }
25918    } else if (params.shape === "triangular") {
25919        var triangularTab = tabs.closest("."+params.shape);
25920        if(!triangularTab.hasClass("active")) {
25921            triangularTab.addClass("active");
25922            triangularTab.find("button.tab-btn").attr("aria-expanded", "true");
25923            tabContent.each(function(index, element) {
25924                if($(element).is("#"+params.shape)) {
25925                    $(element).removeAttr("hidden");
25926                }
25927            });
25928            // input values from ${params} obj
25929            $("#deepEndTriangular").val(params.deepEnd != null ? params.deepEnd : 0);
25930            $("#shallowEndTriangular").val(params.shallowEnd != null ? params.shallowEnd : 0);
25931            $("#heightTriangular").val(params.height != null ? params.height : 0);
25932            $("#baseTriangular").val(params.base != null ? params.base : 0);
25933            $("#calcResultTriangular").text(params.results != null ? params.results : 0);
25934        }
25935    }
25936}
25937
25938function validateForm(form, activeTab, result) {
25939    var inputs = $(form).find("input");
25940    var tab = $(activeTab);
25941
25942    var isValid = true;
25943    for(var i = 0; i < inputs.length; i++) {
25944        var currentInput = inputs[i];
25945        if(!currentInput.value || isNaN(currentInput.value)) {
25946            currentInput.parentElement.classList.add("is-invalid");
25947            isValid = false;
25948        }
25949    }
25950
25951    if(isValid) {
25952
25953        if(window.innerWidth > 767) {
25954            if (activeTab.hasClass("rectangle")) {
25955                $("#calcResultRectangle").text(Math.ceil(Math.trunc(result) / 100) * 100);
25956            } else if (activeTab.hasClass("oblong")) {
25957                $("#calcResultOblong").text(Math.ceil(Math.trunc(result) / 100) * 100);
25958            } else if (activeTab.hasClass("circular")) {
25959                $("#calcResultCircular").text(Math.ceil(Math.trunc(result) / 100) * 100);
25960            } else if (activeTab.hasClass("triangular")) {
25961                $("#calcResultTriangular").text(Math.ceil(Math.trunc(result) / 100) * 100);
25962            }
25963        } else {
25964            if (activeTab.hasClass("rectangle")) {
25965                $("#calcResultRectangle").closest(".tab-content").addClass("toggle-section");
25966                $("#calcResultRectangle").text(Math.ceil(Math.trunc(result) / 100) * 100);
25967            } else if (activeTab.hasClass("oblong")) {
25968                $("#calcResultOblong").closest(".tab-content").addClass("toggle-section");
25969                $("#calcResultOblong").text(Math.ceil(Math.trunc(result) / 100) * 100);
25970            } else if (activeTab.hasClass("circular")) {
25971                $("#calcResultCircular").closest(".tab-content").addClass("toggle-section");
25972                $("#calcResultCircular").text(Math.ceil(Math.trunc(result) / 100) * 100);
25973            } else if (activeTab.hasClass("triangular")) {
25974                $("#calcResultTriangular").closest(".tab-content").addClass("toggle-section");
25975                $("#calcResultTriangular").text(Math.ceil(Math.trunc(result) / 100) * 100);
25976            }
25977            // scroll to results container
25978            var shareComponent = $(tab).closest(".pv-tab-container").find(".pv-calc-share");
25979            var offsetHeader = $("header").height();
25980            var offsetValue = shareComponent.offset().top - offsetHeader;
25981            if(shareComponent.length > 0) {
25982                $('html, body').animate({
25983                    scrollTop: offsetValue
25984                }, 500);
25985            }
25986        }
25987    }
25988
25989    return isValid;
25990}
25991var PoolPumpSavingsCalculator = PoolPumpSavingsCalculator || {};
25992
25993PoolPumpSavingsCalculator.addressAutoComplete = (function(){
25994
25995	var autocomplete;
25996	var successCallback;
25997
25998	// Bias the autocomplete object to the user's geographical location,
25999    // as supplied by the browser's 'navigator.geolocation' object.
26000	var onFocus = function(viewModel, event) {
26001    	if (navigator.geolocation && autocomplete) {
26002	        navigator.geolocation.getCurrentPosition(function(position) {
26003	            var geolocation = {
26004	                lat: position.coords.latitude,
26005	                lng: position.coords.longitude
26006	            };
26007	            var circle = new google.maps.Circle(
26008	                {center: geolocation, radius: position.coords.accuracy});
26009	            autocomplete.setBounds(circle.getBounds());
26010	        });
26011	    }
26012	};
26013
26014	var setSuccessCallback = function (callback) {
26015		successCallback = callback;
26016	};
26017
26018	// Inits autocomplete on first keypress.
26019    var onKeyPress = function(viewModel, event) {
26020        // Create the autocomplete object, restricting the search predictions to
26021        // geographical location types.
26022        // 
26023        if(!autocomplete) {
26024            autocomplete = new google.maps.places.Autocomplete(event.currentTarget, {types: ['geocode']});
26025            // Avoid paying for data that you don't need by restricting the set of
26026            // place fields that are returned to just the address components.
26027            autocomplete.setFields(['address_component', 'formatted_address']);
26028            autocomplete.addListener('place_changed', function() {
26029                //
26030                result = autocomplete.getPlace();
26031                if(typeof result.address_components == 'undefined') {
26032                    // The user pressed enter in the input 
26033                    // without selecting a result from the list
26034                    // Let's get the list from the Google API so that
26035                    // we can retrieve the details about the first result
26036                    // and use it (just as if the user had actually selected it)
26037                    autocompleteService = new google.maps.places.AutocompleteService();
26038                    autocompleteService.getPlacePredictions(
26039                        {
26040                            'input': result.name,
26041                            'types': ['geocode']
26042                        },
26043                        function listentoresult(list, status) {
26044                            if(list == null || list.length == 0) {
26045                                // There are no suggestions available.
26046                                // The user saw an empty list and hit enter.
26047                                //console.log("No results");
26048                            } else {
26049                                // Here's the first result that the user saw
26050                                // in the list. We can use it and it'll be just
26051                                // as if the user actually selected it
26052                                // themselves. But first we need to get its details
26053                                // to receive the result on the same format as we
26054                                // do in the AutoComplete.
26055                                placesService = new google.maps.places.PlacesService(event.currentTarget);
26056                                placesService.getDetails(
26057                                    {'reference': list[0].reference},
26058                                    function detailsresult(detailsResult, placesServiceStatus) {
26059                                        // Here's the first result in the AutoComplete with the exact
26060                                        // same data format as you get from the AutoComplete.
26061                                        //console.log("We selected the first item from the list automatically because the user didn't select anything");
26062                                        var zipcode = detailsResult.address_components[0]['long_name'];
26063                                        successCallback(zipcode);
26064                                    }
26065                                );
26066                            }
26067                        }
26068                    );
26069                } else {
26070                    // The user selected a result from the list, we can 
26071                    // proceed and use it right away
26072                    var place = autocomplete.getPlace();
26073                    var zipcode = place.address_components[0]['long_name'];
26074                    successCallback(zipcode);
26075
26076                }
26077            });
26078        }
26079        return true;
26080    }
26081    return {
26082    	onFocus: onFocus,
26083    	onKeyPress: onKeyPress,
26084    	setSuccessCallback: setSuccessCallback
26085	};
26086})();
26087var PoolPumpSavingsCalculator = PoolPumpSavingsCalculator || {};
26088
26089(function(){
26090
26091    var displayHelpers = function(self){
26092        return {
26093            kValue: function(data){
26094                return data > 1000 ? data / 1000 + 'k' : data;
26095            },
26096            addCommas: function(data){
26097                return data.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
26098            },
26099            isOdd: function(data) {
26100                return data % 2 === 1;
26101            },
26102            isEven: function(data) {
26103                return data % 2 === 0;
26104            },
26105            isFirst: function(index) {
26106                return index === 0;
26107            },
26108            isLast: function (array, index) {
26109                return index === (array.length - 1);
26110            },
26111            isFirstOrLast: function(array, index){
26112                return this.isFirst(index) || this.isLast(array, index);
26113            },
26114            runTimeTickLabel: function(index) {
26115                return (this.isFirstOrLast(self.runTimeTickMarks(), index) || (index == (self.runTimeTickMarks().length - 1) / 2)) ? index : '';
26116            },
26117            inverse: function(currentValue, min, max){
26118                return 1 - (currentValue / (max - min));
26119            },
26120            lastStep: function(){
26121                return self.currentStep() == 6;
26122            },
26123            showPaging: function(){
26124                return !this.lastStep();
26125            },
26126            dollarAmount: function(data){
26127                return '$' + this.addCommas(data);
26128            },
26129            percentAmount: function(data){
26130                return data + '%';
26131            },
26132            kwhAmount: function(data){
26133                return data + ' kWh';
26134            },
26135            hoursAmount: function(data){
26136                return data + ' HRS';
26137            },
26138            addHtml: function(data){
26139                if (data.indexOf("where-to-buy") > -1) {
26140                    return data + ".html?show=local&from=product"
26141                } else {
26142                    return data + ".html"
26143                }
26144            }
26145        }
26146    };
26147
26148    var calculationHelper = function(self){
26149        return {
26150            ppmNeeded : function(salinity){ return 3400 - salinity;},
26151            liters : function(gallons){ return gallons* 3.7854; }, //--- Gives you liters from Gallons
26152            glNeeded : function(ppmNeeded){ return ppmNeeded * 0.001; }, //--- Gives g/L needed
26153            gSaltNeeded : function(liters, glNeeded){ return liters * glNeeded; },
26154            lbsSaltNeeded : function(gSaltNeeded){ return Math.ceil(gSaltNeeded / 453.5923); } //--- Gives you lbs of salt needed.
26155        }
26156    };
26157
26158    var RangeModel = function (min, max, parentModel, currentStyle) {
26159        var self = this;
26160        self.min = ko.observable(min);
26161        self.max = ko.observable(max);
26162        currentStyle = currentStyle || "runTime";
26163
26164        self.selected = ko.computed(function(){
26165            return (parentModel[currentStyle]() - min)/(max - min) * 100 + '%';
26166        });
26167
26168        self.unselected = ko.computed(function(){
26169            return 100 - (parentModel[currentStyle]() - min)/(max - min) * 100 + '%';
26170        });
26171
26172        var tickMarkStyle = {
26173            runTime : function(){
26174                var tickArray = tickArray || (new Array(26).join('0').split('')); // results in array of 25 (0-24)
26175                return tickArray.map(function(elem, index){return parentModel.displayHelpers.isFirstOrLast(tickArray, index) ? 'large-tick' : 'small-tick'});
26176            },
26177            volume : function(){
26178                var tickArray = tickArray || (new Array(18).join('0').split('')); // results in array of 18
26179                return tickArray.map(function(elem, index){return (index % 2 == 0) ? 'large-tick' : 'small-tick'});
26180            },
26181            season : function(){
26182                 var tickArray = tickArray || (new Array(14).join('0').split('')); // results in array of 13
26183                return tickArray.map(function(elem, index){return (index % 2 == 0) ? 'large-tick' : 'small-tick'});
26184            }
26185        };
26186
26187        var labelStyle = {
26188            runTime : function(index){
26189                return (parentModel.displayHelpers.isFirstOrLast(self.tickMarks(), index) || (index == (self.tickMarks().length - 1) / 2)) ? index : '';
26190            },
26191            volume : function(index){
26192                var volumeLabel = (index % 2 === 0) ? min + (max - min) / (self.tickMarks().length - 1) * index : '';
26193                return parentModel.displayHelpers.kValue(volumeLabel)
26194            },
26195            season : function(index){
26196                var seasonLabel = (index % 4 === 0) ? min + (max - min) / (self.tickMarks().length - 1) * index : '';
26197                 return seasonLabel !== '' ? seasonLabel + 'mos' : '';
26198            }
26199        };
26200
26201        self.tickMarks = ko.observableArray(tickMarkStyle[currentStyle]());
26202        self.label = function(index){return labelStyle[currentStyle](index);}
26203    };
26204
26205    PoolPumpSavingsCalculator.ViewModel = function(componentElement) {
26206        var self = this;
26207        self.displayHelpers = displayHelpers(self);
26208        self.calculationHelper = calculationHelper(self);
26209        self.currentStep = ko.observable(1);
26210        self.currentTemplate = ko.computed(function(){
26211            return 'step-' + self.currentStep();
26212        });
26213        self.componentElement = componentElement;
26214        self.zipCode = ko.observable('');
26215        self.zipCodeError = ko.observable(false);
26216        self.state = ko.observable('');
26217        self.rate = ko.observable('');
26218        self.horsePower = ko.observable("0");
26219        self.runTime = ko.observable(12);
26220        self.RunTimeModel = new RangeModel(0, 24, self, 'runTime');
26221
26222        self.itemParam = ko.observable();
26223
26224        self.isLoading = ko.observable(true);
26225
26226        self.volume = ko.observable(35000);
26227        self.VolumeModel = new RangeModel(10000, 50000, self, 'volume');
26228
26229        self.season = ko.observable(6);
26230        self.SeasonModel = new RangeModel(0, 12, self, 'season');
26231
26232        self.userLatLong = ko.observable();
26233        self.userAddress = ko.observable();
26234
26235        self.results = ko.observable();
26236
26237        //Triggered by location button click
26238        self.userLatLong.subscribe(function(newValue){
26239            var geocoder = new google.maps.Geocoder();
26240            if(newValue){
26241                geocoder.geocode({'latLng': newValue}, function(results, status) {
26242                    if (status == google.maps.GeocoderStatus.OK) {
26243                        var addressData = getStateZip(results);
26244                        self.state(addressData.state);
26245                        self.userAddress(results[0].formatted_address);
26246                        self.zipCode(addressData.zip);
26247                        kwhLookup();
26248                    }
26249                });
26250            }
26251        });
26252
26253        //Triggered by user zipcode input
26254        self.lookupZipcode = function(){
26255            var geocoder = new google.maps.Geocoder();
26256            var newValue = $(arguments[1].target).val();
26257            if(newValue){
26258                geocoder.geocode({'address': newValue}, function(results, status) {
26259                    if (status == google.maps.GeocoderStatus.OK) {
26260                        var addressData = getStateZip(results);
26261                        self.userAddress(results[0].formatted_address);
26262                        self.state(addressData.state);
26263                        self.zipCode(addressData.zip);
26264                        kwhLookup();
26265                        self.zipCodeError(false);
26266                    } else {
26267                        self.zipCode('');
26268                        self.rate('');
26269                        self.zipCodeError(true);
26270                    }
26271                });
26272            }
26273        };
26274
26275        var getStateZip = function(results){
26276            var outputData = {state: '', zip: ''};
26277
26278            if(results[0] && results[0]['address_components']){
26279                var postalCodeArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('postal_code') !== -1});
26280                var stateNameArray = results[0]['address_components'].filter(function(elem){return elem.types.indexOf('administrative_area_level_1') !== -1});
26281                outputData['zip'] = (postalCodeArray && postalCodeArray.length > 0) ? postalCodeArray[0]['long_name'] : "";
26282                outputData['state']  = (stateNameArray && stateNameArray.length > 0) ? stateNameArray[0]['long_name'] : "";
26283
26284            }
26285
26286            return outputData;
26287        };
26288
26289        self.zipCodeEnter = function (value, event) {
26290            if(event.keyCode === 13){
26291                self.lookupZipcode(value, event);
26292            }
26293            return true;
26294        }
26295
26296        var kwhLookup = function(){
26297            $.ajax({
26298              url: '/bin/pentair/calculators/poolpumpsavings',
26299              data: {state: self.state()},
26300              success: function(result){
26301                if(result.kw){
26302                    self.rate(Math.round(parseFloat(result.kw)*10000)/10000);
26303                    self.zipCodeError(false);
26304                }
26305              }
26306            });
26307        };
26308
26309        self.params = ko.computed(function(){
26310            return {
26311                state: self.state(),
26312                swimSeason: self.season(),
26313                runTime: self.runTime(),
26314                volume: self.volume(),
26315                hp: self.horsePower(),
26316                electricityCost: self.rate()
26317            }
26318        });
26319
26320        self.populateResults = function(){
26321            $.get({
26322                url: "/bin/pentair/calculators/poolpumpsavings.json",
26323                data: self.params(),
26324                success: function(result){
26325                    var resultsModels = [];
26326                    $.each(result[0].products, function (index, elem) {
26327                         var name = Object.keys(elem)[0];
26328                         resultsModels.push(new self.ProductModel(name, elem[name][0]));
26329                    });
26330                    self.results(resultsModels);
26331                }
26332            });
26333        };
26334
26335        self.ProductModel = function(productName, productResultObj){
26336            var keys = ["brands","categories","cost","cost-savings","hrs-compare","hrs-per-day","kwh-per-month","kwh-savings","ss-cost","ss-hrs-per-day","ss-kwh-per-month","thumbnail","title","url","where-to-buy"];
26337            var self = this;
26338            self.name = productName;
26339
26340            $.each(keys, function(index, elem){
26341                self[elem] = productResultObj[elem];
26342            });
26343
26344            return self;
26345        };
26346
26347        self.shareHelper = function(){
26348            var self = this;
26349
26350            self.shareParams = function(itemIndex){
26351                return {
26352                    zipCode: self.zipCode(),
26353                    rate: self.rate(),
26354                    horsePower: self.horsePower(),
26355                    runTime: self.runTime(),
26356                    volume: self.volume(),
26357                    season: self.season(),
26358                    item: itemIndex + 1  // which accordion to expand
26359                }
26360            };
26361
26362            var facebookLink = function(itemIndex){
26363                var fbLinkBase = 'http://www.facebook.com/sharer/sharer.php?u=';
26364                return fbLinkBase + encodeURIComponent(window.location.origin + window.location.pathname + '?title=' + document.title + '&' + $.param(self.shareParams(itemIndex)));
26365            };
26366
26367            var twitterLink =  function(itemIndex){
26368                var twitterBase = 'http://twitter.com/intent/tweet?status=';
26369                return twitterBase + document.title + ' ' + encodeURIComponent(window.location.origin + window.location.pathname + '?' + $.param(self.shareParams(itemIndex)));
26370            };
26371
26372            var mailToLink = function(itemIndex){
26373                var mailToBase = 'mailto:?subject=';
26374                var bodyKey = '&body=';
26375                return mailToBase + document.title + bodyKey + encodeURIComponent(window.location.origin + window.location.pathname + '?' + $.param(self.shareParams(itemIndex)));
26376            };
26377
26378            return {
26379                facebookLink : facebookLink,
26380                twitterLink : twitterLink,
26381                mailToLink : mailToLink
26382            }
26383        };
26384
26385        self.initRecommendation = function(){
26386            if(self.displayHelpers.lastStep()){
26387                self.populateResults();
26388            }
26389        }
26390
26391        self.checkZipcodeError = function(){
26392            var isValid = (!(self.zipCode()) && self.rate()) || ((self.zipCode) && self.rate());
26393            if(isValid){
26394                self.zipCode('');
26395                self.zipCodeError(false);
26396            } else {
26397                self.zipCodeError(true);
26398            }
26399            return isValid;
26400        };
26401
26402        self.disableNext = function () {
26403            var nextRules = {
26404                1 : function(){
26405                    return !self.rate();
26406                },
26407                2 : function(){
26408                    return self.horsePower() == 0;
26409                },
26410                3 : function(){
26411                    return !self.runTime();
26412                },
26413                4 : function(){
26414                    return !self.volume();
26415                },
26416                5 : function(){
26417                     return !self.season();
26418                }
26419            }
26420            return nextRules[self.currentStep()]();
26421        }
26422
26423        var scrollTop = function(){
26424             setTimeout(function(){$("body,html").animate({
26425                scrollTop: componentElement.offset().top - $('header').outerHeight() - 65
26426              }, 500 )}, 200);
26427        };
26428
26429        self.firstStep = function () {
26430            self.currentStep(1);
26431            scrollTop();
26432        };
26433
26434        self.checkToolTip = function () {
26435            var toolTip = this.componentElement.data('tooltip');
26436            return !!toolTip;
26437        };
26438
26439        self.nextStep = function () {
26440            self.checkZipcodeError();
26441            if(!self.disableNext()){
26442                if(self.currentStep() === 5){
26443                    self.isLoading(true);
26444                    self.results(null);
26445                }
26446                self.currentStep(self.currentStep() + 1);
26447            }
26448            if ( matchMedia('(max-width: 765px)').matches ) {
26449                scrollTop();
26450            }
26451        };
26452
26453        self.prevStep = function () {
26454            self.currentStep(self.currentStep() - 1);
26455            if ( matchMedia('(max-width: 765px)').matches ) {
26456                scrollTop();
26457            }
26458        }
26459
26460        self.locationSearchClick = function () {
26461            self.initLatLong()
26462        };
26463
26464        self.runLatLongSearch = function () {
26465            //console.log('latlongasearch')
26466        }
26467
26468        self.initLatLong = function(){
26469          self.tryBrowserGeoLocation();
26470          self.firstLatLongInit = self.userLatLong.subscribe(function(newValue){
26471            if(newValue){
26472                self.runLatLongSearch(newValue);
26473            }
26474            self.firstLatLongInit.dispose();
26475          });
26476        };
26477
26478        self.tryBrowserGeoLocation = function () {
26479            if (navigator.geolocation) {
26480                geoLocationIETimeout();
26481                navigator.geolocation.getCurrentPosition(function(position) {
26482                    var pos = { lat:position.coords.latitude, lng: position.coords.longitude};
26483                    self.userLatLong(pos);
26484                    self.geoLocationStatus('complete');
26485                }, function(e){ // error
26486                    //self.errorMessage('noGeo');
26487                    //self.firstSearch.dispose();
26488                    self.geoLocationStatus('complete');
26489                    self.isLoading(false);
26490                });
26491            }
26492        };
26493
26494        // If a user hits the 'x' when the location requests pops up in IE, the error section is not hit,
26495        // and the service fails silently.
26496        function geoLocationIETimeout(){
26497            var isIE = /*@cc_on!@*/false || !!document.documentMode; // Internet Explorer 6-11
26498            self.geoLocationStatus = ko.observable('waiting');
26499            if(isIE){
26500                setTimeout(function(){
26501                    if(self.geoLocationStatus() === 'waiting'){
26502                        //self.errorMessage('noGeo');
26503                        //self.firstSearch.dispose();
26504                        self.isLoading(false);
26505                    }
26506                }, 8000);
26507            }
26508        };
26509
26510        ko.bindingHandlers.initAfterRender = {
26511            update: function(element, valueAccessor) {
26512                ko.utils.unwrapObservable(valueAccessor()); //grab a dependency to the obs array
26513                PENTAIR.InitAccordion();
26514                if(self.results()){
26515                    self.isLoading(false);
26516                    if(self.itemParam()){
26517                        var accordionItem = componentElement.find('.accordion.section .accordion dt').eq([self.itemParam()-1]);
26518                        if(!accordionItem.hasClass('active')){
26519                            accordionItem.click();
26520                        };
26521                        self.itemParam(null);
26522                    }
26523                }
26524            }
26525        }
26526
26527        var initParams = function(){
26528            var queryString = location.search.substring(1);
26529            var urlParams = queryString ? JSON.parse('{"' + decodeURIComponent(queryString).replace(/&/g, "\",\"").replace(/=/g,"\":\"") + '"}') : {};
26530
26531            var zipCodeParam = urlParams["zipCode"] || "";
26532            var horsePowerParam = urlParams["horsePower"] || "";
26533            var runTimeParam = urlParams["runTime"] || "";
26534            var volumeParam = urlParams["volume"] || "";
26535            var seasonParam = urlParams["season"] || "";
26536            var rateParam = urlParams["electricityCost"] || "";
26537            var itemParam = urlParams["item"] || "";
26538
26539            var paramsUsed = zipCodeParam || horsePowerParam || runTimeParam || volumeParam || seasonParam || rateParam;
26540
26541            if(paramsUsed){
26542                self.zipCode(zipCodeParam);
26543                self.horsePower(horsePowerParam);
26544                self.runTime(runTimeParam);
26545                self.volume(volumeParam);
26546                self.season(seasonParam);
26547                self.rate(rateParam);
26548                self.itemParam(itemParam ? itemParam : null);
26549
26550                var stepArray = [!!self.rate(), !!self.horsePower(), !!self.runTime(), !!self.volume(), !!self.season()];
26551                var stepIndex = stepArray.indexOf(false);
26552                var currentStep = (stepIndex == -1 ? 6 : (stepIndex + 1));
26553                self.currentStep(stepIndex == -1 ? 6 : (stepIndex + 1));
26554            }
26555        };
26556
26557        initParams();
26558    };
26559
26560    $(document).ready(function() {
26561        $('.pool-pump-savings-calculator.component').each(function() {
26562            ko.applyBindings(new PoolPumpSavingsCalculator.ViewModel($(this)), this);
26563        });
26564    });
26565
26566
26567// WTB Button Analytics - Pool Calculators
26568
26569    // Fire all 'on click' event analytics tracking methods
26570    self.poolWtbAnalytics = function (wtbClickElement) {
26571        trackCTAClick(wtbClickElement);
26572        trackWTBClickEvent(wtbClickElement);
26573        constructAlgoliaAnalyticsWTBObject();
26574        return true;
26575    }
26576
26577    // Fire all 'on click' event analytics tracking methods
26578    self.poolProdClickAnalytics = function (prodClickElement) {
26579        trackCTAClick(prodClickElement);
26580        trackProdClickEvent(prodClickElement);
26581        constructAlgoliaAnalyticsWTBObject();
26582        return true;
26583    }
26584
26585    // [SEAP-145] - Algolia WTB Conversion Tracking
26586        function constructAlgoliaAnalyticsWTBObject() {
26587            var queryParams = window.location.href.indexOf("?") !== -1;
26588            if (queryParams) {
26589                var search = window.location.search.substring(1);
26590                var params = JSON.parse('{"' + decodeURI(search).replace(/&/g, '","').replace(/=/g, '":"') + '"}');
26591                if (params.hasOwnProperty("queryID") && params.hasOwnProperty("objectID") && params.hasOwnProperty("indexName")) {
26592                    var userToken = "";
26593                    if (typeof _satellite !== undefined && _satellite != null) {
26594                        userToken = _satellite.getVisitorId().getMarketingCloudVisitorID();
26595                    }
26596                    // attach to window object with conversion tracking details
26597                    aa('convertedObjectIDsAfterSearch', {
26598                        userToken: userToken,
26599                        eventName: 'Where_To_Buy',
26600                        index: params.indexName,
26601                        queryID: params.queryID,
26602                        objectIDs: [params.objectID]
26603                    });
26604                }
26605            }
26606            return true;
26607        }
26608
26609        // Abode Analytics
26610        // Tracks the WTB button click event
26611        function trackWTBClickEvent(wtbClickElement) {
26612            var wtbText = $(wtbClickElement).text();
26613            wtbText = wtbText ? wtbText.trim() : "";
26614            var eventWTBPayload = {
26615                eventName: 'WTB click',
26616                eventType: 'event',
26617                attributes: {
26618                    visitor: {
26619                        pentairCustomerID: getPentairCustomerID(), //if this is available
26620                        dealerID: getDealerID(), //if this is available
26621                        distributorID: getDistributorID() //if this is available
26622                    },
26623                    page: {
26624                        pageCanonical: getPageViewPageAttribute("pageCanonical"),
26625                        pageName: getPageViewPageAttribute("pageName"),
26626                        pagePath: getPageViewPageAttribute("pagePath"),
26627                        pageType: getPageViewPageAttribute("pageType"),
26628                        pageURL: getPageViewPageAttribute("pageURL"),
26629                        pageTitle: getPageViewPageAttribute("pageTitle"),
26630                        pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
26631                        businessUnitID: getPageViewPageAttribute("businessUnitID"),
26632                        subBrand: getPageViewPageAttribute("subBrand"),
26633                        language: getPageViewPageAttribute("language"),
26634                        author: getPageViewPageAttribute("author"),
26635                    },
26636                    product: {
26637                        skuID: self.productSku,
26638                        productName: wtbClickElement.name,
26639                        type: getPageViewProductAttribute("type")
26640                    },
26641                    cta: {
26642                        cta: wtbText
26643                    }
26644                }
26645            }
26646            trackEventWithQueue(eventWTBPayload);
26647        }
26648
26649        // Abode Analytics
26650        // Tracks the WTB button click event
26651        function trackProdClickEvent(prodClickElement) {
26652            var prodText = $(prodClickElement).text();
26653            prodText = prodText ? prodText.trim() : "";
26654            var eventProdPayload = {
26655                eventName: 'cta product clicked',
26656                eventType: 'event',
26657                attributes: {
26658                    visitor: {
26659                        pentairCustomerID: getPentairCustomerID(), //if this is available
26660                        dealerID: getDealerID(), //if this is available
26661                        distributorID: getDistributorID() //if this is available
26662                    },
26663                    page: {
26664                        pageCanonical: getPageViewPageAttribute("pageCanonical"),
26665                        pageName: getPageViewPageAttribute("pageName"),
26666                        pagePath: getPageViewPageAttribute("pagePath"),
26667                        pageType: getPageViewPageAttribute("pageType"),
26668                        pageURL: getPageViewPageAttribute("pageURL"),
26669                        pageTitle: getPageViewPageAttribute("pageTitle"),
26670                        pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
26671                        businessUnitID: getPageViewPageAttribute("businessUnitID"),
26672                        subBrand: getPageViewPageAttribute("subBrand"),
26673                        language: getPageViewPageAttribute("language"),
26674                        author: getPageViewPageAttribute("author"),
26675                    },
26676                    product: {
26677                        skuID: self.productSku,
26678                        productName: prodClickElement.name,
26679                        type: getPageViewProductAttribute("type")
26680                    },
26681                    cta: {
26682                        cta: prodText
26683                    }
26684                }
26685            }
26686            trackEventWithQueue(eventProdPayload);
26687        }
26688
26689        // CTA Click event
26690        function trackCTAClick(ctaClickElement) {
26691            var ctaText = $(ctaClickElement).text();
26692            ctaText = ctaText ? ctaText.trim() : "";
26693            var eventCTAPayload = {
26694                eventName: 'cta clicked',
26695                eventType: 'event',
26696                attributes: {
26697                    visitor: {
26698                        pentairCustomerID: getPentairCustomerID(), //if this is available
26699                        dealerID: getDealerID() //if this is available
26700                    },
26701                    page: {
26702                        pageCanonical: getPageViewPageAttribute("pageCanonical"),
26703                        pageName: getPageViewPageAttribute("pageName"),
26704                        pagePath: getPageViewPageAttribute("pagePath"),
26705                        pageType: getPageViewPageAttribute("pageType"),
26706                        pageURL: getPageViewPageAttribute("pageURL"),
26707                        pageTitle: getPageViewPageAttribute("pageTitle"),
26708                        pageSEOTags: getPageViewPageAttribute("pageSEOTags"),
26709                        businessUnitID: getPageViewPageAttribute("businessUnitID"),
26710                        subBrand: getPageViewPageAttribute("subBrand"),
26711                        language: getPageViewPageAttribute("language"),
26712                        author: getPageViewPageAttribute("author")
26713                    },
26714                    cta: {
26715                        cta: ctaText
26716                    }
26717                }
26718            }
26719            trackEventWithQueue(eventCTAPayload);
26720        }
26721
26722})();
26723$(function(){
26724    "use strict";
26725
26726    var initHeatPumpCarousel = function(carouselComponent){
26727        var carousel = carouselComponent.find('.hp-carousel.owl-carousel');
26728
26729        // Main Steps Carousel Component
26730        carousel.owlCarousel({
26731            items: 1,
26732            loop: false,
26733            mouseDrag: false,
26734            touchDrag:false,
26735            dots: true,
26736            nav:true,
26737            singleItem:true,
26738            navText: ['<button class="btn btn-white prev"><span>previous</span></button>', '<button class="btn btn-green next"><span>next</span></button>'],
26739            dotsContainer:"#hp-dots-container",
26740            autoHeight:true,
26741            responsive:{
26742                0: {
26743                    margin:20
26744                },
26745                768:{
26746                    margin:0
26747                }
26748            }
26749        }).on("initialized.owl.carousel changed.owl.carousel resized.owl.carousel", function(e) {
26750            handleOnChanged(e);
26751            anchorStepsOnMobile(e);
26752        });
26753
26754        $(".next").on("click", function(e) {
26755            validateSlide(e);
26756            e.preventDefault();
26757            return false;
26758        });
26759
26760        var activeItem = $(this).find(".owl-item.active");
26761        var activeItemInputs = $(activeItem).find("input");
26762        $(activeItemInputs).each(function(index, elem) {
26763            $(this).on("input", function(e) {
26764                if($(this).parent().hasClass("is-invalid")) {
26765                    $(this).parent().removeClass("is-invalid");
26766                }
26767            });
26768        });
26769
26770        $(document).on("click", ".recommended-pump .btn-over", function(e) {
26771            e.preventDefault();
26772            $(this).closest(".heat-pump.component").removeClass("show-recommended-pump");
26773            $(carousel).trigger("to.owl.carousel", [0,0]);
26774            $(carousel).find(".owl-nav").css("textAlign", "");
26775            var recommendedPump = $(".heat-pump.component").find(".recommended-pump");
26776            if(!recommendedPump.find(".loader-wrapper.loader").length) {
26777                var loader = '<div class="loader-wrapper loader"><div class="results-loader"><p class="loading-text">Loading...</p></div></div>';
26778                $(this).closest(".recommended-pump").append(loader);
26779            }
26780        });
26781
26782        // set height since first slide is not as tall as later slides and causes excess whitespace
26783        $('.owl-carousel .owl-stage-outer').addClass('slide-1-height');
26784
26785    };
26786
26787    var heatPumpComponents = $('.component.heat-pump');
26788
26789    if(heatPumpComponents.length){
26790        $(function(){
26791            heatPumpComponents.each(function(index, elem){
26792                initHeatPumpCarousel($(elem));
26793            });
26794        });
26795    }
26796
26797    /*
26798    * Call getTabInputValues() to handle the calculations on input since we removed the calculate button for HP component
26799    */
26800    var poolVolumeComponent = heatPumpComponents.find(".pool-volume.component");
26801    if(poolVolumeComponent.length > 0) {
26802        var tabs = poolVolumeComponent.find("dt");
26803        $(tabs).on("click", function(e) {
26804            var targetEl = e.currentTarget;
26805            var inputs = $(this).next("dd").find("input");
26806            getTabInputValues(targetEl, inputs);
26807        });
26808
26809        getTabInputValues(tabs);
26810    }
26811
26812    if($(".heat-pump.component").length > 0) {
26813
26814        $("#zipCode").on("keyup", function(e) {
26815            if ($(this).val().length === 5) {
26816                getLatLongByZipCode($(this).val());
26817            }
26818        });
26819
26820        $("#allowZip").on("click", function(e) {
26821            getUserPosition();
26822        });
26823
26824        if(!$("body").hasClass("ie")) {
26825            $("#tempSlider").on("input", function(e) {
26826                $(this).closest(".pool-temp-slider").find(".slider-selected").css("width", sliderSelected);
26827                $(this).closest(".pool-temp-slider").find(".slider-unselected").css("width", sliderUnselected);
26828                $(this).closest(".pool-temp-slider").find("#tick-result-num").text(Math.round($(this).val()));
26829                $(this).closest(".pool-temp-container").find("#deg-output-num").text(Math.round($(this).val()));
26830            });
26831
26832            $(".recommended-pump .tabs").on("input", ".slider.left", function(e) {
26833                this.value = Math.min(this.value,this.parentNode.childNodes[2].value-1);
26834                var value=(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.value)-(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.min);
26835                $(this).closest(".slider-container").find(".inverse-left").css("width", value+'%');
26836                $(this).closest(".slider-container").find(".range-overlap").css("left", value+'%');
26837                $(this).closest(".slider-container").find(".thumb.left").css("left", value+'%');
26838                handleActiveBars();
26839            });
26840
26841            $(".recommended-pump .tabs").on("input", ".slider.right", function(e) {
26842                this.value = Math.max(this.value,this.parentNode.childNodes[1].value-(-1));
26843                var value=(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.value)-(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.min);
26844                $(this).closest(".slider-container").find(".inverse-right").css("width", (100-value)+'%');
26845                $(this).closest(".slider-container").find(".range-overlap").css("right", (100-value)+'%');
26846                $(this).closest(".slider-container").find(".thumb.right").css("left", value+'%');
26847                handleActiveBars();
26848            });
26849
26850            $(".recommended-pump .tabs").on("input", ".dollars-per-therm input", function(e) {
26851                $(this).closest(".slider-container").find(".slider-selected").css("width", dptSliderWidths.selectedWidth());
26852                $(this).closest(".slider-container").find(".slider-unselected").css("width", dptSliderWidths.unselectedWidth());
26853                $(this).closest(".slider-container").find("#dptThermVal").text(Number.parseFloat($(this).val()).toFixed(2));
26854            });
26855
26856            $(".recommended-pump .tabs").on("input", ".dollars-per-kwh input", function(e) {
26857                $(this).closest(".slider-container").find(".slider-selected").css("width", dpkSliderWidths.selectedWidth());
26858                $(this).closest(".slider-container").find(".slider-unselected").css("width", dpkSliderWidths.unselectedWidth());
26859                $(this).closest(".slider-container").find(".kwh-value").text(Number.parseFloat($(this).val()).toFixed(4));
26860            });
26861
26862            $(".recommended-pump .tabs").on("input", ".gas-efficiency input", function(e) {
26863                $(this).closest(".slider-container").find(".slider-selected").css("width", gasEfficiencyWidths.selectedWidth());
26864                $(this).closest(".slider-container").find(".slider-unselected").css("width", gasEfficiencyWidths.unselectedWidth());
26865                $(this).closest(".slider-container").find(".gas-value").text(Math.round($(this).val()));
26866            });
26867
26868            $(".recommended-pump .tabs").on("input", ".pool-temp-slider input", function(e) {
26869                $(this).closest(".slider-container").find(".slider-selected").css("width", poolTempWidths.selectedWidth());
26870                $(this).closest(".slider-container").find(".slider-unselected").css("width", poolTempWidths.unselectedWidth());
26871                $(this).closest(".slider-container").find(".pool-temp-value").text(Math.round($(this).val()));
26872            });
26873
26874        } else {
26875            // ie and edge do not support input events, use on change instead
26876            $("#tempSlider").on("change", function(e) {
26877                $(this).closest(".pool-temp-slider").find(".slider-selected").css("width", sliderSelected);
26878                $(this).closest(".pool-temp-slider").find(".slider-unselected").css("width", sliderUnselected);
26879                $(this).closest(".pool-temp-slider").find("#tick-result-num").text(Math.round($(this).val()));
26880                $(this).closest(".pool-temp-container").find("#deg-output-num").text(Math.round($(this).val()));
26881            });
26882
26883            $(".recommended-pump .tabs").on("change", ".slider.left", function(e) {
26884                this.value = Math.min(this.value,this.parentNode.childNodes[2].value-1);
26885                var value=(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.value)-(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.min);
26886                $(this).closest(".slider-container").find(".inverse-left").css("width", value+'%');
26887                $(this).closest(".slider-container").find(".range-overlap").css("left", value+'%');
26888                $(this).closest(".slider-container").find(".thumb.left").css("left", value+'%');
26889                handleActiveBars();
26890            });
26891
26892            $(".recommended-pump .tabs").on("change", ".slider.right", function(e) {
26893                this.value = Math.max(this.value,this.parentNode.childNodes[1].value-(-1));
26894                var value=(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.value)-(100/(parseInt(this.max)-parseInt(this.min)))*parseInt(this.min);
26895                $(this).closest(".slider-container").find(".inverse-right").css("width", (100-value)+'%');
26896                $(this).closest(".slider-container").find(".range-overlap").css("right", (100-value)+'%');
26897                $(this).closest(".slider-container").find(".thumb.right").css("left", value+'%');
26898                handleActiveBars();
26899            });
26900
26901            $(".recommended-pump .tabs").on("change", ".dollars-per-therm input", function(e) {
26902                $(this).closest(".slider-container").find(".slider-selected").css("width", dptSliderWidths.selectedWidth());
26903                $(this).closest(".slider-container").find(".slider-unselected").css("width", dptSliderWidths.unselectedWidth());
26904                $(this).closest(".slider-container").find("#dptThermVal").text(parseFloat($(this).val()).toFixed(2));
26905            });
26906
26907            $(".recommended-pump .tabs").on("change", ".dollars-per-kwh input", function(e) {
26908                $(this).closest(".slider-container").find(".slider-selected").css("width", dpkSliderWidths.selectedWidth());
26909                $(this).closest(".slider-container").find(".slider-unselected").css("width", dpkSliderWidths.unselectedWidth());
26910                $(this).closest(".slider-container").find(".kwh-value").text(parseFloat($(this).val()).toFixed(4));
26911            });
26912
26913            $(".recommended-pump .tabs").on("change", ".gas-efficiency input", function(e) {
26914                $(this).closest(".slider-container").find(".slider-selected").css("width", gasEfficiencyWidths.selectedWidth());
26915                $(this).closest(".slider-container").find(".slider-unselected").css("width", gasEfficiencyWidths.unselectedWidth());
26916                $(this).closest(".slider-container").find(".gas-value").text(Math.round($(this).val()));
26917            });
26918
26919            $(".recommended-pump .tabs").on("change", ".pool-temp-slider input", function(e) {
26920                $(this).closest(".slider-container").find(".slider-selected").css("width", poolTempWidths.selectedWidth());
26921                $(this).closest(".slider-container").find(".slider-unselected").css("width", poolTempWidths.unselectedWidth());
26922                $(this).closest(".slider-container").find(".pool-temp-value").text(Math.round($(this).val()));
26923            });
26924        }
26925
26926        $(document).on("click", "#recommendHeatPump", function(e) {
26927            e.preventDefault();
26928            var tabNames = $(this).closest(".heat-pump.component").find(".recommended-pump dt");
26929            var tabContent = $(this).closest(".heat-pump.component").find(".recommended-pump dd");
26930            // remove old recommended pumps if they exist
26931            if(tabNames.length && tabContent.length) {
26932                tabNames.remove();
26933                tabContent.remove();
26934            }
26935            $(".heat-pump.component").addClass("show-recommended-pump");
26936            var owlItems = $(this).closest(".hp-carousel").find(".owl-item");
26937            constructHeatPumpUrl(owlItems);
26938        });
26939
26940        if($("body").hasClass("ie")) {
26941            // IE and Edge Multirange slider workaround when moving slider thumbs
26942            $(document).on("mousemove", ".swim-season .slider.left, .swim-season .slider.right", setSlider);
26943        }
26944
26945        // toggle functionality for recommended page on mobile
26946        var recommendedPump = $(".recommended-pump");
26947        var tabs = $(recommendedPump).find("dl.tabs");
26948        if($(window).width() < 768) {
26949            var activeTab = $(tabs).find("dt.tab.active");
26950            $(activeTab).next("dd").attr("hidden", "");
26951            activeTab.removeClass("active");
26952            $(activeTab).find(".tab-btn").attr("aria-expanded", "false");
26953        } else {
26954            $(tabs).removeAttr("data-allow-toggle");
26955        }
26956
26957        $(".recommended-pump .tabs").on("click", ".btn-recalc", function(e) {
26958            e.preventDefault();
26959            var leftSlider = $(this).closest(".recommended-slider").find(".slider.left").val();
26960            var rightSlider = $(this).closest(".recommended-slider").find(".slider.right").val();
26961            var swimSeason = leftSlider + ":" + rightSlider;
26962
26963            var dollarsPerTherm = $(this).closest(".recommended-pump-sliders").find(".dollars-per-therm input").val();
26964            var dollarsPerKwh = $(this).closest(".recommended-pump-sliders").find(".dollars-per-kwh input").val();
26965            var gasHeaterEfficiency = Math.round($(this).closest(".recommended-pump-sliders").find(".gas-efficiency input").val());
26966            var desiredWaterTemp = $(this).closest(".recommended-pump-sliders").find(".pool-temp-slider input").val();
26967
26968            var newData = url;
26969            var poolData = poolUrl;
26970            newData.swimSeason = swimSeason;
26971            newData.gasCost = parseFloat(dollarsPerTherm).toFixed(2);
26972            newData.electricityCost = parseFloat(dollarsPerKwh).toFixed(2);
26973            newData.efficiency = parseFloat(gasHeaterEfficiency / 100).toFixed(2);
26974            newData.temp = parseFloat(desiredWaterTemp).toFixed(1);
26975
26976            var tabNames = $(this).closest(".tabs").find("dt");
26977            var tabContent = $(this).closest(".tabs").find("dd");
26978            var loader = '<div class="loader-wrapper loader"><div class="results-loader"><p class="loading-text">Loading...</p></div></div>';
26979            if(tabNames.length && tabContent.length) {
26980                $(this).closest(".tabs").append(loader);
26981                tabNames.remove();
26982                tabContent.remove();
26983            }
26984            var data = $.extend({}, newData, poolData);
26985
26986            heatPumpCalculationData(data, leftSlider, rightSlider, desiredWaterTemp, gasHeaterEfficiency);
26987        });
26988
26989        /** since content is dynamic, we need to check the query parameters every time the mouse moves towards the share links. */
26990        $('.recommended-pump').on('mouseenter', ".calc-share.component", function() {
26991            updateHeatPumpCalcShareLinks();
26992        });
26993
26994        init();
26995    }
26996
26997});
26998
26999var dptSliderWidths = {
27000    selectedWidth : function() {
27001        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27002        var min = 0, max = 5;
27003        var result = (activePump.find("#dptTherm").val() - min) / (max - min) * 100 + "%";
27004        return result;
27005    },
27006    unselectedWidth : function() {
27007        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27008        var min = 0, max = 5;
27009        var result = 100 - (activePump.find("#dptTherm").val() - min) / (max - min) * 100 + "%";
27010        return result;
27011    }
27012};
27013
27014var dpkSliderWidths = {
27015    selectedWidth : function() {
27016        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27017        var min = 0, max = 1;
27018        var result = (activePump.find("#dpkVal").val() - min) / (max - min) * 100 + "%";
27019        return result;
27020    },
27021    unselectedWidth : function() {
27022        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27023        var min = 0, max = 1;
27024        var result = 100 - (activePump.find("#dpkVal").val() - min) / (max - min) * 100 + "%";
27025        return result;
27026    }
27027};
27028
27029var gasEfficiencyWidths = {
27030    selectedWidth : function() {
27031        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27032        var min = 50, max = 100;
27033        var result = (activePump.find("#gasValue").val() - min) / (max - min) * 100 + "%";
27034        return result;
27035    },
27036    unselectedWidth : function() {
27037        var min = 50, max = 100;
27038        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27039        var result = 100 - (activePump.find("#gasValue").val() - min) / (max - min) * 100 + "%";
27040        return result;
27041    }
27042};
27043
27044var poolTempWidths = {
27045    selectedWidth : function() {
27046        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27047        var min = 60, max = 104;
27048        var result = (activePump.find("#poolTempValue").val() - min) / (max - min) * 100 + "%";
27049        return result;
27050    },
27051    unselectedWidth : function() {
27052        var activePump = $(".recommended-pump").find("dt.active").next("dd");
27053        var min = 60, max = 104;
27054        var result = 100 - (activePump.find("#poolTempValue").val() - min) / (max - min) * 100 + "%";
27055        return result;
27056    }
27057};
27058
27059var waterTempTicks = function() {
27060    var ticks = (new Array(14)).join('0').split('');
27061    var tickContainer = $(".heat-pump.component .pool-temp-slider .tick-container");
27062    ticks.map(function(elem, index) {
27063        if (index % 2 === 0) {
27064            if (index === 0) {
27065                $(tickContainer).append('<span class="large-tick"><span class="num-deg">60&deg;</span></span>');
27066            } else if (index === ticks.length - 1) {
27067                $(tickContainer).append('<span class="large-tick"><span class="num-deg">104&deg;</span></span>');
27068            } else {
27069                $(tickContainer).append('<span class="large-tick"></span>');
27070            }
27071        } else {
27072            $(tickContainer).append('<span class="small-tick"></span>');
27073        }
27074    });
27075
27076    /* Recommended Pumps - Slider Ticks */
27077    var thermTicks = (new Array(12)).join('0').split('');
27078    var thermTicksContainer = $(".heat-pump.component .dollars-per-therm .tick-container");
27079    var kwhTicksContainer = $(".heat-pump.component .dollars-per-kwh .tick-container");
27080    var gasEfficiencyContainer = $(".heat-pump.component .gas-efficiency .tick-container");
27081    thermTicks.map(function(elem, index) {
27082        if(index === 0) {
27083            $(thermTicksContainer).append('<span class="large-tick"><span class="num-tick">$0</span></span>');
27084            $(kwhTicksContainer).append('<span class="large-tick"><span class="num-tick">$0</span></span>');
27085            $(gasEfficiencyContainer).append('<span class="large-tick"><span class="num-tick">50%</span></span>');
27086        } else if (index === thermTicks.length -1) {
27087            $(thermTicksContainer).append('<span class="large-tick"><span class="num-tick">$5.00</span></span>');
27088            $(kwhTicksContainer).append('<span class="large-tick"><span class="num-tick">$1.00</span></span>');
27089            $(gasEfficiencyContainer).append('<span class="large-tick"><span class="num-tick">100%</span></span>');
27090        } else {
27091            $(thermTicksContainer).append('<span class="small-tick"></span>');
27092            $(kwhTicksContainer).append('<span class="small-tick"></span>');
27093            $(gasEfficiencyContainer).append('<span class="small-tick"></span>');
27094        }
27095    });
27096
27097}
27098
27099function anchorStepsOnMobile(e) {
27100    if ($(window).width() < 768) {
27101        var hpDotsContainer = $(".heat-pump.component").find("#hp-dots-container");
27102        var offsetHeader = $("header").height();
27103        var offsetValue = hpDotsContainer.offset().top - offsetHeader;
27104        $('html, body').animate({
27105            scrollTop: offsetValue
27106        }, 500);
27107    }
27108}
27109
27110function handleOnChanged(e) {
27111    var position = (e.item.index + 1);
27112    var hpCarousel = $(".heat-pump.component").find(".owl-carousel");
27113    if(position === 1) {
27114        $('.owl-carousel .owl-stage-outer').addClass('slide-1-height');
27115        if ($(window).width() < 768) {
27116            $(hpCarousel).find(".owl-nav").css("textAlign", "");
27117            $(hpCarousel).find(".owl-nav").css("display", "");
27118            if($("#recommendHeatPump").length) { $(hpCarousel).find(".owl-nav > button#recommendHeatPump").remove(); }
27119            // remove full-width class - only applies for slide 2
27120            $(".heat-pump.component").find(".hp-carousel").removeClass("full-width");
27121        } else {
27122            if($("#recommendHeatPump").length) { $(hpCarousel).find(".owl-nav > button#recommendHeatPump").remove(); }
27123        }
27124    } else if (position === 2) {
27125        $('.owl-carousel .owl-stage-outer').removeClass('slide-1-height');
27126        if($(window).width() < 768) {
27127            if($("#recommendHeatPump").length) { $(hpCarousel).find(".owl-nav > button#recommendHeatPump").remove(); }
27128
27129            // position owl-nav buttons to be within each pool volume tab and center
27130            // usually owl-nav buttons are positioned at the bottom
27131            // but designs have the owl-nav buttons within each tab separately.
27132            // will need to clone original owl-nav buttons and append to each tab.
27133            $(hpCarousel).find(".owl-nav").css("textAlign", "center");
27134            var owlNav = $(hpCarousel).find(".owl-nav").clone(); // clone first
27135            $(hpCarousel).find(".owl-nav:not(.tab-content-section > .owl-nav)").css("display", "none"); // hide next
27136
27137            // Manually set height on owl-height wrapper due to autoHeight prop on owl-carousel cuts off content when tabs are expanded
27138            var originalHeight;
27139            setTimeout(function() {
27140                originalHeight = parseFloat($(hpCarousel).find(".owl-height").css("height"));
27141            }, 500);
27142
27143            var tabButton = $(hpCarousel).find("dt > .tab-btn");
27144            $(tabButton).on("click", function(e) {
27145                var currentTab = $(this).closest("dt");
27146                var resultContainer = $(currentTab).next("dd").find(".result-container");
27147                var tabContentSection = $(currentTab).next("dd").find(".tab-content-section").eq(2);
27148                var owlNavInTab = $(tabContentSection).find(".owl-nav");
27149                if(!owlNavInTab.length) {
27150                    $(resultContainer).after(owlNav);
27151                }
27152
27153                var tabContent = $(this).closest("dt").next("dd").height();
27154                var currentBtn = $(this);
27155                setTimeout(function(){
27156                    var isActive = $(currentBtn).closest("dt").hasClass("active");
27157                    var activeTabOwlHeight = originalHeight + tabContent;
27158                    if(isActive) {
27159                        $(currentBtn).closest(".owl-height").css("height", activeTabOwlHeight);
27160                    } else {
27161                        $(currentBtn).closest(".owl-height").css("height", originalHeight);
27162                    }
27163                },10);
27164
27165            });
27166
27167            // separate click event handler for dynamically added prev/next buttons
27168            $(".tab-content-section").on("click", ".owl-next", function(e) {
27169                validateSlide(e);
27170                e.preventDefault();
27171                return false;
27172            });
27173
27174            $(".tab-content-section").on("click", ".owl-prev", function(e) {
27175                hpCarousel.trigger('prev.owl.carousel');
27176            });
27177
27178            $(".heat-pump.component").find(".hp-carousel").addClass("full-width");
27179
27180        } else {
27181            if($("#recommendHeatPump").length) { $(hpCarousel).find(".owl-nav > button#recommendHeatPump").remove(); }
27182            // Manually set height on owl-height wrapper due to autoHeight prop cuts off content when tabs are expanded
27183            var originalHeight;
27184            setTimeout(function() {
27185                originalHeight = parseFloat($(hpCarousel).find(".owl-height").css("height"));
27186            }, 500);
27187
27188            var tabButton = $(hpCarousel).find("dt > .tab-btn");
27189            $(tabButton).on("click", function(e) {
27190                var tabContent = $(this).closest("dt").next("dd").height();
27191                var tabOffset = originalHeight - tabContent;
27192                if (e.currentTarget.innerText === "OBLONG") {
27193                    $(this).closest(".owl-height").css("height", originalHeight + tabOffset);
27194                } else {
27195                    $(this).closest(".owl-height").css("height", originalHeight);
27196                }
27197
27198            });
27199        }
27200    } else if (position === 3) {
27201        $('.owl-carousel .owl-stage-outer').addClass('slide-3-height');
27202        $('.owl-carousel .owl-stage-outer').removeClass('slide-1-height');
27203        var height = $(hpCarousel).find(".owl-item").eq(2).height();
27204        if($(window).width() > 767) {
27205            $(hpCarousel).find(".owl-height").css("height", height); // content cutoff due to rotated container
27206            // next button is replaced with recommended heat pump button on desktop
27207            var recommendButton = '<button class="btn btn-green recommend-btn" id="recommendHeatPump"><span>Calculate Savings</span></button>';
27208            if(!$(hpCarousel).find(".owl-nav .recommend-btn").length) {$(hpCarousel).find(".owl-nav").append(recommendButton);}
27209        } else {
27210            var recommendButton = '<button class="btn btn-green recommend-btn" id="recommendHeatPump"><span>next</span></button>';
27211            if(!$(hpCarousel).find(".owl-nav .recommend-btn").length) {
27212                $(hpCarousel).find(".owl-nav").append(recommendButton);
27213                // text align center owl-nav to match designs
27214                $(hpCarousel).find(".owl-nav").css("display", "");
27215                $(hpCarousel).find(".owl-nav").css("textAlign", "center");
27216            }
27217            // remove full-width class - only applies for slide 2
27218            $(".heat-pump.component").find(".hp-carousel").removeClass("full-width");
27219        }
27220    } else {
27221        $('.owl-carousel .owl-stage-outer').removeClass('slide-1-height');
27222    }
27223}
27224
27225function validateSlide(event) {
27226    var carousel = $(".heat-pump.component").find(".owl-carousel");
27227    var target = event.currentTarget;
27228    var activeOwlItem = $(target).closest(".owl-carousel").find(".owl-item.active");
27229    var activeTab = $(activeOwlItem).find("dt.active");
27230    var inputs = $(activeOwlItem).find("input");
27231    var validated = true;
27232    if(activeTab.length) {
27233        var tabInputs = $(activeTab).next("dd").find("input");
27234        for (var i = 0; i < tabInputs.length; i++) {
27235            if(tabInputs[i] && tabInputs[i].value === "") {
27236                validated = false;
27237            }
27238        }
27239    } else {
27240        var firstOwlItem = carousel.find(".owl-item").eq(0);
27241        var firstSlideInputs = firstOwlItem.find("input");
27242        if(firstOwlItem.hasClass("active")) {
27243            var zipInput = $("#zipCode");
27244            var kwhInput = $("#kw-per-hr");
27245            if (!(zipInput.val()) && !(kwhInput).val()) {
27246                validated = false;
27247            }
27248        } else {
27249            for (var i = 0; i < inputs.length; i++) {
27250                if(inputs[i] && inputs[i].value === "") {
27251                    validated = false;
27252                }
27253            }
27254        }
27255    }
27256    // if invalid - set is-invalid class on input container
27257    if(!validated) {
27258        if(activeTab.length) {
27259            var tabInputs = $(activeTab).next("dd").find("input");
27260            for(var i = 0; i < tabInputs.length; i++) {
27261                if(tabInputs[i] && tabInputs[i].value === "") {
27262                    var parent = tabInputs[i].parentElement;
27263                    $(parent).addClass("is-invalid");
27264                }
27265            }
27266        } else {
27267            var firstOwlItem = carousel.find(".owl-item").eq(0);
27268            if(firstOwlItem.hasClass("active")) {
27269                $("#zipCode").closest(".zip-container").addClass("is-invalid");
27270            } else {
27271                for(var i = 0; i < inputs.length; i++) {
27272                    var parent = inputs[i].parentElement;
27273                    $(parent).addClass("is-invalid");
27274                }
27275            }
27276        }
27277    } else {
27278        carousel.trigger('next.owl.carousel');
27279    }
27280}
27281
27282// perform pool volume calculations after user enters data
27283function getTabInputValues(el, inputs) {
27284    var activeTab = $(el);
27285    var fields = activeTab.next("dd").find("input");
27286    var values = {};
27287    $(fields).each(function(index, element) {
27288        $(element).on("input", function(e) {
27289            var value = e.currentTarget.value;
27290            var id = e.currentTarget.id;
27291            if(!values.hasOwnProperty(id)) {
27292                values[id] = value;
27293            } else {
27294                values[id] = value;
27295            }
27296            handleCalculations(activeTab, values);
27297        });
27298    });
27299}
27300
27301function handleCalculations(activeTab, values) {
27302    if (activeTab.hasClass("rectangle")) {
27303        if(Object.keys(values).length === 4) {
27304            var shallow = parseFloat(values["shallowEndRectangle"]);
27305            var deep = parseFloat(values["deepEndRectangle"]);
27306            var length = parseFloat(values["lengthRectangle"]);
27307            var width = parseFloat(values["widthRectangle"]);
27308
27309            var rectangleShallow = Math.ceil(((length * width) * shallow) * 7.48
2730905);
27310            var rectangleDeep = 0;
27311            if (deep > shallow) {
27312                rectangleDeep = ((Math.ceil((length*width)*deep)*7.4805)-Math.ceil(((length*width)*shallow)* 7.4805))/2;
27313            }
27314            var result = Math.ceil(rectangleShallow + rectangleDeep);
27315            if($("#deepEndRectangle").val() !== "" && $("#shallowEndRectangle").val() !== "" && $("#lengthRectangle").val() !== "" && $("#widthRectangle").val() !== "") {
27316                activeTab.next("dd").find("#calcResultRectangle").text(Math.ceil(result / 100) * 100);
27317            }
27318        }
27319    } else if (activeTab.hasClass("oblong")) {
27320        if(Object.keys(values).length === 5) {
27321            var shallow = parseFloat(values["shallowEndOblong"]);
27322            var deep = parseFloat(values["deepEndOblong"]);
27323            var length = parseFloat(values["lengthOblong"]);
27324            var largeDiameter = parseFloat(values["largeDiameterOblong"]);
27325            var smallDiameter = parseFloat(values["smallDiameterOblong"]);
27326
27327            var oblongArea = Math.ceil(((largeDiameter + smallDiameter) * length) * 0.45);
27328            var depth = (shallow + deep) / 2;
27329
27330            var result = Math.ceil((oblongArea * depth) * 7.4805);
27331            if($("#deepEndOblong").val() !== "" && $("#shallowEndOblong").val() !== "" && $("#largeDiameterOblong").val() !== "" && $("#smallDiameterOblong").val() !== "" && $("#lengthOblong").val() !== "") {
27332                activeTab.next("dd").find("#calcResultOblong").text(Math.ceil(result / 100) * 100);
27333            }
27334        }
27335    } else if (activeTab.hasClass("circular")) {
27336          if(Object.keys(values).length === 3) {
27337              var shallow = parseFloat(values["shallowEndCircular"]);
27338              var deep = parseFloat(values["deepEndCircular"]);
27339              var radius = parseFloat(values["radiusCircular"]);
27340
27341              var cylinderShallow = Math.ceil(((Math.PI * Math.pow(radius,2)) * shallow) * 7.4805);
27342              var cylinderDeep = 0;
27343              if(deep > shallow) {
27344                  cylinderDeep = Math.ceil(Math.ceil(((Math.PI * Math.pow(radius,2))*deep)*7.4805)-Math.ceil(((Math.PI * Math.pow(radius,2))*shallow))*7.4805)/2;
27345              }
27346
27347              var result = Math.ceil(cylinderShallow + cylinderDeep);
27348              if($("#deepEndCircular").val() !== "" && $("#shallowEndCircular").val() !== "" && $("#radiusCircular").val() !== "") {
27349                  activeTab.next("dd").find("#calcResultCircular").text(Math.ceil(result / 100) * 100);
27350              }
27351          }
27352    } else if (activeTab.hasClass("triangular")) {
27353        if(Object.keys(values).length === 4) {
27354            var shallow = parseFloat(values["shallowEndTriangular"]);
27355            var deep = parseFloat(values["deepEndTriangular"]);
27356            var height = parseFloat(values["heightTriangular"]);
27357            var base = parseFloat(values["baseTriangular"]);
27358
27359            var triangleShallow = Math.ceil(((base * height)*shallow)*7.4805) / 2;
27360            var triangleDeep = 0;
27361            if(deep > shallow) {
27362                triangleDeep = Math.ceil((Math.ceil(((base*height)*deep)*7.4805)-Math.ceil(((base*height)*shallow)*7.4805))/2)/2;
27363            }
27364
27365            var result = Math.ceil(triangleShallow + triangleDeep);
27366            if($("#deepEndTriangular").val() !== "" && $("#shallowEndTriangular").val() !== "" && $("#heightTriangular").val() !== "" && $("#baseTriangular").val() !== "") {
27367                activeTab.next("dd").find("#calcResultTriangular").text(Math.ceil(result / 100) * 100);
27368            }
27369        }
27370    }
27371}
27372
27373function setLatLong() {
27374    // Defaults to L.A. if no user input
27375    var points = {lat : 34.052235, long : -118.243683};
27376    return points;
27377}
27378
27379function getUserPosition(){
27380    if (navigator.geolocation) {
27381        navigator.geolocation.getCurrentPosition(success, error);
27382    }
27383}
27384
27385function handleZipCode(zip, res) {
27386    $(".heat-pump.component").find("#zipCode").val(zip[1]);
27387}
27388
27389function success(position) {
27390    var lat = position.coords.latitude;
27391    var long = position.coords.longitude;
27392    var point = new google.maps.LatLng(lat, long);
27393    var geocoder = new google.maps.Geocoder().geocode(
27394        {'latLng': point}, function( res, status) {
27395            var zip = res[0].formatted_address.match(/,\s\w{2}\s(\d{5})/);
27396            var lat = res[0].geometry.location.lat();
27397            var long = res[0].geometry.location.lng();
27398            handleZipCode(zip, res[0]);
27399            reverseGeocode(lat, long);
27400            if($(".heat-pump.component .location-wrapper > div:first-child").hasClass("is-invalid")) {
27401                $(".heat-pump.component .location-wrapper > div:first-child").removeClass("is-invalid");
27402            }
27403        }
27404    );
27405}
27406
27407function error(err) {
27408    if (err.code == err.PERMISSION_DENIED) {
27409        $(".heat-pump.component .location-wrapper > div:first-child").addClass("is-invalid");
27410    }
27411}
27412
27413// populate kW/h field based on user's state
27414function getKilowattPerHours(obj) {
27415    $.ajax({
27416        type: 'GET',
27417        data: obj,
27418        url: '/bin/pentair/calculators/heatpump',
27419        dataType: 'json',
27420        success: function(data) {
27421            var kiloValue = data.kw;
27422            var thermValue = data.gas;
27423            $(".heat-pump.component").find("#kw-per-hr").val(kiloValue);
27424            $(".heat-pump.component").find("#gas-per-therm").val(thermValue);
27425        },
27426        error: function(data) {
27427            console.log("Error requesting Heat Pump Data - Zipcode ", data);
27428        }
27429    });
27430}
27431
27432// reverse geocode
27433var stateObj = {state: "unknown"};
27434
27435var resultObj = {};
27436function reverseGeocode(lat, long) {
27437    var tempLat = lat;
27438    var tempLong = long;
27439    var points = new google.maps.LatLng(tempLat, tempLong);
27440    var geocoder = new google.maps.Geocoder().geocode(
27441        {'latLng': points}, function( res, status) {
27442            res.map(function(item) {
27443                if (item.types.indexOf("administrative_area_level_1") > -1) {
27444                    var stateData  = item.formatted_address.split(",");
27445                    var state = stateData[0];
27446                    resultObj.state = state;
27447                    resultObj.lat = tempLat;
27448                    resultObj.long = tempLong;
27449                    stateObj.state = state;
27450                    getKilowattPerHours(stateObj);
27451                }
27452            });
27453        }
27454    );
27455}
27456
27457function getLatLongByZipCode(zip) {
27458    var geocoder = new google.maps.Geocoder();
27459    var address = zip;
27460    geocoder.geocode({ 'address': 'zipcode '+address, 'componentRestrictions':{'country':'US'}}, function (response, status) {
27461        if (status == google.maps.GeocoderStatus.OK) {
27462            var latitude = response[0].geometry.location.lat();
27463            var longitude = response[0].geometry.location.lng();
27464            reverseGeocode(latitude, longitude);
27465        }
27466    });
27467}
27468
27469// Slider Widths
27470function sliderSelected() {
27471    var min = 60, max = 104;
27472    var selectedWidth = ($("#tempSlider").val() - min) / (max - min) * 100 + "%";
27473    return selectedWidth;
27474}
27475
27476function sliderUnselected() {
27477    var min = 60, max = 104;
27478    var unselectedWidth = 100 - ($("#tempSlider").val() - min) / (max - min) * 100 + "%";
27479    return unselectedWidth;
27480}
27481
27482// Calculate Temp Slider Widths on Load
27483function calcTempSliderWidths() {
27484    var selected = ($("#tempSlider").val() - 60) / (104 - 60) * 100 + "%";
27485    var unselected = 100 - ($("#tempSlider").val() - 60) / (104 - 60) * 100 + "%";
27486    $(".heat-pump.component .pool-temp-slider").find(".slider-selected").css("width", selected);
27487    $(".heat-pump.component .pool-temp-slider").find(".slider-unselected").css("width", unselected);
27488}
27489
27490function handleActiveBars() {
27491    var activePump = $(".recommended-pump").find("dt");
27492    var activePumpContent = $(".recommended-pump").find("dd");
27493
27494    activePumpContent.each(function(index, item) {
27495        var sliderContainer = $(item).find(".swim-season");
27496        var leftSlider = parseFloat($(sliderContainer).find("input.left").val());
27497        var rightSlider = parseFloat($(sliderContainer).find("input.right").val());
27498        var bars = $(sliderContainer).find(".bar");
27499        for(var i = 0; i < bars.length; i++) {
27500            if(i >= (leftSlider-1) && i <= (rightSlider-1)) {
27501                if(!$(bars[i]).hasClass("active")) {
27502                    $(bars[i]).addClass("active");
27503                }
27504            } else {
27505                if($(bars[i]).hasClass("active")) {
27506                    $(bars[i]).removeClass("active");
27507                }
27508            }
27509        }
27510        showSliderMonths(sliderContainer);
27511    });
27512}
27513
27514function showSliderMonths(sliderContainer) {
27515    var bars = $(sliderContainer).find(".bar.active");
27516    $(bars).each(function(index, elem) {
27517        if(index === 0 || index === bars.length-1) {
27518            $(bars[0]).addClass("show");
27519            $(bars[bars.length-1]).addClass("show");
27520        } else {
27521            $(bars[index]).removeClass("show");
27522        }
27523    });
27524}
27525
27526function setSlider(event) {
27527    var sliderLeft = $(".swim-season .slider.left");
27528    var sliderRight = $(".swim-season .slider.right");
27529    var min = parseInt($(sliderLeft).attr("min"), 10);
27530    var max = parseInt($(sliderLeft).attr("max"), 10);
27531    var maxOffset = 297; // width of swim seasons range inputs
27532    var mousePosition = event.offsetX / maxOffset;
27533    var mouseValue = parseInt((mousePosition * (max - min)) + min, 10);
27534    var distSliderLeft = Math.abs($(sliderLeft).val() - mouseValue);
27535    var distSliderRight = Math.abs($(sliderRight).val() - mouseValue);
27536    if (distSliderLeft < distSliderRight) {
27537        $(sliderLeft).css("zIndex", 11);
27538        $(sliderRight).css("zIndex", 10);
27539    } else {
27540        $(sliderLeft).css("zIndex", 10);
27541        $(sliderRight).css("zIndex", 11);
27542    }
27543}
27544
27545function poolVolumeHelper(shape) {
27546    var classes = $(shape).attr("class").split(/\s+/);
27547    var pvUrl = {};
27548    if(classes.indexOf("rectangle") > -1) {
27549        pvUrl.shape = classes[0];
27550        pvUrl.length = $("#lengthRectangle").val();
27551        pvUrl.width = $("#widthRectangle").val();
27552        pvUrl.shallow = $("#shallowEndRectangle").val();
27553        pvUrl.deep = $("#deepEndRectangle").val();
27554    } else if (classes.indexOf("oblong") > -1) {
27555        pvUrl.shape = classes[0];
27556        pvUrl.length = $("#lengthOblong").val();
27557        pvUrl.smallDiameter = $("#smallDiameterOblong").val();
27558        pvUrl.largeDiameter = $("#largeDiameterOblong").val();
27559        pvUrl.shallow = $("#shallowEndOblong").val();
27560        pvUrl.deep = $("#deepEndOblong").val();
27561    } else if (classes.indexOf("circular") > -1) {
27562        pvUrl.shape = "circle";
27563        pvUrl.shallow = $("#shallowEndCircular").val();
27564        pvUrl.deep = $("#deepEndCircular").val();
27565        pvUrl.radius = $("#radiusCircular").val();
27566    } else if (classes.indexOf("triangular") > -1) {
27567        pvUrl.shape = "triangle";
27568        pvUrl.shallow = $("#shallowEndTriangular").val();
27569        pvUrl.deep = $("#deepEndTriangular").val();
27570        pvUrl.length = $("#heightTriangular").val();
27571        pvUrl.width = $("#baseTriangular").val();
27572    }
27573    return pvUrl;
27574}
27575
27576function tempSliderHelper(sliders) {
27577    var result = "";
27578    $(sliders).each(function(index, elem) {
27579        if (index === 0) {
27580            result += $(elem).val() + ":";
27581        } else {
27582            result += $(elem).val();
27583        }
27584    });
27585    return result;
27586}
27587
27588var url = {};
27589var poolUrl = {};
27590function constructHeatPumpUrl(items) {
27591    var inputs = [];
27592    var slideOneInputs = $(items).eq(0).find("input");
27593    var slideTwoInputs = $(items).eq(1).find(".pool-volume.component dt.active").next("dd").find("input");
27594    var slideThreeInputs = $(items).eq(2).find("input");
27595    Array.prototype.push.apply(inputs, [slideOneInputs, slideTwoInput
27595s, slideThreeInputs]);
27596
27597    var tempValue = parseFloat($(slideThreeInputs).val()).toFixed(1);
27598    var shape = $(items).eq(1).find(".pool-volume.component dt.active");
27599
27600    poolUrl = poolVolumeHelper(shape);
27601    var poolTempSliders = $(items).closest(".heat-pump.component").find(".recommended-pump dt.active").next("dd").find(".swim-season input");
27602    var poolTemps = tempSliderHelper(poolTempSliders);
27603
27604    // Lat Long Values
27605    var defaultLongLong = setLatLong();
27606    var reverseGeoObj = resultObj;
27607
27608    var eCost = $("#kw-per-hr").val();
27609    var gCost = $("#gas-per-therm").val();
27610
27611    // construct object that holds our data values
27612    url.temp = parseFloat(tempValue).toFixed(1);
27613    url.state = (reverseGeoObj.state !== undefined ? reverseGeoObj.state : "Ohio");
27614    url.swimSeason = (poolTemps === "" ? '3:9' : poolTemps);
27615    url.lat = (reverseGeoObj.lat !== undefined ? reverseGeoObj.lat : defaultLongLong.lat);
27616    url.long = (reverseGeoObj.long !== undefined ? reverseGeoObj.long : defaultLongLong.long);
27617    url.efficiency = 0.82;
27618    url.gasCost = parseFloat(gCost).toFixed(2);
27619    url.electricityCost = parseFloat(eCost).toFixed(2);
27620
27621    var data = $.extend({}, url, poolUrl);
27622
27623    // send data values to function to send ajax request to servlet
27624    heatPumpCalculationData(data);
27625}
27626
27627// request servlet based on calculation data provided
27628function heatPumpCalculationData(data, leftSlider, rightSlider, desiredWaterTemp, gasHeaterEfficiency) {
27629    $.ajax({
27630        type: 'GET',
27631        data: data,
27632        url: '/bin/pentair/calculators/heatpump',
27633        dataType: 'json',
27634        success: function(data) {
27635            handleRecommendedPumpData(data[0].products, data[1][0], leftSlider, rightSlider, desiredWaterTemp, gasHeaterEfficiency);
27636        },
27637        error: function(data) {
27638            console.log("Error requesting Heat Pump Data - Calculations ", data);
27639        }
27640    });
27641}
27642
27643function handleRecommendedPumpData(data, sliderData, leftSlider, rightSlider, desiredWaterTemp, gasHeaterEfficiency) {
27644    var recommendedPump = $(".heat-pump.component").find(".recommended-pump");
27645    $(".heat-pump.component").find(".recommended-pump .loader-wrapper.loader").remove();
27646
27647    var kwhValue = sliderData.kw;
27648    var gasValue = sliderData.gas;
27649    var waterTempSlider = $(".heat-pump.component .owl-item").eq(2).find("#tempSlider");
27650    var waterTempValue = Math.round(waterTempSlider.val());
27651    var desiredTemp = Math.round(desiredWaterTemp);
27652
27653    leftSlider = Math.min(leftSlider,rightSlider - 1);
27654    var leftSliderValue = (100/(12 - 1))*leftSlider-(100/(12 - 1))*1;
27655
27656    rightSlider = Math.max(rightSlider,leftSlider - (-1));
27657    var rightSliderValue = (100/(12 - 1))*rightSlider-(100/(12 - 1))*1;
27658
27659    // wtb data sfdc dealers ajax
27660    var defaultLongLong = setLatLong();
27661    var reverseGeoObj = resultObj;
27662    var locationData = {};
27663    locationData.latitude = (reverseGeoObj.lat !== undefined ? reverseGeoObj.lat : defaultLongLong.lat);
27664    locationData.longitude = (reverseGeoObj.long !== undefined ? reverseGeoObj.long : defaultLongLong.long);
27665
27666    data.map(function(elem, index) {
27667        Object.keys(elem).forEach(function(key) {
27668            var title = elem[key][0].title;
27669            var url = elem[key][0].url;
27670            var thumbnail = elem[key][0].thumbnail;
27671            var whereToBuy = elem[key][0]["where-to-buy"];
27672            var brands = elem[key][0].brands;
27673            var categories = elem[key][0].categories;
27674            var cost = elem[key][0].cost;
27675            var savings = elem[key][0].savings;
27676            var timeToHeat = elem[key][0]["time-to-heat"];
27677
27678            // create tab markup
27679            var tabButton = generateTabMarkUp(title, index);
27680            var tabContent = generateTabContentMarkUp(title, url, thumbnail, whereToBuy, brands, categories, cost, savings, timeToHeat, kwhValue, gasValue, waterTempValue, desiredTemp, gasHeaterEfficiency, leftSlider, leftSliderValue, rightSlider, rightSliderValue, index);
27681            $(recommendedPump).find("dl.tabs").append(tabButton);
27682            $(recommendedPump).find("dl.tabs").append(tabContent);
27683
27684            // sfdc dealers ajax
27685            var extendLocationData = {distance: 200, brands: brands.split(",").join(','), categories: categories.split(",").join(',')};
27686            $.extend(locationData, extendLocationData);
27687
27688            handleWTBResults(locationData, index);
27689        });
27690    });
27691
27692    handleActiveBars();
27693}
27694
27695function handleSFDCResults(value, index) {
27696    if (value === false) {
27697        $(".heat-pump.component .recommended-pump dd").eq(index).find(".btn-wtb").attr("data-show", false);
27698    }
27699}
27700
27701function handleWTBResults(data, index) {
27702    var showButton;
27703    var locationData = data;
27704    $.ajax({
27705        type: 'GET',
27706        data: locationData,
27707        url: '/bin/pentair/sfdc/dealers',
27708        beforeSend: function() {},
27709        success: function(data) {
27710            jsonData = JSON.parse(data);
27711            var filteredResults = jsonData.results.filter(function(elem){return elem.hideAddress == false;});
27712            if(filteredResults.length > 0) {
27713                showButton = true;
27714                handleSFDCResults(showButton, index);
27715            }
27716        },
27717        error: function(data) {
27718            console.error('No dealers found. -> ', data.length);
27719            showButton = false;
27720            handleSFDCResults(showButton, index);
27721        }
27722    });
27723}
27724
27725function generateTabMarkUp(title, index) {
27726    var tab = '<dt class="tab'+(index === 0 ? ' active' : '')+'" role="heading">';
27727    tab += '<button class="tab-btn" aria-expanded="'+(index === 0 ? 'true':'false')+'" aria-controls="tab'+index+'" id="tab'+index+'Toggle" type="button" aria-disabled="true">';
27728    tab += '<span class="tab-text">' + title + '</span></button></dt>';
27729    return tab;
27730}
27731function generateTabContentMarkUp(title, url, thumbnail, whereToBuy, brands, categories, cost, savings, timeToHeat, kwhValue, gasValue, waterTempValue, desiredTemp, gasHeaterEfficiency, leftSlider, leftSliderValue, rightSlider, rightSliderValue, index) {
27732    var content = '<dd id="tab'+index+'" role="region" aria-labelledby="tab'+index+'Toggle" '+(index === 0 ? '': 'hidden')+'>';
27733    content += '<div class="tab-content"><div class="tab-content-section"><div class="recommended-pump-title h6">'+title+'</div>';
27734    content += '<p class="model-desc">Your estimated savings are $'+(Math.round(savings))+', compared to conventional heating. Use the sliders below to change the swim season months.</p>';
27735    content += '<div class="button-container"><a href="'+whereToBuy+'.html?show=local&from=product" class="btn btn-green btn-wtb" data-brands="'+brands+'" data-categories="'+categories+'" data-show="true" onclick="poolWtbAnalytics(this)" target="_blank"><span>where to buy</span></a><a href="'+url+'.html" class="btn btn-white btn-product" onclick="poolProdClickAnalytics(this)" target="_blank"><span>view product</span></a></div>';
27736    content += '<div class="share-container"><div class="calc-share component"><div class="calc-share-component-label">Share Results</div><ul><li>';
27737    content += '<a class="calc-share-link mailto-link" href="#"><span class="icon-envelope" aria-hidden="true"></span><span class="sr-only">Share via Email</span></a></li>';
27738    content += '<li><a class="calc-share-link twitter-link" href="#" target="_blank"><span class="icon-twitter" aria-hidden="true"></span><span class="sr-only">Share via Twitter</span></a></li>';
27739    content += '<li><a class="calc-share-link facebook-link" href="#" target="_blank"><span class="icon-facebook" aria-hidden="true"></span><span class="sr-only">Share via Facebook</span></a></li>';
27740    content += '<li><a href="javascript:window.print()"><span class="icon-print" aria-hidden="true"></span><span class="sr-only">Print</span></a></li></ul></div><button class="btn btn-over"><span>start over</span></button></div></div>';
27741    content += '<div class="tab-content-section"><div class="estimated-savings'+(savings == 0.00 ? ' no-savings' : '')+'"><div class="has-savings"><div class="h6">your estimated seasonal savings</div><span class="savings-amount">$'+(Math.round(savings))+'</span><p>dollars</p></div><div class="zero-savings"><p>Based on the information you provided, a gas heater may be a better option for you.</p><a class="btn btn-green" href="https://www.pentair.com/en-us/products/pool-spa-equipment/pool-heaters/gas-pool-heaters.html" target="_blank"><span>browse gas heaters</span></a></div></div>';
27742    content += '<img loading="lazy" class="results-pump" src="'+thumbnail+'" alt="'+title+'"><div class="water-temp h6">average time to raise water 10&deg;f: <span class="water-temp-val">'+timeToHeat+'<span>hrs</span></span></div></div></div>';
27743    content += '<div class="recommended-pump-sliders"><div class="recommended-slider"><div class="h6">utility costs</div><div class="dollars-per-therm slider-container"><label>gas dollars per therm</label>';
27744    content += '<input type="range" class="slider" min="0" max="5" step="any" value="'+gasValue+'" id="dptTherm"><div class="slider-selected" style="width:'+(gasValue - 0)/(5-0) * 100+'%"></div><div class="slider-unselected" style="width:'+(100 - (gasValue - 0) / (5 - 0) * 100 )+'%"></div>';
27745    content += '<div class="tick-container"><span class="large-tick"><span class="num-tick">$0</span></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span> ';
27746    content += '<span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="large-tick"><span class="num-tick">$5.00</span></span> ';
27747    content += '</div><div class="tick-result"><span>$<span id="dptThermVal">'+gasValue+'</span></span><span>/therm</span></div></div><div class="dollars-per-kwh slider-container"><label>electricity dollars per kwh</label>';
27748    content += '<input type="range" class="slider" min="0" max="1" step="any" value="'+kwhValue+'" id="dpkVal"><div class="slider-selected" style="width:'+(kwhValue - 0)/(1-0) * 100+'%"></div><div class="slider-unselected" style="width:'+(100 - (kwhValue - 0) / (1 - 0) * 100 )+'%"></div>';
27749    content += '<div class="tick-container"><span class="large-tick"><span class="num-tick">$0</span></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span> ';
27750    content += '<span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span>';
27751    content += '<span class="large-tick"><span class="num-tick">$1.00</span></span></div><div class="tick-result"><span>$<span class="kwh-value">'+kwhValue+'</span></span><span>/kWh</span></div></div></div>';
27752    content += '<div class="recommended-slider"><div class="h6">Inputs</div><div class="gas-efficiency slider-container"><label>
27752gas heater efficiency</label>';
27753    content += '<input type="range" class="slider" min="50" max="100" step="any" value="'+(isNaN(gasHeaterEfficiency) ? 82 : gasHeaterEfficiency)+'" id="gasValue"><div class="slider-selected" style="width:'+(isNaN(gasHeaterEfficiency) ? ((82 - 50) / (100 - 50) * 100) : ((gasHeaterEfficiency - 50) / (100 - 50) * 100))+'%;"></div>';
27754    content += '<div class="slider-unselected" style="width:'+(isNaN(gasHeaterEfficiency) ? (100 - (82 - 50) / (100 - 50) * 100) : (100 - (gasHeaterEfficiency - 50) / (100 - 50) * 100))+'%;"></div><div class="tick-container"><span class="large-tick"><span class="num-tick">50%</span></span>';
27755    content += '<span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span><span class="small-tick"></span>';
27756    content += '<span class="small-tick"></span><span class="small-tick"></span><span class="large-tick"><span class="num-tick">100%</span></span></div>';
27757    content += '<div class="tick-result"><span class="gas-value">'+(isNaN(gasHeaterEfficiency) ? 82 : gasHeaterEfficiency)+'</span><span>%</span></div></div>';
27758    content += '<div class="pool-temp-slider slider-container"><label>desired water temp</label><input type="range" class="slider" min="60" max="104" step="any" value="'+(!isNaN(desiredTemp) ? desiredTemp : waterTempValue)+'" id="poolTempValue">';
27759    content += '<div class="slider-selected" style="width:'+(!isNaN(desiredTemp) ? ((desiredTemp - 60)/(104-60) * 100) : ((waterTempValue - 60)/(104-60) * 100))+'%;"></div><div class="slider-unselected" style="width:'+(!isNaN(desiredTemp) ? (100 - (desiredTemp - 60) / (104 - 60) * 100) : (100 - (waterTempValue - 60) / (104 - 60) * 100))+'%;"></div><div class="tick-container"><span class="large-tick"><span class="num-deg">60&deg;</span></span>';
27760    content += '<span class="small-tick"></span><span class="large-tick"></span><span class="small-tick"></span><span class="large-tick"></span><span class="small-tick"></span><span class="large-tick"></span><span class="small-tick"></span>';
27761    content += '<span class="large-tick"></span><span class="small-tick"></span><span class="large-tick"></span><span class="small-tick"></span><span class="large-tick"><span class="num-deg">104&deg;</span></span></div>';
27762    content += '<div class="tick-result"><span class="pool-temp-value">'+(!isNaN(desiredTemp) ? desiredTemp : waterTempValue)+'</span><span>&deg;</span></div></div></div>';
27763    content += '<div class="recommended-slider"><div class="h6">swim season</div><div class="swim-season slider-container"><label>swim season months</label><input type="range" class="slider left" min="1" max="12" step="1" value="'+(isNaN(leftSlider) ? 3 : leftSlider)+'">';
27764    content += '<input type="range" class="slider right" min="1" max="12" step="1" value="'+(isNaN(rightSlider) ? 9 : rightSlider)+'"><div class="inverse-left" style="width:'+(isNaN(leftSliderValue) ? 70 : leftSliderValue)+'%;"></div><div class="inverse-right" style="width:'+(isNaN(rightSliderValue) ? 70 : (100 - rightSliderValue))+'%;"></div>';
27765    content += '<div class="range-overlap" style="left:'+(isNaN(leftSliderValue) ? 18 : leftSliderValue)+'%;right:'+(isNaN(rightSliderValue) ? 28 : (100 - rightSliderValue))+'%;"></div><span class="thumb left" style="left:'+(isNaN(leftSliderValue) ? 22 : leftSliderValue)+'%;"></span><span class="thumb right" style="left:'+(isNaN(rightSliderValue) ? 72 : (100 - rightSliderValue))+'%;"></span><div class="bar-container">';
27766    content += '<div class="bar bar-53"><span class="degree">J</span><span class="month">Jan</span></div><div class="bar bar-61"><span class="degree">F</span><span class="month">Feb</span></div>';
27767    content += '<div class="bar bar-73 active show"><span class="degree">M</span><span class="month">Mar</span></div><div class="bar bar-75 active"><span class="degree">A</span><span class="month">Apr</span></div>';
27768    content += '<div class="bar bar-82 active"><span class="degree">M</span><span class="month">May</span></div><div class="bar bar-89 active"><span class="degree">J</span><span class="month">Jun</span></div>';
27769    content += '<div class="bar bar-84 active"><span class="degree">J</span><span class="month">Jul</span></div><div class="bar bar-80 active"><span class="degree">A</span><span class="month">Aug</span></div>';
27770    content += '<div class="bar bar-74 active show"><span class="degree">S</span><span class="month">Sep</span></div><div class="bar bar-69"><span class="degree">O</span><span class="month">
27770Oct</span></div>';
27771    content += '<div class="bar bar-56"><span class="degree">N</span><span class="month">Nov</span></div><div class="bar bar-49"><span class="degree">D</span><span class="month">Dec</span></div></div></div>';
27772    content += '<div class="button-container"><button class="btn btn-recalc"><span>recalculate</span></button></div></div></div></dd>';
27773    return content;
27774}
27775
27776// share functionality for Recommended Heat Pump Results page
27777var host = window.location.href;
27778var shareLink = "";
27779
27780function createRecommendedPumpShareLink() {
27781    var hasQuery = window.location.href.indexOf('?') !== -1;
27782    var recommendedPump = $(".heat-pump.component .recommended-pump");
27783    var activeTab = recommendedPump.find("dt.active");
27784    var activeTabContent = activeTab.next("dd");
27785    var pump = activeTabContent.find(".recommended-pump-title").text();
27786    var title = pump.toLowerCase().split(" ").join("-");
27787    var savings = activeTabContent.find(".savings-amount").text().substring(1);
27788    var timeToHeat = activeTabContent.find(".water-temp-val").contents().not($(".water-temp-val").children()).text();
27789    shareLink = (hasQuery ? '&' : '?') + "recommended=" + title + "&savings=" + savings + "&timeToHeat=" + timeToHeat;
27790    var pvComponent = $(".heat-pump.component .pool-volume.component");
27791    var activePVTab = pvComponent.find("dt.active");
27792    var tempValue = $(".heat-pump.component .owl-item").eq(2).find("#tempSlider").val();
27793    if (activePVTab.hasClass("rectangle")) {
27794        shareLink += "&shape=rectangle&deepEnd=" + $("#deepEndRectangle").val() + "&shallowEnd=" + $("#shallowEndRectangle").val();
27795        shareLink += "&length=" + $("#lengthRectangle").val() + "&width=" + $("#widthRectangle").val() + "&temp=" + parseFloat(tempValue).toFixed(1);
27796    } else if (activePVTab.hasClass("oblong")) {
27797        shareLink += "&shape=oblong&deepEnd=" + $("#deepEndOblong").val() + "&shallowEnd=" + $("#shallowEndOblong").val();
27798        shareLink += "&largeDiameter=" + $("#largeDiameterOblong").val() + "&smallDiameter=" + $("#smallDiameterOblong").val() + "&length=" + $("#lengthOblong").val() + "&temp=" + parseFloat(tempValue).toFixed(1);
27799    } else if (activePVTab.hasClass("circular")) {
27800        shareLink += "&shape=circular&deepEnd=" + $("#deepEndCircular").val() + "&shallowEnd=" + $("#shallowEndCircular").val();
27801        shareLink += "&radius=" + $("#radiusCircular").val() + "&temp=" + parseFloat(tempValue).toFixed(1);
27802    } else if (activePVTab.hasClass("triangular")) {
27803        shareLink += "&shape=triangular&deepEnd=" + $("#deepEndTriangular").val() + "&shallowEnd=" + $("#shallowEndTriangular").val();
27804        shareLink += "&height=" + $("#heightTriangular").val() + "&base=" + $("#baseTriangular").val() + "&temp=" + parseFloat(tempValue).toFixed(1);
27805    }
27806}
27807
27808function createRecommendedPumpMailToLink() {
27809    var mailToBase = 'mailto:?subject=';
27810    var bodyKey = '&body=';
27811    var mailToString = mailToBase + document.title + bodyKey + encodeURIComponent(host + shareLink);
27812    var recommendedPump = $(".heat-pump.component .recommended-pump");
27813    var activeTab = recommendedPump.find("dt.active");
27814    activeTab.next("dd").find(".calc-share.component .mailto-link").attr("href", mailToString);
27815}
27816
27817function createRecommendedPumpTwitterLink() {
27818    var twitterBase = 'http://twitter.com/intent/tweet?text=';
27819    var twitterUrl = twitterBase + document.title + ' ' + encodeURIComponent(host + shareLink);
27820    var recommendedPump = $(".heat-pump.component .recommended-pump");
27821    var activeTab = recommendedPump.find("dt.active");
27822    activeTab.next("dd").find(".calc-share.component .twitter-link").attr("href", twitterUrl);
27823}
27824
27825function createRecommendedPumpFacebookLink() {
27826    var fbLinkBase = 'http://www.facebook.com/sharer/sharer.php?u=';
27827    var fbUrl = fbLinkBase + encodeURIComponent(host) + "&title=" + document.title + encodeURIComponent(shareLink);
27828    var recommendedPump = $(".heat-pump.component .recommended-pump");
27829    var activeTab = recommendedPump.find("dt.active");
27830    activeTab.next("dd").find(".calc-share.component .facebook-link").attr("href", fbUrl);
27831}
27832
27833function updateHeatPumpCalcShareLinks() {
27834    createRecommendedPumpShareLink();
27835    createRecommendedPumpMailToLink();
27836    createRecommendedPumpTwitterLink();
27837    createRecommendedPumpFacebookLink();
27838}
27839
27840function poolUrlHelper (obj) {
27841    var poolUrlObj = {};
27842    if(obj.shape == "rectangle") {
27843        poolUrlObj.shape = "rectangle";
27844        poolUrlObj.length = obj.length;
27845        poolUrlObj.width = obj.width;
27846        poolUrlObj.shallow = obj.shallowEnd;
27847        poolUrlObj.deep = obj.deepEnd;
27848    } else if (obj.shape == "oblong") {
27849        poolUrlObj.shape = "oblong";
27850        poolUrlObj.length = obj.length;
27851        poolUrlObj.smallDiameter = obj.smallDiameter;
27852        poolUrlObj.largeDiameter = obj.largeDiameter;
27853        poolUrlObj.shallow = obj.shallowEnd;
27854        poolUrlObj.deep = obj.deepEnd;
27855    } else if (obj.shape == "circular") {
27856        poolUrlObj.shape = "circle";
27857        poolUrlObj.shallow = obj.shallowEnd;
27858        poolUrlObj.deep = obj.deepEnd;
27859        poolUrlObj.radius = obj.radius;
27860    } else if (obj.shape == "triangular") {
27861        poolUrlObj.shape = "triangle";
27862        poolUrlObj.shallow = obj.shallowEnd;
27863        poolUrlObj.deep = obj.deepEnd;
27864        poolUrlObj.length = obj.height;
27865        poolUrlObj.width = obj.base;
27866    }
27867    return poolUrlObj;
27868}
27869
27870function handleUrlData(obj) {
27871    var inputs = [];
27872    var data = {};
27873    var poolObj = {};
27874    var items = $(".heat-pump.component").find(".owl-item");
27875    poolObj = poolUrlHelper(obj);
27876    var poolTempSliders = $(items).closest(".heat-pump.component").find(".recommended-pump dt.active").next("dd").find(".swim-season input");
27877    var poolTemps = tempSliderHelper(poolTempSliders);
27878    // Lat Long Values
27879    var defaultLongLong = setLatLong();
27880    var reverseGeoObj = resultObj;
27881    // construct object that holds our data values
27882    data.temp = obj.temp;
27883    data.state = (reverseGeoObj.state !== undefined ? reverseGeoObj.state : "Ohio");
27884    data.swimSeason = (poolTemps === "" ? '3:9' : poolTemps);
27885    data.lat = (reverseGeoObj.lat !== undefined ? reverseGeoObj.lat : defaultLongLong.lat);
27886    data.long = (reverseGeoObj.long !== undefined ? reverseGeoObj.long : defaultLongLong.long);
27887    data.efficiency = 0.82;
27888    data.gasCost = 1.13;
27889    data.electricityCost = 0.12;
27890    var finalData = $.extend({}, data, poolObj);
27891    // send data values to function to send ajax request to servlet
27892    heatPumpCalculationData(finalData);
27893    $(".heat-pump.component").addClass("show-recommended-pump");
27894}
27895
27896function checkHeatPumpUrl() {
27897    var url = window.location.search.substring(1);
27898    if(url.indexOf("recommended=") !== -1 && url.indexOf("savings=") !== -1 && url.indexOf("timeToHeat=") !== -1 && url.indexOf("shape=") !== -1) {
27899        var params = {}, queries, temp, i, l;
27900        // Split into key/value pairs
27901        queries = url.split("&");
27902        // Convert the array of strings into an object
27903        for ( i = 0, l = queries.length; i < l; i++ ) {
27904            temp = queries[i].split('=');
27905            params[temp[0]] = temp[1];
27906        }
27907        handleUrlData(params);
27908    }
27909}
27910
27911var init = function() {
27912    waterTempTicks();
27913    calcTempSliderWidths();
27914    checkHeatPumpUrl();
27915};
27916
27917var PENTAIR = PENTAIR || {};
27918PENTAIR.SHARE = PENTAIR.SHARE || {};
27919PENTAIR.SHARE.URLPARAMS = PENTAIR.SHARE.URLPARAMS || {};
27920
27921$(function() {
27922
27923    /** Primary objective of the share component view model is to bind the dynamic query parameters, if they exist, to the various social media buttons. */
27924    var ShareViewModel = function ShareViewModel(parentElement) {
27925        var self = this;
27926        var currentPageTitle = PENTAIR.SHARE.currentPageTitle ? PENTAIR.SHARE.currentPageTitle : '';
27927        var host = PENTAIR.SHARE.host ? PENTAIR.SHARE.host : '';
27928        var titleKey = '&title=';
27929        var shape = 'shape=';
27930        var deepEnd = '&deepEnd=';
27931        var shallowEnd = '&shallowEnd=';
27932        var length = '&length=';
27933        var width = '&width=';
27934        var largeDiameter = '&largeDiameter=';
27935        var smallDiameter = '&smallDiameter=';
27936        var radius = '&radius=';
27937        var height = '&height=';
27938        var base = '&base=';
27939        var results = '&results=';
27940        var activeTab = $(".pool-volume.component > .pv-tab-container");
27941        var shareLink = "";
27942
27943        var parentCalculatorType = $(".calc-share").parents('.salinity-calculator.component').length > 0 ? 'salinity' : '';
27944        parentCalculatorType = parentCalculatorType || ($(".calc-share").parents('.pool-volume.component').length > 0 ? 'pool-volume' : '');
27945
27946        /** KO Observable Variables */
27947        self.queryParamString = ko.observable('');
27948        self.mailingLink = ko.observable('');
27949        self.modifiedTwitterLink = ko.observable('');
27950        self.modifiedFbLink = ko.observable('');
27951        self.modifiedLinkedInLink = ko.observable('');
27952
27953        function setQueryString() {
27954            var query = window.location.href;
27955            var hasQueryString = query.indexOf('?');
27956            if(hasQueryString !== -1) {
27957                self.queryParamString('?' + window.location.href.split('?')[1]);
27958            }
27959        }
27960
27961        function getEncodedUrl(url) {
27962            if(self.queryParamString() !== '') {
27963                return url + encodeURIComponent(self.queryParamString());
27964            } else {
27965                return url;
27966            }
27967        }
27968
27969        function createVolumeCalcShareLinks() {
27970            var hasQuery = window.location.href.indexOf('?') !== -1;
27971            if(activeTab.hasClass("rectangular-active")) {
27972                shareLink = (hasQuery ? '&' : '?') + shape + "rectangle" + deepEnd + $("#deepEndRectangle").val() + shallowEnd + $("#shallowEndRectangle").val();
27973                shareLink += length + $("#lengthRectangle").val() + width + $("#widthRectangle").val() + results + $("#calcResultRectangle").text();
27974            } else if (activeTab.hasClass("oblong-active")) {
27975                shareLink = (hasQuery ? '&' : '?') + shape + "oblong" + deepEnd + $("#deepEndOblong").val() + shallowEnd + $("#shallowEndOblong").val();
27976                shareLink += length + $("#lengthOblong").val() + largeDiameter + $("#largeDiameterOblong").val() + smallDiameter + $("#smallDiameterOblong").val() + results + $("#calcResultOblong").text();
27977            } else if (activeTab.hasClass("circular-active")) {
27978                shareLink = (hasQuery ? '&' : '?') + shape + "circular" + deepEnd + $("#deepEndCircular").val() + shallowEnd + $("#shallowEndCircular").val();
27979                shareLink += radius + $("#radiusCircular").val() + results + $("#calcResultCircular").text();
27980            } else if (activeTab.hasClass("triangular-active")) {
27981                shareLink = (hasQuery ? '&' : '?') + shape + "triangular" + deepEnd + $("#deepEndTriangular").val() + shallowEnd + $("#shallowEndTriangular").val();
27982                shareLink += height + $("#heightTriangular").val() + base + $("#baseTriangular").val() + results + $("#calcResultTriangular").text();
27983            }
27984            //return shareLink;
27985        }
27986
27987        function createSalinityCalcShareLinks() {
27988            var hasQuery = window.location.href.indexOf('?') !== -1;
27989            shareLink = '?gallons=' + $(".gallons-of-water input").val() +
27990                        '&salt=' + $(".current-salt-level input").val();
27991            console.log(shareLink)
27992        }
27993
27994        function createCalcMailToLink() {
27995            var mailToBase = 'mailto:?subject=';
27996            var bodyKey = '&body=';
27997            var mailToString = mailToBase + currentPageTitle + bodyKey + encodeURIComponent(host + shareLink);
27998            self.mailingLink(mailToString);
27999        }
28000
28001        function createCalcTwitterLink() {
28002            var twitterBase = 'http://twitter.com/intent/tweet?text=';
28003            var twitterUrl = twitterBase + currentPageTitle + ' ' + encodeURIComponent(host + shareLink);
28004            self.modifiedTwitterLink(twitterUrl);
28005        }
28006
28007        function createCalcFacebookLink() {
28008            var fbLinkBase = 'http://www.facebook.com/sharer/sharer.php?u=';
28009            var fbUrl = fbLinkBase + getEncodedUrl(host) + titleKey + currentPageTitle + encodeURIComponent(shareLink);
28010            self.modifiedFbLink(fbUrl);
28011        }
28012        
28013        function updateCalcShareLinks() {
28014            setQueryString();
28015            if(parentCalculatorType === 'pool-volume'){
28016                createVolumeCalcShareLinks();
28017            } else if(parentCalculatorType === 'salinity'){
28018                createSalinityCalcShareLinks();
28019            }
28020            createCalcMailToLink();
28021            createCalcTwitterLink();
28022            createCalcFacebookLink();
28023        }
28024
28025        /** Since the url is dynamic on Download center pages, we need to check the query parameters every time the mouse moves towards the share links. */
28026        $('.calc-share.component')
28027            .on('mouseenter', function() {
28028                updateCalcShareLinks();
28029        });
28030
28031        /** Initialize the links on load */
28032        updateCalcShareLinks();
28033
28034    };
28035
28036    //
28037    // $(function() {
28038        /** Initialize the knockout viewmodel on the share component. (on load)*/
28039
28040        // var $hareComponent = $('#shareComponent');
28041        // if($hareComponent.length) {
28042        //
28043        //     ko.applyBindings(new ShareViewModel($hareComponent));
28044        // }
28045
28046    $('.calc-share.component').each(function() {
28047        try {
28048            ko.applyBindings(new ShareViewModel($(this)), this);
28049        } catch (koError) {
28050            console.log('Knockout JS error detected on the Share Component - Calculators ==> ', koError);
28051        }
28052    });
28053
28054});
28055
28056$(document).ready(function(){
28057
28058    var initAccessoriesCarousel = function(accessoriesComponent){
28059
28060        var accessoriesCarousel = accessoriesComponent.find('.owl-carousel');
28061        var pagination = accessoriesComponent.find('.pagination');
28062        var currentSlide = 0;
28063        var totalItems;
28064        var paginator;
28065
28066        accessoriesCarousel.owlCarousel({
28067            nav:false,
28068            dots:true,
28069            mouseDrag: false,
28070            items: 1
28071        }).on('initialized.owl.carousel changed.owl.carousel resized.owl.carousel', function(event) {
28072        	paginator.paginationItems(paginationItems());
28073            update();
28074        });
28075
28076        // How many pagination buttons to display depends on screen size.
28077        var paginationItems = function(){
28078        	if ( matchMedia('(max-width: 765px)').matches ) {
28079        		return 3;
28080        	}
28081        	return 5;
28082        };
28083
28084        var update = function () {
28085            setTimeout(function(){
28086                var activeDot = accessoriesCarousel.find('.owl-dot.active');
28087                var currentSlide = accessoriesCarousel.find('.owl-dot').index(activeDot) + 1;
28088                paginator.currentPage(currentSlide);
28089                reInitEvents();
28090            }, 10);
28091        };
28092
28093        var reInitEvents = function () {
28094        	pagination.find('a').on('click', function(e){
28095        		e.preventDefault();
28096        	});
28097
28098        	pagination.find('li a').on('click', function(e){
28099        		var targetPage = $(e.target).text();
28100        		var targetIndex = targetPage - 1;
28101	            var dist = targetPage - paginator.currentPage();
28102	            var direction = (dist < 0) ? 'prev.owl.carousel' : 'next.owl.carousel';
28103	            dist = Math.abs(dist);
28104	            for(var i = 0; i < dist; i++){
28105	                accessoriesCarousel.trigger(direction);
28106	            }
28107        		paginator.currentPage(targetPage);
28108        	});
28109        };
28110
28111        var init = function(){
28112        	totalItems = accessoriesComponent.find('.owl-item li').length;
28113        	var itemsPerPage = accessoriesComponent.find('.active.owl-item li').length;
28114        	paginator = new PaginationViewModel(totalItems, itemsPerPage, paginationItems());
28115        	ko.applyBindings(paginator);
28116        	paginator.init(totalItems);
28117        	
28118        	pagination.find('a.prev').on('click', function(){
28119        		if(paginator.previousPageExists()){
28120        			accessoriesCarousel.trigger('prev.owl.carousel');
28121        		}
28122        	});
28123
28124        	pagination.find('a.next').on('click', function(){
28125        		if(paginator.nextPageExists()){
28126        			accessoriesCarousel.trigger('next.owl.carousel');	
28127        		}
28128        	});
28129
28130        	update();
28131        };
28132
28133        init();
28134    };
28135
28136    var accessoriesCarousels = $('.accessories-grid.component:not(.edit)');
28137
28138    if(accessoriesCarousels.length){
28139        $(function(){
28140            accessoriesCarousels.each(function(index, elem){
28141                initAccessoriesCarousel($(elem));
28142            });
28143        });
28144    }
28145    
28146    ////////////////////////////////////////////////////////
28147	//// building data analytics layer object start ///////
28148	//////////////////////////////////////////////////////
28149
28150    $('.accessories-grid.component').on('click','ul li',function(e){	
28151    	try{
28152			if( digitalData){
28153				
28154				if(digitalData.product){
28155					digitalData.product.productName = $('h1').text(); 
28156					if( $(this).find('div p strong') ){
28157						digitalData.product.productID = $(this).find('div p strong').text();
28158					}
28159					digitalData.product.productAccessoryName =  $(this).find('h4').text();
28160				}
28161				if( digitalData.event ){
28162					var eventData = {};
28163					eventData.eventName = "product accessory"
28164					eventData.eventAction = "accessory click";
28165					eventData.type = "shopping";
28166					eventData.timeStamp = new Date();
28167					digitalData.event.push(eventData);					
28168				}
28169				
28170			}
28171			
28172		}catch(err) {
28173			console.log(err)
28174		}
28175    })	
28176	////////////////////////////////////////////////////////
28177	///// building data analytics layer object end  ///////
28178	//////////////////////////////////////////////////////
28179
28180});
28181////////////////////////////////////////////////////////////////
28182///////////////building data layer oject////////////////////////
28183////////////////////////////////////////////////////////////////
28184
28185$(document).ready(function(){
28186    try{
28187        if(digitalData.resource){
28188            var eventData = {};
28189            $('.item .downloads .downloads-resources .pdf').on('click',function(e) {
28190                var timeStamp = new Date();
28191                digitalData.resource.resourceName = $(this).text();
28192                eventData.eventName = "resource";
28193                eventData.eventAction = "click";
28194                eventData.type = "resource library";
28195                eventData.timeStamp = timeStamp;
28196                digitalData.event.push(eventData);
28197            });
28198        }
28199    }catch(err){
28200        console.log(err);
28201    }
28202});
28203
28204////////////////////////////////////////////////////////////////
28205///////////////building data layer oject////////////////////////
28206////////////////////////////////////////////////////////////////
28207/*******************************************************************************
28208 * Copyright 2022 Adobe
28209 *
28210 * Licensed under the Apache License, Version 2.0 (the "License");
28211 * you may not use this file except in compliance with the License.
28212 * You may obtain a copy of the License at
28213 *
28214 *     http://www.apache.org/licenses/LICENSE-2.0
28215 *
28216 * Unless required by applicable law or agreed to in writing, software
28217 * distributed under the License is distributed on an "AS IS" BASIS,
28218 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28219 * See the License for the specific language governing permissions and
28220 * limitations under the License.
28221 ******************************************************************************/
28222(function(document) {
28223    "use strict";
28224
28225    window.CMP = window.CMP || {};
28226    window.CMP.utils = (function() {
28227        var NS = "cmp";
28228
28229        /**
28230         * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes
28231         *
28232         * @param {HTMLElement} element The component element to read options data from
28233         * @param {String} is The component identifier
28234         * @returns {String[]} The options read from the component data attributes
28235         */
28236        var readData = function(element, is) {
28237            var data = element.dataset;
28238            var options = [];
28239            var capitalized = is;
28240            capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
28241            var reserved = ["is", "hook" + capitalized];
28242
28243            for (var key in data) {
28244                if (Object.prototype.hasOwnProperty.call(data, key)) {
28245                    var value = data[key];
28246
28247                    if (key.indexOf(NS) === 0) {
28248                        key = key.slice(NS.length);
28249                        key = key.charAt(0).toLowerCase() + key.substring(1);
28250
28251                        if (reserved.indexOf(key) === -1) {
28252                            options[key] = value;
28253                        }
28254                    }
28255                }
28256            }
28257            return options;
28258        };
28259
28260        /**
28261         * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand
28262         * @param {String[]} options the options to transform
28263         * @param {Object} properties object of properties of property functions
28264         * @returns {Object} transformed properties
28265         */
28266        var setupProperties = function(options, properties) {
28267            var transformedProperties = {};
28268
28269            for (var key in properties) {
28270                if (Object.prototype.hasOwnProperty.call(properties, key)) {
28271                    var property = properties[key];
28272                    if (options && options[key] != null) {
28273                        if (property && typeof property.transform === "function") {
28274                            transformedProperties[key] = property.transform(options[key]);
28275                        } else {
28276                            transformedProperties[key] = options[key];
28277                        }
28278                    } else {
28279                        transformedProperties[key] = properties[key]["default"];
28280                    }
28281                }
28282            }
28283            return transformedProperties;
28284        };
28285
28286
28287        return {
28288            readData: readData,
28289            setupProperties: setupProperties
28290        };
28291    }());
28292}(window.document));
28293
28294/*******************************************************************************
28295 * Copyright 2018 Adobe
28296 *
28297 * Licensed under the Apache License, Version 2.0 (the "License");
28298 * you may not use this file except in compliance with the License.
28299 * You may obtain a copy of the License at
28300 *
28301 *     http://www.apache.org/licenses/LICENSE-2.0
28302 *
28303 * Unless required by applicable law or agreed to in writing, software
28304 * distributed under the License is distributed on an "AS IS" BASIS,
28305 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28306 * See the License for the specific language governing permissions and
28307 * limitations under the License.
28308 ******************************************************************************/
28309(function() {
28310    "use strict";
28311
28312    var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined;
28313    if (!containerUtils) {
28314        // eslint-disable-next-line no-console
28315        console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page.");
28316    }
28317    var dataLayerEnabled;
28318    var dataLayer;
28319    var dataLayerName;
28320
28321    var NS = "cmp";
28322    var IS = "carousel";
28323
28324    var keyCodes = {
28325        SPACE: 32,
28326        END: 35,
28327        HOME: 36,
28328        ARROW_LEFT: 37,
28329        ARROW_UP: 38,
28330        ARROW_RIGHT: 39,
28331        ARROW_DOWN: 40
28332    };
28333
28334    var selectors = {
28335        self: "[data-" + NS + '-is="' + IS + '"]'
28336    };
28337
28338    var properties = {
28339        /**
28340         * Determines whether the Carousel will automatically transition between slides
28341         *
28342         * @memberof Carousel
28343         * @type {Boolean}
28344         * @default false
28345         */
28346        "autoplay": {
28347            "default": false,
28348            "transform": function(value) {
28349                return !(value === null || typeof value === "undefined");
28350            }
28351        },
28352        /**
28353         * Duration (in milliseconds) before automatically transitioning to the next slide
28354         *
28355         * @memberof Carousel
28356         * @type {Number}
28357         * @default 5000
28358         */
28359        "delay": {
28360            "default": 5000,
28361            "transform": function(value) {
28362                value = parseFloat(value);
28363                return !isNaN(value) ? value : null;
28364            }
28365        },
28366        /**
28367         * Determines whether automatic pause on hovering the carousel is disabled
28368         *
28369         * @memberof Carousel
28370         * @type {Boolean}
28371         * @default false
28372         */
28373        "autopauseDisabled": {
28374            "default": false,
28375            "transform": function(value) {
28376                return !(value === null || typeof value === "undefined");
28377            }
28378        }
28379    };
28380
28381    /**
28382     * Carousel Configuration
28383     *
28384     * @typedef {Object} CarouselConfig Represents a Carousel configuration
28385     * @property {HTMLElement} element The HTMLElement representing the Carousel
28386     * @property {*[]} options The Carousel options
28387     */
28388
28389    /**
28390     * Carousel
28391     *
28392     * @class Carousel
28393     * @classdesc An interactive Carousel component for navigating a list of generic items
28394     * @param {CarouselConfig} config The Carousel configuration
28395     */
28396    function Carousel(config) {
28397        var that = this;
28398
28399        if (config && config.element) {
28400            init(config);
28401        }
28402
28403        /**
28404         * Initializes the Carousel
28405         *
28406         * @private
28407         * @param {CarouselConfig} config The Carousel configuration
28408         */
28409        function init(config) {
28410            that._config = config;
28411
28412            // prevents multiple initialization
28413            config.element.removeAttribute("data-" + NS + "-is");
28414
28415            setupProperties(config.options);
28416            cacheElements(config.element);
28417
28418            that._active = 0;
28419            that._paused = false;
28420
28421            if (that._elements.item) {
28422                initializeActive();
28423                bindEvents();
28424                resetAutoplayInterval();
28425                refreshPlayPauseActions();
28426                scrollToDeepLinkIdInCarousel();
28427            }
28428
28429            // TODO: This section is only relevant in edit mode and should move to the editor clientLib
28430            if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
28431                /*
28432                 * Editor message handling:
28433                 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
28434                 * - check that the message data panel container type is correct and that the id (path) matches this specific Carousel component
28435                 * - if so, route the "navigate" operation to enact a navigation of the Carousel based on index data
28436                 */
28437                window.CQ = window.CQ || {};
28438                window.CQ.CoreComponents = window.CQ.CoreComponents || {};
28439                window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
28440                window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) {
28441                    if (message.data && message.data.type === "cmp-carousel" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) {
28442                        if (message.data.operation === "navigate") {
28443                            navigate(message.data.index);
28444                        }
28445                    }
28446                });
28447            }
28448        }
28449
28450        /**
28451         * Displays the slide containing the element that corresponds to the deep link in the URI fragment
28452         * and scrolls the browser to this element.
28453         */
28454        function scrollToDeepLinkIdInCarousel() {
28455            if (containerUtils) {
28456                var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "item", "item");
28457                if (deepLinkItemIdx > -1) {
28458                    var deepLinkItem = that._elements["item"][deepLinkItemIdx];
28459                    if (deepLinkItem && that._elements["item"][that._active].id !== deepLinkItem.id) {
28460                        navigateAndFocusIndicator(deepLinkItemIdx, true);
28461                        // pause the carousel auto-rotation
28462                        pause();
28463                    }
28464                    var hashId = window.location.hash.substring(1);
28465                    if (hashId) {
28466                        var hashItem = document.querySelector("[id='" + hashId + "']");
28467                        if (hashItem) {
28468                            hashItem.scrollIntoView();
28469                        }
28470                    }
28471                }
28472            }
28473        }
28474
28475        /**
28476         * Caches the Carousel elements as defined via the {@code data-carousel-hook="ELEMENT_NAME"} markup API
28477         *
28478         * @private
28479         * @param {HTMLElement} wrapper The Carousel wrapper element
28480         */
28481        function cacheElements(wrapper) {
28482            that._elements = {};
28483            that._elements.self = wrapper;
28484            var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]");
28485
28486            for (var i = 0; i < hooks.length; i++) {
28487                var hook = hooks[i];
28488                var capitalized = IS;
28489                capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
28490                var key = hook.dataset[NS + "Hook" + capitalized];
28491                if (that._elements[key]) {
28492                    if (!Array.isArray(that._elements[key])) {
28493                        var tmp = that._elements[key];
28494                        that._elements[key] = [tmp];
28495                    }
28496                    that._elements[key].push(hook);
28497                } else {
28498                    that._elements[key] = hook;
28499                }
28500            }
28501        }
28502
28503        /**
28504         * Sets up properties for the Carousel based on the passed options.
28505         *
28506         * @private
28507         * @param {Object} options The Carousel options
28508         */
28509        function setupProperties(options) {
28510            that._properties = {};
28511
28512            for (var key in properties) {
28513                if (Object.prototype.hasOwnProperty.call(properties, key)) {
28514                    var property = properties[key];
28515                    var value = null;
28516
28517                    if (options && options[key] != null) {
28518                        value = options[key];
28519
28520                        // transform the provided option
28521                        if (property && typeof property.transform === "function") {
28522                            value = property.transform(value);
28523                        }
28524                    }
28525
28526                    if (value === null) {
28527                        // value still null, take the property default
28528                        value = properties[key]["default"];
28529                    }
28530
28531                    that._properties[key] = value;
28532                }
28533            }
28534        }
28535
28536        /**
28537         * Binds Carousel event handling
28538         *
28539         * @private
28540         */
28541        function bindEvents() {
28542            window.addEventListener("hashchange", scrollToDeepLinkIdInCarousel, false);
28543            if (that._elements["previous"]) {
28544                that._elements["previous"].addEventListener("click", function() {
28545                    var index = getPreviousIndex();
28546                    navigate(index);
28547                    if (dataLayerEnabled) {
28548                        dataLayer.push({
28549                            event: "cmp:show",
28550                            eventInfo: {
28551                                path: "component." + getDataLayerId(that._elements.item[index])
28552                            }
28553                        });
28554                    }
28555                });
28556            }
28557
28558            if (that._elements["next"]) {
28559                that._elements["next"].addEventListener("click", function() {
28560                    var index = getNextIndex();
28561                    navigate(index);
28562                    if (dataLayerEnabled) {
28563                        dataLayer.push({
28564                            event: "cmp:show",
28565                            eventInfo: {
28566                                path: "component." + getDataLayerId(that._elements.item[index])
28567                            }
28568                        });
28569                    }
28570                });
28571            }
28572
28573            var indicators = that._elements["indicator"];
28574            if (indicators) {
28575                for (var i = 0; i < indicators.length; i++) {
28576                    (function(index) {
28577                        indicators[i].addEventListener("click", function(event) {
28578                            navigateAndFocusIndicator(index);
28579                            // pause the carousel auto-rotation
28580                            pause();
28581                        });
28582                    })(i);
28583                }
28584            }
28585
28586            if (that._elements["pause"]) {
28587                if (that._properties.autoplay) {
28588                    that._elements["pause"].addEventListener("click", onPauseClick);
28589                }
28590            }
28591
28592            if (that._elements["play"]) {
28593                if (that._properties.autoplay) {
28594                    that._elements["play"].addEventListener("click", onPlayClick);
28595                }
28596            }
28597
28598            that._elements.self.addEventListener("keydown", onKeyDown);
28599
28600            if (!that._properties.autopauseDisabled) {
28601                that._elements.self.addEventListener("mouseenter", onMouseEnter);
28602                that._elements.self.addEventListener("mouseleave", onMouseLeave);
28603            }
28604
28605            // for accessibility we pause animation when a element get focused
28606            var items = that._elements["item"];
28607            if (items) {
28608                for (var j = 0; j < items.length; j++) {
28609                    items[j].addEventListener("focusin", onMouseEnter);
28610                    items[j].addEventListener("focusout", onMouseLeave);
28611                }
28612            }
28613        }
28614
28615        /**
28616         * Handles carousel keydown events
28617         *
28618         * @private
28619         * @param {Object} event The keydown event
28620         */
28621        function onKeyDown(event) {
28622            var index = that._active;
28623            var lastIndex = that._elements["indicator"].length - 1;
28624
28625            switch (event.keyCode) {
28626                case keyCodes.ARROW_LEFT:
28627                case keyCodes.ARROW_UP:
28628                    event.preventDefault();
28629                    if (index > 0) {
28630                        navigateAndFocusIndicator(index - 1);
28631                    }
28632                    break;
28633                case keyCodes.ARROW_RIGHT:
28634                case keyCodes.ARROW_DOWN:
28635                    event.preventDefault();
28636                    if (index < lastIndex) {
28637                        navigateAndFocusIndicator(index + 1);
28638                    }
28639                    break;
28640                case keyCodes.HOME:
28641                    event.preventDefault();
28642                    navigateAndFocusIndicator(0);
28643                    break;
28644                case keyCodes.END:
28645                    event.preventDefault();
28646                    navigateAndFocusIndicator(lastIndex);
28647                    break;
28648                case keyCodes.SPACE:
28649                    if (that._properties.autoplay && (event.target !== that._elements["previous"] && event.target !== that._elements["next"])) {
28650                        event.preventDefault();
28651                        if (!that._paused) {
28652                            pause();
28653                        } else {
28654                            play();
28655                        }
28656                    }
28657                    if (event.target === that._elements["pause"]) {
28658                        that._elements["play"].focus();
28659                    }
28660                    if (event.target === that._elements["play"]) {
28661                        that._elements["pause"].focus();
28662                    }
28663                    break;
28664                default:
28665                    return;
28666            }
28667        }
28668
28669        /**
28670         * Handles carousel mouseenter events
28671         *
28672         * @private
28673         * @param {Object} event The mouseenter event
28674         */
28675        function onMouseEnter(event) {
28676            clearAutoplayInterval();
28677        }
28678
28679        /**
28680         * Handles carousel mouseleave events
28681         *
28682         * @private
28683         * @param {Object} event The mouseleave event
28684         */
28685        function onMouseLeave(event) {
28686            resetAutoplayInterval();
28687        }
28688
28689        /**
28690         * Handles pause element click events
28691         *
28692         * @private
28693         * @param {Object} event The click event
28694         */
28695        function onPauseClick(event) {
28696            pause();
28697            that._elements["play"].focus();
28698        }
28699
28700        /**
28701         * Handles play element click events
28702         *
28703         * @private
28704         * @param {Object} event The click event
28705         */
28706        function onPlayClick() {
28707            play();
28708            that._elements["pause"].focus();
28709        }
28710
28711        /**
28712         * Pauses the playing of the Carousel. Sets {@code Carousel#_paused} marker.
28713         * Only relevant when autoplay is enabled
28714         *
28715         * @private
28716         */
28717        function pause() {
28718            that._paused = true;
28719            clearAutoplayInterval();
28720            refreshPlayPauseActions();
28721        }
28722
28723        /**
28724         * Enables the playing of the Carousel. Sets {@code Carousel#_paused} marker.
28725         * Only relevant when autoplay is enabled
28726         *
28727         * @private
28728         */
28729        function play() {
28730            that._paused = false;
28731
28732            // If the Carousel is hovered, don't begin auto transitioning until the next mouse leave event
28733            var hovered = false;
28734            if (that._elements.self.parentElement) {
28735                hovered = that._elements.self.parentElement.querySelector(":hover") === that._elements.self;
28736            }
28737            if (that._properties.autopauseDisabled || !hovered) {
28738                resetAutoplayInterval();
28739            }
28740
28741            refreshPlayPauseActions();
28742        }
28743
28744        /**
28745         * Refreshes the play/pause action markup based on the {@code Carousel#_paused} state
28746         *
28747         * @private
28748         */
28749        function refreshPlayPauseActions() {
28750            setActionDisabled(that._elements["pause"], that._paused);
28751            setActionDisabled(that._elements["play"], !that._paused);
28752        }
28753
28754        /**
28755         * Initialize {@code Carousel#_active} based on the active item of the carousel.
28756         */
28757        function initializeActive() {
28758            var items = that._elements["item"];
28759            if (items && Array.isArray(items)) {
28760                for (var i = 0; i < items.length; i++) {
28761                    if (items[i].classList.contains("cmp-carousel__item--active")) {
28762                        that._active = i;
28763                        break;
28764                    }
28765                }
28766            }
28767        }
28768
28769        /**
28770         * Refreshes the item markup based on the current {@code Carousel#_active} index
28771         *
28772         * @private
28773         */
28774        function refreshActive() {
28775            var items = that._elements["item"];
28776            var indicators = that._elements["indicator"];
28777
28778            if (items) {
28779                if (Array.isArray(items)) {
28780                    for (var i = 0; i < items.length; i++) {
28781                        if (i === parseInt(that._active)) {
28782                            items[i].classList.add("cmp-carousel__item--active");
28783                            items[i].removeAttribute("aria-hidden");
28784                            indicators[i].classList.add("cmp-carousel__indicator--active");
28785                            indicators[i].setAttribute("aria-selected", true);
28786                            indicators[i].setAttribute("tabindex", "0");
28787                        } else {
28788                            items[i].classList.remove("cmp-carousel__item--active");
28789                            items[i].setAttribute("aria-hidden", true);
28790                            indicators[i].classList.remove("cmp-carousel__indicator--active");
28791                            indicators[i].setAttribute("aria-selected", false);
28792                            indicators[i].setAttribute("tabindex", "-1");
28793                        }
28794                    }
28795                } else {
28796                    // only one item
28797                    items.classList.add("cmp-carousel__item--active");
28798                    indicators.classList.add("cmp-carousel__indicator--active");
28799                }
28800            }
28801        }
28802
28803        /**
28804         * Focuses the element and prevents scrolling the element into view
28805         *
28806         * @param {HTMLElement} element Element to focus
28807         */
28808        function focusWithoutScroll(element) {
28809            var x = window.scrollX || window.pageXOffset;
28810            var y = window.scrollY || window.pageYOffset;
28811            element.focus();
28812            window.scrollTo(x, y);
28813        }
28814
28815        /**
28816         * Retrieves the next active index, with looping
28817         *
28818         * @private
28819         * @returns {Number} Index of the next carousel item
28820         */
28821        function getNextIndex() {
28822            return that._active === (that._elements["item"].length - 1) ? 0 : that._active + 1;
28823        }
28824
28825        /**
28826         * Retrieves the previous active index, with looping
28827         *
28828         * @private
28829         * @returns {Number} Index of the previous carousel item
28830         */
28831        function getPreviousIndex() {
28832            return that._active === 0 ? (that._elements["item"].length - 1) : that._active - 1;
28833        }
28834
28835        /**
28836         * Navigates to the item at the provided index
28837         *
28838         * @private
28839         * @param {Number} index The index of the item to navigate to
28840         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
28841         */
28842        function navigate(index, keepHash) {
28843            if (index < 0 || index > (that._elements["item"].length - 1)) {
28844                return;
28845            }
28846
28847            that._active = index;
28848            refreshActive();
28849
28850            if (!keepHash && containerUtils) {
28851                containerUtils.updateUrlHash(that, "item", index);
28852            }
28853
28854            if (dataLayerEnabled) {
28855                var carouselId = that._elements.self.id;
28856                var activeItem = getDataLayerId(that._elements.item[index]);
28857                var updatePayload = { component: {} };
28858                updatePayload.component[carouselId] = { shownItems: [activeItem] };
28859
28860                var removePayload = { component: {} };
28861                removePayload.component[carouselId] = { shownItems: undefined };
28862
28863                dataLayer.push(removePayload);
28864                dataLayer.push(updatePayload);
28865            }
28866
28867            // reset the autoplay transition interval following navigation, if not already hovering the carousel
28868            if (that._elements.self.parentElement) {
28869                if (that._elements.self.parentElement.querySelector(":hover") !== that._elements.self) {
28870                    resetAutoplayInterval();
28871                }
28872            }
28873        }
28874
28875        /**
28876         * Navigates to the item at the provided index and ensures the active indicator gains focus
28877         *
28878         * @private
28879         * @param {Number} index The index of the item to navigate to
28880         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
28881         */
28882        function navigateAndFocusIndicator(index, keepHash) {
28883            navigate(index, keepHash);
28884            focusWithoutScroll(that._elements["indicator"][index]);
28885
28886            if (dataLayerEnabled) {
28887                dataLayer.push({
28888                    event: "cmp:show",
28889                    eventInfo: {
28890                        path: "component." + getDataLayerId(that._elements.item[index])
28891                    }
28892                });
28893            }
28894        }
28895
28896        /**
28897         * Starts/resets automatic slide transition interval
28898         *
28899         * @private
28900         */
28901        function resetAutoplayInterval() {
28902            if (that._paused || !that._properties.autoplay) {
28903                return;
28904            }
28905            clearAutoplayInterval();
28906            that._autoplayIntervalId = window.setInterval(function() {
28907                if (document.visibilityState && document.hidden) {
28908                    return;
28909                }
28910                var indicators = that._elements["indicators"];
28911                if (indicators !== document.activeElement && indicators.contains(document.activeElement)) {
28912                    // if an indicator has focus, ensure we switch focus following navigation
28913                    navigateAndFocusIndicator(getNextIndex(), true);
28914                } else {
28915                    navigate(getNextIndex(), true);
28916                }
28917            }, that._properties.delay);
28918        }
28919
28920        /**
28921         * Clears/pauses automatic slide transition interval
28922         *
28923         * @private
28924         */
28925        function clearAutoplayInterval() {
28926            window.clearInterval(that._autoplayIntervalId);
28927            that._autoplayIntervalId = null;
28928        }
28929
28930        /**
28931         * Sets the disabled state for an action and toggles the appropriate CSS classes
28932         *
28933         * @private
28934         * @param {HTMLElement} action Action to disable
28935         * @param {Boolean} [disable] {@code true} to disable, {@code false} to enable
28936         */
28937        function setActionDisabled(action, disable) {
28938            if (!action) {
28939                return;
28940            }
28941            if (disable !== false) {
28942                action.disabled = true;
28943                action.classList.add("cmp-carousel__action--disabled");
28944            } else {
28945                action.disabled = false;
28946                action.classList.remove("cmp-carousel__action--disabled");
28947            }
28948        }
28949    }
28950
28951    /**
28952     * Parses the dataLayer string and returns the ID
28953     *
28954     * @private
28955     * @param {HTMLElement} item the accordion item
28956     * @returns {String} dataLayerId or undefined
28957     */
28958    function getDataLayerId(item) {
28959        if (item) {
28960            if (item.dataset.cmpDataLayer) {
28961                return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0];
28962            } else {
28963                return item.id;
28964            }
28965        }
28966        return null;
28967    }
28968
28969    /**
28970     * Document ready handler and DOM mutation observers. Initializes Carousel components as necessary.
28971     *
28972     * @private
28973     */
28974    function onDocumentReady() {
28975        dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled");
28976        if (dataLayerEnabled) {
28977            dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer";
28978            dataLayer = window[dataLayerName] = window[dataLayerName] || [];
28979        }
28980
28981        var elements = document.querySelectorAll(selectors.self);
28982        for (var i = 0; i < elements.length; i++) {
28983            new Carousel({ element: elements[i], options: CMP.utils.readData(elements[i], IS) });
28984        }
28985
28986        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
28987        var body = document.querySelector("body");
28988        var observer = new MutationObserver(function(mutations) {
28989            mutations.forEach(function(mutation) {
28990                // needed for IE
28991                var nodesArray = [].slice.call(mutation.addedNodes);
28992                if (nodesArray.length > 0) {
28993                    nodesArray.forEach(function(addedNode) {
28994                        if (addedNode.querySelectorAll) {
28995                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
28996                            elementsArray.forEach(function(element) {
28997                                new Carousel({ element: element, options: CMP.utils.readData(element, IS) });
28998                            });
28999                        }
29000                    });
29001                }
29002            });
29003        });
29004
29005        observer.observe(body, {
29006            subtree: true,
29007            childList: true,
29008            characterData: true
29009        });
29010    }
29011
29012    var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) {
29013        document.addEventListener("DOMContentLoaded", resolve);
29014    });
29015    Promise.all([documentReady]).then(onDocumentReady);
29016
29017    if (containerUtils) {
29018        window.addEventListener("load", containerUtils.scrollToAnchor, false);
29019    }
29020
29021}());
29022
29023/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29024 ~ Copyright 2018 Adobe
29025 ~
29026 ~ Licensed under the Apache License, Version 2.0 (the "License");
29027 ~ you may not use this file except in compliance with the License.
29028 ~ You may obtain a copy of the License at
29029 ~
29030 ~     http://www.apache.org/licenses/LICENSE-2.0
29031 ~
29032 ~ Unless required by applicable law or agreed to in writing, software
29033 ~ distributed under the License is distributed on an "AS IS" BASIS,
29034 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29035 ~ See the License for the specific language governing permissions and
29036 ~ limitations under the License.
29037 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
29038(function($) {
29039    "use strict";
29040
29041    var selectors = {
29042        dialogContent: ".cmp-carousel__editor",
29043        autoplay: "[data-cmp-carousel-v1-dialog-hook='autoplay']",
29044        autoplayGroup: "[data-cmp-carousel-v1-dialog-hook='autoplayGroup']",
29045        childreneditorSelector: "[data-cmp-is='childrenEditor']",
29046        activeItemSelector: "[data-cmp-carousel-v1-dialog-edit-hook='activeItem']",
29047        activeSelectSelector: "[data-cmp-carousel-v1-dialog-edit-hook='activeSelect']"
29048    };
29049
29050    var autoplay;
29051    var autoplayGroup;
29052
29053    $(document).on("dialog-loaded", function(event) {
29054        var $dialog = event.dialog;
29055
29056        if ($dialog.length) {
29057            var dialogContent = $dialog[0].querySelector(selectors.dialogContent);
29058
29059            if (dialogContent) {
29060                autoplay = dialogContent.querySelector(selectors.autoplay);
29061                autoplayGroup = dialogContent.querySelector(selectors.autoplayGroup);
29062
29063                if (autoplay) {
29064                    Coral.commons.ready(autoplay, function() {
29065                        autoplay.on("change", onAutoplayChange);
29066                        onAutoplayChange();
29067                    });
29068                }
29069
29070                setupActiveSelect(dialogContent);
29071            }
29072        }
29073    });
29074
29075    /**
29076     * Handles a change in the autoplay checkbox state.
29077     * Conditionally toggles hidden state of the related autoplay group which contains
29078     * additional fields that are only relevant when autoplay is enabled.
29079     *
29080     * @private
29081     */
29082    function onAutoplayChange() {
29083        if (autoplay && autoplayGroup) {
29084            if (!autoplay.checked) {
29085                autoplayGroup.setAttribute("hidden", true);
29086            } else {
29087                autoplayGroup.removeAttribute("hidden");
29088            }
29089        }
29090    }
29091
29092    /**
29093     * Set up event handlers to populate active select and active item fields.
29094     *
29095     * @param {HTMLElement} dialogContent content element of the edit dialog
29096     */
29097    function setupActiveSelect(dialogContent) {
29098        var childrenEditor = dialogContent.querySelector(selectors.childreneditorSelector);
29099        var activeSelect = dialogContent.querySelector(selectors.activeSelectSelector);
29100        var activeItem = dialogContent.querySelector(selectors.activeItemSelector);
29101
29102        if (childrenEditor && activeSelect && activeItem) {
29103            Coral.commons.ready(childrenEditor, function() {
29104                updateActiveSelect(childrenEditor, activeSelect, activeItem);
29105            });
29106
29107            childrenEditor.on("change", function() {
29108                updateActiveSelect(childrenEditor, activeSelect, activeItem);
29109            });
29110
29111            activeSelect.on("change", function() {
29112                activeItem.value = activeSelect.value;
29113            });
29114        }
29115    }
29116
29117    /**
29118     * Update the list of items in the active item selector.
29119     *
29120     * @param {HTMLElement} childrenEditor Children editor multifield
29121     * @param {HTMLElement} activeSelect Active item select field
29122     * @param {HTMLElement} activeItem Active item hidden input
29123     */
29124    function updateActiveSelect(childrenEditor, activeSelect, activeItem) {
29125        if (childrenEditor && activeSelect && activeItem) {
29126            var selectedValue = activeSelect.value || activeItem.value;
29127            activeSelect.items.getAll().forEach(function(item) {
29128                if (item.value !== "") {
29129                    activeSelect.items.remove(item);
29130                }
29131            });
29132            var cmpChildrenEditor = $(childrenEditor).adaptTo("cmp-childreneditor");
29133            if (cmpChildrenEditor) {
29134                cmpChildrenEditor.items().forEach(function(item) {
29135                    activeSelect.items.add({
29136                        selected: item.name === selectedValue,
29137                        value: item.name,
29138                        content: {
29139                            textContent: item.description
29140                        }
29141                    });
29142                });
29143            }
29144        }
29145    }
29146})(jQuery);
29147
29148/*******************************************************************************
29149 * Copyright 2018 Adobe
29150 *
29151 * Licensed under the Apache License, Version 2.0 (the "License");
29152 * you may not use this file except in compliance with the License.
29153 * You may obtain a copy of the License at
29154 *
29155 *     http://www.apache.org/licenses/LICENSE2.0
29156 *
29157 * Unless required by applicable law or agreed to in writing, software
29158 * distributed under the License is distributed on an "AS IS" BASIS,
29159 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29160 * See the License for the specific language governing permissions and
29161 * limitations under the License.
29162 ******************************************************************************/
29163
29164/**
29165 * Element.matches()
29166 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill
29167 */
29168if (!Element.prototype.matches) {
29169    Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
29170}
29171
29172// eslint-disable-next-line valid-jsdoc
29173/**
29174 * Element.closest()
29175 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill
29176 */
29177if (!Element.prototype.closest) {
29178    Element.prototype.closest = function(s) {
29179        "use strict";
29180        var el = this;
29181        if (!document.documentElement.contains(el)) {
29182            return null;
29183        }
29184        do {
29185            if (el.matches(s)) {
29186                return el;
29187            }
29188            el = el.parentElement || el.parentNode;
29189        } while (el !== null && el.nodeType === 1);
29190        return null;
29191    };
29192}
29193
29194/*******************************************************************************
29195 * Copyright 2018 Adobe
29196 *
29197 * Licensed under the Apache License, Version 2.0 (the "License");
29198 * you may not use this file except in compliance with the License.
29199 * You may obtain a copy of the License at
29200 *
29201 *     http://www.apache.org/licenses/LICENSE-2.0
29202 *
29203 * Unless required by applicable law or agreed to in writing, software
29204 * distributed under the License is distributed on an "AS IS" BASIS,
29205 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29206 * See the License for the specific language governing permissions and
29207 * limitations under the License.
29208 ******************************************************************************/
29209/* global
29210    CQ
29211 */
29212(function() {
29213    "use strict";
29214
29215    var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined;
29216    if (!containerUtils) {
29217        // eslint-disable-next-line no-console
29218        console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page.");
29219    }
29220    var dataLayerEnabled;
29221    var dataLayer;
29222    var dataLayerName;
29223
29224    var NS = "cmp";
29225    var IS = "tabs";
29226
29227    var keyCodes = {
29228        END: 35,
29229        HOME: 36,
29230        ARROW_LEFT: 37,
29231        ARROW_UP: 38,
29232        ARROW_RIGHT: 39,
29233        ARROW_DOWN: 40
29234    };
29235
29236    var selectors = {
29237        self: "[data-" + NS + '-is="' + IS + '"]',
29238        active: {
29239            tab: "cmp-tabs__tab--active",
29240            tabpanel: "cmp-tabs__tabpanel--active"
29241        }
29242    };
29243
29244    /**
29245     * Tabs Configuration
29246     *
29247     * @typedef {Object} TabsConfig Represents a Tabs configuration
29248     * @property {HTMLElement} element The HTMLElement representing the Tabs
29249     * @property {Object} options The Tabs options
29250     */
29251
29252    /**
29253     * Tabs
29254     *
29255     * @class Tabs
29256     * @classdesc An interactive Tabs component for navigating a list of tabs
29257     * @param {TabsConfig} config The Tabs configuration
29258     */
29259    function Tabs(config) {
29260        var that = this;
29261
29262        if (config && config.element) {
29263            init(config);
29264        }
29265
29266        /**
29267         * Initializes the Tabs
29268         *
29269         * @private
29270         * @param {TabsConfig} config The Tabs configuration
29271         */
29272        function init(config) {
29273            that._config = config;
29274
29275            // prevents multiple initialization
29276            config.element.removeAttribute("data-" + NS + "-is");
29277
29278            cacheElements(config.element);
29279            that._active = getActiveIndex(that._elements["tab"]);
29280
29281            if (that._elements.tabpanel) {
29282                refreshActive();
29283                bindEvents();
29284                scrollToDeepLinkIdInTabs();
29285            }
29286
29287            if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
29288                /*
29289                 * Editor message handling:
29290                 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
29291                 * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
29292                 * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
29293                 */
29294                CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
29295                CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) {
29296                    if (message.data && message.data.type === "cmp-tabs" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) {
29297                        if (message.data.operation === "navigate") {
29298                            navigate(message.data.index);
29299                        }
29300                    }
29301                });
29302            }
29303        }
29304
29305        /**
29306         * Displays the panel containing the element that corresponds to the deep link in the URI fragment
29307         * and scrolls the browser to this element.
29308         */
29309        function scrollToDeepLinkIdInTabs() {
29310            if (containerUtils) {
29311                var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "tab", "tabpanel");
29312                if (deepLinkItemIdx > -1) {
29313                    var deepLinkItem = that._elements["tab"][deepLinkItemIdx];
29314                    if (deepLinkItem && that._elements["tab"][that._active].id !== deepLinkItem.id) {
29315                        navigateAndFocusTab(deepLinkItemIdx, true);
29316                    }
29317                    var hashId = window.location.hash.substring(1);
29318                    if (hashId) {
29319                        var hashItem = document.querySelector("[id='" + hashId + "']");
29320                        if (hashItem) {
29321                            hashItem.scrollIntoView();
29322                        }
29323                    }
29324                }
29325            }
29326        }
29327
29328        /**
29329         * Returns the index of the active tab, if no tab is active returns 0
29330         *
29331         * @param {Array} tabs Tab elements
29332         * @returns {Number} Index of the active tab, 0 if none is active
29333         */
29334        function getActiveIndex(tabs) {
29335            if (tabs) {
29336                for (var i = 0; i < tabs.length; i++) {
29337                    if (tabs[i].classList.contains(selectors.active.tab)) {
29338                        return i;
29339                    }
29340                }
29341            }
29342            return 0;
29343        }
29344
29345        /**
29346         * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API
29347         *
29348         * @private
29349         * @param {HTMLElement} wrapper The Tabs wrapper element
29350         */
29351        function cacheElements(wrapper) {
29352            that._elements = {};
29353            that._elements.self = wrapper;
29354            var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]");
29355
29356            for (var i = 0; i < hooks.length; i++) {
29357                var hook = hooks[i];
29358                if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own tab elements
29359                    var capitalized = IS;
29360                    capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
29361                    var key = hook.dataset[NS + "Hook" + capitalized];
29362                    if (that._elements[key]) {
29363                        if (!Array.isArray(that._elements[key])) {
29364                            var tmp = that._elements[key];
29365                            that._elements[key] = [tmp];
29366                        }
29367                        that._elements[key].push(hook);
29368                    } else {
29369                        that._elements[key] = hook;
29370                    }
29371                }
29372            }
29373        }
29374
29375        /**
29376         * Binds Tabs event handling
29377         *
29378         * @private
29379         */
29380        function bindEvents() {
29381            window.addEventListener("hashchange", scrollToDeepLinkIdInTabs, false);
29382            var tabs = that._elements["tab"];
29383            if (tabs) {
29384                for (var i = 0; i < tabs.length; i++) {
29385                    (function(index) {
29386                        tabs[i].addEventListener("click", function(event) {
29387                            navigateAndFocusTab(index);
29388                        });
29389                        tabs[i].addEventListener("keydown", function(event) {
29390                            onKeyDown(event);
29391                        });
29392                    })(i);
29393                }
29394            }
29395        }
29396
29397        /**
29398         * Handles tab keydown events
29399         *
29400         * @private
29401         * @param {Object} event The keydown event
29402         */
29403        function onKeyDown(event) {
29404            var index = that._active;
29405            var lastIndex = that._elements["tab"].length - 1;
29406
29407            switch (event.keyCode) {
29408                case keyCodes.ARROW_LEFT:
29409                case keyCodes.ARROW_UP:
29410                    event.preventDefault();
29411                    if (index > 0) {
29412                        navigateAndFocusTab(index - 1);
29413                    }
29414                    break;
29415                case keyCodes.ARROW_RIGHT:
29416                case keyCodes.ARROW_DOWN:
29417                    event.preventDefault();
29418                    if (index < lastIndex) {
29419                        navigateAndFocusTab(index + 1);
29420                    }
29421                    break;
29422                case keyCodes.HOME:
29423                    event.preventDefault();
29424                    navigateAndFocusTab(0);
29425                    break;
29426                case keyCodes.END:
29427                    event.preventDefault();
29428                    navigateAndFocusTab(lastIndex);
29429                    break;
29430                default:
29431                    return;
29432            }
29433        }
29434
29435        /**
29436         * Refreshes the tab markup based on the current {@code Tabs#_active} index
29437         *
29438         * @private
29439         */
29440        function refreshActive() {
29441            var tabpanels = that._elements["tabpanel"];
29442            var tabs = that._elements["tab"];
29443
29444            if (tabpanels) {
29445                if (Array.isArray(tabpanels)) {
29446                    for (var i = 0; i < tabpanels.length; i++) {
29447                        if (i === parseInt(that._active)) {
29448                            tabpanels[i].classList.add(selectors.active.tabpanel);
29449                            tabpanels[i].removeAttribute("aria-hidden");
29450                            tabs[i].classList.add(selectors.active.tab);
29451                            tabs[i].setAttribute("aria-selected", true);
29452                            tabs[i].setAttribute("tabindex", "0");
29453                        } else {
29454                            tabpanels[i].classList.remove(selectors.active.tabpanel);
29455                            tabpanels[i].setAttribute("aria-hidden", true);
29456                            tabs[i].classList.remove(selectors.active.tab);
29457                            tabs[i].setAttribute("aria-selected", false);
29458                            tabs[i].setAttribute("tabindex", "-1");
29459                        }
29460                    }
29461                } else {
29462                    // only one tab
29463                    tabpanels.classList.add(selectors.active.tabpanel);
29464                    tabs.classList.add(selectors.active.tab);
29465                }
29466            }
29467        }
29468
29469        /**
29470         * Focuses the element and prevents scrolling the element into view
29471         *
29472         * @param {HTMLElement} element Element to focus
29473         */
29474        function focusWithoutScroll(element) {
29475            var x = window.scrollX || window.pageXOffset;
29476            var y = window.scrollY || window.pageYOffset;
29477            element.focus();
29478            window.scrollTo(x, y);
29479        }
29480
29481        /**
29482         * Navigates to the tab at the provided index
29483         *
29484         * @private
29485         * @param {Number} index The index of the tab to navigate to
29486         */
29487        function navigate(index) {
29488            that._active = index;
29489            refreshActive();
29490        }
29491
29492        /**
29493         * Navigates to the item at the provided index and ensures the active tab gains focus
29494         *
29495         * @private
29496         * @param {Number} index The index of the item to navigate to
29497         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
29498         */
29499        function navigateAndFocusTab(index, keepHash) {
29500            var exActive = that._active;
29501            if (!keepHash && containerUtils) {
29502                containerUtils.updateUrlHash(that, "tab", index);
29503            }
29504            navigate(index);
29505            focusWithoutScroll(that._elements["tab"][index]);
29506
29507            if (dataLayerEnabled) {
29508
29509                var activeItem = getDataLayerId(that._elements.tabpanel[index]);
29510                var exActiveItem = getDataLayerId(that._elements.tabpanel[exActive]);
29511
29512                dataLayer.push({
29513                    event: "cmp:show",
29514                    eventInfo: {
29515                        path: "component." + activeItem
29516                    }
29517                });
29518
29519                dataLayer.push({
29520                    event: "cmp:hide",
29521                    eventInfo: {
29522                        path: "component." + exActiveItem
29523                    }
29524                });
29525
29526                var tabsId = that._elements.self.id;
29527                var uploadPayload = { component: {} };
29528                uploadPayload.component[tabsId] = { shownItems: [activeItem] };
29529
29530                var removePayload = { component: {} };
29531                removePayload.component[tabsId] = { shownItems: undefined };
29532
29533                dataLayer.push(removePayload);
29534                dataLayer.push(uploadPayload);
29535            }
29536        }
29537    }
29538
29539    /**
29540     * Reads options data from the Tabs wrapper element, defined via {@code data-cmp-*} data attributes
29541     *
29542     * @private
29543     * @param {HTMLElement} element The Tabs element to read options data from
29544     * @returns {Object} The options read from the component data attributes
29545     */
29546    function readData(element) {
29547        var data = element.dataset;
29548        var options = [];
29549        var capitalized = IS;
29550        capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
29551        var reserved = ["is", "hook" + capitalized];
29552
29553        for (var key in data) {
29554            if (Object.prototype.hasOwnProperty.call(data, key)) {
29555                var value = data[key];
29556
29557                if (key.indexOf(NS) === 0) {
29558                    key = key.slice(NS.length);
29559                    key = key.charAt(0).toLowerCase() + key.substring(1);
29560
29561                    if (reserved.indexOf(key) === -1) {
29562                        options[key] = value;
29563                    }
29564                }
29565            }
29566        }
29567
29568        return options;
29569    }
29570
29571    /**
29572     * Parses the dataLayer string and returns the ID
29573     *
29574     * @private
29575     * @param {HTMLElement} item the accordion item
29576     * @returns {String} dataLayerId or undefined
29577     */
29578    function getDataLayerId(item) {
29579        if (item) {
29580            if (item.dataset.cmpDataLayer) {
29581                return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0];
29582            } else {
29583                return item.id;
29584            }
29585        }
29586        return null;
29587    }
29588
29589    /**
29590     * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary.
29591     *
29592     * @private
29593     */
29594    function onDocumentReady() {
29595        dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled");
29596        if (dataLayerEnabled) {
29597            dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer";
29598            dataLayer = window[dataLayerName] = window[dataLayerName] || [];
29599        }
29600
29601        var elements = document.querySelectorAll(selectors.self);
29602        for (var i = 0; i < elements.length; i++) {
29603            new Tabs({ element: elements[i], options: readData(elements[i]) });
29604        }
29605
29606        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
29607        var body = document.querySelector("body");
29608        var observer = new MutationObserver(function(mutations) {
29609            mutations.forEach(function(mutation) {
29610                // needed for IE
29611                var nodesArray = [].slice.call(mutation.addedNodes);
29612                if (nodesArray.length > 0) {
29613                    nodesArray.forEach(function(addedNode) {
29614                        if (addedNode.querySelectorAll) {
29615                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
29616                            elementsArray.forEach(function(element) {
29617                                new Tabs({ element: element, options: readData(element) });
29618                            });
29619                        }
29620                    });
29621                }
29622            });
29623        });
29624
29625        observer.observe(body, {
29626            subtree: true,
29627            childList: true,
29628            characterData: true
29629        });
29630    }
29631
29632    if (document.readyState !== "loading") {
29633        onDocumentReady();
29634    } else {
29635        document.addEventListener("DOMContentLoaded", onDocumentReady);
29636    }
29637
29638    if (containerUtils) {
29639        window.addEventListener("load", containerUtils.scrollToAnchor, false);
29640    }
29641
29642}());
29643

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.