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={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},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: '…', 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"> </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:"«",rightArrow:"»"},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,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").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")+'"> </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")+'"> </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> </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||"")||" ")+"</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: '…', 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===' ') { 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===' ') { 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, '&') 8411 .replace(/</g, '<') 8412 .replace(/>/g, '>') 8413 .replace(/"/g, '"'); 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, '&') 8426 .replace(/</g, '<') 8427 .replace(/>/g, '>') 8428 .replace(/<(mark|em)>/gi, '<$1>') 8429 .replace(/<\/(mark|em)>/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}">& 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(' '); 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°</span></span>'); 27066 } else if (index === ticks.length - 1) { 27067 $(tickContainer).append('<span class="large-tick"><span class="num-deg">104°</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°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°</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°</span></span></div>'; 27762 content += '<div class="tick-result"><span class="pool-temp-value">'+(!isNaN(desiredTemp) ? desiredTemp : waterTempValue)+'</span><span>°</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.