vendor: 39,680 bytes, lines 1-6
1/*! 2 * Bootstrap v3.4.1 (https://getbootstrap.com/) 3 * Copyright 2011-2019 Twitter, Inc. 4 * Licensed under the MIT license 5 */ 6if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3<e[0])throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(),function(n){"use strict";n.fn.emulateTransitionEnd=function(t){var e=!1,i=this;n(this).one("bsTransitionEnd",function(){e=!0});return setTimeout(function(){e||n(i).trigger(n.support.transition.end)},t),this},n(function(){n.support.transition=function o(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(t.style[i]!==undefined)return{end:e[i]};return!1}(),n.support.transition&&(n.event.special.bsTransitionEnd={bindType:n.support.transition.end,delegateType:n.support.transition.end,handle:function(t){if(n(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}})})}(jQuery),function(s){"use strict";var e='[data-dismiss="alert"]',a=function(t){s(t).on("click",e,this.close)};a.VERSION="3.4.1",a.TRANSITION_DURATION=150,a.prototype.close=function(t){var e=s(this),i=e.attr("data-target");i||(i=(i=e.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),i="#"===i?[]:i;var o=s(document).find(i);function n(){o.detach().trigger("closed.bs.alert").remove()}t&&t.preventDefault(),o.length||(o=e.closest(".alert")),o.trigger(t=s.Event("close.bs.alert")),t.isDefaultPrevented()||(o.removeClass("in"),s.support.transition&&o.hasClass("fade")?o.one("bsTransitionEnd",n).emulateTransitionEnd(a.TRANSITION_DURATION):n())};var t=s.fn.alert;s.fn.alert=function o(i){return this.each(function(){var t=s(this),e=t.data("bs.alert");e||t.data("bs.alert",e=new a(this)),"string"==typeof i&&e[i].call(t)})},s.fn.alert.Constructor=a,s.fn.alert.noConflict=function(){return s.fn.alert=t,this},s(document).on("click.bs.alert.data-api",e,a.prototype.close)}(jQuery),function(s){"use strict";var n=function(t,e){this.$element=s(t),this.options=s.extend({},n.DEFAULTS,e),this.isLoading=!1};function i(o){return this.each(function(){var t=s(this),e=t.data("bs.button"),i="object"==typeof o&&o;e||t.data("bs.button",e=new n(this,i)),"toggle"==o?e.toggle():o&&e.setState(o)})}n.VERSION="3.4.1",n.DEFAULTS={loadingText:"loading..."},n.prototype.setState=function(t){var e="disabled",i=this.$element,o=i.is("input")?"val":"html",n=i.data();t+="Text",null==n.resetText&&i.data("resetText",i[o]()),setTimeout(s.proxy(function(){i[o](null==n[t]?this.options[t]:n[t]),"loadingText"==t?(this.isLoading=!0,i.addClass(e).attr(e,e).prop(e,!0)):this.isLoading&&(this.isLoading=!1,i.removeClass(e).removeAttr(e).prop(e,!1))},this),0)},n.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var i=this.$element.find("input");"radio"==i.prop("type")?(i.prop("checked")&&(t=!1),e.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==i.prop("type")&&(i.prop("checked")!==this.$element.hasClass("active")&&(t=!1),this.$element.toggleClass("active")),i.prop("checked",this.$element.hasClass("active")),t&&i.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var t=s.fn.button;s.fn.button=i,s.fn.button.Constructor=n,s.fn.button.noConflict=function(){return s.fn.button=t,this},s(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(t){var e=s(t.target).closest(".btn");i.call(e,"toggle"),s(t.target).is('input[type="radio"], input[type="checkbox"]')||(t.preventDefault(),e.is("input,button")?e.trigger("focus"):e.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(t){s(t.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(t.type))})}(jQuery),function(p){"use strict";var c=function(t,e){this.$element=p(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=e,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",p.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",p.proxy(this.pause,this)).on("mouseleave.bs.carousel",p.proxy(this.cycle,this))};function r(n){return this.each(function(){var t=p(this),e=t.data("bs.carousel"),i=p.extend({},c.DEFAULTS,t.data(),"object"==typeof n&&n),o="string"==typeof n?n:i.slide;e||t.data("bs.carousel",e=new c(this,i)),"number"==typeof n?e.to(n):o?e[o]():i.interval&&e.pause().cycle()})}c.VERSION="3.4.1",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(t){if(!/input|textarea/i.test(t.target.tagName)){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()}},c.prototype.cycle=function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(p.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},c.prototype.getItemForDirection=function(t,e){var i=this.getItemIndex(e);if(("prev"==t&&0===i||"next"==t&&i==this.$items.length-1)&&!this.options.wrap)return e;var o=(i+("prev"==t?-1:1))%this.$items.length;return this.$items.eq(o)},c.prototype.to=function(t){var e=this,i=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(t>this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(i<t?"next":"prev",this.$items.eq(t))},c.prototype.pause=function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&p.support.transition&&(this.$element.trigger(p.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(t,e){var i=this.$element.find(".item.active"),o=e||this.getItemForDirection(t,i),n=this.interval,s="next"==t?"left":"right",a=this;if(o.hasClass("active"))return this.sliding=!1;var r=o[0],l=p.Event("slide.bs.carousel",{relatedTarget:r,direction:s});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,n&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=p(this.$indicators.children()[this.getItemIndex(o)]);h&&h.addClass("active")}var d=p.Event("slid.bs.carousel",{relatedTarget:r,direction:s});return p.support.transition&&this.$element.hasClass("slide")?(o.addClass(t),"object"==typeof o&&o.length&&o[0].offsetWidth,i.addClass(s),o.addClass(s),i.one("bsTransitionEnd",function(){o.removeClass([t,s].join(" ")).addClass("active"),i.removeClass(["active",s].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger(d)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(i.removeClass("active"),o.addClass("active"),this.sliding=!1,this.$element.trigger(d)),n&&this.cycle(),this}};var t=p.fn.carousel;p.fn.carousel=r,p.fn.carousel.Constructor=c,p.fn.carousel.noConflict=function(){return p.fn.carousel=t,this};var e=function(t){var e=p(this),i=e.attr("href");i&&(i=i.replace(/.*(?=#[^\s]+$)/,""));var o=e.attr("data-target")||i,n=p(document).find(o);if(n.hasClass("carousel")){var s=p.extend({},n.data(),e.data()),a=e.attr("data-slide-to");a&&(s.interval=!1),r.call(n,s),a&&n.data("bs.carousel").to(a),t.preventDefault()}};p(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),p(window).on("load",function(){p('[data-ride="carousel"]').each(function(){var t=p(this);r.call(t,t.data())})})}(jQuery),function(a){"use strict";var r=function(t,e){this.$element=a(t),this.options=a.extend({},r.DEFAULTS,e),this.$trigger=a('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};function n(t){var e,i=t.attr("data-target")||(e=t.attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"");return a(document).find(i)}function l(o){return this.each(function(){var t=a(this),e=t.data("bs.collapse"),i=a.extend({},r.DEFAULTS,t.data(),"object"==typeof o&&o);!e&&i.toggle&&/show|hide/.test(o)&&(i.toggle=!1),e||t.data("bs.collapse",e=new r(this,i)),"string"==typeof o&&e[o]()})}r.VERSION="3.4.1",r.TRANSITION_DURATION=350,r.DEFAULTS={toggle:!0},r.prototype.dimension=function(){return this.$element.hasClass("width")?"width":"height"},r.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var t,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(t=e.data("bs.collapse"))&&t.transitioning)){var i=a.Event("show.bs.collapse");if(this.$element.trigger(i),!i.isDefaultPrevented()){e&&e.length&&(l.call(e,"hide"),t||e.data("bs.collapse",null));var o=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[o](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var n=function(){this.$element.removeClass("collapsing").addClass("collapse in")[o](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return n.call(this);var s=a.camelCase(["scroll",o].join("-"));this.$element.one("bsTransitionEnd",a.proxy(n,this)).emulateTransitionEnd(r.TRANSITION_DURATION)[o](this.$element[0][s])}}}},r.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var t=a.Event("hide.bs.collapse");if(this.$element.trigger(t),!t.isDefaultPrevented()){var e=this.dimension();this.$element[e](this.$element[e]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var i=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!a.support.transition)return i.call(this);this.$element[e](0).one("bsTransitionEnd",a.proxy(i,this)).emulateTransitionEnd(r.TRANSITION_DURATION)}}},r.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},r.prototype.getParent=function(){return a(document).find(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(t,e){var i=a(e);this.addAriaAndCollapsedClass(n(i),i)},this)).end()},r.prototype.addAriaAndCollapsedClass=function(t,e){var i=t.hasClass("in");t.attr("aria-expanded",i),e.toggleClass("collapsed",!i).attr("aria-expanded",i)};var t=a.fn.collapse;a.fn.collapse=l,a.fn.collapse.Constructor=r,a.fn.collapse.noConflict=function(){return a.fn.collapse=t,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(t){var e=a(this);e.attr("data-target")||t.preventDefault();var i=n(e),o=i.data("bs.collapse")?"toggle":e.data();l.call(i,o)})}(jQuery),function(a){"use strict";var r='[data-toggle="dropdown"]',o=function(t){a(t).on("click.bs.dropdown",this.toggle)};function l(t){var e=t.attr("data-target");e||(e=(e=t.attr("href"))&&/#[A-Za-z]/.test(e)&&e.replace(/.*(?=#[^\s]*$)/,""));var i="#"!==e?a(document).find(e):null;return i&&i.length?i:t.parent()}function s(o){o&&3===o.which||(a(".dropdown-backdrop").remove(),a(r).each(function(){var t=a(this),e=l(t),i={relatedTarget:this};e.hasClass("open")&&(o&&"click"==o.type&&/input|textarea/i.test(o.target.tagName)&&a.contains(e[0],o.target)||(e.trigger(o=a.Event("hide.bs.dropdown",i)),o.isDefaultPrevented()||(t.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",i)))))}))}o.VERSION="3.4.1",o.prototype.toggle=function(t){var e=a(this);if(!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(s(),!o){"ontouchstart"in document.documentElement&&!i.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",s);var n={relatedTarget:this};if(i.trigger(t=a.Event("show.bs.dropdown",n)),t.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),i.toggleClass("open").trigger(a.Event("shown.bs.dropdown",n))}return!1}},o.prototype.keydown=function(t){if(/(38|40|27|32)/.test(t.which)&&!/input|textarea/i.test(t.target.tagName)){var e=a(this);if(t.preventDefault(),t.stopPropagation(),!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(!o&&27!=t.which||o&&27==t.which)return 27==t.which&&i.find(r).trigger("focus"),e.trigger("click");var n=i.find(".dropdown-menu li:not(.disabled):visible a");if(n.length){var s=n.index(t.target);38==t.which&&0<s&&s--,40==t.which&&s<n.length-1&&s++,~s||(s=0),n.eq(s).trigger("focus")}}}};var t=a.fn.dropdown;a.fn.dropdown=function e(i){return this.each(function(){var t=a(this),e=t.data("bs.dropdown");e||t.data("bs.dropdown",e=new o(this)),"string"==typeof i&&e[i].call(t)})},a.fn.dropdown.Constructor=o,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=t,this},a(document).on("click.bs.dropdown.data-api",s).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",r,o.prototype.toggle).on("keydown.bs.dropdown.data-api",r,o.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",o.prototype.keydown)}(jQuery),function(a){"use strict";var s=function(t,e){this.options=e,this.$body=a(document.body),this.$element=a(t),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.fixedContent=".navbar-fixed-top, .navbar-fixed-bottom",this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};function r(o,n){return this.each(function(){var t=a(this),e=t.data("bs.modal"),i=a.extend({},s.DEFAULTS,t.data(),"object"==typeof o&&o);e||t.data("bs.modal",e=new s(this,i)),"string"==typeof o?e[o](n):i.show&&e.show(n)})}s.VERSION="3.4.1",s.TRANSITION_DURATION=300,s.BACKDROP_TRANSITION_DURATION=150,s.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},s.prototype.toggle=function(t){return this.isShown?this.hide():this.show(t)},s.prototype.show=function(i){var o=this,t=a.Event("show.bs.modal",{relatedTarget:i});this.$element.trigger(t),this.isShown||t.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){o.$element.one("mouseup.dismiss.bs.modal",function(t){a(t.target).is(o.$element)&&(o.ignoreBackdropClick=!0)})}),this.backdrop(function(){var t=a.support.transition&&o.$element.hasClass("fade");o.$element.parent().length||o.$element.appendTo(o.$body),o.$element.show().scrollTop(0),o.adjustDialog(),t&&o.$element[0].offsetWidth,o.$element.addClass("in"),o.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:i});t?o.$dialog.one("bsTransitionEnd",function(){o.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(s.TRANSITION_DURATION):o.$element.trigger("focus").trigger(e)}))},s.prototype.hide=function(t){t&&t.preventDefault(),t=a.Event("hide.bs.modal"),this.$element.trigger(t),this.isShown&&!t.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(s.TRANSITION_DURATION):this.hideModal())},s.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(t){document===t.target||this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")},this))},s.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(t){27==t.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},s.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},s.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$body.removeClass("modal-open"),t.resetAdjustments(),t.resetScrollbar(),t.$element.trigger("hidden.bs.modal")})},s.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},s.prototype.backdrop=function(t){var e=this,i=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var o=a.support.transition&&i;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+i).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(t){this.ignoreBackdropClick?this.ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide())},this)),o&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!t)return;o?this.$backdrop.one("bsTransitionEnd",t).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):t()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var n=function(){e.removeBackdrop(),t&&t()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",n).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):n()}else t&&t()},s.prototype.handleUpdate=function(){this.adjustDialog()},s.prototype.adjustDialog=function(){var t=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<t,this.scrollbarWidth=this.measureScrollbar()},s.prototype.setScrollbar=function(){var t=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"";var n=this.scrollbarWidth;this.bodyIsOverflowing&&(this.$body.css("padding-right",t+n),a(this.fixedContent).each(function(t,e){var i=e.style.paddingRight,o=a(e).css("padding-right");a(e).data("padding-right",i).css("padding-right",parseFloat(o)+n+"px")}))},s.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad),a(this.fixedContent).each(function(t,e){var i=a(e).data("padding-right");a(e).removeData("padding-right"),e.style.paddingRight=i||""})},s.prototype.measureScrollbar=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",this.$body.append(t);var e=t.offsetWidth-t.clientWidth;return this.$body[0].removeChild(t),e};var t=a.fn.modal;a.fn.modal=r,a.fn.modal.Constructor=s,a.fn.modal.noConflict=function(){return a.fn.modal=t,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(t){var e=a(this),i=e.attr("href"),o=e.attr("data-target")||i&&i.replace(/.*(?=#[^\s]+$)/,""),n=a(document).find(o),s=n.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(i)&&i},n.data(),e.data());e.is("a")&&t.preventDefault(),n.one("show.bs.modal",function(t){t.isDefaultPrevented()||n.one("hidden.bs.modal",function(){e.is(":visible")&&e.trigger("focus")})}),r.call(n,s,this)})}(jQuery),function(g){"use strict";var o=["sanitize","whiteList","sanitizeFn"],a=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],t={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},r=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,l=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function u(t,e){var i=t.nodeName.toLowerCase();if(-1!==g.inArray(i,e))return-1===g.inArray(i,a)||Boolean(t.nodeValue.match(r)||t.nodeValue.match(l));for(var o=g(e).filter(function(t,e){return e instanceof RegExp}),n=0,s=o.length;n<s;n++)if(i.match(o[n]))return!0;return!1}function n(t,e,i){if(0===t.length)return t;if(i&&"function"==typeof i)return i(t);if(!document.implementation||!document.implementation.createHTMLDocument)return t;var o=document.implementation.createHTMLDocument("sanitization");o.body.innerHTML=t;for(var n=g.map(e,function(t,e){return e}),s=g(o.body).find("*"),a=0,r=s.length;a<r;a++){var l=s[a],h=l.nodeName.toLowerCase();if(-1!==g.inArray(h,n))for(var d=g.map(l.attributes,function(t){return t}),p=[].concat(e["*"]||[],e[h]||[]),c=0,f=d.length;c<f;c++)u(d[c],p)||l.removeAttribute(d[c].nodeName);else l.parentNode.removeChild(l)}return o.body.innerHTML}var m=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};m.VERSION="3.4.1",m.TRANSITION_DURATION=150,m.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0},sanitize:!0,sanitizeFn:null,whiteList:t},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){var e=this.$element.data();for(var i in e)e.hasOwnProperty(i)&&-1!==g.inArray(i,o)&&delete e[i];return(t=g.extend({},this.getDefaults(),e,t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t.sanitize&&(t.template=n(t.template,t.whiteList,t.sanitizeFn)),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-d<c.top?"bottom":"right"==s&&l.right+h>c.width?"left":"left"==s&&l.left-h<c.left?"right":s,o.removeClass(p).addClass(s)}var f=this.getCalculatedOffset(s,l,h,d);this.applyPlacement(f,s);var u=function(){var t=i.hoverState;i.$element.trigger("shown.bs."+i.type),i.hoverState=null,"out"==t&&i.leave(i)};g.support.transition&&this.$tip.hasClass("fade")?o.one("bsTransitionEnd",u).emulateTransitionEnd(m.TRANSITION_DURATION):u()}},m.prototype.applyPlacement=function(t,e){var i=this.tip(),o=i[0].offsetWidth,n=i[0].offsetHeight,s=parseInt(i.css("margin-top"),10),a=parseInt(i.css("margin-left"),10);isNaN(s)&&(s=0),isNaN(a)&&(a=0),t.top+=s,t.left+=a,g.offset.setOffset(i[0],g.extend({using:function(t){i.css({top:Math.round(t.top),left:Math.round(t.left)})}},t),0),i.addClass("in");var r=i[0].offsetWidth,l=i[0].offsetHeight;"top"==e&&l!=n&&(t.top=t.top+n-l);var h=this.getViewportAdjustedDelta(e,t,r,l);h.left?t.left+=h.left:t.top+=h.top;var d=/top|bottom/.test(e),p=d?2*h.left-o+r:2*h.top-n+l,c=d?"offsetWidth":"offsetHeight";i.offset(t),this.replaceArrow(p,i[0][c],d)},m.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?"left":"top",50*(1-t/e)+"%").css(i?"top":"left","")},m.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();this.options.html?(this.options.sanitize&&(e=n(e,this.options.whiteList,this.options.sanitizeFn)),t.find(".tooltip-inner").html(e)):t.find(".tooltip-inner").text(e),t.removeClass("fade in top bottom left right")},m.prototype.hide=function(t){var e=this,i=g(this.$tip),o=g.Event("hide.bs."+this.type);function n(){"in"!=e.hoverState&&i.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),t&&t()}if(this.$element.trigger(o),!o.isDefaultPrevented())return i.removeClass("in"),g.support.transition&&i.hasClass("fade")?i.one("bsTransitionEnd",n).emulateTransitionEnd(m.TRANSITION_DURATION):n(),this.hoverState=null,this},m.prototype.fixTitle=function(){var t=this.$element;(t.attr("title")||"string"!=typeof t.attr("data-original-title"))&&t.attr("data-original-title",t.attr("title")||"").attr("title","")},m.prototype.hasContent=function(){return this.getTitle()},m.prototype.getPosition=function(t){var e=(t=t||this.$element)[0],i="BODY"==e.tagName,o=e.getBoundingClientRect();null==o.width&&(o=g.extend({},o,{width:o.right-o.left,height:o.bottom-o.top}));var n=window.SVGElement&&e instanceof window.SVGElement,s=i?{top:0,left:0}:n?null:t.offset(),a={scroll:i?document.documentElement.scrollTop||document.body.scrollTop:t.scrollTop()},r=i?{width:g(window).width(),height:g(window).height()}:null;return g.extend({},o,a,r,s)},m.prototype.getCalculatedOffset=function(t,e,i,o){return"bottom"==t?{top:e.top+e.height,left:e.left+e.width/2-i/2}:"top"==t?{top:e.top-o,left:e.left+e.width/2-i/2}:"left"==t?{top:e.top+e.height/2-o/2,left:e.left-i}:{top:e.top+e.height/2-o/2,left:e.left+e.width}},m.prototype.getViewportAdjustedDelta=function(t,e,i,o){var n={top:0,left:0};if(!this.$viewport)return n;var s=this.options.viewport&&this.options.viewport.padding||0,a=this.getPosition(this.$viewport);if(/right|left/.test(t)){var r=e.top-s-a.scroll,l=e.top+s-a.scroll+o;r<a.top?n.top=a.top-r:l>a.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;h<a.left?n.left=a.left-h:d>a.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})},m.prototype.sanitizeHtml=function(t){return n(t,this.options.whiteList,this.options.sanitizeFn)};var e=g.fn.tooltip;g.fn.tooltip=function i(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=e,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.1",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();if(this.options.html){var o=typeof i;this.options.sanitize&&(e=this.sanitizeHtml(e),"string"===o&&(i=this.sanitizeHtml(i))),t.find(".popover-title").html(e),t.find(".popover-content").children().detach().end()["string"===o?"html":"append"](i)}else t.find(".popover-title").text(e),t.find(".popover-content").children().detach().end().text(i);t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.1",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e<n[0])return this.activeTarget=null,this.clear();for(t=n.length;t--;)a!=s[t]&&e>=n[t]&&(n[t+1]===undefined||e<n[t+1])&&this.activate(s[t])},n.prototype.activate=function(t){this.activeTarget=t,this.clear();var e=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',i=s(e).parents("li").addClass("active");i.parent(".dropdown-menu").length&&(i=i.closest("li.dropdown").addClass("active")),i.trigger("activate.bs.scrollspy")},n.prototype.clear=function(){s(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var t=s.fn.scrollspy;s.fn.scrollspy=e,s.fn.scrollspy.Constructor=n,s.fn.scrollspy.noConflict=function(){return s.fn.scrollspy=t,this},s(window).on("load.bs.scrollspy.data-api",function(){s('[data-spy="scroll"]').each(function(){var t=s(this);e.call(t,t.data())})})}(jQuery),function(r){"use strict";var a=function(t){this.element=r(t)};function e(i){return this.each(function(){var t=r(this),e=t.data("bs.tab");e||t.data("bs.tab",e=new a(this)),"string"==typeof i&&e[i]()})}a.VERSION="3.4.1",a.TRANSITION_DURATION=150,a.prototype.show=function(){var t=this.element,e=t.closest("ul:not(.dropdown-menu)"),i=t.data("target");if(i||(i=(i=t.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),!t.parent("li").hasClass("active")){var o=e.find(".active:last a"),n=r.Event("hide.bs.tab",{relatedTarget:t[0]}),s=r.Event("show.bs.tab",{relatedTarget:o[0]});if(o.trigger(n),t.trigger(s),!s.isDefaultPrevented()&&!n.isDefaultPrevented()){var a=r(document).find(i);this.activate(t.closest("li"),e),this.activate(a,a.parent(),function(){o.trigger({type:"hidden.bs.tab",relatedTarget:t[0]}),t.trigger({type:"shown.bs.tab",relatedTarget:o[0]})})}}},a.prototype.activate=function(t,e,i){var o=e.find("> .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.1",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n<i&&"top";if("bottom"==this.affixed)return null!=i?!(n+this.unpin<=s.top)&&"bottom":!(n+a<=t-o)&&"bottom";var r=null==this.affixed,l=r?n:s.top;return null!=i&&n<=i?"top":null!=o&&t-o<=l+(r?a:e)&&"bottom"},h.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(h.RESET).addClass("affix");var t=this.$target.scrollTop(),e=this.$element.offset();return this.pinnedOffset=e.top-t},h.prototype.checkPositionWithEventLoop=function(){setTimeout(l.proxy(this.checkPosition,this),1)},h.prototype.checkPosition=function(){if(this.$element.is(":visible")){var t=this.$element.height(),e=this.options.offset,i=e.top,o=e.bottom,n=Math.max(l(document).height(),l(document.body).height());"object"!=typeof e&&(o=i=e),"function"==typeof i&&(i=e.top(this.$element)),"function"==typeof o&&(o=e.bottom(this.$element));var s=this.getState(n,t,i,o);if(this.affixed!=s){null!=this.unpin&&this.$element.css("top","");var a="affix"+(s?"-"+s:""),r=l.Event(a+".bs.affix");if(this.$element.trigger(r),r.isDefaultPrevented())return;this.affixed=s,this.unpin="bottom"==s?this.getPinnedOffset():null,this.$element.removeClass(h.RESET).addClass(a).trigger(a.replace("affix","affixed")+".bs.affix")}"bottom"==s&&this.$element.offset({top:n-t-o})}};var t=l.fn.affix;l.fn.affix=i,l.fn.affix.Constructor=h,l.fn.affix.noConflict=function(){return l.fn.affix=t,this},l(window).on("load",function(){l('[data-spy="affix"]').each(function(){var t=l(this),e=t.data();e.offset=e.offset||{},null!=e.offsetBottom&&(e.offset.bottom=e.offsetBottom),null!=e.offsetTop&&(e.offset.top=e.offsetTop),i.call(t,e)})})}(jQuery);
vendor: 4,705 bytes, lines 6-18
6 7/* 8 Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 9*/ 10(function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 11if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("<div />"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 12u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),e<F&&(m=!1,c=q,null==p&&("left"!==r&&"right"!==r||a.insertAfter(h), 13h.detach()),b={position:"",width:"",top:""},a.css(b).removeClass(t).trigger("sticky_kit:unstick")),B&&(b=f.height(),u+q>b&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 14a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 15y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n<K;n++)d=this[n],J(b(d));return this}}).call(this); 16 17/*!@license Copyright 2013, Heinrich Goebl, License: MIT, see https://github.com/hgoebl/mobile-detect.js*/ 18!function(a,b){a(function(){"use strict";function a(a,b){return null!=a&&null!=b&&a.toLowerCase()===b.toLowerCase()}function c(a,b){var c,d,e=a.length;if(!e||!b)return!1;for(c=b.toLowerCase(),d=0;d<e;++d)if(c===a[d].toLowerCase())return!0;return!1}function d(a){for(var b in a)i.call(a,b)&&(a[b]=new RegExp(a[b],"i"))}function e(a){return(a||"").substr(0,500)}function f(a,b){this.ua=e(a),this._cache={},this.maxPhoneWidth=b||600}var g={};g.mobileDetectRules={phones:{iPhone:"\\biPhone\\b|\\biPod\\b",BlackBerry:"BlackBerry|\\bBB10\\b|rim[0-9]+|\\b(BBA100|BBB100|BBD100|BBE100|BBF100|STH100)\\b-[0-9]+",HTC:"HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\\bEVO\\b|T-Mobile G1|Z520m|Android [0-9.]+; Pixel",Nexus:"Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6",Dell:"Dell[;]? (Streak|Aero|Venue|Venue Pro|Flash|Smoke|Mini 3iX)|XCD28|XCD35|\\b001DL\\b|\\b101DL\\b|\\bGS01\\b",Motorola:"Motorola|DROIDX|DROID BIONIC|\\bDroid\\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\\bMoto E\\b|XT1068|XT1092|XT1052",Samsung:
vendor: 5,421 bytes, line 18
18"\\bSamsung\\b|SM-G950F|SM-G955F|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C|SM-A310F|GT-I9190|SM-J500FN|SM-G903F|SM-J330F
18",LG:"\\bLG\\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323|M257)|LM-G710",Sony:"SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533",Asus:"Asus.*Galaxy|PadFone.*Mobile",NokiaLumia:"Lumia [0-9]{3,4}",Micromax:"Micromax.*\\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\\b",Palm:"PalmSource|Palm",Vertu:"Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature",Pantech:"PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790",Fly:"IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250",Wiko:"KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLI
18M|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM",iMobile:"i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)",SimValley:"\\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\\b",Wolfgang:"AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q",Alcatel:"Alcatel",Nintendo:"Nintendo (3DS|Switch)",Amoi:"Amoi",INQ:"INQ",OnePlus:"ONEPLUS",GenericPhone:"Tapatalk|PDA;|SAGEM|\\bmmp\\b|pocket|\\bpsp\\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\\bwap\\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser"},tablets:{iPad:"iPad|iPad.*Mobile",NexusTablet:"Android.*Nexus[\\s]+(7|9|10)",GoogleTablet:"Android.*Pixel C",SamsungTablet:"SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-T116BU|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y?|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587|SM-P350|SM-P555M|SM-P355M|SM-T113NU|SM-T815Y|SM-T585|SM-T285|SM-T825|SM-W708|SM-T835|SM-T830|SM-T837V|SM-T720|SM-T510|SM-T387V",Kindle:"Kindle|Silk.*Accelerated|Android.*\\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)",SurfaceTablet:"Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)",HPTablet:"HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10",AsusTablet:"^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\\bK00F\\b|\\bK00C\\b|\\bK00E\\b|\\bK00L\\b|TX201LA|ME176C|ME102A|\\bM80TA\\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\\bME70C\\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z|\\bP027\\b|\\bP024\\b|\\bP00C\\b",BlackBerryTablet:"PlayBook|RIM Tablet",HTCtablet:"HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410",MotorolaTablet:"xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617",NookTablet:"Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2",AcerTablet:"Android.*; \\b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\\b|W3-810|\\bA3-A10\\b|\\bA3-A11\\b|\\bA3-A20\\b|\\bA3-A30",ToshibaTablet:"Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO",LGTablet:"\\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V4
1800|LG-VK810\\b",FujitsuTablet:"Android.*\\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\\b",PrestigioTablet:"PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002",LenovoTablet:"Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-850M|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)|TB-X103F|TB-X304X|TB-X304F|TB-X304L|TB-X505F|TB-X505L|TB-X505X|TB-X605F|TB-X605L|TB-8703F|TB-8703X|TB-8703N|TB-8704N|TB-8704F|TB-8704X|TB-8704V|TB-7304F|TB-7304I|TB-7304X|Tab2A7-10F|Tab2A7-20F|TB2-X30L|YT3-X50L|YT3-X50F|YT3-X50M|YT-X705F|YT-X703F|YT-X703L|YT-X705L|YT-X705X|TB2-X30F|TB2-X30L|TB2-X30M|A2107A-F|A2107A-H|TB3-730F|TB3-730M|TB3-730X|TB-7504F|TB-7504X",DellTablet:"Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7",YarvikTablet:"Android.*\\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\\b",MedionTablet:"Android.*\\bOYO\\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB",ArnovaTablet:"97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2",IntensoTablet:"INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004",IRUTablet:"M702pro",MegafonTablet:"MegaFon V9|\\bZTE V9\\b|Android.*\\bMT7A\\b",EbodaTablet:"E-Boda (Supreme|Impresspeed|Izzycomm|Essential)",AllViewTablet:"Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)",ArchosTablet:"\\b(101G9|80G9|A101IT)\\b|Qilive 97R|Archos5|\\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\\b",AinolTablet:"NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark",NokiaLumiaTablet:"Lumia 2520",SonyTablet:"Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP641|SGP612|SOT31|SGP771|SGP611|SGP612|SGP712",PhilipsTablet:"\\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\\b",CubeTablet:"Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT",CobyTablet:"MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010",MIDTablet:"M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10",MSITablet:"MSI \\b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\\b",SMiTTablet:"Android.*(\\bMID\\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)",RockChipTablet:"Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A",FlyTablet:"IQ310|Fly Vision",bqTablet:"Android.*(bq)?.*\\b(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris ([E|M]10|M8))\\b|Maxwell.*Lite|Maxwell.*Plus",HuaweiTablet:"MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim|M2-A01L|BAH-L09|BAH-W09|AGS-L09|CMR-AL19",NecTablet:"\\bN-06D|\\bN-08D",PantechTablet:"Pantech.*P4100",Bronch
18oTablet:"Broncho.*(N701|N708|N802|a710)",VersusTablet:"TOUCHPAD.*[78910]|\\bTOUCHTAB\\b",ZyncTablet:"z1000|Z99 2G|z930|z990|z909|Z919|z900",PositivoTablet:"TB07STA|TB10STA|TB07FTA|TB10FTA",NabiTablet:"Android.*\\bNabi",KoboTablet:"Kobo Touch|\\bK080\\b|\\bVox\\b Build|\\bArc\\b Build",DanewTablet:"DSlide.*\\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\\b",TexetTablet:"NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE",PlaystationTablet:"Playstation.*(Portable|Vita)",TrekstorTablet:"ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab",PyleAudioTablet:"\\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\\b",AdvanTablet:"Android.* \\b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\\b ",DanyTechTablet:"Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1",GalapadTablet:"Android.*\\bG1\\b(?!\\))
vendor: 9,224 bytes, line 18
18",MicromaxTablet:"Funbook|Micromax.*\\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\\b",KarbonnTablet:"Android.*\\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\\b",AllFineTablet:"Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide",PROSCANTablet:"\\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\\b",YONESTablet:"BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026",ChangJiaTablet:"TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503",GUTablet:"TX-A1301|TX-M9002|Q702|kf026",PointOfViewTablet:"TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10",OvermaxTablet:"OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)|Qualcore 1027",HCLTablet:"HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync",DPSTablet:"DPS Dream 9|DPS Dual 7",VistureTablet:"V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10",CrestaTablet:"CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989",MediatekTablet:"\\bMT8125|MT8389|MT8135|MT8377\\b",ConcordeTablet:"Concorde([ ]+)?Tab|ConCorde ReadMan",GoCleverTablet:"GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042",ModecomTablet:"FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003",VoninoTablet:"\\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\\bQ8\\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\\b",ECSTablet:"V07OT2|TM105A|S10OT1|TR10CS1",StorexTablet:"eZee[_']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab",VodafoneTablet:"SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497|VFD 1400",EssentielBTablet:"Smart[ ']?TAB[ ]+?[0-9]+|Family[ ']?TAB2",RossMoorTablet:"RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711",iMobileTablet:"i-mobile i-note",TolinoTablet:"tolino tab [0-9.]+|tolino shine",AudioSonicTablet:"\\bC-22Q|T7-QC|T-17B|T-17P\\b",AMPETablet:"Android.* A78 ",SkkTablet:"Android.* (SKYPAD|PHOENIX|CYCLOPS)",TecnoTablet:"TECNO P9|TECNO DP8D",JXDTablet:"Android.* \\b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\\b",iJoyTablet:"Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)",FX2Tablet:"FX2 PAD7|FX2 PAD10",XoroTablet:"KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151",ViewsonicTablet:"ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a",VerizonTablet:"QTAQZ3|QTAIR7|QTAQTZ3|QTASUN1|QTASUN2|QTAXIA1",OdysTablet:"LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\\bXELIO\\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10",CaptivaTablet:"CAPTIVA PAD",IconbitTablet:"NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S",TeclastTablet:"T98 4G|\\bP80\\b|\\bX90HD\\b|X98 Air|X98 Air 3G|\\bX89\\b|P80 3G|\\bX80h\\b|P98 Air|\\bX89HD\\b|P98 3G|\\bP90HD\\b|P89 3G|X98 3G|\\bP70h\\b|P79HD 3G|G18d 3G|\\bP79HD\\b|\\bP89s\\b|\\bA88\\b|\\bP10HD\\b|\\bP19HD\\b|G18 3G|\\bP78HD\\b|\\bA78\\b|\\bP75\\b|G17s 3G|G17h 3G|\\bP85t\\b|\\bP90\\b|\\bP11\\b|\\bP98t\\b|\\bP98HD\\b|\\bG18d\\b|\\bP85s\\b|\\bP11HD\\b|\\bP88s\\b|\\bA80HD\\b|\\bA80se\\b|\\bA10h\\b|\\bP89\\b|\\bP78s\\b|\\bG18\\b|\\bP85\\b|\\bA70h\\b|\\bA70\\b|\\bG17\\b|\\bP18\\b|\\bA80s\\b|\\bA11s\\b|\\bP88HD\\b|\\bA80h\\b|\\bP76s\\b|\\bP76h\\b|\\bP98\\b|\\bA10HD\\b|\\bP78\\b|\\bP88\\b|\\bA11\\b|\\bA10t\\b|\\bP76a\\b|\\bP76t\\b|\\bP76e\\b|\\bP85HD\\b|\\bP85a\\b|\\bP86\\b|\\bP75HD\\b|\\bP76v\\b|\\bA12\\b|\\bP75a\\b|\\bA15\\b|\\bP76Ti\\b|\\bP81HD\\b|\\bA10\\b|\\bT760VE\\b|\\bT720HD\\b|\\bP76\\b|\\bP73\\b|\\bP71\\b|\\bP72\\b|\\bT720SE\\b|\\bC520Ti\\b|\\bT760\\b|\\bT720VE\\b|T720-3GE|T720-WiFi",OndaTablet:"\\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\\b[\\s]+|V10 \\b4G\\b",JaytechTablet:"TPC-PA762",BlaupunktTablet:"Endeavour 800NG|Endeavour 1010",DigmaTablet:"\\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\\b",EvolioTablet:"ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\\bEvotab\\b|\\bNeura\\b",LavaTablet:"QPAD E704|\\bIvoryS\\b|E-TAB IVORY|\\bE-TAB\\b",AocTablet:"MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712",MpmanTablet:"MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\\bMPG7\\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010",CelkonTablet:"CT695|CT888|CT[\\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\\bCT-1\\b",WolderTablet:"miTab \\b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\\b",MediacomTablet:"M-MPI10C3G|M-SP10EG|M-SP10EGP|M-SP10HXAH|M-SP7HXAH|M-SP10HXBH|M-SP8HXAH|M-SP8MXA",MiTablet:"\\bMI PAD\\b|\\bHM NOTE 1W\\b",NibiruTablet:"Nibiru M1|Nibiru Jupiter One",NexoTablet:"NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI",LeaderTablet:"TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100",UbislateTablet:"UbiSlate[\\s]?7C",PocketBookTablet:"Pocketbook",KocasoTablet:"\\b(TB-1207)\\b",HisenseTablet:"\\b(F5281|E2371)\\b",Hudl:"Hudl HT7S3|Hudl 2",TelstraTablet:"T-Hub2",GenericTablet:"Android.*\\b97D\\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\\bA7EB\\b|CatNova8|A1_07|CT704|CT1002|\\bM721\\b|rk30sdk|\\bEVOTAB\\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\\bM6pro\\b|CT1020W|arc 10HD|\\bTP750\\b|\\bQTAQZ3\\b|WVT101|TM1088|KT107"},oss:{AndroidOS:"Android",BlackBerryOS:"blackberry|\\bBB10\\b|rim tablet os",PalmOS:"PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino",SymbianOS:"Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\\bS60\\b",WindowsMobileOS:"Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Windows Mobile|Windows Phone [0-9.]+|WCE;",WindowsPhoneOS:"Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;",iOS:"\\biPhone.*Mobile|\\biPod|\\biPad|AppleCoreMedia",iPadOS:"CPU OS 13",
18MeeGoOS:"MeeGo",MaemoOS:"Maemo",JavaOS:"J2ME/|\\bMIDP\\b|\\bCLDC\\b",webOS:"webOS|hpwOS",badaOS:"\\bBada\\b",BREWOS:"BREW"},uas:{Chrome:"\\bCrMo\\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?",Dolfin:"\\bDolfin\\b",Opera:"Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+$|Coast/[0-9.]+",Skyfire:"Skyfire",Edge:"Mobile Safari/[.0-9]* Edge",IE:"IEMobile|MSIEMobile",Firefox:"fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS",Bolt:"bolt",TeaShark:"teashark",Blazer:"Blazer",Safari:"Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari",WeChat:"\\bMicroMessenger\\b",UCBrowser:"UC.*Browser|UCWEB",baiduboxapp:"baiduboxapp",baidubrowser:"baidubrowser",DiigoBrowser:"DiigoBrowser",Mercury:"\\bMercury\\b",ObigoBrowser:"Obigo",NetFront:"NF-Browser",GenericBrowser:"NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger",PaleMoon:"Android.*PaleMoon|Mobile.*PaleMoon"},props:{Mobile:"Mobile/[VER]",Build:"Build/[VER]",Version:"Version/[VER]",VendorID:"VendorID/[VER]",iPad:"iPad.*CPU[a-z ]+[VER]",iPhone:"iPhone.*CPU[a-z ]+[VER]",iPod:"iPod.*CPU[a-z ]+[VER]",Kindle:"Kindle/[VER]",Chrome:["Chrome/[VER]","CriOS/[VER]","CrMo/[VER]"],Coast:["Coast/[VER]"],Dolfin:"Dolfin/[VER]",Firefox:["Firefox/[VER]","FxiOS/[VER]"],Fennec:"Fennec/[VER]",Edge:"Edge/[VER]",IE:["IEMobile/[VER];","IEMobile [VER]","MSIE [VER];","Trident/[0-9.]+;.*rv:[VER]"],NetFront:"NetFront/[VER]",NokiaBrowser:"NokiaBrowser/[VER]",Opera:[" OPR/[VER]","Opera Mini/[VER]","Version/[VER]"],"Opera Mini":"Opera Mini/[VER]","Opera Mobi":"Version/[VER]",UCBrowser:["UCWEB[VER]","UC.*Browser/[VER]"],MQQBrowser:"MQQBrowser/[VER]",MicroMessenger:"MicroMessenger/[VER]",baiduboxapp:"baiduboxapp/[VER]",baidubrowser:"baidubrowser/[VER]",SamsungBrowser:"SamsungBrowser/[VER]",Iron:"Iron/[VER]",Safari:["Version/[VER]","Safari/[VER]"],Skyfire:"Skyfire/[VER]",Tizen:"Tizen/[VER]",Webkit:"webkit[ /][VER]",PaleMoon:"PaleMoon/[VER]",Gecko:"Gecko/[VER]",Trident:"Trident/[VER]",Presto:"Presto/[VER]",Goanna:"Goanna/[VER]",iOS:" \\bi?OS\\b [VER][ ;]{1}",Android:"Android [VER]",BlackBerry:["BlackBerry[\\w]+/[VER]","BlackBerry.*Version/[VER]","Version/[VER]"],BREW:"BREW [VER]",Java:"Java/[VER]","Windows Phone OS":["Windows Phone OS [VER]","Windows Phone [VER]"],"Windows Phone":"Windows Phone [VER]","Windows CE":"Windows CE/[VER]","Windows NT":"Windows NT [VER]",Symbian:["SymbianOS/[VER]","Symbian/[VER]"],webOS:["webOS/[VER]","hpwOS/[VER];"]},utils:{Bot:"Googlebot|facebookexternalhit|Google-AMPHTML|s~amp-validator|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom|contentkingapp",MobileBot:"Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2",DesktopMode:"WPDesktop",TV:"SonyDTV|HbbTV",WebKit:"(webkit)[ /]([\\w.]+)",Console:"\\b(Nintendo|Nintendo WiiU|Nintendo 3DS|Nintendo Switch|P
vendor: 7,341 bytes, lines 18-19
18LAYSTATION|Xbox)\\b",Watch:"SM-V700"}},g.detectMobileBrowsers={fullPattern:/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i,shortPattern:/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i, 19tabletPattern:/android|ipad|playbook|silk/i};var h,i=Object.prototype.hasOwnProperty;return g.FALLBACK_PHONE="UnknownPhone",g.FALLBACK_TABLET="UnknownTablet",g.FALLBACK_MOBILE="UnknownMobile",h="isArray"in Array?Array.isArray:function(a){return"[object Array]"===Object.prototype.toString.call(a)},function(){var a,b,c,e,f,j,k=g.mobileDetectRules;for(a in k.props)if(i.call(k.props,a)){for(b=k.props[a],h(b)||(b=[b]),f=b.length,e=0;e<f;++e)c=b[e],j=c.indexOf("[VER]"),j>=0&&(c=c.substring(0,j)+"([\\w._\\+]+)"+c.substring(j+5)),b[e]=new RegExp(c,"i");k.props[a]=b}d(k.oss),d(k.phones),d(k.tablets),d(k.uas),d(k.utils),k.oss0={WindowsPhoneOS:k.oss.WindowsPhoneOS,WindowsMobileOS:k.oss.WindowsMobileOS}}(),g.findMatch=function(a,b){for(var c in a)if(i.call(a,c)&&a[c].test(b))return c;return null},g.findMatches=function(a,b){var c=[];for(var d in a)i.call(a,d)&&a[d].test(b)&&c.push(d);return c},g.getVersionStr=function(a,b){var c,d,e,f,h=g.mobileDetectRules.props;if(i.call(h,a))for(c=h[a],e=c.length,d=0;d<e;++d)if(f=c[d].exec(b),null!==f)return f[1];return null},g.getVersion=function(a,b){var c=g.getVersionStr(a,b);return c?g.prepareVersionNo(c):NaN},g.prepareVersionNo=function(a){var b;return b=a.split(/[a-z._ \/\-]/i),1===b.length&&(a=b[0]),b.length>1&&(a=b[0]+".",b.shift(),a+=b.join("")),Number(a)},g.isMobileFallback=function(a){return g.detectMobileBrowsers.fullPattern.test(a)||g.detectMobileBrowsers.shortPattern.test(a.substr(0,4))},g.isTabletFallback=function(a){return g.detectMobileBrowsers.tabletPattern.test(a)},g.prepareDetectionCache=function(a,c,d){if(a.mobile===b){var e,h,i;return(h=g.findMatch(g.mobileDetectRules.tablets,c))?(a.mobile=a.tablet=h,void(a.phone=null)):(e=g.findMatch(g.mobileDetectRules.phones,c))?(a.mobile=a.phone=e,void(a.tablet=null)):void(g.isMobileFallback(c)?(i=f.isPhoneSized(d),i===b?(a.mobile=g.FALLBACK_MOBILE,a.tablet=a.phone=null):i?(a.mobile=a.phone=g.FALLBACK_PHONE,a.tablet=null):(a.mobile=a.tablet=g.FALLBACK_TABLET,a.phone=null)):g.isTabletFallback(c)?(a.mobile=a.tablet=g.FALLBACK_TABLET,a.phone=null):a.mobile=a.tablet=a.phone=null)}},g.mobileGrade=function(a){var b=null!==a.mobile();return a.os("iOS")&&a.version("iPad")>=4.3||a.os("iOS")&&a.version("iPhone")>=3.1||a.os("iOS")&&a.version("iPod")>=3.1||a.version("Android")>2.1&&a.is("Webkit")||a.version("Windows Phone OS")>=7||a.is("BlackBerry")&&a.version("BlackBerry")>=6||a.match("Playbook.*Tablet")||a.version("webOS")>=1.4&&a.match("Palm|Pre|Pixi")||a.match("hp.*TouchPad")||a.is("Firefox")&&a.version("Firefox")>=12||a.is("Chrome")&&a.is("AndroidOS")&&a.version("Android")>=4||a.is("Skyfire")&&a.version("Skyfire")>=4.1&&a.is("AndroidOS")&&a.version("Android")>=2.3||a.is("Opera")&&a.version("Opera Mobi")>11&&a.is("AndroidOS")||a.is("MeeGoOS")||a.is("Tizen")||a.is("Dolfin")&&a.version("Bada")>=2||(a.is("UC Browser")||a.is("Dolfin"))&&a.version("Android")>=2.3||a.match("Kindle Fire")||a.is("Kindle")&&a.version("Kindle")>=3||a.is("AndroidOS")&&a.is("NookTablet")||a.version("Chrome")>=11&&!b||a.version("Safari")>=5&&!b||a.version("Firefox")>=4&&!b||a.version("MSIE")>=7&&!b||a.version("Opera")>=10&&!b?"A":a.os("iOS")&&a.version("iPad")<4.3||a.os("iOS")&&a.version("iPhone")<3.1||a.os("iOS")&&a.version("iPod")<3.1||a.is("Blackberry")&&a.version("BlackBerry")>=5&&a.version("BlackBerry")<6||a.version("Opera Mini")>=5&&a.version("Opera Mini")<=6.5&&(a.version("Android")>=2.3||a.is("iOS"))||a.match("NokiaN8|NokiaC7|N97.*Series60|Symbian/3")||a.version("Opera Mobi")>=11&&a.is("SymbianOS")?"B":(a.version("BlackBerry")<5||a.match("MSIEMobile|Windows CE.*Mobile")||a.version("Windows Mobile")<=5.2,"C")},g.detectOS=function(a){return g.findMatch(g.mobileDetectRules.oss0,a)||g.findMatch(g.mobileDetectRules.oss,a)},g.getDeviceSmallerSide=function(){return window.screen.width<window.screen.height?window.screen.width:window.screen.height},f.prototype={constructor:f,mobile:function(){return g.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.mobile},phone:function(){return g.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.phone},tablet:function(){return g.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.tablet},userAgent:function(){return this._cache.userAgent===b&&(this._cache.userAgent=g.findMatch(g.mobileDetectRules.uas,this.ua)),this._cache.userAgent},userAgents:function(){return this._cache.userAgents===b&&(this._cache.userAgents=g.findMatches(g.mobileDetectRules.uas,this.ua)),this._cache.userAgents},os:function(){return this._cache.os===b&&(this._cache.os=g.detectOS(this.ua)),this._cache.os},version:function(a){return g.getVersion(a,this.ua)},versionStr:function(a){return g.getVersionStr(a,this.ua)},is:function(b){return c(this.userAgents(),b)||a(b,this.os())||a(b,this.phone())||a(b,this.tablet())||c(g.findMatches(g.mobileDetectRules.utils,this.ua),b)},match:function(a){return a instanceof RegExp||(a=new RegExp(a,"i")),a.test(this.ua)},isPhoneSized:function(a){return f.isPhoneSized(a||this.maxPhoneWidth)},mobileGrade:function(){return this._cache.grade===b&&(this._cache.grade=g.mobileGrade(this)),this._cache.grade}},"undefined"!=typeof window&&window.screen?f.isPhoneSized=function(a){return a<0?b:g.getDeviceSmallerSide()<=a}:f.isPhoneSized=function(){},f._impl=g,f.version="1.4.4 2019-09-21",f})}
19(function(a){if("undefined"!=typeof module&&module.exports)return function(a){module.exports=a()};if("function"==typeof define&&define.amd)return define;if("undefined"!=typeof window)return function(a){window.MobileDetect=a()};throw new Error("unknown environment")}()); 20/*! jQuery slabtext plugin v2.2 MIT/GPL2 @freqdec */ 21(function($){$.fn.slabText=function(options){var settings={fontRatio:0.78,forceNewCharCount:true,wrapAmpersand:true,headerBreakpoint:null,viewportBreakpoint:null,noResizeEvent:false,resizeThrottleTime:300,maxFontSize:999,postTweak:true,precision:3,minCharsPerLine:0};$("body").addClass("slabtexted");return this.each(function(){if(options){$.extend(settings,options);}var $this=$(this),keepSpans=$("span.slabtext",$this).length,words=keepSpans?[]:String($.trim($this.text())).replace(/\s{2,}/g," ").split(" "),origFontSize=null,idealCharPerLine=null,fontRatio=settings.fontRatio,forceNewCharCount=settings.forceNewCharCount,headerBreakpoint=settings.headerBreakpoint,viewportBreakpoint=settings.viewportBreakpoint,postTweak=settings.postTweak,precision=settings.precision,resizeThrottleTime=settings.resizeThrottleTime,minCharsPerLine=settings.minCharsPerLine,resizeThrottle=null,viewportWidth=$(window).width(),headLink=$this.find("a:first").attr("href")||$this.attr("href"),linkTitle=headLink?$this.find("a:first").attr("title"):"";if(!keepSpans&&minCharsPerLine&&words.join(" ").length<minCharsPerLine){return;}var grabPixelFontSize=function(){var dummy=jQuery('<div style="display:none;font-size:1em;margin:0;padding:0;height:auto;line-height:1;border:0;"> </div>').appendTo($this),emH=dummy.height();dummy.remove();return emH;};var resizeSlabs=function resizeSlabs(){var parentWidth=$this.width(),fs;$this.removeClass("slabtextdone slabtextinactive");if(viewportBreakpoint&&viewportBreakpoint>viewportWidth||headerBreakpoint&&headerBreakpoint>parentWidth){$this.addClass("slabtextinactive");return;}fs=grabPixelFontSize();if(!keepSpans&&(forceNewCharCount||fs!=origFontSize)){origFontSize=fs;var newCharPerLine=Math.min(60,Math.floor(parentWidth/(origFontSize*fontRatio))),wordIndex=0,lineText=[],counter=0,preText="",postText="",finalText="",slice,preDiff,postDiff;if(newCharPerLine!=idealCharPerLine){idealCharPerLine=newCharPerLine;while(wordIndex<words.length){postText="";while(postText.length<idealCharPerLine){preText=postText;postText+=words[wordIndex]+" ";if(++wordIndex>=words.length){break;}}if(minCharsPerLine){slice=words.slice(wordIndex).join(" ");if(slice.length<minCharsPerLine){postText+=slice;preText=postText;wordIndex=words.length+2;}}preDiff=idealCharPerLine-preText.length;postDiff=postText.length-idealCharPerLine;if((preDiff<postDiff)&&(preText.length>=(minCharsPerLine||2))){finalText=preText;wordIndex--;}else{finalText=postText;}finalText=$("<div/>").text(finalText).html();if(settings.wrapAmpersand){finalText=finalText.replace(/&/g,'<span class="amp">&</span>');}finalText=$.trim(finalText);lineText.push('<span class="slabtext">'+finalText+"</span>");}$this.html(lineText.join(" "));if(headLink){$this.wrapInner('<a href="'+headLink+'" '+(linkTitle?'title="'+linkTitle+'" ':"")+"/>");}}}else{origFontSize=fs;}$("span.slabtext",$this).each(function(){var $span=$(this),innerText=$span.text(),wordSpacing=innerText.split(" ").length>1,diff,ratio,fontSize;if(postTweak){$span.css({"word-spacing":0,"letter-spacing":0});}ratio=parentWidth/$span.width();fontSize=parseFloat(this.style.fontSize)||origFontSize;$span.css("font-size",Math.min((fontSize*ratio).toFixed(precision),settings.maxFontSize)+"px");diff=!!postTweak?parentWidth-$span.width():false;if(diff){$span.css((wordSpacing?"word":"letter")+"-spacing",(diff/(wordSpacing?innerText.split(" ").length-1:innerText.length)).toFixed(precision)+"px");}});$this.addClass("slabtextdone");};resizeSlabs();if(!settings.noResizeEvent){$(window).resize(function(){if($(window).width()==viewportWidth){return;}viewportWidth=$(window).width();clearTimeout(resizeThrottle);resizeThrottle=setTimeout(resizeSlabs,resizeThrottleTime);});}});};})(jQuery); 22/*! jQuery Lazy 1.6.7 - MIT & GPL-2.0 license - Copyright 2012-2016 Daniel 'Eisbehr' Kern */ 23!function(e,t,a,r){"use strict";function n(a,r,n,o){function i(){p=t.devicePixelRatio>1,l(n),r("delay")>=0&&setTimeout(function(){u(!0)},r("delay")),(r("delay")<0||r("combined"))&&(o.e=m(r("throttle"),function(e){"resize"===e.type&&(b=v=-1),u(e.all)}),o.a=function(e){l(e),n.push.apply(n,e)},o.g=function(){return n=e(n).filter(function(){return!e(this).data(r("loadedName"))})},u(),e(r("appendScroll")).on("scroll."+a.name+" resize."+a.name,o.e))}function l(t){if(t=e(t).filter(function(){return!e(this).data(r("handledName"))&&(e(this).attr(r("attribute"))||e(this).attr(r("loaderAttribute")))}).data("plugin_"+a.name,a),r("defaultImage")||r("placeholder"))for(var n=0;n<t.length;n++){var o=e(t[n]),i=t[n].tagName.toLowerCase(),l="background-image";"img"==i&&r("defaultImage")&&!o.attr("src")?o.attr("src",r("defaultImage")):"img"==i||!r("placeholder")||o.css(l)&&"none"!=o.css(l)||o.css(l,"url("/js/vendor/jquery-lazy/+r("placeholder")+")")}}function u(t){if(!n.length)return void(r("autoDestroy")&&a.destroy());for(var o=!1,i=r("imageBase")?r("imageBase"):"",l=0;l<n.length;
23l++)(function(a){if(c(a)||t){var n,l=e(a),u=a.tagName.toLowerCase(),f=l.attr(r("attribute"));l.data(r("handledName"))||r("visibleOnly")&&!l.is(":visible")||!(f&&("img"==u&&i+f!=l.attr("src")||"img"!=u&&i+f!=l.css("background-image"))||(n=l.attr(r("loaderAttribute"))))||(o=!0,l.data(r("handledName"),!0),d(l,u,i,n))}})(n[l]);o&&(n=e(n).filter(function(){return!e(this).data(r("handledName"))}))}function d(t,a,n,o){++h;var i=function(){A("onError",t),g()};if(A("beforeLoad",t),o)t.off("error").one("error",i),t.one("load",function(){r("removeAttribute")&&t.removeAttr(r("loaderAttribute")),t.data(r("loadedName"),!0),A("afterLoad",t),g()}),A(o,t,function(e){e?t.load():t.error()})||t.error();else{var l=e(new Image);l.one("error",i),l.one("load",function(){t.hide(),"img"==a?t.attr("src",l.attr("src")):t.css("background-image","url('"+l.attr("src")+"')"),t[r("effect")](r("effectTime")),r("removeAttribute")&&t.removeAttr(r("attribute")+" "+r("retinaAttribute")),t.data(r("loadedName"),!0),A("afterLoad",t),l.remove(),g()}),l.attr("src",n+t.attr(r(p&&t.attr(r("retinaAttribute"))?"retinaAttribute":"attribute"))),l.complete&&l.load()}}function c(e){var t=e.getBoundingClientRect(),a=r("scrollDirection"),n=r("threshold"),o=s()+n>t.top&&-n<t.bottom,i=f()+n>t.left&&-n<t.right;return"vertical"==a?o:"horizontal"==a?i:o&&i}function f(){return b>=0?b:b=e(t).width()}function s(){return v>=0?v:v=e(t).height()}function m(e,t){var n,o=0;return function(i,l){function u(){o=+new Date,t.call(a,i)}var d=+new Date-o;n&&clearTimeout(n),d>e||!r("enableThrottle")||l?u():n=setTimeout(u,e-d)}}function g(){--h,n.length||h||A("onFinishedAll")}function A(e,t,n){return(e=r(e))?(e.apply(a,[].slice.call(arguments,1)),!0):!1}var h=0,b=-1,v=-1,p=!1;!function(){"event"==r("bind")?i():e(t).on("load."+a.name,i)}()}function o(a,o){var i=this,l=e.extend({},i.configuration,o),u={};return i.config=function(e,t){return t===r?l[e]:(l[e]=t,i)},i.addItems=function(t){return u.a&&u.a("string"===e.type(t)?e(t):t),i},i.getItems=function(){return u.g?u.g():{}},i.update=function(e){return u.e&&u.e({},!e),i},i.loadAll=function(){return u.e&&u.e({all:!0},!0),i},i.destroy=function(){return e(i.config("appendScroll")).off("."+i.name,u.e),e(t).off("."+i.name),u={},r},n(i,i.config,a,u),i.config("chainable")?a:i}e.fn.Lazy=e.fn.lazy=function(e){return new o(this,e)},e.extend(o.prototype,{name:"lazy",configuration:{chainable:!0,autoDestroy:!0,bind:"load",threshold:500,visibleOnly:!1,appendScroll:t,scrollDirection:"both",imageBase:null,defaultImage:"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",placeholder:null,delay:-1,combined:!1,attribute:"data-src",retinaAttribute:"data-retina",loaderAttribute:"data-loader",removeAttribute:!0,handledName:"handled",loadedName:"loaded",effect:"show",effectTime:0,enableThrottle:!0,throttle:250,beforeLoad:null,afterLoad:null,onError:null,onFinishedAll:null}})}(jQuery,window,document); 24$(function() { 25 if ($('div.StageVoting_groupId').length) { 26 var vid = $('div.StageVoting_groupId').data('voting'); 27 var detail = $('div.StageVoting_groupId').data('detail'); 28 $.ajax({
29 url: '/_votings/arena/last.voting.php', 30 type: 'GET', 31 data: { 32 location: $(location).attr('href'), 33 select: 'id', 34 id:vid, 35 detail: detail 36 }, 37 dataType: 'html', 38 success: function (data) { 39 $('div.StageVoting_groupId').html(data); 40 41 } 42 }) 43 } 44 if($('div.StageVoting_groupAuto').length) { 45 $.ajax({ 46 url: '/_votings/arena/last.voting.php', 47 type: 'GET', 48 data: { 49 location: $(location).attr('href'), 50 select: 'last' 51 }, 52 dataType: 'html', 53 success: function (data) { 54 $('div.StageVoting_groupAuto').html(data); 55 56 } 57 }) 58 } 59 var request; 60 $(document).on('submit','form.StageVoting_form',function(e){ 61 e.preventDefault(); 62 var hash = $("input[name='i_vhash']:checked").val(); 63 if( typeof hash === "undefined"){ 64 $(".StageVoting_info").text("Bitte treffen Sie eine Auswahl"); 65 } else { 66 var $form = $(this); 67 var $inputs = $form.find("input, select, button, textarea"); 68 var serializedData = $form.serialize(); 69 $inputs.prop("disabled", true); 70 71 request = $.ajax({ 72 type: "POST", 73 url: "/_votings/arena/post.php", 74 data: serializedData, 75 }); 76 request.done(function (response, textStatus, jqXHR){ 77 // Log a message to the console 78 if($('div.StageVoting_groupAuto').length) { 79 $('div.StageVoting_groupAuto').html(response); 80 } 81 if($('div.StageVoting_groupId').length) { 82 $('div.StageVoting_groupId').html(response); 83 } 84 85 }); 86 request.fail(function (jqXHR, textStatus, errorThrown){ 87 // Log the error to the console 88 console.error( 89 "The following error occurred: "+ 90 textStatus, errorThrown 91 ); 92 }); 93 request.always(function () { 94 // Reenable the inputs 95 $inputs.prop("disabled", false); 96 }); 97 } 98 }) 99 100}); 101/* Click auf Logo nicht scrollen */ 102$(".Logo").on("click", function () { 103 localStorage.setItem('click','Logo'); 104}); 105 106/* ---- iPad-Events --- */ 107$(window).on("orientationchange resize",function(){ 108 if ( $(".Ad-superbanner .ad_superbanner").length) { 109 $(document).trigger("webskin"); 110 } 111}); 112 113/* --------------- GA Event Zählung --------------- */ 114 115$(".SiteHeader").on("click", ".NavigationMeta .FormLogoutPopup input[type=\"submit\"]", function(event){ 116 // Trigger Event bei Logout-Link im Header 117 var fo_mr = { 118 'hitType': 'event', 119 'eventCategory': event.currentTarget.getAttribute('data-ga'), 120 'eventAction': 'Klick', 121 'eventLabel': 'Oben rechts', 122 'page': window.location.pathname, 123 'location': window.location.href 124 }; 125 dfv_ga_repl(fo_mr); 126}); 127 128$("body").on("click", ".ButtonMoreContent", function(event){ 129 // Trigger Event bei Klick auf Alle Nachrichten 130 131 var stageTitle = 'ohne Titel'; 132 var stageTitleFound = false; 133 134 // Bühnen-Titel finden 135 if ($(this).closest('section')) { 136 137 stageTitle = $(this).closest('section').find('.StageTitle').text(); 138 stageTitle = stageTitle.trim(); 139 if (stageTitle.length > 1) { 140 stageTitleFound = true; 141 } else { 142 stageTitleFound = true; 143 stageTitle = "ohne Titel"; 144 } 145 } 146 147 var fo_pw = { 148 'hitType': 'event', 149 'eventCategory': 'Alle ' + stageTitle, 150 'eventAction': 'Klick', 151 'eventLabel': '' 152 }; 153 154 dfv_ga_repl(fo_pw); 155}); 156 157$(".StageGalleriesEdgewise, .StageStorechecks, .StageGalleries").on("click", "a", function(event){ 158 // Trigger Event bei Click auf Galerie Fotogaleriebühnen 159 var d = event.currentTarget.getAttribute('data-te'); 160 if (d !== null) { 161 var stageTitle = $(this).closest('article').parent().parent().find('.StageTitle a').text(); 162 if (typeof stageTitle === 'undefined' || stageTitle === '') { 163 stageTitle = $(this).closest('article').parent().parent().parent().find('.StageTitle a').text(); 164 } 165 166 var fo_pw = { 167 'hitType': 'event', 168 'eventCategory': stageTitle + ' Bühne', 169 'eventAction': 'Klick', 170 'eventLabel': event.currentTarget.getAttribute('data-te'), 171 'page': window.location.pathname, 172 'location': window.location.href 173 }; 174 dfv_ga_repl(fo_pw); 175 } 176}); 177 178$(".StageFewOneRow, .StageTeaserFewTwoRows").on("click", "a", function(event){
179 // Trigger Event bei Click auf News Fashionbühne 180 var d = event.currentTarget.getAttribute('data-te'); 181 if (d !== null) { 182 var fo_pw = { 183 'hitType': 'event', 184 'eventCategory': $(this).closest('article').parent().parent().find('.StageTitle a').text() + ' Bühne', 185 'eventAction': 'Klick', 186 'eventLabel': event.currentTarget.getAttribute('data-te'), 187 'page': window.location.pathname, 188 'location': window.location.href 189 }; 190 dfv_ga_repl(fo_pw); 191 } 192}); 193 194$(".PageArticle_body").on("submit", ".StageVoting_form",function(){ 195 // Trigger Event bei Umfrage 196 var fo_mr = { 197 'hitType': 'event', 198 'eventCategory': 'Umfrage', 199 'eventAction': 'Klick', 200 'eventLabel': 'Detail', 201 'page': window.location.pathname, 202 'location': window.location.href 203 }; 204 dfv_ga_repl(fo_mr); 205 206}); 207 208$(".StageVoting").on("submit", ".StageVoting_form",function(){ 209 // Trigger Event bei Umfrage 210 var fo_mr = { 211 'hitType': 'event', 212 'eventCategory': 'Umfrage', 213 'eventAction': 'Klick', 214 'eventLabel': 'Arena', 215 'page': window.location.pathname, 216 'location': window.location.href 217 }; 218 dfv_ga_repl(fo_mr); 219 220}); 221 222/* --------------- Suche ---------- */ 223 224$(function(){ 225 var showSearch = function() { 226 227 var l = $("a.navsearch").position().left; 228 console.log($("a.navsearch").position()); 229 230 $("#header-searchinput").show(); 231 $("#header-searchinput").animate({ 232 width: "250px", 233 right: "0" 234 }, 200 ); 235 }; 236 237 var hideSearch = function() { 238 $( "#header-searchinput" ).animate({ 239 width: "0px", 240 right: "0" 241 }, 200, function() { 242 $("#header-searchinput").hide(); 243 }); 244 }; 245 246 var searchurl = $(location).attr('href'); 247 248 $(document).on("click touchstart",function(e) { 249 250 if($(e.target).attr('id') == "headersearch" && $("#header-searchinput").css("display") == "none") { 251 e.preventDefault(); 252 showSearch(); 253 } 254 else { 255 if ($(e.target).attr('id') == "header-searchfield" || $(e.target).attr('id') == "header-searchbutton") { 256 ;// Klick innerhalb des Suchfeldes 257 } 258 else { 259 hideSearch(); 260 } 261 } 262 }); 263 264}); 265 266/*---------- Aktionsseiten-Infobox ----------*/ 267 268$(document).on("show-infobox", function(event, info_box_id, info_icon_position){ 269 $("#"+info_box_id).css('top',info_icon_position.top + 30) 270 .css('left', info_icon_position.left - 160) 271 .css('display', 'block'); 272}); 273 274/*---------- Jobs auf News-Detailseite im Footer ----------*/ 275 276$(".NewsJobs_item, .NewsJobs_header, .NewsJobs_footer").on("click", function(event){ 277 if(event.currentTarget.getAttribute('data-te') !== undefined){ 278 var fo_pw = { 279 'hitType': 'event', 280 'eventCategory': 'Jobs', 281 'eventAction': 'Klick', 282 'eventLabel': event.currentTarget.getAttribute('data-te'), 283 'page': window.location.pathname, 284 'location': window.location.href 285 }; 286 dfv_ga_repl(fo_pw); 287 } 288}); 289 290/*---------- Online-Specials Homepage ----------*/ 291 292if($('.StageLeadOnlineSpecialHomepage_sponsorWrapper').find('div.Sponsor_item').length !== 0) { 293 294} else { 295 $('.StageLeadOnlineSpecialHomepage_rightCol-inner').hide(); 296} 297 298 299/* Online-Specials Sponsoren */ 300 301$(".Sponsor_item-image img").on("click", function(){ 302 var val = $(this).parent().parent().attr('href'); 303 console.log("val: "); 304 console.log(val); 305 if(val !== undefined){ 306 var fo_mr = { 307 'hitType': 'event', 308 'eventCategory': 'Dossiers', 309 'eventAction': 'click', 310 'eventLabel': val, 311 'page': window.location.pathname, 312 'location': window.location.href 313 }; 314 dfv_ga_repl(fo_mr); 315 316 317 } else { 318 return false; 319 } 320}); 321 322 323var md = new MobileDetect(window.navigator.userAgent); 324var oldScrollPosition; 325 326function preventEmptySearch() { 327 $('.SiteHeader_searchform button[type="submit"]').click(function(e) { 328 e.preventDefault(); 329 if ( $('.SiteHeader_searchform input[type="text"]').val() !== '' ) { 330 $('.SiteHeader_searchform form').submit(); 331 } 332 }); 333 334 $('.SiteHeaderSticky_formSearch button[type="submit"]').click(function(e) { 335 e.preventDefault(); 336 if ( $('.SiteHeaderSticky_formSearch input[type="text"]').val() !== '' ) { 337 $('.SiteHeaderSticky_formSearch form').submit(); 338 } 339 }); 340 341 $('.FormSearchMobile button[type="submit"]').click(function(e) { 342 e.preventDefault(); 343 if ( $('.FormSearchMobile input[type="text"]').val() !== '' ) { 344 $('.FormSearchMobile').submit(); 345 } 346 }); 347 348 $('.FormSearch button[type="submit"]').click(function(e) { 349 e.preventDefault(); 350 if ( $('.FormSearch input[type="text"]').val() !== '' ) { 351 $('.FormSearch').submit(); 352 } 353 }); 354} 355 356function initAsideNav() { 357 $('.aside-menu .toggle-menu').click(function(e) { 358 e.preventDefault(); 359 $(this).closest('.aside-menu').toggleClass('open');
360 $(this).closest('.aside-menu').find('.collapse-area').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) { 361 if (e.originalEvent.propertyName === 'max-height') { 362 $(document.body).trigger("sticky_kit:recalc"); 363 } 364 }); 365 }); 366} 367 368function initSearchToggle() { 369 $('.ToggleSearch').click(function() { 370 var searchform = '.SiteHeader .SiteHeader_searchform'; 371 372 if ( $(searchform+':visible').length === 0 ) { 373 $(searchform).slideDown(225); 374 $('.ToggleSearch').css('color', '#BA1818') 375 .parent().addClass('isActive'); 376 } else if ( $(searchform+':visible').length > 0) { 377 $(searchform).slideUp(225); 378 $('.ToggleSearch').removeAttr('style') 379 .parent().removeClass('isActive'); 380 } 381 }); 382} 383 384function initMobileNav() { 385 $('.toggle-mobile-nav').click(function(e) { 386 $('body').toggleClass('mobile-nav-open'); 387 }); 388} 389 390function initNewsletterSelect() { 391 $('.newsletter-select').click(function(e) { 392 $(this).toggleClass('selected'); 393 }); 394} 395 396function initStickyColumn() { 397 var ButtonsSharing_margin_top = $('.PageArticle_content .PageArticle_sticky .ButtonsSharing, ' + 398 '.PageArticleAdvertorial_content .PageArticleAdvertorial_sticky .ButtonsSharing').css('margin-top'); 399 400 $('.PageArticle_content .PageArticle_sticky, .PageArticleAdvertorial_content .PageArticleAdvertorial_sticky').stick_in_parent({ 401 parent : '.sticky-container', 402 offset_top: 97, 403 bottoming: true 404 }).on("sticky_kit:stick", function(e) { 405 $(this).addClass('is_sticky'); 406 $('.PageArticle_content .PageArticle_sticky .ButtonsSharing,' + 407 '.PageArticleAdvertorial_content .PageArticleAdvertorial_sticky .ButtonsSharing ').css('margin-top',0); 408 }) 409 .on("sticky_kit:bottom", function(e) { 410 $(this).parent().css('position', 'static'); 411 }) 412 .on("sticky_kit:unstick", function(e) { 413 $(this).removeClass('is_sticky'); 414 $('.PageArticle_content .PageArticle_sticky .ButtonsSharing,' + 415 '.PageArticleAdvertorial_content .PageArticleAdvertorial_sticky .ButtonsSharing').css('margin-top',ButtonsSharing_margin_top); 416 }); 417 418 $('a[href="#"]').click(function(e){ 419 e.preventDefault(); 420 }); 421} 422 423function initCards() { 424 $('.card-collapse').on('click',(function(e) { 425 var me = $(this); 426 $('.card-collapse.open').not(this).removeClass('open'); 427 me.toggleClass('open'); 428 })); 429 $('.card-collapse').on('click','a',(function(e) { 430 //e.stopImmediatePropagation(); 431 console.log('offa'); 432 console.log($(this)); 433 $(this).trigger('click'); 434 })); 435} 436 437 438 439// __________________________________________________ 440// 441// 442// !Check Idle Time Mobile 443 444var timeoutID; 445 446function goInactive() { 447 if($('body').scrollTop() > 0) { 448 $('body').addClass('idle'); 449 } 450 451 $('.modal').addClass('idle'); 452} 453 454function goActive() { 455 $('body.idle').removeClass('idle'); 456 $('.modal.idle').removeClass('idle'); 457 startTimer(); 458} 459 460function resetTimer(e) { 461 window.clearTimeout(timeoutID); 462 goActive(); 463} 464 465function startTimer() { 466 // wait 2 seconds before calling goInactive 467 timeoutID = window.setTimeout(goInactive, 2000); 468} 469 470 471function make_square(element) { 472// var cw = $(element).width(); 473// $(element).css({'height':cw+'px'}); 474} 475 476 477 478 479 480 481function setupIdle() { 482 this.addEventListener("mousemove", resetTimer); 483 this.addEventListener("mousedown", resetTimer); 484 this.addEventListener("keypress", resetTimer); 485 this.addEventListener("DOMMouseScroll", resetTimer); 486 this.addEventListener('mousewheel', resetTimer, {passive: true}); 487 this.addEventListener("touchmove", resetTimer); 488 this.addEventListener("touchstart", resetTimer); 489 this.addEventListener("MSPointerMove", resetTimer); 490 491 startTimer(); 492} 493 494function createYoutubeApi() { 495 var tag = document.createElement('script'); 496 tag.src = "https://www.youtube.com/iframe_api"; 497 var firstScriptTag = document.getElementsByTagName('script')[0]; 498 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 499} 500 501function initToggleList() { 502 $('.toggleList li').click(function () { 503 $(this).toggleClass('isActive'); 504 $('div', this).toggle(); 505 }); 506} 507 508$(document).ready(function(){ 509// $("a[href=#]").click(function(e) { 510// e.preventDefault(); 511// }); 512// if (md.mobile() != null) { 513// $('body').addClass('is-mobile'); 514// }; 515// if (md.phone() != null) { 516// $('.stage-fashion > .row > .col-sm-4').slice(-2).remove(); 517// } 518 initSearchToggle(); 519 setupIdle(); 520 initStickyColumn(); 521 initAsideNav(); 522 initMobileNav(); 523 preventEmptySearch(); 524 initCards(); 525 initNewsletterSelect(); 526 createYoutubeApi(); 527 initToggleList(); 528 529 $('.ImageModal').colorbox({iframe:false, opacity: 0.8, maxWidth:'95%', maxHeight:'95%'}); 530 531 // mobile Navigation Flyout 532 $(".NavigationFlyout_toggleButton").on('click',function(e){ 533 e.preventDefault();$('.NavigationFlyout').toggleClass('isActive'); 534 }); 535 536 // mobile Navigation Flyout 537 $(".NavigationMobile_toggle").on('click',function(e){ 538 e.preventDefault();$('.NavigationMobile').toggleClass('isActive'); 539 $('body').toggleClass('isFixed'); 540 }); 541 542 $('.paneltop').click( function() { 543 $(this).css({"background-position":"0px -21px"}) 544 .siblings().animate({"height":"100px"}, 200) 545 }, function() { 546 $(this).css({"background-position":"0px 0px"}) 547 .siblings().animate({"height":"0px"}, 200); 548 }) 549 550 // Bilder quadratisieren 551 $( '.to-be-squared .teaser-image' ).each(function( index ) { 552 make_square($(this)); 553 }); 554 555 // Login-Popup/Logout-Popup 556 var accountBtn = $(".NavigationMeta_item-account"); 557 var accountBtnLink = $(".NavigationMeta_item-account .NavigationMeta_itemLink"); 558 var loginPanel = $(".NavigationMeta .FormLoginPopup"); 559 var logoutPanel = $(".NavigationMeta .FormLogoutPopup"); 560 var panel = accountBtn.hasClass('isSignedOut') ? loginPanel : logoutPanel; 561 var panel_input = $(".NavigationMeta .FormLoginPopup input"); 562 563 function showPanel(selector, a) { 564 selector.css('visibility', 'visible'); 565 a.addClass('isActive'); 566 } 567 function hidePanel(selector, a) { 568 selector.removeAttr('style'); 569 a.removeClass('isActive'); 570 } 571 572 $(".NavigationMeta .FormLoginPopup .FormField_icon").click(function() { 573 $('.NavigationMeta .FormLoginPopup .FormField_control').trigger('click'); 574 }); 575 576 accountBtn.click(function(e) { 577 e.preventDefault(); 578 }); 579 580 accountBtn.mouseover( function() { showPanel(panel, accountBtn); } ); 581 accountBtn.mouseout( function() { hidePanel(panel, accountBtn); } ); 582 panel.mouseover( function() { showPanel(panel, accountBtn); } ); 583 panel.mouseout( function() { 584 if ( !panel_input.is(":focus") ) { 585 hidePanel(panel, accountBtn); 586 } 587 }); 588 589}); 590
591// quadratische Bildergrößen beim Fenster-Verkleinern neu berechnen 592$( window ).resize(function() { 593 $( '.to-be-squared .teaser-image' ).each(function( index ) { 594 make_square($(this)); 595 }); 596}); 597 598function manage_input_active_state(selector) { 599 $(selector).each(function() { 600 if ( $(this).val() ) { 601 $(this).addClass('FormField_control-filled'); 602 } 603 $(this).change(function() { 604 if ( $(this).val() ) { 605 $(this).addClass('FormField_control-filled'); 606 } 607 if ( $(this).val() === '' ) { 608 $(this).removeClass('FormField_control-filled'); 609 } 610 }); 611 }); 612} 613 614manage_input_active_state(".FormField_control:not([type='submit'])"); 615manage_input_active_state(".FormField_controlGroupField:not([type='submit'])"); 616 617$(document).ready(function() { 618 /** 619 * ersetzt das Carousel 620 * durch ein swipen beim neu Laden der Seite 621 * in data-ride wird onPageLoad getsetzt 622 * die Ids des Elements muessen eindeutig sein !!! 623 */ 624 $.each($("[data-ride]"), function (k, v) { 625 if ($(this).data('ride') == 'onPageLoad') { 626 var id = $(this).attr('id'); 627 var store_name = 'onPageLoad' + id; 628 var stack = []; 629 var count_elm = $(this).children(".carousel-inner").children(".item").length; 630 var random_stack_index = Math.floor(Math.random() * ((count_elm -1) + 1)); 631 632 if (sessionStorage.getItem(store_name)) { 633 stack = JSON.parse(sessionStorage.getItem(store_name)); 634 } 635 if (stack.length !== count_elm) { 636 stack = []; 637 for (var i = 0; i < count_elm; i++) { 638 stack[i] = 0; 639 } 640 stack[random_stack_index] = 1; 641 } else { 642 stack.unshift('0'); 643 if (stack.pop() == 1) { 644 stack[0] = 1; 645 } 646 } 647 $.each($(this).children(".carousel-inner").children(".item"), function (i, x) { 648 if (stack[i] == 0) { 649 $(this).removeClass('active'); 650 } else { 651 $(this).addClass('active'); 652 } 653 }) 654 sessionStorage.setItem(store_name, JSON.stringify(stack)); 655 } 656 }); 657}); 658(()=>{var __webpack_modules__={768:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";__webpack_require__.d(__webpack_exports__,{Z:()=>Embed});var _module__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(631),_utils_sendRequest__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(58),_utils_adBlockCheck__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(173),_tracking_module__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(558);function _await(e,t,n){return n?t?t(e):e:(e&&e.then||(e=Promise.resolve(e)),t?e.then(t):e)}function _empty(){}function _invokeIgnored(e){var t=e();if(t&&t.then)return t.then(_empty)}function _async(e){return function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];try{return Promise.resolve(e.apply(this,t))}catch(e){return Promise.reject(e)}}}function _awaitIgnored(e,t){if(!t)return e&&e.then?e.then(_empty):Promise.resolve()}function _invoke(e,t){var n=e();return n&&n.then?n.then(t):t(n)}function ownKeys(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function _objectSpread(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ownKeys(Object(n),!0).forEach((function(t){_defineProperty(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ownKeys(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var loadAutoplayList=_async((function(e,t,n,i){var o;return _invoke((function(){if(e.fallbackElementsPromise)return _awaitIgnored(e.fallbackElementsPromise)}),(function(){var a,r=null===(a=e.fallbackElements)||void 0===a?void 0:a.length;return _await(r?e.fallbackElements.map((function(e){return _objectSpread(_objectSpread({},e),{},{fallback_id:e.id})})):new Promise((function(n){(0,_utils_sendRequest__WEBPACK_IMPORTED_MODULE_1__.w)("https://api.embed.pinpoll.com/autoplay/nextEmbeds",{elementId:t,url:e.url,topic:e.topic},window.Pinpoll.storage).then((function(e){return e.json()})).then((function(t){var o;return n(null===(o=window.Pinpoll.embed)||void 0===o?void 0:o.sortPreferredAutoEmbeddedElements(t.elements,e,i))})).catch((function(e){console.log("Pinpoll: error during fetching autoplay polls",e),n([])}))})),(function(e){var t;return o=e,n&&(o=null===(t=o)||void 0===t?void 0:t.slice(0,n)),o}),r)}))})),Embed=function(){function Embed(e,t,n){var i=this;if(_classCallCheck(this,Embed),_defineProperty(this,"targetWindow",void 0),_defineProperty(this,"lazyLoading",void 0),_defineProperty(this,"type",void 0),_defineProperty(this,"id",void 0),_defineProperty(this,"iframe",void 0),_defineProperty(this,"element",void 0),_defineProperty(this,"mode",void 0),_defineProperty(this,"data",void 0),_defineProperty(this,"loaded",!1),_defineProperty(this,"instance",void 0),_defineProperty(this,"questionViewTriggered",!1),_defineProperty(this,"url",void 0),_defineProperty(this,"autoplay",null),_defineProperty(this,"nativeAd",null),_defineProperty(this,"pendings",{}),_defineProperty(this,"pendingPostMessages",[]),_defineProperty(this,"loadDataSet",!1),_defineProperty(this,"widgetIndex",void 0),_defineProperty(this,"stats",void 0),this.element=t,this.targetWindow=e.location,this.type=e.type,this.mode=e.mode,this.data=e,this.stats=n,this.id=generateId(e),this.widgetIndex=window.Pinpoll.embed.initedEmbeds,window.Pinpoll.embed.initedEmbeds+=1,this.lazyLoading="eager"!==e.loading&&"preload"!==e.loading,this.data.native)return this.loadNative(t,e).then((function(t){if(t){t.targetId=i.id,i.instance=t,i.instance.promises.preload?i.instance.promises.preload.then((function(){return i.stats.markLoad()})):i.stats.markLoad();var n=!1;i.instance.on("poll:initialized","global.js - statTracker",(function(){var e;n||(n=!0,i.stats.markRender(),i.stats.observeImpression((null===(e=i.instance)||void 0===e?void 0:e.container)||i.element))})),i.instance.on("poll:initialized","global.js",(function(){var n,o;t.elementId&&(e.id=+t.elementId,(0,_tracking_module__WEBPACK_IMPORTED_MODULE_2__.Z)(t.visitorStorage,{widgetIndex:"e"+(null!==(n=null===(o=window.Pinpoll.embed)||void 0===o?void 0:o.embeds.findIndex((function(e){return e===i})))&&void 0!==n?n:0),originPage:e.url,widgetLocation:buildUrl(e,t.targetId||"")}).start())}))}})).catch((function(e){console.error("Pinpoll: error during loading native embed",e)})),void this.registerEventListener();this.iframe=buildIframe(e,this.id),this.lazyLoading?(this.iframe.setAttribute("class","lazyload"),document.addEventListener("lazybeforeunveil",(function e(t){t.target===i.iframe&&((0,_module__WEBPACK_IMPORTED_MODULE_0__.oW)(i.data,i.element),i.url=buildUrl(i.data,i.id),i.iframe.setAttribute("data-src",
658i.url),i.stats.markLoad(),document.removeEventListener("lazybeforeunveil",e))})),document.addEventListener("lazyloaded",(function e(t){t.target===i.iframe&&(i.loaded=!0,i.stats.markRender(),i.stats.observeImpression(i.iframe),document.removeEventListener("lazyloaded",e))}))):(this.loaded=!0,this.stats.markLoad(),this.url=buildUrl(e,this.id),this.iframe.src=this.url),this.registerEventListener(),t.parentNode===document.getElementsByTagName("head")[0]?document.body.appendChild(this.iframe):t.parentElement?t.parentElement.insertBefore(this.iframe,t):document.body.appendChild(this.iframe),this.lazyLoading||(this.stats.markRender(),this.stats.observeImpression(this.iframe))}return _createClass(Embed,[{key:"loadNative",value:function(e,t){if(!window.Pinpoll.nativeLoader){var n=document.createElement("script");n.async=!0,n.type="module",n.innerHTML="window.Pinpoll.nativeLoader = async (embedElement, options) => {\n const { createEmbed } = await import('".concat("https://tools.pinpoll.com/embed-v2/main.js?v=1790061720894","');\n return createEmbed(embedElement, options);\n }"),document.head.appendChild(n)}return new Promise((function(n){!function i(){if("function"==typeof window.Pinpoll.nativeLoader)return n(window.Pinpoll.nativeLoader(e,t));setTimeout(i,100)}()}))}},{key:"loadNextEmbed",value:function(){if(this.autoplay){var e;this.autoplay.currentIndex=this.autoplay.currentIndex||0;var t=null===(e=this.autoplay.nextAutoplayedElements)||void 0===e?void 0:e[this.autoplay.currentIndex++];t&&this.loadEmbedItem(t)}}},{key:"registerEventListener",value:function(){var e=this;window.addEventListener("message",(function(t){var n,i,o=t.data;try{if("string"==typeof o){if(!o.startsWith("{"))return!1;o=JSON.parse(o)}}catch(e){console.warn(e)}if(o&&"object"===_typeof(o)&&o.action)if("vote"===o.action||"unvote"===o.action)-1!==navigator.appName.indexOf("Internet Explorer")&&-1===navigator.appVersion.indexOf("MSIE 1")&&(o=JSON.stringify(o)),null!==(n=e.iframe)&&void 0!==n&&n.contentWindow||(e.iframe=document.getElementById(e.id)),null===(i=e.iframe.contentWindow)||void 0===i||i.postMessage(o,e.targetWindow);else if(o.target===e.id)switch(o.action){case"get:loaddata":e.setLoadData();break;case"set:height":e.data.height||e.setEmbedHeight(o.value);break;case"get:recaptcha":e.activateRecaptcha(o.top,o.sitekey);break;case"poll-view:finished":e.questionViewTriggered=!0;break;case"autoplay:check":var a;e.initAutoplay(),e.autoplay&&(null===(a=e.autoplay.loadPromise)||void 0===a||a.then((function(){var t,n,i,o;null!==(t=e.autoplay)&&void 0!==t&&null!==(n=t.nextAutoplayedElements)&&void 0!==n&&n.length&&e.autoplay.nextAutoplayedElements[e.autoplay.currentIndex||0]&&(null===(i=e.iframe)||void 0===i||null===(o=i.contentWindow)||void 0===o||o.postMessage({action:"autoplay:ready"},"*"))})));break;case"autoplay:fire":e.loadNextEmbed();break;case"update:visitor":window.Pinpoll.storage.visitor=o.visitor;break;case"native-ad:set":(0,_utils_adBlockCheck__WEBPACK_IMPORTED_MODULE_3__.I)().finally((function(){var t;if(window.Pinpoll.userHasAdblock&&1===(null===(t=o.adConfig)||void 0===t?void 0:t.type))return console.warn("Pinpoll Native Ad: AdBlock detected, no native ad will be shown");e.setNativeAd(o.adTag,o.adConfig),e.nativeAd&&e.pendings.nativeinterstitial&&(e.nativeAd.onInterstitialStart(""+e.pendings.nativeinterstitial),e.pendings.nativeinterstitial=null)}));break;case"interstitial-start":e.nativeAd?e.nativeAd.onInterstitialStart(o.ad.duration):e.pendings.nativeinterstitial=o.ad.duration}}))}}
658,{key:"setLoadData",value:function(){var e,t=this;if(null!==(e=this.iframe)&&void 0!==e&&e.contentWindow){var n,i,o={embed_url:this.url,visitor:window.Pinpoll.storage.visitor,trackingDone:null===(n=window.Pinpoll.tracking)||void 0===n?void 0:n.requestDone,cookieEnabled:navigator.cookieEnabled,originPage:this.data.url,path:window.location.pathname,fallback_id:this.data.fallback_id,autoplayedElementId:this.data.autoplayedElementId,cssClass:this.data.cssClass,parent_id:this.id,autoplayDelay:this.data.autoplayDelay};for(["consent","targetAds","customURL","ppId"].forEach((function(e){t.data[e]&&(o[e]=t.data[e])})),window.Pinpoll.appName&&(o.app=window.Pinpoll.appName),this.loadDataSet||void 0===this.widgetIndex||(o.widgetIndex="e"+this.widgetIndex),null===(i=this.iframe)||void 0===i||i.contentWindow.postMessage({action:"set:loaddata",data:o},"*"),this.loadDataSet=!0;this.pendingPostMessages.length;){var a=this.pendingPostMessages.shift();a&&this.postMessage(a)}}}},{key:"setNativeAd",value:function setNativeAd(adTag,adConfig){var _this4=this;if(adTag)if(this.nativeAd)this.nativeAd.handle("reinitialized",{adTag,adConfig})||this.nativeAd.show();else{var _ref,_this$instance2,container=document.createElement("div");container.setAttribute("style","position:relative;"),null===(_ref=this.iframe||(null===(_this$instance2=this.instance)||void 0===_this$instance2?void 0:_this$instance2.container))||void 0===_ref||_ref.after(container);var script=document.createElement("script");script.adData={config:adConfig,embed:this},script.innerText=adTag,container.append(script),this.nativeAd={script,container,handle:function handle(handlerName,params){return!!_this4.nativeAd&&!!_this4.nativeAd.script.adData.config[handlerName]&&(eval(String(_this4.nativeAd.script.adData.config[handlerName]))(params),!0)},hide:function(){_this4.nativeAd&&(_this4.nativeAd.handle("hide")||(_this4.nativeAd.container.style.visibility="hidden"),_this4.nativeAd.handle("hidden"))},show:function(){_this4.nativeAd&&(_this4.nativeAd.handle("show")||(_this4.nativeAd.container.style.visibility="visible"),_this4.nativeAd.handle("shown"))},onInterstitialStart:function(e){var t,n,i;null!==(t=_this4.nativeAd)&&void 0!==t&&t.handle("interstitialStart",{duration:e})||(null===(i=_this4.nativeAd)||void 0===i||i.hide(),setTimeout((function(){var e,t,n;(null===(e=_this4.nativeAd)||void 0===e?void 0:e.handle("interstitialStop"))||null===(t=_this4.nativeAd)||void 0===t||t.show(),null===(n=_this4.nativeAd)||void 0===n||n.handle("interstitialStopped")}),1e3*+e)),null===(n=_this4.nativeAd)||void 0===n||n.handle("interstitialStarted")}},this.nativeAd.handle("initialized",{adConfig})}}},{key:"loadEmbedItem",value:function(e){var t,n;this.iframe&&e&&(this.data.id=e.element_id,e.id&&(this.data.fallback_id=e.id),e.element_id&&(this.data.autoplayedElementId=e.element_id),e.custom_design_id&&(this.data.design=e.custom_design_id),null===(t=this.nativeAd)||void 0===t||t.hide(),this.id=generateId(this.data),this.url=buildUrl(this.data,this.id),null===(n=this.iframe)||void 0===n||n.setAttribute("id",this.id),this.iframe.src=this.url)}},{key:"setEmbedHeight",value:function(e){if(e&&parseFloat(e)){var t=document.getElementById(this.id);t&&(t.setAttribute("height",e),t.setAttribute("style","display:block;height:".concat(parseFloat(e),"px!important;")))}}},{key:"activateRecaptcha",value:function(e,t){var n=this,i=function(e){var i,o,a,r,l,s=document.createElement("div"),d=document.createElement("div");window.grecaptcha.render(d,{sitekey:t,callback:function(e){var t,i;null===(t=n.iframe)||void 0===t||null===(i=t.contentWindow)||void 0===i||i.postMessage({action:"recaptcha:success",response:e},n.targetWindow),s.style.opacity="0",s.style.transform="translateY(20px)",window.setTimeout((function(){var e;null==s||null===(e=s.parentNode)||void 0===e||e.removeChild(s)}),400)}}),s.appendChild(d),s.setAttribute("style","-webkit-transition:opacity .4s,-webkit-transform .4s;transition:opacity .4s,-webkit-transform .4s;transition:opacity .4s,transform .4s;transition:opacity .4s,transform .4s,-webkit-transform .4s;-webkit-transform:translateY(20px);transform:translateY(20px)"),s.style.position="absolute",s.style.width="".concat(null===(i=n.iframe)||void 0===i?void 0:i.offsetWidth,"px"),s.style.left="".concat(null===(o=n.iframe)||void 0===o?void 0:o.offsetLeft,"px"),s.style.top="".concat((null===(a=n.iframe)||void 0===a?void 0:a.offsetTop)||0+e,"px"),s.style["text-align"]="answer"!=n.type?"center":"left",d.style.display="inline-block",d.style.margin="answer"!=n.type?"0 0 0 12%":"0 0 0 8em",s.style.opacity="0",window.setTimeout((function(){s.style.opacity="1",s.setAttribute("style",s.getAttribute("style").replace("translateY(20px)","translateY(0)"))}),1),null===(r=n.iframe)||void 0===r||null===(l=r.parentNode)||void 0===l||l.insertBefore(s,n.iframe.nextSibling)};if(window.grecaptcha)i(e);
658else{var o="recaptcha_".concat(this.id),a=document.createElement("script");a.src="https://www.google.com/recaptcha/api.js?onload=".concat(o,"&render=explicit"),a.async=!0,a.defer=!0,window[o]=function(){i(e)},document.head.appendChild(a)}}},{key:"postMessage",value:function(e){var t,n;this.loadDataSet?null===(t=this.iframe)||void 0===t||null===(n=t.contentWindow)||void 0===n||n.postMessage(e,this.targetWindow):this.pendingPostMessages.push(e)}},{key:"initPreload",value:function(){(0,_module__WEBPACK_IMPORTED_MODULE_0__.oW)(this.data,this.element);var e=this.instance;if(e)e.dispatch("poll:initPreload",e);else{var t=_objectSpread(_objectSpread({},this.data),{},{fallbackElementsPromise:void 0});this.postMessage({action:"preload:init",data:t})}"preload"===this.data.loading&&(this.data.loading="eager")}},{key:"reload",value:function(){this.iframe&&(this.iframe.src=buildUrl(this.data,this.id))}},{key:"loadAutoplayedElements",value:function(e){var t=this;this.autoplay&&(this.autoplay.loadPromise=_async((function(){return _invokeIgnored((function(){if(t.autoplay)return _await(loadAutoplayList(t.data,t.autoplay.elementId,e||t.autoplay.limit,t.iframe),(function(e){t.autoplay.nextAutoplayedElements=e,t.data.id||t.loadNextEmbed()}))}))}))())}},{key:"initAutoplay",value:function(){this.autoplay||void 0===this.data.autoplay||(this.autoplay={nextAutoplayedElements:void 0,limit:this.data.autoplay,elementId:this.data.id},this.loadAutoplayedElements())}}]),Embed}();function generateId(e){return"pinpoll_".concat(e.type,"_").concat(e.id,"_").concat(e.mode)}function buildIframe(e,t){var n;switch(e.type){case"quiz":n=500;break;case"answer":n=50;break;default:n=0}var i=document.createElement("iframe");i.setAttribute("title","Pinpoll Widget"),i.setAttribute("frameborder","0"),i.setAttribute("scrolling","no"),i.setAttribute("width","100%"),i.setAttribute("id",t),i.setAttribute("name",window.location.toString()),i.setAttribute("style","display:block; height:"+e.height||0);var o=e.height||n;return o&&i.setAttribute("height",o.toString()),i}function buildUrl(e,t){var n,i=!1,o="";e.styles&&(o+=e.styles),e.height&&(o+="".concat(o.length>0?"&":"","height=").concat(e.height)),e.trackmode&&"preview"===e.trackmode&&(o+="".concat(o.length>0?"&":"","previewMode=1")),e.simulate&&"on"===e.simulate&&(o+="".concat(o.length>0?"&":"","simulate=1")),e.editmode&&"on"===e.editmode&&(o+="".concat(o.length>0?"&":"","editMode=1"),i=!0),e.randomQuestions&&(o+="".concat(o.length>0?"&":"","randomQuestions=1")),e.randomAnswers&&(o+="".concat(o.length>0?"&":"","randomAnswers=1")),"preload"===e.loading&&(o+="".concat(o.length>0?"&":"","preloadMode=1")),e.blockAds&&(o+="".concat(o.length>0?"&":"","blockAds=1")),e.info&&Object.keys(e.info).length&&(o+="".concat(o.length>0?"&":"","info=").concat(encodeURIComponent(JSON.stringify(e.info)))),t&&(o+="".concat(o.length>0?"&":"","parentID=").concat(encodeURIComponent(t)));var a="";if(e.version)return"".concat(e.location,"/embed/").concat(e.version,"?id=").concat(e.id).concat(o?"&".concat(o):"");switch(e.type){case"answer":n="".concat(e.location,"/embed/answer/").concat(e.id).concat(o?"?".concat(o):"");break;default:"result"===e.mode&&(a+="/result"),n="".concat(e.location||"","/").concat(i?"direct/":"","embed/").concat("aipoll"===e.mode?"inspire/":"").concat(e.id).concat(a),e.design&&(n+="/cd/"+e.design),n+=o?"?".concat(o):""}return n}},631:(e,t,n)=>{"use strict";n.d(t,{ZP:()=>g,oW:()=>v});var i=n(768);function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var l=["served","loads","renders","impressions"],s=new Set(["url","ppid","class","consent","style","opointdata","rect_data","bis_style"]),d=["target-ads-","_","font-"],c=function(){function e(t,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:500;o(this,e),r(this,"endpoint",void 0),r(this,"flushDelayMs",void 0),r(this,"url",void 0),r(this,"embedcode",void 0),r(this,"stage",-1),r(this,"sentStage",-1),r(this,"flushTimer",null),r(this,"flushing",!1),r(this,"impressionObserver",void 0),this.endpoint=this.resolveEndpoint(),this.flushDelayMs=i,this.url=n,this.embedcode=this.buildEmbedcode(t),this.registerLifecycleFlush()}var t,n;return t=e,(n=[{key:"markServed",value:function(){this.mark("served")}},{key:"markLoad",value:function(){this.mark("loads")}},{key:"markRender",value:function(){this.mark("renders")}},{key:"markImpression",value:function(){var e=this.stage;this.mark("impressions",!1),this.stage>e&&(null!==this.flushTimer&&(window.clearTimeout(this.flushTimer),this.flushTimer=null),this.flush(!1))}},{key:"observeImpression",value:function(e){var t=this;this.stage>=l.indexOf("impressions")||("IntersectionObserver"in window?(this.impressionObserver||(this.impressionObserver=new IntersectionObserver((function(e){e.forEach((function(e){var n;e.isIntersecting&&e.intersectionRatio>=.5&&(t.markImpression(),null===(n=t.impressionObserver)||void 0===n||n.disconnect())}
658))}),{threshold:[.5]})),this.impressionObserver.observe(e)):this.markImpression())}},{key:"resolveEndpoint",value:function(){var e="https://api.embed.pinpoll.com";return"".concat(e.replace(/\/+$/,""),"/v3/widget")}},{key:"buildEmbedcode",value:function(e){var t=this,n={};Array.from(e.attributes).sort((function(e,t){return e.name.localeCompare(t.name)})).forEach((function(e){var i=t.normalizeAttrName(e.name);!i||s.has(i)||d.some((function(e){return i.startsWith(e)}))||void 0!==n[i]||(n[i]=e.value)}));var i={};return Object.keys(n).sort().forEach((function(e){i[e]=n[e]})),JSON.stringify(i)}},{key:"normalizeAttrName",value:function(e){return e.startsWith("data-pinpoll-")?e.substring(13):e.startsWith("data-")?e.substring(5):e}},{key:"advance",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=l.indexOf(e);if(!(n<=this.stage)){if(n>this.stage+1)for(var i=this.stage+1;i<n;i++){var o=l[i];console.warn('Pinpoll: automatically marked skipped stage "'.concat(o,'" for embed ').concat(this.embedcode))}this.stage=n,t&&this.scheduleFlush()}}},{key:"scheduleFlush",value:function(){var e=this;this.endpoint&&(null!==this.flushTimer&&window.clearTimeout(this.flushTimer),this.flushTimer=window.setTimeout((function(){e.flushTimer=null,e.flush(!1)}),this.flushDelayMs))}},{key:"hasPending",value:function(){return this.stage>this.sentStage}},{key:"buildPayloadRow",value:function(e,t){var n=function(n){var i=l.indexOf(n);return i>e&&i<=t?1:0};return{url:this.url,embedcode:this.embedcode,served:n("served"),loads:n("loads"),renders:n("renders"),impressions:n("impressions")}}},{key:"flush",value:function(e){var t=this;if(this.endpoint&&this.hasPending()&&!this.flushing){var n=this.stage,i=this.buildPayloadRow(this.sentStage,n);if(i.served+i.loads+i.renders+i.impressions!==0){var o=i;e&&navigator.sendBeacon?navigator.sendBeacon(this.endpoint,new Blob([JSON.stringify(o)],{type:"application/json"}))&&(this.sentStage=Math.max(this.sentStage,n)):(this.flushing=!0,fetch(this.endpoint,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},credentials:"include",keepalive:e,body:JSON.stringify(o)}).then((function(){t.sentStage=Math.max(t.sentStage,n)})).catch((function(){})).finally((function(){t.flushing=!1,t.hasPending()&&t.scheduleFlush()})))}}}},{key:"mark",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.advance(e,t)}},{key:"registerLifecycleFlush",value:function(){var e=this;window.addEventListener("pagehide",(function(){return e.flush(!0)})),document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e.flush(!0)}))}}])&&a(t.prototype,n),e}();function u(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=p(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,o=function(){};return{s:o,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,r=!0,l=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return r=e.done,e},e:function(e){l=!0,a=e},f:function(){try{r||null==n.return||n.return()}finally{if(l)throw a}}}}function p(e,t){if(e){if("string"==typeof e)return f(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?f(e,t):void 0}}function f(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}var m={1:"poll",2:"quiz",6:"personality_test"};function h(e){var t,n,i=e.getAttribute("data-pinpoll-location")||e.getAttribute("data-location")||"https://embed.pinpoll.com",o=e.getAttribute("data-design");return{type:e.getAttribute("data-pinpoll-type")||e.getAttribute("data-type")||"poll",aiPollMode:"aipoll"===e.getAttribute("data-mode"),version:e.getAttribute("data-version"),native:null!==e.getAttribute("data-native")||"v2"===e.getAttribute("data-version"),mode:e.getAttribute("data-pinpoll-mode")||e.getAttribute("data-mode")||"poll",location:i,trackmode:e.getAttribute("data-pinpoll-trackmode")||e.getAttribute("data-trackmode")||"default",editmode:e.getAttribute("data-pinpoll-editmode")||e.getAttribute("data-editmode")||"default",simulate:e.getAttribute("data-pinpoll-simulate")||e.getAttribute("data-simulate")||"default",id:parseInt(e.getAttribute("data-pinpoll-id")||e.getAttribute("data-id"),10)||0,height:parseInt(e.getAttribute("data-pinpoll-height")||e.getAttribute("data-height"),10)||0,label:e.getAttribute("data-pinpoll-label")||e.getAttribute("data-label")||"",bgcolor:e.getAttribute("data-pinpoll-bgcolor")||e.getAttribute("data-bgcolor")||"#2395a6",styles:function(){var t,n=/data(?:-pinpoll)?-style-(.+)/,i=[],o=u(e.attributes);try{for(o.s();!(t=o.n()).done;){var a=t.value,r=a.name.match(n);r&&i.push("".concat(encodeURIComponent(r[1]),"=").concat(encodeURIComponent(a.value)))}}catch(e){o.e(e)}finally{o.f()}return!!i.length&&i.join("&")}(),loading:e.getAttribute("data-loading")||!1,design:o?+o:null,randomQuestions:null!==e.getAttribute("random-questions"),randomAnswers:null!==e.getAttribute("random-answers"),forceLoad:null!==e.getAttribute("force-load"),cssClass:null===(t=e.getAttribute("data-css-class"))||void 0===t?void 0:t.trim(),customURL:null===(n=e.getAttribute("data-url"))||void 0===n?void 0:n.trim(),url:e.getAttribute("data-url")||(window.location.origin||"unknown_origin")+window.location.pathname,info:e.getAttributeNames().reduce((function(t,n){return n.startsWith("data-info-")&&(t[n.substring(10)]=e.getAttribute(n)),t}),{}),targetAds:e.getAttributeNames().reduce((function(t,n){return n.startsWith("data-target-a
658ds-")&&(t[n.substring(16)]=e.getAttribute(n)),t}),{}),autoplay:[null,"false"].includes(e.getAttribute("data-autoplay"))?void 0:+(e.getAttribute("data-autoplay")||0),autoplayDelay:[null,""].includes(e.getAttribute("data-autoplay-delay"))?void 0:+(e.getAttribute("data-autoplay-delay")||0),mqeDelay:[null,""].includes(e.getAttribute("data-mqe-delay"))?void 0:+(e.getAttribute("data-mqe-delay")||0),blockAds:![null,"false","0"].includes(e.getAttribute("data-block-ads")),topic:e.getAttribute("data-topic"),ppId:e.getAttribute("data-ppid"),consent:e.getAttribute("data-consent"),muteVoted:![null,"false","0"].includes(e.getAttribute("data-mute-voted"))}}function v(e,t){var n,i=h(t);Object.assign(e,i,{id:i.id||e.id,design:null!==(n=i.design)&&void 0!==n?n:e.design})}const g=function(){return{embeds:[],initedEmbeds:0,fallbackElementsPromise:{},isElementAlreadyEmbedded:function(e,t,n){var i=t?m[t]:null;try{var o=['[data-pinpoll-id="'.concat(e,'"]'),'script[data-location*="'.concat(n||"pinpoll.com",'"][data-id="').concat(e,'"]')],a=i?o.map((function(e){return"".concat(e,":not([data-type]), ").concat(e,'[data-type="').concat(i,'"]')})).join(", "):o.join(", ");return!!document.body.querySelector(a)||!!this.embeds.find((function(t){var n,i,o;return(null===(n=t.data)||void 0===n?void 0:n.id)===e&&("poll"===(null===(i=t.data)||void 0===i?void 0:i.type)||"aipoll"===(null===(o=t.data)||void 0===o?void 0:o.type))}))}catch(e){return!1}},isAnyElementEmbedded:function(){return!!this.embeds.find((function(e){return"aipoll"!==e.mode}))||!!document.body.querySelector('[data-pinpoll-id]:not([data-mode="aipoll"]), script[data-location*="'.concat("pinpoll.com",'"][data-id]'))},getElementVotedStatus:function(e){var t,n,i=e.questions,o=e.multiple_vote_interval,a=null===(t=window.Pinpoll)||void 0===t||null===(n=t.storage)||void 0===n?void 0:n.votes;if(i&&a){var r=a.filter((function(e){return i.includes(e.question_id)}));if(null!=r&&r.length)return!o||r.find((function(e){return e.voted_at+o>(new Date).getTime()}))?2:1}return 0},sortPreferredAutoEmbeddedElements:function(e,t,n){var i=this,o=t.location,a=t.muteVoted,r=t.height,l=[];if(e){var s,d;if(l=e.filter((function(e){return!i.isElementAlreadyEmbedded(e.element_id,e.type_id,o)})),null!==(s=window.Pinpoll)&&void 0!==s&&s.appName&&(l=l.filter((function(e){return 1===e.type_id&&2===e.max_answers}))),null!==(d=window.Pinpoll)&&void 0!==d&&d.heightFilterActive&&r){var c=n&&n.parentNode!==document.getElementsByTagName("head")[0]&&n.parentElement?n.clientWidth:document.body.clientWidth;l=l.filter((function(e){try{var t=JSON.parse(e.height),n=Math.max.apply(Math,function(e){if(Array.isArray(e))return f(e)}(i=Object.keys(t).map(Number).filter((function(e){return e<=c})))||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(i)||p(i)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}());if(t[n])return parseInt(t[n])<=r}catch(e){return!1}var i}))}a?l=l.filter((function(e){return 2!==i.getElementVotedStatus(e)})):l.length&&void 0===l[0].sort&&(l=l.sort((function(e,t){var n=i.getElementVotedStatus(e),o=i.getElementVotedStatus(t);return n===o?0:n<o?-1:1})))}return l},getFallbackElements:function(e,t){var n=t+e;if(!this.fallbackElementsPromise[n]){var i={url:e};t&&(i.topic=t),this.fallbackElementsPromise[n]=fetch("https://api.embed.pinpoll.com/aipolls/search?"+new URLSearchParams(i),{method:"GET"}).then((function(e){return e.json()})).then((function(e){return e})).catch((function(e){console.log("Pinpoll: error during fetching aipolls",e)}))}return this.fallbackElementsPromise[n]},initEmbed:function(e){var t=this;if(!this.embeds.find((function(t){return t.element===e}))){var n=h(e),o=new c(e,n.url);e.classList.add("loaded"),o.markServed(),n.id&&!n.native?this.embeds.push(new i.Z(n,e,o)):new Promise((function(t){"eager"!==n.loading&&"preload"!==n.loading?(e.classList.add("lazyload"),new Promise((function(t){document.addEventListener("lazybeforeunveil",(function(n){n.target===e&&t()}))})).finally((function(){t()}))):t()})).then((function(){v(n,e),n.native?t.embeds.push(new i.Z(n,e,o)):n.aiPollMode||n.topic?n.forceLoad||!t.isAnyElementEmbedded()?new Promise((function(e){n.aiPollMode?(o.markLoad(),fetch("https://api.embed.pinpoll.com/aipolls/first?"+new URLSearchParams({url:n.url}),{method:"GET"}).then((function(e){return e.json()})).then((function(t){n.id=t.id,e()})).catch((function(t){console.log("Pinpoll: error during fetching aipoll",t),e()}))):e()})).finally((function(){n.id?t.embeds.push(new i.Z(n,e,o)):(n.aiPollMode&&!n.topic||!n.aiPollMode&&n.topic)&&(o.markLoad(),n.fallbackElementsPromise=t.getFallbackElements(n.url,n.topic).then((function(a){var r,l=a.elements;n.fallbackElements=t.sortPreferredAutoEmbeddedElements(l,n,e);var s=null===(r=n.fallbackElements)||void 0===r?void 0:r.shift();s?(n.id=s.element_id,!n.design&&s.custom_design_id&&(n.design=s.custom_design_id),n.fallback_id=s.id,t.embeds.push(new i.Z(n,e,o))):console.log("Pinpoll: no suitable element found for",e)})))})):console.log("Pinpoll: not embedding as another element is already embedded",e):console.log("Pinpoll: no id or data specified for element",e)}))}},start:function(){var e=this;window.MutationObserver=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;var t=function(){var t,n=u(document.querySelectorAll("div[data-pinpoll-id]:not(.loaded), div.pinpoll:not(.loaded)"));try{for(n.s();!(t=n.n()).done;){var i=t.value;e.initEmbed(i)}}catch(e){n.e(e)}finally{n.f()}};t();var n=window.setInterval((function(){t()}),500);window.MutationObserver&&(window.setTimeout((function(){window.clearInterval(n)}),1e4),new window.MutationObserver((function(t){t.forEach((function(t){var n,i=u(t.addedNodes);try{for(i.s();!(n=i.n()).done;){var o=n.value;o.matches&&o.matches("div[data-pinpoll-id]:not(.loaded), div.pinpoll:not(.loaded)")&&e.initEmbed(o)}}catch(e){i.e(e)}finally{i.f()}}))})).observe(document,{childList:!0,subtree:!0}))},broadcast:function(e){var t,n=u(this.embeds);try{for(n.s();!(t=n.n()).done;)t.value.postMessage(e)}catch(e){n.e(e)}finally{n.f()}}}}},726:()=>{function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function t(t){for(var i=1;i<arguments.length;i++){var o=null!=arguments[i]?arguments[i]:{};
658i%2?e(Object(o),!0).forEach((function(e){n(t,e,o[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e){var t=window.Pinpoll.storage.votes;t||(t=[]),-1===t.findIndex((function(t){return t.answer_id===e.answer_id&&t.voted_at===e.voted_at}))&&t.push(e),window.Pinpoll.storage.votes=t}window.addEventListener("message",(function(e){var n=e.data;try{if("string"==typeof n){if(!n.startsWith("{"))return!1;n=JSON.parse(n)}}catch(e){console.warn(e)}var a=function(t){e.source&&e.source.postMessage(t,e.origin)};if(n&&"object"===i(n)&&n.action)switch(n.action){case"get:visitor-votes":a({action:"return:visitor-votes",data:window.Pinpoll.storage.votes.map((function(e){return t(t({},e),{},{justVoted:!!window.Pinpoll.votelinkVotes.find((function(t){return t.answer_id===e.answer_id&&t.voted_at===e.voted_at}))})}))});break;case"add:visitor-vote":o(n.data);break;case"remove:visitor-vote":var r=window.Pinpoll.storage.votes,l=n.data,s=l.questionId,d=l.answerId;if(r){var c=r.filter((function(e){return(e.question_id||e.poll_id)!==s||e.answer_id!==d}));window.Pinpoll.storage.votes=c}break;case"remove:visitor-vote-element":var u=window.Pinpoll.storage.votes,p=n.data.questionIds;if(u){var f=u.filter((function(e){return!p.some((function(t){return t===e.question_id}))}));window.Pinpoll.storage.votes=f}break;case"add":var m=n.key;if(!m)break;var h=window.Pinpoll.storage[m];if(!h)break;if(!(h instanceof Array))break;h.push(n.value),window.Pinpoll.storage[m]=h;break;case"get":var v=n.key;if(!v)break;a({action:"return:"+v,data:{key:v,value:window.Pinpoll.storage[v]}})}return null})),function(){var e=new URL(window.location.href),t=e.searchParams.get("pinpoll_votes");if(t){var n;try{n=JSON.parse(t)}catch(e){console.warn("Pinpoll: Failed parsing pinpoll_votes GET parameter")}n&&n instanceof Array&&n.forEach((function(e){o(e),window.Pinpoll.votelinkVotes.push(e)}));try{e.searchParams.delete("pinpoll_votes"),window.history.pushState({},document.title,e.toString())}catch(e){}}}()},558:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var i=n(38),o=n(58),a=n(173);function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}const d=function(e,t){var n=t||{},d=n.widgetIndex,c=n.originPage,u=n.widgetLocation,p={},f=(0,i.G)({BASE_DOMAIN:"pinpoll.com",CDN_ENDPOINT:"https://static.pinpoll.com",API_ENDPOINT:"https://pa.pinpoll.com/v1",cookiesEnabled:function(){if(navigator.cookieEnabled)return!0;document.cookie="cookietest=1";var e=-1!==document.cookie.indexOf("cookietest=");return document.cookie="cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT",e}(),thirdPartyCookiesEnabled:!1,tcfApi:{},requestSent:!1,requestDone:!1,start:function(e){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",m):m(),e&&(p=e)}});function m(){window.setTimeout((function(){Promise.all([(0,a.I)(),window.location.hostname.match(f.BASE_DOMAIN)?Promise.resolve():new Promise((function(e){try{var t=document.createElement("iframe");t.style.display="none",t.title="Pinpoll Third Party Cookie Test",t.src="".concat(f.CDN_ENDPOINT,"/static/start.html"),window.addEventListener("message",(function(t){"MM:3PCunsupported"===t.data?f.thirdPartyCookiesEnabled=!1:"MM:3PCsupported"===t.data&&(f.thirdPartyCookiesEnabled=!0),e()}),!1),document.body.appendChild(t),window.setTimeout((function(){t.remove(),e()}),5e3)}catch(t){f.log("Could not check ThirdPartyCookiesEnabled",t),e()}})),window.ppTcString?(f.tcfApi.tcString=window.ppTcString,f.tcfApi.available=!!window.__tcfapi,Promise.resolve()):window.__tcfapi?(f.tcfApi.available=!0,new Promise((function(e){var t=(new Date).getTime();window.__tcfapi("addEventListener",2,(function(n,i){f.tcfApi.responseTime=(new Date).getTime()-t,i?f.tcfApi.tcString=n.tcString:f.log("tcf api responded with error",n),f.tcfApi.timeout||(f.tcfApi.timeout=!1),f.tcfApi.checkFinished=!0,e()})),window.setTimeout((function(){f.tcfApi.checkFinished||(f.tcfApi.timeout=!0,e())}),1e3)}))):(f.tcfApi.available=!1,Promise.resolve())]).then((function(){var t,n;t=u?function(){try{return new URL(u)}catch(e){return f.log("Could not parse widget location",e),document.location}}():document.location,n=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};
658t%2?l(Object(n),!0).forEach((function(t){s(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({timezone:(new Date).getTimezoneOffset(),adblock:window.Pinpoll.userHasAdblock?1:0,dnt:window.navigator.doNotTrack,cookiesEnabled:f.cookiesEnabled?1:0,localStorageEnabled:v(),thirdPartyCookiesEnabled:f.thirdPartyCookiesEnabled?1:0,referrer:c||document.referrer,title:document.title,tcString:f.tcfApi.tcString,tcfApiAvailable:f.tcfApi.available,location:{hash:t.hash,hostname:t.hostname,pathname:t.pathname,protocol:t.protocol,search:t.search},screen:{width:window.screen.width,height:window.screen.height,colorDepth:window.screen.colorDepth,orientation:window.screen.orientation?window.screen.orientation.type:null},metaTags:h(),widgetIndex:d||""},p),(0,o.w)(f.API_ENDPOINT,n,e).then((function(t){var n,i,o=t.headers.get("PP-Visitor");o&&(e.visitor=o,null===(n=window.Pinpoll)||void 0===n||null===(i=n.embed)||void 0===i||i.broadcast({action:"global:trackingDone",visitor:o}))})).catch((function(e){var t,n;f.log("fetch request failed",e),null===(t=window.Pinpoll)||void 0===t||null===(n=t.embed)||void 0===n||n.broadcast({action:"global:trackingDone"})})).finally((function(){f.requestDone=!0}))}))}))}function h(){var e,t={},n=function(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,o=function(){};return{s:o,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,l=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return l=e.done,e},e:function(e){s=!0,a=e},f:function(){try{l||null==n.return||n.return()}finally{if(s)throw a}}}}(document.getElementsByTagName("meta"));try{for(n.s();!(e=n.n()).done;){var i=e.value,o=i.getAttribute("name")||i.getAttribute("property"),a=i.getAttribute("content");if(o&&a&&o.replace(/\s/g,"").length>0){var l=o.trim().toLowerCase(),s=t[l];s?s instanceof Array?t[l].push(a):t[l]=[s,a]:t[l]=a}}}catch(e){n.e(e)}finally{n.f()}return t}function v(){var e="test";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(e){return!1}}return f}},38:(e,t,n)=>{"use strict";function i(e){var t=e;return t.logs=[],t.log=function(){for(var e=arguments.length,n=new Array(e),i=0;i<e;i++)n[i]=arguments[i];t.logs.push([new Date,n])},t}n.d(t,{G:()=>i})},173:(e,t,n)=>{"use strict";function i(){var e;return void 0!==(null===(e=window.Pinpoll)||void 0===e?void 0:e.userHasAdblock)?Promise.resolve(window.Pinpoll.userHasAdblock):new Promise((function(e){var t=window.setTimeout((function(){var e;null!==(e=window.Pinpoll)&&void 0!==e&&e.userHasAdblock||n(!1)}),1e3),n=function(n){clearTimeout(t),window.Pinpoll=window.Pinpoll||{},window.Pinpoll.userHasAdblock=n,e(n)},i=document.createElement("div");i.innerHTML=" ",i.style.position="absolute",i.className="native-ad-container mobile-ad js-ad_iframe";try{document.body.appendChild(i)}catch(e){console.log("Could not check Adblock",e),n(!1)}window.setTimeout((function(){n(0===i.offsetHeight),i.remove()}),100)}))}n.d(t,{I:()=>i})},58:(e,t,n)=>{"use strict";function i(e,t,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"post",o={Accept:"application/json","Content-Type":"application/json"},a=n.visitor;return a&&(o["PP-Visitor"]=a),fetch(e,{method:i,headers:o,credentials:"include",body:JSON.stringify(t)})}n.d(t,{w:()=>i})},90:e=>{!function(t,n){var i=function(e,t,n){"use strict";var i,o;if(function(){var t,n={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",fastLoadedClass:"ls-is-cached",iframeLoadMode:0,srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(t in o=e.lazySizesConfig||e.lazysizesConfig||{},n)t in o||(o[t]=n[t])}(),!t||!t.getElementsByClassName)return{init:function(){},cfg:o,noSupport:!0};var a,r,l,s,d,c,u,p,f,m,h,v,g,b,w,y,_,k,P,A,E,O,S,I,C,T,x,M,N,D,j,z,L,q,R,W,B,U,G,F,V,J,H,K,$=t.documentElement,Z=e.HTMLPictureElement,Y="addEventListener",X=e.addEventListener.bind(e),Q=e.setTimeout,ee=e.requestAnimationFrame||Q,te=e.requestIdleCallback,ne=/^picture$/i,ie=["load","error","lazyincluded","_lazyloaded"],oe={},ae=Array.prototype.forEach,re=function(e,t){return oe[t]||(oe[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),oe[t].test(e.getAttribute("class")||"")&&oe[t]},le=function(e,t){re(e,t)||e.setAttribute("class",(e.getAttribute("class")||"").trim()+" "+t)},se=function(e,t){var n;(n=re(e,t))&&e.setAttribute("class",(e.getAttribute("class")||"").replace(n," "))},de=function(e,t,n){var i=n?Y:"removeEventListener";n&&de(e,t),ie.forEach((function(n){e[i](n,t)}))},ce=function(e,n,o,a,r){var l=t.createEvent("Event");return o||(o={}),o.instance=i,l.initEvent(n,!a,!r),l.detail=o,e.dispatchEvent(l),l},ue=function(t,n){var i;!Z&&(i=e.picturefill||o.pf)?(n&&n.src&&!t.getAttribute("srcset")&&t.setAttribute("srcset",n.src),i({reevaluate:!0,elements:[t]})):n&&n.src&&(t.src=n.src)},pe=function(e,t){return(getComputedStyle(e,null)||{})[t]},fe=function(e,t,n){for(n=n||e.offsetWidth;n<o.minSize&&t&&!e._lazysizesWidth;)n=t.offsetWidth,t=t.parentNode;return n},me=(V=[],J=F=[],(K=function(e,n){U&&!n?e.apply(this,arguments):(J.push(e),G||(G=!0,(t.hidden?Q:ee)(H)))})._lsFlush=H=function(){var e=J;for(J=F.length?V:F,U=!0,G=!1;e.length;)e.shift()();U=!1},K),he=function(e,t){return t?function(){me(e)}:function(){var t=this,n=arguments;me((function(){e.apply(t,n)}))}},ve=function(e){var t,i,o=function(){t=null,e()},a=function(){var e=n.now()-i;e<99?Q(a,99-e):(te||o)(o)};return function(){i=n.now(),t||(t=Q(a,99))}},ge=(_=/^img$/i,k=/^iframe$/i,P="onscroll"in e&&!/(gle|ing)bot/.test(navigator.userAgent),0,A=0,E=0,O=-1,S=function(e){E--,(!e||E<0||!e.target)&&(E=0)},I=function(e){return null==y&&(y="hidden"==pe(t.body,"visibility")),y||!("hidden"==pe(e.parentNode,"visibility")&&"hidden"==pe(e,"visibility"))},C=function(e,n){var i,o=e,a=I(e);for(v-=n,w+=n,g-=n,b+=n;a&&(o=o.offsetParent)&&o!=t.body&&o!=$;)(a=(pe(o,"opacity")||1)>0)&&"visible"!=pe(o,"overflow")&&(i=o.getBoundingClientRect(),a=b>i.left&&g<i.right&&w>i.top-1&&v<i.bottom+1);return a},x=function(e){var t,i=0,a=o.throttleDelay,r=o.ricTimeout,l=function(){t=!1,i=n.now(),e()},s=te&&r>49?function(){te(l,{timeout:r}),r!==o.ricTimeout&&(r=o.ricTimeout)}:he((function(){Q(l)}),!0);return function(e){var o;(e=!0===e)&&(r=33),t||(t=!0,(o=a-(n.now()-i))<0&&(o=0),e||o<9?s():Q(s,o))}}(T=function(){var e,n,a,r,l,s,u,f,_,k,S,T,x=i.elements;if((p=o.loadMode)&&E<8&&(e=x.length)){for(n=0,O++;n<e;n++)if(x[n]&&!x[n]._lazyRace)if(!P||i.prematureUnveil&&i.prematureUnveil(x[n]))q(x[n]);else if((f=x[n].getAttribute("data-expand"))&&(s=1*f)||(s=A),k||(k=!o.expand||o.expand<1?$.clientHeight>500&&$.clientWidth>500?500:370:o.expand,i._defEx=k,S=k*o.expFactor,T=o.hFac,y=null,A<S&&E<1&&O>2&&p>2&&!t.hidden?(A=S,O=0):A=p>1&&O>1&&E<6?k:0),_!==s&&(m=innerWidth+s*T,h=innerHeight+s,u=-1*s,_=s),a=x[n].getBoundingClientRect(),(w=a.bottom)>=u&&(v=a.top)<=h&&(b=a.right)>=u*T&&(g=a.left)<=m&&(w||b||g||v)&&(o.loadHidden||I(x[n]))&&(c&&E<3&&!f&&(p<3||O<4)||C(x[n],s))){if(q(x[n]),l=!0,E>9)break}else!l&&c&&!r&&E<4&&O<4&&p>
6582&&(d[0]||o.preloadAfterLoad)&&(d[0]||!f&&(w||b||g||v||"auto"!=x[n].getAttribute(o.sizesAttr)))&&(r=d[0]||x[n]);r&&!l&&q(r)}}),N=he(M=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(S(e),le(t,o.loadedClass),se(t,o.loadingClass),de(t,D),ce(t,"lazyloaded"))}),D=function(e){N({target:e.target})},j=function(e,t){var n=e.getAttribute("data-load-mode")||o.iframeLoadMode;0==n?e.contentWindow.location.replace(t):1==n&&(e.src=t)},z=function(e){var t,n=e.getAttribute(o.srcsetAttr);(t=o.customMedia[e.getAttribute("data-media")||e.getAttribute("media")])&&e.setAttribute("media",t),n&&e.setAttribute("srcset",n)},L=he((function(e,t,n,i,a){var r,l,s,d,c,p;(c=ce(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(n?le(e,o.autosizesClass):e.setAttribute("sizes",i)),l=e.getAttribute(o.srcsetAttr),r=e.getAttribute(o.srcAttr),a&&(d=(s=e.parentNode)&&ne.test(s.nodeName||"")),p=t.firesLoad||"src"in e&&(l||r||d),c={target:e},le(e,o.loadingClass),p&&(clearTimeout(u),u=Q(S,2500),de(e,D,!0)),d&&ae.call(s.getElementsByTagName("source"),z),l?e.setAttribute("srcset",l):r&&!d&&(k.test(e.nodeName)?j(e,r):e.src=r),a&&(l||d)&&ue(e,{src:r})),e._lazyRace&&delete e._lazyRace,se(e,o.lazyClass),me((function(){var t=e.complete&&e.naturalWidth>1;p&&!t||(t&&le(e,o.fastLoadedClass),M(c),e._lazyCache=!0,Q((function(){"_lazyCache"in e&&delete e._lazyCache}),9)),"lazy"==e.loading&&E--}),!0)})),q=function(e){if(!e._lazyRace){var t,n=_.test(e.nodeName),i=n&&(e.getAttribute(o.sizesAttr)||e.getAttribute("sizes")),a="auto"==i;(!a&&c||!n||!e.getAttribute("src")&&!e.srcset||e.complete||re(e,o.errorClass)||!re(e,o.lazyClass))&&(t=ce(e,"lazyunveilread").detail,a&&be.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,E++,L(e,t,a,i,n))}},R=ve((function(){o.loadMode=3,x()})),B=function(){c||(n.now()-f<999?Q(B,999):(c=!0,o.loadMode=3,x(),X("scroll",W,!0)))},{_:function(){f=n.now(),i.elements=t.getElementsByClassName(o.lazyClass),d=t.getElementsByClassName(o.lazyClass+" "+o.preloadClass),X("scroll",x,!0),X("resize",x,!0),X("pageshow",(function(e){if(e.persisted){var n=t.querySelectorAll("."+o.loadingClass);n.length&&n.forEach&&ee((function(){n.forEach((function(e){e.complete&&q(e)}))}))}})),e.MutationObserver?new MutationObserver(x).observe($,{childList:!0,subtree:!0,attributes:!0}):($.addEventListener("DOMNodeInserted",x,!0),$.addEventListener("DOMAttrModified",x,!0),setInterval(x,999)),X("hashchange",x,!0),["focus","mouseover","click","load","transitionend","animationend"].forEach((function(e){t.addEventListener(e,x,!0)})),/d$|^c/.test(t.readyState)?B():(X("load",B),t.addEventListener("DOMContentLoaded",x),Q(B,2e4)),i.elements.length?(T(),me._lsFlush()):x()},checkElems:x,unveil:q,_aLSL:W=function(){3==o.loadMode&&(o.loadMode=2),R()}}),be=(r=he((function(e,t,n,i){var o,a,r;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),ne.test(t.nodeName||""))for(a=0,r=(o=t.getElementsByTagName("source")).length;a<r;a++)o[a].setAttribute("sizes",i);n.detail.dataAttr||ue(e,n.detail)})),l=function(e,t,n){var i,o=e.parentNode;o&&(n=fe(e,o,n),(i=ce(e,"lazybeforesizes",{width:n,dataAttr:!!t})).defaultPrevented||(n=i.detail.width)&&n!==e._lazysizesWidth&&r(e,o,i,n))},{_:function(){a=t.getElementsByClassName(o.autosizesClass),X("resize",s)},checkElems:s=ve((function(){var e,t=a.length;if(t)for(e=0;e<t;e++)l(a[e])})),updateElem:l}),we=function(){!we.i&&t.getElementsByClassName&&(we.i=!0,be._(),ge._())};return Q((function(){o.init&&we()})),i={cfg:o,autoSizer:be,loader:ge,init:we,uP:ue,aC:le,rC:se,hC:re,fire:ce,gW:fe,rAF:me}}(t,t.document,Date);t.lazySizes=i,e.exports&&(e.exports=i)}("undefined"!=typeof window?window:{})}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{"use strict";const e={embed:null,tracking:null,retargeting:null,remarketing:null,storage:function(){var e={};Object.defineProperty(e,"visitor",{set:function(e){if(window.Pinpoll.embed){var t;try{t=JSON.parse(localStorage.PP_visitor).value}catch(e){t=null}t!==e&&setTimeout((function(){window.Pinpoll.embed.broadcast({action:"set:visitor",visitor:e})}))}try{localStorage.PP_visitor=e&&"null"!==e?JSON.stringify({value:e,expires:(new Date).setDate((new Date).getDate()+30)}):JSON.stringify({value:e,expires:0})}catch(e){console.warn(e)}},get:function(){try{if(!localStorage.PP_visitor)return null;var e=JSON.parse(localStorage.PP_visitor);return e.expires&&e.expires<Date.now()?(delete localStorage.PP_visitor,null):(e.expires=(new Date).setDate((new Date).getDate()+30),localStorage.PP_visitor=JSON.stringify(e),e.value)}catch(e){return console.warn(e),null}}});for(var t=function(){var t=i[n];Object.defineProperty(e,t.id,{set:function(e){try{localStorage[t.key]=JSON.stringify(e)}catch(e){console.warn(e)}},get:function(){try{var e=localStorage[t.key];return e?JSON.parse(e):t.d}catch(e){return console.warn(e),t.d}}})},n=0,i=[{id:"votes",key:"PP_votes",d:[]},{id:"leadForms",key:"PP_forms",d:[]},{id:"lastTriggered",key:"PP_marketing",d:null}];n<i.length;n++)t();try{localStorage.pinpoll_allVisitorVotes&&(localStorage.PP_votes=localStorage.pinpoll_allVisitorVotes,delete localStorage.pinpoll_allVisitorVotes)}catch(e){}return e}(),heightFilterActive:!1,nativeLoader:void 0,votelinkVotes:[],init:function(){var e=document.querySelector("script[src*='pinpoll.com/global.js'][data-app]");e&&(this.appName=e.getAttribute("data-app"))}};window.Pinpoll&&Object.keys(window.Pinpoll).length>0||(window.Pinpoll=e,e.init())})(),(()=>{"use strict";var e=__webpack_require__(558);window.Pinpoll.tracking||(window.Pinpoll.tracking=(0,e.Z)(window.Pinpoll.storage,{widgetIndex:"global"}),window.Pinpoll.tracking.start(window.Pinpoll.appName?{app:window.Pinpoll.appName}:void 0))})(),(()=>{"use strict";var e=__webpack_require__(38),t=__webpack_require__(58);function n(){var e;if(null!==(e=window.Pinpoll)&&void 0!==e&&e.appName)return!0;var t=window.navigator,n=t.userAgent.toLowerCase();return/iphone|ipod|ipad/.test(n)&&!window.MSStream?!t.standalone&&!/safari/.test(n):n.includes("wv")}var i=eval;window.Pinpoll.retargeting||(window.Pinpoll.retargeting=function(o,a){var r,l,s=(0,e.G)({RETARGETING_ENDPOINT:"https://api2.dmp.pinpoll.com",pixelsLoaded:!1,pixels:[],isMobileDevice:(l=!1,r=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(r)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|
658sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(r.substr(0,4)))&&(l=!0),l),isApp:n(),googleLoaded:!1,trackEmbedEvent:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;if(s.pixelsLoaded)d(e,n);else{var o=window.location!==window.parent.location?document.referrer:document.location.href;p({referrer:o,questionId:t,leadFormId:i}).then((function(t){s.pixelsLoaded=!0,t&&"success"===t.status&&t.data.length>0&&(s.pixels=t.data),d(e,n)})).catch((function(e){s.log("Retargeting Endpoint not reachable:",e)}))}},triggerPixels:function(e){c(e,!1)}});function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=s.pixels.filter((function(n){if(("vote"===e||"vote_click"===e)&&n.answer_id&&(!t.length||!t.includes(n.answer_id)))return!1;if("all"!==n.device_type){if(a&&n.device_type!==a)return!1;if(s.isApp&&"app"!==n.device_type)return!1;if(s.isMobileDevice&&"desktop"===n.device_type)return!1;if(!s.isMobileDevice&&"mobile"===n.device_type)return!1}return n.event===e}));(n=n.filter((function(e,t,n){return t===n.findIndex((function(t){return t.id===e.id}))}))).length&&c(n,!0)}function c(e,n){var a;e&&e.length>0&&(e.forEach((function(e){!function(e){switch(e.type){case"javascript":!function(e,t){e.externalcode?u({src:e.externalcode,async:!0},(function(){e.staticcode&&u({text:e.staticcode}),e.loaded=!0,t()})):e.staticcode?(u({text:e.staticcode}),e.loaded=!0,t()):t()}(e,(function(){e.trigger_code&&i(e.trigger_code)}));break;case"google":!function(e,t,n){if(window.google_trackConversion)window.google_trackConversion&&window.google_trackConversion({google_conversion_id:e,google_conversion_label:t,google_custom_value:n,google_custom_params:window.google_tag_params,google_remarketing_only:!0});else{var i=document.createElement("script");i.src="https://www.googleadservices.com/pagead/conversion_async.js",i.async=!0,i.addEventListener("load",(function(){s.googleLoaded=!0,window.google_trackConversion&&window.google_trackConversion({google_conversion_id:e,google_conversion_label:t,google_custom_value:n,google_custom_params:window.google_tag_params,google_remarketing_only:!0})}),!1),document.body.appendChild(i)}}(e.conversion_id,e.conversion_label,e.custom_value);break;case"facebook":e.event&&(e.group_title=e.event),function(e,t,n){if(function(e,t,n,i,o,a,r){e.fbq||(o=e.fbq=function(){o.callMethod?o.callMethod.apply(o,arguments):o.queue.push(arguments)},e._fbq||(e._fbq=o),o.push=o,o.loaded=!0,o.version="2.0",o.queue=[],(a=t.createElement(n)).async=!0,a.src="https://connect.facebook.net/en_US/fbevents.js",(r=t.getElementsByTagName(n)[0]).parentNode.insertBefore(a,r))}(window,document,"script"),window.fbq){window.fbq("init",e),window.fbq("track","PageView");var i="string"==typeof n&&n.length>0?{customValue:n}:{};window.fbq("trackCustom",t,i)}}(e.facebook_id,e.group_title,e.custom_value);break;case"image":t=e.source,(n=new Image).onload=function(){n.naturalHeight+n.naturalWidth!==0?document.body.appendChild(n):s.log("Error on loadImage: natural height and width === 0")},n.onerror=function(e){s.log(e)},t&&(n.src=t);break;default:s.log("Pixel execution error: no type specified!")}var t,n}(e)})),n&&(a={triggeredPixels:e.map((function(e){return{pixel_id:e.id,campaign_id:e.campaign_id}}))},(0,t.w)(s.RETARGETING_ENDPOINT+"/public/triggered",a,o).then((function(e){return e.json()})).then((function(e){"success"!==e.status&&s.log("Return type of triggered data did not success!",e.data)})).catch((function(e){s.log("Failed to send triggered data!",e)}))))}function u(e,t){var n=document.createElement("script");Object.keys(e).forEach((function(t){n[t]=e[t]})),t&&"function"==typeof t&&n.addEventListener("load",(function(e){t(null,e)}),!1),document.body.appendChild(n)}function p(e){return(0,t.w)(s.RETARGETING_ENDPOINT+"/public/tr",e,o).then((function(e){return e.json()}))}return s}(window.Pinpoll.storage),window.Pinpoll.remarketing=function(n,i){var o=(0,e.G)({RETARGETING_ENDPOINT:"https://api2.dmp.pinpoll.com",REMARKETING_MAX_TRIGGER_TIME:parseInt("MISSING_ENV_VAR".MIX_REMARKETING_MAX_TRIGGER_TIME||"",10)||36e5,start:function(){window.requestIdleCallback?window.requestIdleCallback((function(){a()}),{timeout:3e3}):window.setTimeout((function(){a()}),3e3)}});function a(){var e,a;!(a=i.lastTriggered)||Date.now()-a>o.REMARKETING_MAX_TRIGGER_TIME?(e={referrer:window.location.origin||window.location.hostname},(0,t.w)(o.RETARGETING_ENDPOINT+"/public/remarketing",e,i).then((function(e){return e.json()}))).then((function(e){i.lastTriggered=Date.now(),e.data.length&&n.triggerPixels(e.data)})).catch((function(e){o.log("Failed to send getRemarketingPixels",e)})):o.log("Checked Remarketing; last triggered happened within max trigger time, last triggered at:",i.lastTriggered)}return o.start(),o}(window.Pinpoll.retargeting,window.Pinpoll.storage))})(),(()=>{"use strict";var e=__webpack_require__(631);__webpack_require__(90),__webpack_require__(726),window.Pinpoll.embed||(window.Pinpoll.embed=(0,e.ZP)(),window.Pinpoll.embed.start())})()})(); 659/*! 660 Colorbox 1.6.3 661 license: MIT 662 http://www.jacklmoore.com/colorbox 663*/
vendor: 4,671 bytes, line 664
664(function(t,e,i){function n(i,n,o){var r=e.createElement(i);return n&&(r.id=Z+n),o&&(r.style.cssText=o),t(r)}function o(){return i.innerHeight?i.innerHeight:t(i).height()}function r(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return void 0===this.cache[e]&&(n=t(this.el).attr("data-cbox-"+e),void 0!==n?this.cache[e]=n:void 0!==i[e]?this.cache[e]=i[e]:void 0!==X[e]&&(this.cache[e]=X[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function h(t){var e=W.length,i=(A+t)%e;return 0>i?e+i:i}function a(t,e){return Math.round((/%/.test(t)?("x"===e?E.width():o())/100:1)*parseInt(t,10))}function s(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function l(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function d(t){"contains"in x[0]&&!x[0].contains(t.target)&&t.target!==v[0]&&(t.stopPropagation(),x.focus())}function c(t){c.str!==t&&(x.add(v).removeClass(c.str).addClass(t),c.str=t)}function g(e){A=0,e&&e!==!1&&"nofollow"!==e?(W=t("."+te).filter(function(){var i=t.data(this,Y),n=new r(this,i);return n.get("rel")===e}),A=W.index(_.el),-1===A&&(W=W.add(_.el),A=W.length-1)):W=t(_.el)}function u(i){t(e).trigger(i),ae.triggerHandler(i)}function f(i){var o;if(!G){if(o=t(i).data(Y),_=new r(i,o),g(_.get("rel")),!$){$=q=!0,c(_.get("className")),x.css({visibility:"hidden",display:"block",opacity:""}),I=n(se,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),b.css({width:"",height:""}).append(I),j=T.height()+k.height()+b.outerHeight(!0)-b.height(),D=C.width()+H.width()+b.outerWidth(!0)-b.width(),N=I.outerHeight(!0),z=I.outerWidth(!0);var h=a(_.get("initialWidth"),"x"),s=a(_.get("initialHeight"),"y"),l=_.get("maxWidth"),f=_.get("maxHeight");_.w=Math.max((l!==!1?Math.min(h,a(l,"x")):h)-z-D,0),_.h=Math.max((f!==!1?Math.min(s,a(f,"y")):s)-N-j,0),I.css({width:"",height:_.h}),J.position(),u(ee),_.get("onOpen"),O.add(F).hide(),x.focus(),_.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",d,!0),ae.one(re,function(){e.removeEventListener("focus",d,!0)})),_.get("returnFocus")&&ae.one(re,function(){t(_.el).focus()})}var p=parseFloat(_.get("opacity"));v.css({opacity:p===p?p:"",cursor:_.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),_.get("closeButton")?B.html(_.get("close")).appendTo(b):B.appendTo("<div/>"),w()}}function p(){x||(V=!1,E=t(i),x=n(se).attr({id:Y,"class":t.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),v=n(se,"Overlay").hide(),L=t([n(se,"LoadingOverlay")[0],n(se,"LoadingGraphic")[0]]),y=n(se,"Wrapper"),b=n(se,"Content").append(F=n(se,"Title"),R=n(se,"Current"),P=t('<button type="button"/>').attr({id:Z+"Previous"}),K=t('<button type="button"/>').attr({id:Z+"Next"}),S=n("button","Slideshow"),L),B=t('<button type="button"/>').attr({id:Z+"Close"}),y.append(n(se).append(n(se,"TopLeft"),T=n(se,"TopCenter"),n(se,"TopRight")),n(se,!1,"clear:left").append(C=n(se,"MiddleLeft"),b,H=n(se,"MiddleRight")),n(se,!1,"clear:left").append(n(se,"BottomLeft"),k=n(se,"BottomCenter"),n(se,"BottomRight"))).find("div div").css({"float":"left"}),M=n(se,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),O=K.add(P).add(R).add(S)),e.body&&!x.parent().length&&t(e.body).append(v,x.append(y,M))}function m(){function i(t){t.which>1||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),f(this))}return x?(V||(V=!0,K.click(function(){J.next()}),P.click(function(){J.prev()}),B.click(function(){J.close()}),v.click(function(){_.get("overlayClose")&&J.close()}),t(e).bind("keydown."+Z,function(t){var e=t.keyCode;$&&_.get("escKey")&&27===e&&(t.preventDefault(),J.close()),$&&_.get("arrowKey")&&W[1]&&!t.altKey&&(37===e?(t.preventDefault(),P.click()):39===e&&(t.preventDefault(),K.click()))}),t.isFunction(t.fn.on)?t(e).on("click."+Z,"."+te,i):t("."+te).live("click."+Z,i)),!0):!1}function w(){var e,o,r,h=J.prep,d=++le;if(q=!0,U=!1,u(he),u(ie),_.get("onLoad"),_.h=_.get("height")?a(_.get("height"),"y")-N-j:_.get("innerHeight")&&a(_.get("innerHeight"),"y"),_.w=_.get("width")?a(_.get("width"),"x")-z-D:_.get("innerWidth")&&a(_.get("innerWidth"),"x"),_.mw=_.w,_.mh=_.h,_.get("maxWidth")&&(_.mw=a(_.get("maxWidth"),"x")-z-D,_.mw=_.w&&_.w<_.mw?_.w:_.mw),_.get("maxHeight")&&(_.mh=a(_.get("maxHeight"),"y")-N-j,_.mh=_.h&&_.h<_.mh?_.h:_.mh),e=_.get("href"),Q=setTimeout(function(){L.show()},100),_.get("inline")){var c=t(e);r=t("<div>").hide().insertBefore(c),ae.one(he,function(){r.replaceWith(c)}),h(c)}else _.get("iframe")?h(" "):_.get("html")?h(_.get("html")):s(_,e)?(e=l(_,e),U=_.get("
664createImg"),t(U).addClass(Z+"Photo").bind("error."+Z,function(){h(n(se,"Error").html(_.get("imgError")))}).one("load",function(){d===le&&setTimeout(function(){var e;_.get("retinaImage")&&i.devicePixelRatio>1&&(U.height=U.height/i.devicePixelRatio,U.width=U.width/i.devicePixelRatio),_.get("scalePhotos")&&(o=function(){U.height-=U.height*e,U.width-=U.width*e},_.mw&&U.width>_.mw&&(e=(U.width-_.mw)/U.width,o()),_.mh&&U.height>_.mh&&(e=(U.height-_.mh)/U.height,o())),_.h&&(U.style.marginTop=Math.max(_.mh-U.height,0)/2+"px"),W[1]&&(_.get("loop")||W[A+1])&&(U.style.cursor="pointer",t(U).bind("click."+Z,function(){J.next()})),U.style.width=U.width+"px",U.style.height=U.height+"px",h(U)},1)}),U.src=e):e&&M.load(e,_.get("data"),function(e,i){d===le&&h("error"===i?n(se,"Error").html(_.get("xhrError")):t(this).contents())})}var v,x,y,b,T,C,H,k,W,E,I,M,L,F,R,S,K,P,B,O,_,j,D,N,z,A,U,$,q,G,Q,J,V,X={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,rel:function(){return this.rel},href:function(){return t(this).attr("href")},title:function(){return this.title},createImg:function(){var e=new Image,i=t(this).data("cbox-img-attrs");return"object"==typeof i&&t.each(i,function(t,i){e[t]=i}),e},createIframe:function(){var i=e.createElement("iframe"),n=t(this).data("cbox-iframe-attrs");return"object"==typeof n&&t.each(n,function(t,e){i[t]=e}),"frameBorder"in i&&(i.frameBorder=0),"allowTransparency"in i&&(i.allowTransparency="true"),i.name=(new Date).getTime(),i.allowFullscreen=!0,i}},Y="colorbox",Z="cbox",te=Z+"Element",ee=Z+"_open",ie=Z+"_load",ne=Z+"_complete",oe=Z+"_cleanup",re=Z+"_closed",he=Z+"_purge",ae=t("<a/>"),se="div",le=0,de={},ce=function(){function t(){clearTimeout(h)}function e(){(_.get("loop")||W[A+1])&&(t(),h=setTimeout(J.next,_.get("slideshowSpeed")))}function i(){S.html(_.get("slideshowStop")).unbind(s).one(s,n),ae.bind(ne,e).bind(ie,t),x.removeClass(a+"off").addClass(a+"on")}function n(){t(),ae.unbind(ne,e).unbind(ie,t),S.html(_.get("slideshowStart")).unbind(s).one(s,function(){J.next(),i()}),x.removeClass(a+"on").addClass(a+"off")}function o(){r=!1,S.hide(),t(),ae.unbind(ne,e).unbind(ie,t),x.removeClass(a+"off "+a+"on")}var r,h,a=Z+"Slideshow_",s="click."+Z;return function(){r?_.get("slideshow")||(ae.unbind(oe,o),o()):_.get("slideshow")&&W[1]&&(r=!0,ae.one(oe,o),_.get("slideshowAuto")?i():n(),S.show())}}();t[Y]||(t(p),J=t.fn[Y]=t[Y]=function(e,i){var n,o=this;return e=e||{},t.isFunction(o)&&(o=t("<a/>"),e.open=!0),o[0]?(p(),m()&&(i&&(e.onComplete=i),o.each(function(){var i=t.data(this,Y)||{};t.data(this,Y,t.extend(i,e))}).addClass(te),n=new r(o[0],e),n.get("open")&&f(o[0])),o):o},J.position=function(e,i){function n(){T[0].style.width=k[0].style.width=b[0].style.width=parseInt(x[0].style.width,10)-D+"px",b[0].style.height=C[0].style.height=H[0].style.height=parseInt(x[0].style.height,10)-j+"px"}var r,h,s,l=0,d=0,c=x.offset();if(E.unbind("resize."+Z),x.css({top:-9e4,left:-9e4}),h=E.scrollTop(),s=E.scrollLeft(),_.get("fixed")?(c.top-=h,c.left-=s,x.css({position:"fixed"})):(l=h,d=s,x.css({position:"absolute"})),d+=_.get("right")!==!1?Math.max(E.width()-_.w-z-D-a(_.get("right"),"x"),0):_.get("left")!==!1?a(_.get("left"),"x"):Math.round(Math.max(E.width()-_.w-z-D,0)/2),l+=_.get("bottom")!==!1?Math.max(o()-_.h-N-j-a(_.get("bottom"),"y"),0):_.get("top")!==!1?a(_.get("top"),"y"):Math.round(Math.max(o()-_.h-N-j,0)/2),x.css({top:c.top,left
664:c.left,visibility:"visible"}),y[0].style.width=y[0].style.height="9999px",r={width:_.w+z+D,height:_.h+N+j,top:l,left:d},e){var g=0;t.each(r,function(t){return r[t]!==de[t]?(g=e,void 0):void 0}),e=g}de=r,e||x.css(r),x.dequeue().animate(r,{duration:e||0,complete:function(){n(),q=!1,y[0].style.width=_.w+z+D+"px",y[0].style.height=_.h+N+j+"px",_.get("reposition")&&setTimeout(function(){E.bind("resize."+Z,J.position)},1),t.isFunction(i)&&i()},step:n})},J.resize=function(t){var e;$&&(t=t||{},t.width&&(_.w=a(t.width,"x")-z-D),t.innerWidth&&(_.w=a(t.innerWidth,"x")),I.css({width:_.w}),t.height&&(_.h=a(t.height,"y")-N-j),t.innerHeight&&(_.h=a(t.innerHeight,"y")),t.innerHeight||t.height||(e=I.scrollTop(),I.css({height:"auto"}),_.h=I.height()),I.css({height:_.h}),e&&I.scrollTop(e),J.position("none"===_.get("transition")?0:_.get("speed")))},J.prep=function(i){function o(){return _.w=_.w||I.width(),_.w=_.mw&&_.mw<_.w?_.mw:_.w,_.w}function a(){return _.h=_.h||I.height(),_.h=_.mh&&_.mh<_.h?_.mh:_.h,_.h}if($){var d,g="none"===_.get("transition")?0:_.get("speed");I.remove(),I=n(se,"LoadedContent").append(i),I.hide().appendTo(M.show()).css({width:o(),overflow:_.get("scrolling")?"auto":"hidden"}).css({height:a()}).prependTo(b),M.hide(),t(U).css({"float":"none"}),c(_.get("className")),d=function(){function i(){t.support.opacity===!1&&x[0].style.removeAttribute("filter")}var n,o,a=W.length;$&&(o=function(){clearTimeout(Q),L.hide(),u(ne),_.get("onComplete")},F.html(_.get("title")).show(),I.show(),a>1?("string"==typeof _.get("current")&&R.html(_.get("current").replace("{current}",A+1).replace("{total}",a)).show(),K[_.get("loop")||a-1>A?"show":"hide"]().html(_.get("next")),P[_.get("loop")||A?"show":"hide"]().html(_.get("previous")),ce(),_.get("preloading")&&t.each([h(-1),h(1)],function(){var i,n=W[this],o=new r(n,t.data(n,Y)),h=o.get("href");h&&s(o,h)&&(h=l(o,h),i=e.createElement("img"),i.src=h)})):O.hide(),_.get("iframe")?(n=_.get("createIframe"),_.get("scrolling")||(n.scrolling="no"),t(n).attr({src:_.get("href"),"class":Z+"Iframe"}).one("load",o).appendTo(I),ae.one(he,function(){n.src="//about:blank"}),_.get("fastIframe")&&t(n).trigger("load")):o(),"fade"===_.get("transition")?x.fadeTo(g,1,i):i())},"fade"===_.get("transition")?x.fadeTo(g,0,function(){J.position(0,d)}):J.position(g,d)}},J.next=function(){!q&&W[1]&&(_.get("loop")||W[A+1])&&(A=h(1),f(W[A]))},J.prev=function(){!q&&W[1]&&(_.get("loop")||A)&&(A=h(-1),f(W[A]))},J.close=function(){$&&!G&&(G=!0,$=!1,u(oe),_.get("onCleanup"),E.unbind("."+Z),v.fadeTo(_.get("fadeOut")||0,0),x.stop().fadeTo(_.get("fadeOut")||0,0,function(){x.hide(),v.hide(),u(he),I.remove(),setTimeout(function(){G=!1,u(re),_.get("onClosed")},1)}))},J.remove=function(){x&&(x.stop(),t[Y].close(),x.stop(!1,!0).remove(),v.remove(),G=!1,x=null,t("."+te).removeData(Y).removeClass(te),t(e).unbind("click."+Z).unbind("keydown."+Z))},J.element=function(){return t(_.el)},J.settings=X)})(jQuery,document,window); 665/* Javascript plotting library for jQuery, version 0.8.3. 666 667Copyright (c) 2007-2014 IOLA and Ole Laursen. 668Licensed under the MIT license. 669 670*/ 671 672// first an inline dependency, jquery.colorhelpers.js, we inline it here 673// for convenience 674 675/* Plugin for jQuery for working with colors. 676 * 677 * Version 1.1. 678 * 679 * Inspiration from jQuery color animation plugin by John Resig. 680 * 681 * Released under the MIT license by Ole Laursen, October 2009. 682 * 683 * Examples: 684 * 685 * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() 686 * var c = $.color.extract($("#mydiv"), 'background-color'); 687 * console.log(c.r, c.g, c.b, c.a); 688 * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" 689 * 690 * Note that .scale() and .add() return the same modified object 691 * instead of making a new one. 692 * 693 * V. 1.1: Fix error handling so e.g. parsing an empty string does 694 * produce a color rather than just crashing. 695 */ 696(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3}
vendor: 124,626 bytes, lines 696-3847
696)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); 697 698// the actual Flot code 699(function($) { 700 701 // Cache the prototype hasOwnProperty for faster access 702 703 var hasOwnProperty = Object.prototype.hasOwnProperty; 704 705 // A shim to provide 'detach' to jQuery versions prior to 1.4. Using a DOM 706 // operation produces the same effect as detach, i.e. removing the element 707 // without touching its jQuery data. 708 709 // Do not merge this into Flot 0.9, since it requires jQuery 1.4.4+. 710 711 if (!$.fn.detach) { 712 $.fn.detach = function() { 713 return this.each(function() { 714 if (this.parentNode) { 715 this.parentNode.removeChild( this ); 716 } 717 }); 718 }; 719 } 720 721 /////////////////////////////////////////////////////////////////////////// 722 // The Canvas object is a wrapper around an HTML5 <canvas> tag. 723 // 724 // @constructor 725 // @param {string} cls List of classes to apply to the canvas. 726 // @param {element} container Element onto which to append the canvas. 727 // 728 // Requiring a container is a little iffy, but unfortunately canvas 729 // operations don't work unless the canvas is attached to the DOM. 730 731 function Canvas(cls, container) { 732 733 var element = container.children("." + cls)[0]; 734 735 if (element == null) { 736 737 element = document.createElement("canvas"); 738 element.className = cls; 739 740 $(element).css({ direction: "ltr", position: "absolute", left: 0, top: 0 }) 741 .appendTo(container); 742 743 // If HTML5 Canvas isn't available, fall back to [Ex|Flash]canvas 744 745 if (!element.getContext) { 746 if (window.G_vmlCanvasManager) { 747 element = window.G_vmlCanvasManager.initElement(element); 748 } else { 749 throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode."); 750 } 751 } 752 } 753 754 this.element = element; 755 756 var context = this.context = element.getContext("2d"); 757 758 // Determine the screen's ratio of physical to device-independent 759 // pixels. This is the ratio between the canvas width that the browser 760 // advertises and the number of pixels actually present in that space. 761 762 // The iPhone 4, for example, has a device-independent width of 320px, 763 // but its screen is actually 640px wide. It therefore has a pixel 764 // ratio of 2, while most normal devices have a ratio of 1. 765 766 var devicePixelRatio = window.devicePixelRatio || 1, 767 backingStoreRatio = 768 context.webkitBackingStorePixelRatio || 769 context.mozBackingStorePixelRatio || 770 context.msBackingStorePixelRatio || 771 context.oBackingStorePixelRatio || 772 context.backingStorePixelRatio || 1; 773 774 this.pixelRatio = devicePixelRatio / backingStoreRatio; 775 776 // Size the canvas to match the internal dimensions of its container 777 778 this.resize(container.width(), container.height()); 779 780 // Collection of HTML div layers for text overlaid onto the canvas 781 782 this.textContainer = null; 783 this.text = {}; 784 785 // Cache of text fragments and metrics, so we can avoid expensively 786 // re-calculating them when the plot is re-rendered in a loop. 787 788 this._textCache = {}; 789 } 790 791 // Resizes the canvas to the given dimensions. 792 // 793 // @param {number} width New width of the canvas, in pixels. 794 // @param {number} width New height of the canvas, in pixels. 795 796 Canvas.prototype.resize = function(width, height) { 797 798 if (width <= 0 || height <= 0) { 799 throw new Error("Invalid dimensions for plot, width = " + width + ", height = " + height); 800 } 801 802 var element = this.element, 803 context = this.context, 804 pixelRatio = this.pixelRatio; 805 806 // Resize the canvas, increasing its density based on the display's 807 // pixel ratio; basically giving it more pixels without increasing the 808 // size of its element, to take advantage of the fact that retina 809 // displays have that many more pixels in the same advertised space. 810 811 // Resizing should reset the state (excanvas seems to be buggy though) 812 813 if (this.width != width) { 814 element.width = width * pixelRatio; 815 element.style.width = width + "px"; 816 this.width = width; 817 } 818 819 if (this.height != height) { 820 element.height = height * pixelRatio; 821 element.style.height = height + "px"; 822 this.height = height; 823 } 824 825 // Save the context, so we can reset in case we get replotted. The 826 // restore ensure that we're really back at the initial state, and 827 // should be safe even if we haven't saved the initial state yet. 828 829 context.restore(); 830 context.save(); 831 832 // Scale the coordinate space to match the display density; so even though we 833 // may have twice as many pixels, we still want lines and other drawing to 834 // appear at the same size; the extra pixels will just make them crisper. 835 836 context.scale(pixelRatio, pixelRatio); 837 }; 838 839 // Clears the entire canvas area, not including any overlaid HTML text 840 841 Canvas.prototype.clear = function() { 842 this.context.clearRect(0, 0, this.width, this.height); 843 }; 844 845 // Finishes rendering the canvas, including managing the text overlay. 846 847 Canvas.prototype.render = function() { 848 849 var cache = this._textCache; 850 851 // For each text layer, add elements marked as active that haven't 852 // already been rendered, and remove those that are no longer active. 853 854 for (var layerKey in cache) { 855 if (hasOwnProperty.call(cache, layerKey)) { 856 857 var layer = this.getTextLayer(layerKey), 858 layerCache = cache[layerKey]; 859 860 layer.hide(); 861 862 for (var styleKey in layerCache) { 863 if (hasOwnProperty.call(layerCache, styleKey)) { 864 var styleCache = layerCache[styleKey]; 865 for (var key in styleCache) { 866 if (hasOwnProperty.call(styleCache, key)) { 867 868 var positions = styleCache[key].positions; 869 870 for (var i = 0, position; position = positions[i]; i++) { 871 if (position.active) { 872 if (!position.rendered) { 873 layer.append(position.element); 874 position.rendered = true; 875 } 876 } else { 877 positions.splice(i--, 1); 878 if (position.rendered) { 879 position.element.detach(); 880 } 881 } 882 } 883 884 if (positions.length == 0) { 885 delete styleCache[key]; 886 } 887 } 888 } 889 } 890 } 891 892 layer.show(); 893 } 894 } 895 }; 896 897 // Creates (if necessary) and returns the text overlay container. 898 // 899 // @param {string} classes String of space-separated CSS classes used to 900 // uniquely identify the text layer. 901 // @return {object} The jQuery-wrapped text-layer div. 902 903 Canvas.prototype.getTextLayer = function(classes) { 904 905 var layer = this.text[classes]; 906 907 // Create the text layer if it doesn't exist 908 909 if (layer == null) { 910 911 // Create the text layer container, if it doesn't exist 912 913 if (this.textContainer == null) { 914 this.textContainer = $("<div class='flot-text'></div>") 915 .css({ 916 position: "absolute", 917 top: 0, 918 left: 0, 919 bottom: 0, 920 right: 0, 921 'font-size': "smaller", 922 color: "#545454" 923 }) 924 .insertAfter(this.element); 925 } 926 927 layer = this.text[classes] = $("<div></div>") 928 .addClass(classes) 929 .css({ 930 position: "absolute", 931 top: 0, 932 left: 0, 933 bottom: 0, 934 right: 0 935 }) 936 .appendTo(this.textContainer); 937 } 938 939 return layer; 940 }; 941 942 // Creates (if necessary) and returns a text info object. 943 // 944 // The object looks like this: 945 // 946 // { 947 // width: Width of the text's wrapper div. 948 // height: Height of the text's wrapper div. 949 // element: The jQuery-wrapped HTML div containing the text. 950 // positions: Array of positions at which this text is drawn. 951 // } 952 // 953 // The positions array contains objects that look like this: 954 // 955 // { 956 // active: Flag indicating whether the text should be visible. 957 // rendered: Flag indicating whether the text is currently visible. 958 // element: The jQuery-wrapped HTML div containing the text. 959 // x: X coordinate at which to draw the text. 960 // y: Y coordinate at which to draw the text. 961 // } 962 // 963 // Each position after the first receives a clone of the original element. 964 // 965 // The idea is that that the width, height, and general 'identity' of the 966 // text is constant no matter where it is placed; the placements are a 967 // secondary property. 968 // 969 // Canvas maintains a cache of recently-used text info objects; getTextInfo 970 // either returns the cached element or creates a new entry. 971 // 972 // @param {string} layer A string of space-separated CSS classes uniquely 973 // identifying the layer containing this text. 974 // @param {string} text Text string to retrieve info for. 975 // @param {(string|object)=} font Either a string of space-separated CSS 976 // classes or a font-spec object, defining the text's font and style. 977 // @param {number=} angle Angle at which to rotate the text, in degrees. 978 // Angle is currently unused, it will be implemented in the future. 979 // @param {number=} width Maximum width of the text before it wraps. 980 // @return {object} a text info object. 981 982 Canvas.prototype.getTextInfo = function(layer, text, font, angle, width) { 983 984 var textStyle, layerCache, styleCache, info; 985 986 // Cast the value to a string, in case we were given a number or such 987 988 text = "" + text; 989 990 // If the font is a font-spec object, generate a CSS font definition 991 992 if (typeof font === "object") { 993 textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px/" + font.lineHeight + "px " + font.family; 994 } else { 995 textStyle = font; 996 } 997 998 // Retrieve (or create) the cache for the text's layer and styles 999 1000 layerCache = this._textCache[layer]; 1001 1002 if (layerCache == null) { 1003 layerCache = this._textCache[layer] = {}; 1004 } 1005 1006 styleCache = layerCache[textStyle]; 1007 1008 if (styleCache == null) { 1009 styleCache = layerCache[textStyle] = {}; 1010 } 1011 1012 info = styleCache[text]; 1013 1014 // If we can't find a matching element in our cache, create a new one 1015 1016 if (info == null) { 1017 1018 var element = $("<div></div>").html(text) 1019 .css({ 1020 position: "absolute", 1021 'max-width': width, 1022 top: -9999 1023 }) 1024 .appendTo(this.getTextLayer(layer)); 1025 1026 if (typeof font === "object") { 1027 element.css({ 1028 font: textStyle, 1029 color: font.color 1030 }); 1031 } else if (typeof font === "string") { 1032 element.addClass(font); 1033 } 1034 1035 info = styleCache[text] = { 1036 width: element.outerWidth(true), 1037 height: element.outerHeight(true), 1038 element: element, 1039 positions: [] 1040 }; 1041 1042 element.detach(); 1043 } 1044 1045 return info; 1046 }; 1047 1048 // Adds a text string to the canvas text overlay. 1049 // 1050 // The text isn't drawn immediately; it is marked as rendering, which will 1051 // result in its addition to the canvas on the next render pass. 1052 // 1053 // @param {string} layer A string of space-separated CSS classes uniquely 1054 // identifying the layer containing this text. 1055 // @param {number} x X coordinate at which to draw the text. 1056 // @param {number} y Y coordinate at which to draw the text. 1057 // @param {string} text Text string to draw. 1058 // @param {(string|object)=} font Either a string of space-separated CSS 1059 // classes or a font-spec object, defining the text's font and style. 1060 // @param {number=} angle Angle at which to rotate the text, in degrees. 1061 // Angle is currently unused, it will be implemented in the future. 1062 // @param {number=} width Maximum width of the text before it wraps. 1063 // @param {string=} halign Horizontal alignment of the text; either "left", 1064 // "center" or "right". 1065 // @param {string=} valign Vertical alignment of the text; either "top", 1066 // "middle" or "bottom". 1067 1068 Canvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) { 1069 1070 var info = this.getTextInfo(layer, text, font, angle, width), 1071 positions = info.positions; 1072 1073 // Tweak the div's position to match the text's alignment 1074 1075 if (halign == "center") { 1076 x -= info.width / 2; 1077 } else if (halign == "right") { 1078 x -= info.width; 1079 } 1080 1081 if (valign == "middle") { 1082 y -= info.height / 2; 1083 } else if (valign == "bottom") { 1084 y -= info.height; 1085 } 1086 1087 // Determine whether this text already exists at this position. 1088 // If so, mark it for inclusion in the next render pass. 1089 1090 for (var i = 0, position; position = positions[i]; i++) { 1091 if (position.x == x && position.y == y) { 1092 position.active = true; 1093 return; 1094 } 1095 } 1096 1097 // If the text doesn't exist at this position, create a new entry 1098 1099 // For the very first position we'll re-use the original element, 1100 // while for subsequent ones we'll clone it. 1101 1102 position = { 1103 active: true, 1104 rendered: false, 1105 element: positions.length ? info.element.clone() : info.element, 1106 x: x, 1107 y: y 1108 }; 1109 1110 positions.push(position); 1111 1112 // Move the element to its final position within the container 1113 1114 position.element.css({ 1115 top: Math.round(y), 1116 left: Math.round(x), 1117 'text-align': halign // In case the text wraps 1118 }); 1119 }; 1120 1121 // Removes one or more text strings from the canvas text overlay. 1122 // 1123 // If no parameters are given, all text within the layer is removed. 1124 // 1125 // Note that the text is not immediately removed; it is simply marked as 1126 // inactive, which will result in its removal on the next render pass. 1127 // This avoids the performance penalty for 'clear and redraw' behavior, 1128 // where we potentially get rid of all text on a layer, but will likely 1129 // add back most or all of it later, as when redrawing axes, for example. 1130 // 1131 // @param {string} layer A string of space-separated CSS classes uniquely 1132 // identifying the layer containing this text. 1133 // @param {number=} x X coordinate of the text. 1134 // @param {number=} y Y coordinate of the text. 1135 // @param {string=} text Text string to remove. 1136 // @param {(string|object)=} font Either a string of space-separated CSS 1137 // classes or a font-spec object, defining the text's font and style. 1138 // @param {number=} angle Angle at which the text is rotated, in degrees. 1139 // Angle is currently unused, it will be implemented in the future. 1140 1141 Canvas.prototype.removeText = function(layer, x, y, text, font, angle) { 1142 if (text == null) { 1143 var layerCache = this._textCache[layer]; 1144 if (layerCache != null) { 1145 for (var styleKey in layerCache) { 1146 if (hasOwnProperty.call(layerCache, styleKey)) { 1147 var styleCache = layerCache[styleKey]; 1148 for (var key in styleCache) { 1149 if (hasOwnProperty.call(styleCache, key)) { 1150 var positions = styleCache[key].positions; 1151 for (var i = 0, position; position = positions[i]; i++) { 1152 position.active = false; 1153 } 1154 } 1155 } 1156 } 1157 } 1158 } 1159 } else { 1160 var positions = this.getTextInfo(layer, text, font, angle).positions; 1161 for (var i = 0, position; position = positions[i]; i++) { 1162 if (position.x == x && position.y == y) { 1163 position.active = false; 1164 } 1165 } 1166 } 1167 }; 1168 1169 /////////////////////////////////////////////////////////////////////////// 1170 // The top-level container for the entire plot. 1171 1172 function Plot(placeholder, data_, options_, plugins) { 1173 // data is on the form: 1174 // [ series1, series2 ... ] 1175 // where series is either just the data as [ [x1, y1], [x2, y2], ... ] 1176 // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... } 1177 1178 var series = [], 1179 options = { 1180 // the color theme used for graphs 1181 colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"], 1182 legend: { 1183 show: true, 1184 noColumns: 1, // number of colums in legend table 1185 labelFormatter: null, // fn: string -> string 1186 labelBoxBorderColor: "#ccc", // border color for the little label boxes 1187 container: null, // container (as jQuery object) to put legend in, null means default on top of graph 1188 position: "ne", // position of default legend container within plot 1189 margin: 5, // distance from grid edge to default legend container within plot 1190 backgroundColor: null, // null means auto-detect 1191 backgroundOpacity: 0.85, // set to 0 to avoid background 1192 sorted: null // default to no legend sorting 1193 }, 1194 xaxis: { 1195 show: null, // null = auto-detect, true = always, false = never 1196 position: "bottom", // or "top" 1197 mode: null, // null or "time" 1198 font: null, // null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" } 1199 color: null, // base color, labels, ticks 1200 tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)" 1201 transform: null, // null or f: number -> number to transform axis 1202 inverseTransform: null, // if transform is set, this should be the inverse function 1203 min: null, // min. value to show, null means set automatically 1204 max: null, // max. value to show, null means set automatically 1205 autoscaleMargin: null, // margin in % to add if auto-setting min/max 1206 ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks 1207 tickFormatter: null, // fn: number -> string 1208 labelWidth: null, // size of tick labels in pixels 1209 labelHeight: null, 1210 reserveSpace: null, // whether to reserve space even if axis isn't shown 1211 tickLength: null, // size in pixels of ticks, or "full" for whole line 1212 alignTicksWithAxis: null, // axis number or null for no sync 1213 tickDecimals: null, // no. of decimals, null means auto 1214 tickSize: null, // number or [number, "unit"] 1215 minTickSize: null // number or [number, "unit"] 1216 }, 1217 yaxis: { 1218 autoscaleMargin: 0.02, 1219 position: "left" // or "right" 1220 }, 1221 xaxes: [], 1222 yaxes: [], 1223 series: { 1224 points: { 1225 show: false, 1226 radius: 3, 1227 lineWidth: 2, // in pixels 1228 fill: true, 1229 fillColor: "#ffffff", 1230 symbol: "circle" // or callback 1231 }, 1232 lines: { 1233 // we don't put in show: false so we can see 1234 // whether lines were actively disabled 1235 lineWidth: 2, // in pixels 1236 fill: false, 1237 fillColor: null, 1238 steps: false 1239 // Omit 'zero', so we can later default its value to 1240 // match that of the 'fill' option. 1241 }, 1242 bars: { 1243 show: false, 1244 lineWidth: 2, // in pixels 1245 barWidth: 1, // in units of the x axis 1246 fill: true, 1247 fillColor: null, 1248 align: "left", // "left", "right", or "center" 1249 horizontal: false, 1250 zero: true 1251 }, 1252 shadowSize: 3, 1253 highlightColor: null 1254 }, 1255 grid: { 1256 show: true, 1257 aboveData: false, 1258 color: "#545454", // primary color used for outline and labels 1259 backgroundColor: null, // null for transparent, else color 1260 borderColor: null, // set if different from the grid color 1261 tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)" 1262 margin: 0, // distance from the canvas edge to the grid 1263 labelMargin: 5, // in pixels 1264 axisMargin: 8, // in pixels 1265 borderWidth: 2, // in pixels 1266 minBorderMargin: null, // in pixels, null means taken from points radius 1267 markings: null, // array of ranges or fn: axes -> array of ranges 1268 markingsColor: "#f4f4f4", 1269 markingsLineWidth: 2, 1270 // interactive stuff 1271 clickable: false, 1272 hoverable: false, 1273 autoHighlight: true, // highlight in case mouse is near 1274 mouseActiveRadius: 10 // how far the mouse can be away to activate an item 1275 }, 1276 interaction: { 1277 redrawOverlayInterval: 1000/60 // time between updates, -1 means in same flow 1278 }, 1279 hooks: {} 1280 }, 1281 surface = null, // the canvas for the plot itself 1282 overlay = null, // canvas for interactive stuff on top of plot 1283 eventHolder = null, // jQuery object that events should be bound to 1284 ctx = null, octx = null, 1285 xaxes = [], yaxes = [], 1286 plotOffset = { left: 0, right: 0, top: 0, bottom: 0}, 1287 plotWidth = 0, plotHeight = 0, 1288 hooks = { 1289 processOptions: [], 1290 processRawData: [], 1291 processDatapoints: [], 1292 processOffset: [], 1293 drawBackground: [], 1294 drawSeries: [], 1295 draw: [], 1296 bindEvents: [], 1297 drawOverlay: [], 1298 shutdown: [] 1299 }, 1300 plot = this; 1301 1302 // public functions 1303 plot.setData = setData; 1304 plot.setupGrid = setupGrid; 1305 plot.draw = draw; 1306 plot.getPlaceholder = function() { return placeholder; }; 1307 plot.getCanvas = function() { return surface.element; }; 1308 plot.getPlotOffset = function() { return plotOffset; }; 1309 plot.width = function () { return plotWidth; }; 1310 plot.height = function () { return plotHeight; }; 1311 plot.offset = function () { 1312 var o = eventHolder.offset(); 1313 o.left += plotOffset.left; 1314 o.top += plotOffset.top; 1315 return o; 1316 }; 1317 plot.getData = function () { return series; }; 1318 plot.getAxes = function () { 1319 var res = {}, i; 1320 $.each(xaxes.concat(yaxes), function (_, axis) { 1321 if (axis) 1322 res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis; 1323 }); 1324 return res; 1325 }; 1326 plot.getXAxes = function () { return xaxes; }; 1327 plot.getYAxes = function () { return yaxes; }; 1328 plot.c2p = canvasToAxisCoords; 1329 plot.p2c = axisToCanvasCoords; 1330 plot.getOptions = function () { return options; }; 1331 plot.highlight = highlight; 1332 plot.unhighlight = unhighlight; 1333 plot.triggerRedrawOverlay = triggerRedrawOverlay; 1334 plot.pointOffset = function(point) { 1335 return { 1336 left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left, 10), 1337 top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top, 10) 1338 }; 1339 }; 1340 plot.shutdown = shutdown; 1341 plot.destroy = function () { 1342 shutdown(); 1343 placeholder.removeData("plot").empty(); 1344 1345 series = []; 1346 options = null; 1347 surface = null; 1348 overlay = null; 1349 eventHolder = null; 1350 ctx = null; 1351 octx = null; 1352 xaxes = []; 1353 yaxes = []; 1354 hooks = null; 1355 highlights = []; 1356 plot = null; 1357 }; 1358 plot.resize = function () { 1359 var width = placeholder.width(), 1360 height = placeholder.height(); 1361 surface.resize(width, height); 1362 overlay.resize(width, height); 1363 }; 1364 1365 // public attributes 1366 plot.hooks = hooks; 1367 1368 // initialize 1369 initPlugins(plot); 1370 parseOptions(options_); 1371 setupCanvases(); 1372 setData(data_); 1373 setupGrid(); 1374 draw(); 1375 bindEvents(); 1376 1377 1378 function executeHooks(hook, args) { 1379 args = [plot].concat(args); 1380 for (var i = 0; i < hook.length; ++i) 1381 hook[i].apply(this, args); 1382 } 1383 1384 function initPlugins() { 1385 1386 // References to key classes, allowing plugins to modify them 1387 1388 var classes = { 1389 Canvas: Canvas 1390 }; 1391 1392 for (var i = 0; i < plugins.length; ++i) { 1393 var p = plugins[i]; 1394 p.init(plot, classes); 1395 if (p.options) 1396 $.extend(true, options, p.options); 1397 } 1398 } 1399 1400 function parseOptions(opts) { 1401 1402 $.extend(true, options, opts); 1403 1404 // $.extend merges arrays, rather than replacing them. When less 1405 // colors are provided than the size of the default palette, we 1406 // end up with those colors plus the remaining defaults, which is 1407 // not expected behavior; avoid it by replacing them here. 1408 1409 if (opts && opts.colors) { 1410 options.colors = opts.colors; 1411 } 1412 1413 if (options.xaxis.color == null) 1414 options.xaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString(); 1415 if (options.yaxis.color == null) 1416 options.yaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString(); 1417 1418 if (options.xaxis.tickColor == null) // grid.tickColor for back-compatibility 1419 options.xaxis.tickColor = options.grid.tickColor || options.xaxis.color; 1420 if (options.yaxis.tickColor == null) // grid.tickColor for back-compatibility 1421 options.yaxis.tickColor = options.grid.tickColor || options.yaxis.color; 1422 1423 if (options.grid.borderColor == null) 1424 options.grid.borderColor = options.grid.color; 1425 if (options.grid.tickColor == null) 1426 options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString(); 1427 1428 // Fill in defaults for axis options, including any unspecified 1429 // font-spec fields, if a font-spec was provided. 1430 1431 // If no x/y axis options were provided, create one of each anyway, 1432 // since the rest of the code assumes that they exist. 1433 1434 var i, axisOptions, axisCount, 1435 fontSize = placeholder.css("font-size"), 1436 fontSizeDefault = fontSize ? +fontSize.replace("px", "") : 13, 1437 fontDefaults = { 1438 style: placeholder.css("font-style"), 1439 size: Math.round(0.8 * fontSizeDefault), 1440 variant: placeholder.css("font-variant"), 1441 weight: placeholder.css("font-weight"), 1442 family: placeholder.css("font-family") 1443 }; 1444 1445 axisCount = options.xaxes.length || 1; 1446 for (i = 0; i < axisCount; ++i) { 1447 1448 axisOptions = options.xaxes[i]; 1449 if (axisOptions && !axisOptions.tickColor) { 1450 axisOptions.tickColor = axisOptions.color; 1451 } 1452 1453 axisOptions = $.extend(true, {}, options.xaxis, axisOptions); 1454 options.xaxes[i] = axisOptions; 1455 1456 if (axisOptions.font) { 1457 axisOptions.font = $.extend({}, fontDefaults, axisOptions.font); 1458 if (!axisOptions.font.color) { 1459 axisOptions.font.color = axisOptions.color; 1460 } 1461 if (!axisOptions.font.lineHeight) { 1462 axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15); 1463 } 1464 } 1465 } 1466 1467 axisCount = options.yaxes.length || 1; 1468 for (i = 0; i < axisCount; ++i) { 1469 1470 axisOptions = options.yaxes[i]; 1471 if (axisOptions && !axisOptions.tickColor) { 1472 axisOptions.tickColor = axisOptions.color; 1473 } 1474 1475 axisOptions = $.extend(true, {}, options.yaxis, axisOptions); 1476 options.yaxes[i] = axisOptions; 1477 1478 if (axisOptions.font) { 1479 axisOptions.font = $.extend({}, fontDefaults, axisOptions.font); 1480 if (!axisOptions.font.color) { 1481 axisOptions.font.color = axisOptions.color; 1482 } 1483 if (!axisOptions.font.lineHeight) { 1484 axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15); 1485 } 1486 } 1487 } 1488 1489 // backwards compatibility, to be removed in future 1490 if (options.xaxis.noTicks && options.xaxis.ticks == null) 1491 options.xaxis.ticks = options.xaxis.noTicks; 1492 if (options.yaxis.noTicks && options.yaxis.ticks == null) 1493 options.yaxis.ticks = options.yaxis.noTicks; 1494 if (options.x2axis) { 1495 options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis); 1496 options.xaxes[1].position = "top"; 1497 // Override the inherit to allow the axis to auto-scale 1498 if (options.x2axis.min == null) { 1499 options.xaxes[1].min = null; 1500 } 1501 if (options.x2axis.max == null) { 1502 options.xaxes[1].max = null; 1503 } 1504 } 1505 if (options.y2axis) { 1506 options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis); 1507 options.yaxes[1].position = "right"; 1508 // Override the inherit to allow the axis to auto-scale 1509 if (options.y2axis.min == null) { 1510 options.yaxes[1].min = null; 1511 } 1512 if (options.y2axis.max == null) { 1513 options.yaxes[1].max = null; 1514 } 1515 } 1516 if (options.grid.coloredAreas) 1517 options.grid.markings = options.grid.coloredAreas; 1518 if (options.grid.coloredAreasColor) 1519 options.grid.markingsColor = options.grid.coloredAreasColor; 1520 if (options.lines) 1521 $.extend(true, options.series.lines, options.lines); 1522 if (options.points) 1523 $.extend(true, options.series.points, options.points); 1524 if (options.bars) 1525 $.extend(true, options.series.bars, options.bars); 1526 if (options.shadowSize != null) 1527 options.series.shadowSize = options.shadowSize; 1528 if (options.highlightColor != null) 1529 options.series.highlightColor = options.highlightColor; 1530 1531 // save options on axes for future reference 1532 for (i = 0; i < options.xaxes.length; ++i) 1533 getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i]; 1534 for (i = 0; i < options.yaxes.length; ++i) 1535 getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i]; 1536 1537 // add hooks from options 1538 for (var n in hooks) 1539 if (options.hooks[n] && options.hooks[n].length) 1540 hooks[n] = hooks[n].concat(options.hooks[n]); 1541 1542 executeHooks(hooks.processOptions, [options]); 1543 } 1544 1545 function setData(d) { 1546 series = parseData(d); 1547 fillInSeriesOptions(); 1548 processData(); 1549 } 1550 1551 function parseData(d) { 1552 var res = []; 1553 for (var i = 0; i < d.length; ++i) { 1554 var s = $.extend(true, {}, options.series); 1555 1556 if (d[i].data != null) { 1557 s.data = d[i].data; // move the data instead of deep-copy 1558 delete d[i].data; 1559 1560 $.extend(true, s, d[i]); 1561 1562 d[i].data = s.data; 1563 } 1564 else 1565 s.data = d[i]; 1566 res.push(s); 1567 } 1568 1569 return res; 1570 } 1571 1572 function axisNumber(obj, coord) { 1573 var a = obj[coord + "axis"]; 1574 if (typeof a == "object") // if we got a real axis, extract number 1575 a = a.n; 1576 if (typeof a != "number") 1577 a = 1; // default to first axis 1578 return a; 1579 } 1580 1581 function allAxes() { 1582 // return flat array without annoying null entries 1583 return $.grep(xaxes.concat(yaxes), function (a) { return a; }); 1584 } 1585 1586 function canvasToAxisCoords(pos) { 1587 // return an object with x/y corresponding to all used axes 1588 var res = {}, i, axis; 1589 for (i = 0; i < xaxes.length; ++i) { 1590 axis = xaxes[i]; 1591 if (axis && axis.used) 1592 res["x" + axis.n] = axis.c2p(pos.left); 1593 } 1594 1595 for (i = 0; i < yaxes.length; ++i) { 1596 axis = yaxes[i]; 1597 if (axis && axis.used) 1598 res["y" + axis.n] = axis.c2p(pos.top); 1599 } 1600 1601 if (res.x1 !== undefined) 1602 res.x = res.x1; 1603 if (res.y1 !== undefined) 1604 res.y = res.y1; 1605 1606 return res; 1607 } 1608 1609 function axisToCanvasCoords(pos) { 1610 // get canvas coords from the first pair of x/y found in pos 1611 var res = {}, i, axis, key; 1612 1613 for (i = 0; i < xaxes.length; ++i) { 1614 axis = xaxes[i]; 1615 if (axis && axis.used) { 1616 key = "x" + axis.n; 1617 if (pos[key] == null && axis.n == 1) 1618 key = "x"; 1619 1620 if (pos[key] != null) { 1621 res.left = axis.p2c(pos[key]); 1622 break; 1623 } 1624 } 1625 } 1626 1627 for (i = 0; i < yaxes.length; ++i) { 1628 axis = yaxes[i]; 1629 if (axis && axis.used) { 1630 key = "y" + axis.n; 1631 if (pos[key] == null && axis.n == 1) 1632 key = "y"; 1633 1634 if (pos[key] != null) { 1635 res.top = axis.p2c(pos[key]); 1636 break; 1637 } 1638 } 1639 } 1640 1641 return res; 1642 } 1643 1644 function getOrCreateAxis(axes, number) { 1645 if (!axes[number - 1]) 1646 axes[number - 1] = { 1647 n: number, // save the number for future reference 1648 direction: axes == xaxes ? "x" : "y", 1649 options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis) 1650 }; 1651 1652 return axes[number - 1]; 1653 } 1654 1655 function fillInSeriesOptions() { 1656 1657 var neededColors = series.length, maxIndex = -1, i; 1658 1659 // Subtract the number of series that already have fixed colors or 1660 // color indexes from the number that we still need to generate. 1661 1662 for (i = 0; i < series.length; ++i) { 1663 var sc = series[i].color; 1664 if (sc != null) { 1665 neededColors--; 1666 if (typeof sc == "number" && sc > maxIndex) { 1667 maxIndex = sc; 1668 } 1669 } 1670 } 1671 1672 // If any of the series have fixed color indexes, then we need to 1673 // generate at least as many colors as the highest index. 1674 1675 if (neededColors <= maxIndex) { 1676 neededColors = maxIndex + 1; 1677 } 1678 1679 // Generate all the colors, using first the option colors and then 1680 // variations on those colors once they're exhausted. 1681 1682 var c, colors = [], colorPool = options.colors, 1683 colorPoolSize = colorPool.length, variation = 0; 1684 1685 for (i = 0; i < neededColors; i++) { 1686 1687 c = $.color.parse(colorPool[i % colorPoolSize] || "#666"); 1688 1689 // Each time we exhaust the colors in the pool we adjust 1690 // a scaling factor used to produce more variations on 1691 // those colors. The factor alternates negative/positive 1692 // to produce lighter/darker colors. 1693 1694 // Reset the variation after every few cycles, or else 1695 // it will end up producing only white or black colors. 1696 1697 if (i % colorPoolSize == 0 && i) { 1698 if (variation >= 0) { 1699 if (variation < 0.5) { 1700 variation = -variation - 0.2; 1701 } else variation = 0; 1702 } else variation = -variation; 1703 } 1704 1705 colors[i] = c.scale('rgb', 1 + variation); 1706 } 1707 1708 // Finalize the series options, filling in their colors 1709 1710 var colori = 0, s; 1711 for (i = 0; i < series.length; ++i) { 1712 s = series[i]; 1713 1714 // assign colors 1715 if (s.color == null) { 1716 s.color = colors[colori].toString(); 1717 ++colori; 1718 } 1719 else if (typeof s.color == "number") 1720 s.color = colors[s.color].toString(); 1721 1722 // turn on lines automatically in case nothing is set 1723 if (s.lines.show == null) { 1724 var v, show = true; 1725 for (v in s) 1726 if (s[v] && s[v].show) { 1727 show = false; 1728 break; 1729 } 1730 if (show) 1731 s.lines.show = true; 1732 } 1733 1734 // If nothing was provided for lines.zero, default it to match 1735 // lines.fill, since areas by default should extend to zero. 1736 1737 if (s.lines.zero == null) { 1738 s.lines.zero = !!s.lines.fill; 1739 } 1740 1741 // setup axes 1742 s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x")); 1743 s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y")); 1744 } 1745 } 1746 1747 function processData() { 1748 var topSentry = Number.POSITIVE_INFINITY, 1749 bottomSentry = Number.NEGATIVE_INFINITY, 1750 fakeInfinity = Number.MAX_VALUE, 1751 i, j, k, m, length, 1752 s, points, ps, x, y, axis, val, f, p, 1753 data, format; 1754 1755 function updateAxis(axis, min, max) { 1756 if (min < axis.datamin && min != -fakeInfinity) 1757 axis.datamin = min; 1758 if (max > axis.datamax && max != fakeInfinity) 1759 axis.datamax = max; 1760 } 1761 1762 $.each(allAxes(), function (_, axis) { 1763 // init axis 1764 axis.datamin = topSentry; 1765 axis.datamax = bottomSentry; 1766 axis.used = false; 1767 }); 1768 1769 for (i = 0; i < series.length; ++i) { 1770 s = series[i]; 1771 s.datapoints = { points: [] }; 1772 1773 executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]); 1774 } 1775 1776 // first pass: clean and copy data 1777 for (i = 0; i < series.length; ++i) { 1778 s = series[i]; 1779 1780 data = s.data; 1781 format = s.datapoints.format; 1782 1783 if (!format) { 1784 format = []; 1785 // find out how to copy 1786 format.push({ x: true, number: true, required: true }); 1787 format.push({ y: true, number: true, required: true }); 1788 1789 if (s.bars.show || (s.lines.show && s.lines.fill)) { 1790 var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero)); 1791 format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale }); 1792 if (s.bars.horizontal) { 1793 delete format[format.length - 1].y; 1794 format[format.length - 1].x = true; 1795 } 1796 } 1797 1798 s.datapoints.format = format; 1799 } 1800 1801 if (s.datapoints.pointsize != null) 1802 continue; // already filled in 1803 1804 s.datapoints.pointsize = format.length; 1805 1806 ps = s.datapoints.pointsize; 1807 points = s.datapoints.points; 1808 1809 var insertSteps = s.lines.show && s.lines.steps; 1810 s.xaxis.used = s.yaxis.used = true; 1811 1812 for (j = k = 0; j < data.length; ++j, k += ps) { 1813 p = data[j]; 1814 1815 var nullify = p == null; 1816 if (!nullify) { 1817 for (m = 0; m < ps; ++m) { 1818 val = p[m]; 1819 f = format[m]; 1820 1821 if (f) { 1822 if (f.number && val != null) { 1823 val = +val; // convert to number 1824 if (isNaN(val)) 1825 val = null; 1826 else if (val == Infinity) 1827 val = fakeInfinity; 1828 else if (val == -Infinity) 1829 val = -fakeInfinity; 1830 } 1831 1832 if (val == null) { 1833 if (f.required) 1834 nullify = true; 1835 1836 if (f.defaultValue != null) 1837 val = f.defaultValue; 1838 } 1839 } 1840 1841 points[k + m] = val; 1842 } 1843 } 1844 1845 if (nullify) { 1846 for (m = 0; m < ps; ++m) { 1847 val = points[k + m]; 1848 if (val != null) { 1849 f = format[m]; 1850 // extract min/max info 1851 if (f.autoscale !== false) { 1852 if (f.x) { 1853 updateAxis(s.xaxis, val, val); 1854 } 1855 if (f.y) { 1856 updateAxis(s.yaxis, val, val); 1857 } 1858 } 1859 } 1860 points[k + m] = null; 1861 } 1862 } 1863 else { 1864 // a little bit of line specific stuff that 1865 // perhaps shouldn't be here, but lacking 1866 // better means... 1867 if (insertSteps && k > 0 1868 && points[k - ps] != null 1869 && points[k - ps] != points[k] 1870 && points[k - ps + 1] != points[k + 1]) { 1871 // copy the point to make room for a middle point 1872 for (m = 0; m < ps; ++m) 1873 points[k + ps + m] = points[k + m]; 1874 1875 // middle point has same y 1876 points[k + 1] = points[k - ps + 1]; 1877 1878 // we've added a point, better reflect that 1879 k += ps; 1880 } 1881 } 1882 } 1883 } 1884 1885 // give the hooks a chance to run 1886 for (i = 0; i < series.length; ++i) { 1887 s = series[i]; 1888 1889 executeHooks(hooks.processDatapoints, [ s, s.datapoints]); 1890 } 1891 1892 // second pass: find datamax/datamin for auto-scaling 1893 for (i = 0; i < series.length; ++i) { 1894 s = series[i]; 1895 points = s.datapoints.points; 1896 ps = s.datapoints.pointsize; 1897 format = s.datapoints.format; 1898 1899 var xmin = topSentry, ymin = topSentry, 1900 xmax = bottomSentry, ymax = bottomSentry; 1901 1902 for (j = 0; j < points.length; j += ps) { 1903 if (points[j] == null) 1904 continue; 1905 1906 for (m = 0; m < ps; ++m) { 1907 val = points[j + m]; 1908 f = format[m]; 1909 if (!f || f.autoscale === false || val == fakeInfinity || val == -fakeInfinity) 1910 continue; 1911 1912 if (f.x) { 1913 if (val < xmin) 1914 xmin = val; 1915 if (val > xmax) 1916 xmax = val; 1917 } 1918 if (f.y) { 1919 if (val < ymin) 1920 ymin = val; 1921 if (val > ymax) 1922 ymax = val; 1923 } 1924 } 1925 } 1926 1927 if (s.bars.show) { 1928 // make sure we got room for the bar on the dancing floor 1929 var delta; 1930 1931 switch (s.bars.align) { 1932 case "left": 1933 delta = 0; 1934 break; 1935 case "right": 1936 delta = -s.bars.barWidth; 1937 break; 1938 default: 1939 delta = -s.bars.barWidth / 2; 1940 } 1941 1942 if (s.bars.horizontal) { 1943 ymin += delta; 1944 ymax += delta + s.bars.barWidth; 1945 } 1946 else { 1947 xmin += delta; 1948 xmax += delta + s.bars.barWidth; 1949 } 1950 } 1951 1952 updateAxis(s.xaxis, xmin, xmax); 1953 updateAxis(s.yaxis, ymin, ymax); 1954 } 1955 1956 $.each(allAxes(), function (_, axis) { 1957 if (axis.datamin == topSentry) 1958 axis.datamin = null; 1959 if (axis.datamax == bottomSentry) 1960 axis.datamax = null; 1961 }); 1962 } 1963 1964 function setupCanvases() { 1965 1966 // Make sure the placeholder is clear of everything except canvases 1967 // from a previous plot in this container that we'll try to re-use. 1968 1969 placeholder.css("padding", 0) // padding messes up the positioning 1970 .children().filter(function(){ 1971 return !$(this).hasClass("flot-overlay") && !$(this).hasClass('flot-base'); 1972 }).remove(); 1973 1974 if (placeholder.css("position") == 'static') 1975 placeholder.css("position", "relative"); // for positioning labels and overlay 1976 1977 surface = new Canvas("flot-base", placeholder); 1978 overlay = new Canvas("flot-overlay", placeholder); // overlay canvas for interactive features 1979 1980 ctx = surface.context; 1981 octx = overlay.context; 1982 1983 // define which element we're listening for events on 1984 eventHolder = $(overlay.element).unbind(); 1985 1986 // If we're re-using a plot object, shut down the old one 1987 1988 var existing = placeholder.data("plot"); 1989 1990 if (existing) { 1991 existing.shutdown(); 1992 overlay.clear(); 1993 } 1994 1995 // save in case we get replotted 1996 placeholder.data("plot", plot); 1997 } 1998 1999 function bindEvents() { 2000 // bind events 2001 if (options.grid.hoverable) { 2002 eventHolder.mousemove(onMouseMove); 2003 2004 // Use bind, rather than .mouseleave, because we officially 2005 // still support jQuery 1.2.6, which doesn't define a shortcut 2006 // for mouseenter or mouseleave. This was a bug/oversight that 2007 // was fixed somewhere around 1.3.x. We can return to using 2008 // .mouseleave when we drop support for 1.2.6. 2009 2010 eventHolder.bind("mouseleave", onMouseLeave); 2011 } 2012 2013 if (options.grid.clickable) 2014 eventHolder.click(onClick); 2015 2016 executeHooks(hooks.bindEvents, [eventHolder]); 2017 } 2018 2019 function shutdown() { 2020 if (redrawTimeout) 2021 clearTimeout(redrawTimeout); 2022 2023 eventHolder.unbind("mousemove", onMouseMove); 2024 eventHolder.unbind("mouseleave", onMouseLeave); 2025 eventHolder.unbind("click", onClick); 2026 2027 executeHooks(hooks.shutdown, [eventHolder]); 2028 } 2029 2030 function setTransformationHelpers(axis) { 2031 // set helper functions on the axis, assumes plot area 2032 // has been computed already 2033 2034 function identity(x) { return x; } 2035 2036 var s, m, t = axis.options.transform || identity, 2037 it = axis.options.inverseTransform; 2038 2039 // precompute how much the axis is scaling a point 2040 // in canvas space 2041 if (axis.direction == "x") { 2042 s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min)); 2043 m = Math.min(t(axis.max), t(axis.min)); 2044 } 2045 else { 2046 s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min)); 2047 s = -s; 2048 m = Math.max(t(axis.max), t(axis.min)); 2049 } 2050 2051 // data point to canvas coordinate 2052 if (t == identity) // slight optimization 2053 axis.p2c = function (p) { return (p - m) * s; }; 2054 else 2055 axis.p2c = function (p) { return (t(p) - m) * s; }; 2056 // canvas coordinate to data point 2057 if (!it) 2058 axis.c2p = function (c) { return m + c / s; }; 2059 else 2060 axis.c2p = function (c) { return it(m + c / s); }; 2061 } 2062 2063 function measureTickLabels(axis) { 2064 2065 var opts = axis.options, 2066 ticks = axis.ticks || [], 2067 labelWidth = opts.labelWidth || 0, 2068 labelHeight = opts.labelHeight || 0, 2069 maxWidth = labelWidth || (axis.direction == "x" ? Math.floor(surface.width / (ticks.length || 1)) : null), 2070 legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis", 2071 layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles, 2072 font = opts.font || "flot-tick-label tickLabel"; 2073 2074 for (var i = 0; i < ticks.length; ++i) { 2075 2076 var t = ticks[i]; 2077 2078 if (!t.label) 2079 continue; 2080 2081 var info = surface.getTextInfo(layer, t.label, font, null, maxWidth); 2082 2083 labelWidth = Math.max(labelWidth, info.width); 2084 labelHeight = Math.max(labelHeight, info.height); 2085 } 2086 2087 axis.labelWidth = opts.labelWidth || labelWidth; 2088 axis.labelHeight = opts.labelHeight || labelHeight; 2089 } 2090 2091 function allocateAxisBoxFirstPhase(axis) { 2092 // find the bounding box of the axis by looking at label 2093 // widths/heights and ticks, make room by diminishing the 2094 // plotOffset; this first phase only looks at one 2095 // dimension per axis, the other dimension depends on the 2096 // other axes so will have to wait 2097 2098 var lw = axis.labelWidth, 2099 lh = axis.labelHeight, 2100 pos = axis.options.position, 2101 isXAxis = axis.direction === "x", 2102 tickLength = axis.options.tickLength, 2103 axisMargin = options.grid.axisMargin, 2104 padding = options.grid.labelMargin, 2105 innermost = true, 2106 outermost = true, 2107 first = true, 2108 found = false; 2109 2110 // Determine the axis's position in its direction and on its side 2111 2112 $.each(isXAxis ? xaxes : yaxes, function(i, a) { 2113 if (a && (a.show || a.reserveSpace)) { 2114 if (a === axis) { 2115 found = true; 2116 } else if (a.options.position === pos) { 2117 if (found) { 2118 outermost = false; 2119 } else { 2120 innermost = false; 2121 } 2122 } 2123 if (!found) { 2124 first = false; 2125 } 2126 } 2127 }); 2128 2129 // The outermost axis on each side has no margin 2130 2131 if (outermost) { 2132 axisMargin = 0; 2133 } 2134 2135 // The ticks for the first axis in each direction stretch across 2136 2137 if (tickLength == null) { 2138 tickLength = first ? "full" : 5; 2139 } 2140 2141 if (!isNaN(+tickLength)) 2142 padding += +tickLength; 2143 2144 if (isXAxis) { 2145 lh += padding; 2146 2147 if (pos == "bottom") { 2148 plotOffset.bottom += lh + axisMargin; 2149 axis.box = { top: surface.height - plotOffset.bottom, height: lh }; 2150 } 2151 else { 2152 axis.box = { top: plotOffset.top + axisMargin, height: lh }; 2153 plotOffset.top += lh + axisMargin; 2154 } 2155 } 2156 else { 2157 lw += padding; 2158 2159 if (pos == "left") { 2160 axis.box = { left: plotOffset.left + axisMargin, width: lw }; 2161 plotOffset.left += lw + axisMargin; 2162 } 2163 else { 2164 plotOffset.right += lw + axisMargin; 2165 axis.box = { left: surface.width - plotOffset.right, width: lw }; 2166 } 2167 } 2168 2169 // save for future reference 2170 axis.position = pos; 2171 axis.tickLength = tickLength; 2172 axis.box.padding = padding; 2173 axis.innermost = innermost; 2174 } 2175 2176 function allocateAxisBoxSecondPhase(axis) { 2177 // now that all axis boxes have been placed in one 2178 // dimension, we can set the remaining dimension coordinates 2179 if (axis.direction == "x") { 2180 axis.box.left = plotOffset.left - axis.labelWidth / 2; 2181 axis.box.width = surface.width - plotOffset.left - plotOffset.right + axis.labelWidth; 2182 } 2183 else { 2184 axis.box.top = plotOffset.top - axis.labelHeight / 2; 2185 axis.box.height = surface.height - plotOffset.bottom - plotOffset.top + axis.labelHeight; 2186 } 2187 } 2188 2189 function adjustLayoutForThingsStickingOut() { 2190 // possibly adjust plot offset to ensure everything stays 2191 // inside the canvas and isn't clipped off 2192 2193 var minMargin = options.grid.minBorderMargin, 2194 axis, i; 2195 2196 // check stuff from the plot (FIXME: this should just read 2197 // a value from the series, otherwise it's impossible to 2198 // customize) 2199 if (minMargin == null) { 2200 minMargin = 0; 2201 for (i = 0; i < series.length; ++i) 2202 minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth/2)); 2203 } 2204 2205 var margins = { 2206 left: minMargin, 2207 right: minMargin, 2208 top: minMargin, 2209 bottom: minMargin 2210 }; 2211 2212 // check axis labels, note we don't check the actual 2213 // labels but instead use the overall width/height to not 2214 // jump as much around with replots 2215 $.each(allAxes(), function (_, axis) { 2216 if (axis.reserveSpace && axis.ticks && axis.ticks.length) { 2217 if (axis.direction === "x") { 2218 margins.left = Math.max(margins.left, axis.labelWidth / 2); 2219 margins.right = Math.max(margins.right, axis.labelWidth / 2); 2220 } else { 2221 margins.bottom = Math.max(margins.bottom, axis.labelHeight / 2); 2222 margins.top = Math.max(margins.top, axis.labelHeight / 2); 2223 } 2224 } 2225 }); 2226 2227 plotOffset.left = Math.ceil(Math.max(margins.left, plotOffset.left)); 2228 plotOffset.right = Math.ceil(Math.max(margins.right, plotOffset.right)); 2229 plotOffset.top = Math.ceil(Math.max(margins.top, plotOffset.top)); 2230 plotOffset.bottom = Math.ceil(Math.max(margins.bottom, plotOffset.bottom)); 2231 } 2232 2233 function setupGrid() { 2234 var i, axes = allAxes(), showGrid = options.grid.show; 2235 2236 // Initialize the plot's offset from the edge of the canvas 2237 2238 for (var a in plotOffset) { 2239 var margin = options.grid.margin || 0; 2240 plotOffset[a] = typeof margin == "number" ? margin : margin[a] || 0; 2241 } 2242 2243 executeHooks(hooks.processOffset, [plotOffset]); 2244 2245 // If the grid is visible, add its border width to the offset 2246 2247 for (var a in plotOffset) { 2248 if(typeof(options.grid.borderWidth) == "object") { 2249 plotOffset[a] += showGrid ? options.grid.borderWidth[a] : 0; 2250 } 2251 else { 2252 plotOffset[a] += showGrid ? options.grid.borderWidth : 0; 2253 } 2254 } 2255 2256 $.each(axes, function (_, axis) { 2257 var axisOpts = axis.options; 2258 axis.show = axisOpts.show == null ? axis.used : axisOpts.show; 2259 axis.reserveSpace = axisOpts.reserveSpace == null ? axis.show : axisOpts.reserveSpace; 2260 setRange(axis); 2261 }); 2262 2263 if (showGrid) { 2264 2265 var allocatedAxes = $.grep(axes, function (axis) { 2266 return axis.show || axis.reserveSpace; 2267 }); 2268 2269 $.each(allocatedAxes, function (_, axis) { 2270 // make the ticks 2271 setupTickGeneration(axis); 2272 setTicks(axis); 2273 snapRangeToTicks(axis, axis.ticks); 2274 // find labelWidth/Height for axis 2275 measureTickLabels(axis); 2276 }); 2277 2278 // with all dimensions calculated, we can compute the 2279 // axis bounding boxes, start from the outside 2280 // (reverse order) 2281 for (i = allocatedAxes.length - 1; i >= 0; --i) 2282 allocateAxisBoxFirstPhase(allocatedAxes[i]); 2283 2284 // make sure we've got enough space for things that 2285 // might stick out 2286 adjustLayoutForThingsStickingOut(); 2287 2288 $.each(allocatedAxes, function (_, axis) { 2289 allocateAxisBoxSecondPhase(axis); 2290 }); 2291 } 2292 2293 plotWidth = surface.width - plotOffset.left - plotOffset.right; 2294 plotHeight = surface.height - plotOffset.bottom - plotOffset.top; 2295 2296 // now we got the proper plot dimensions, we can compute the scaling 2297 $.each(axes, function (_, axis) { 2298 setTransformationHelpers(axis); 2299 }); 2300 2301 if (showGrid) { 2302 drawAxisLabels(); 2303 } 2304 2305 insertLegend(); 2306 } 2307 2308 function setRange(axis) { 2309 var opts = axis.options, 2310 min = +(opts.min != null ? opts.min : axis.datamin), 2311 max = +(opts.max != null ? opts.max : axis.datamax), 2312 delta = max - min; 2313 2314 if (delta == 0.0) { 2315 // degenerate case 2316 var widen = max == 0 ? 1 : 0.01; 2317 2318 if (opts.min == null) 2319 min -= widen; 2320 // always widen max if we couldn't widen min to ensure we 2321 // don't fall into min == max which doesn't work 2322 if (opts.max == null || opts.min != null) 2323 max += widen; 2324 } 2325 else { 2326 // consider autoscaling 2327 var margin = opts.autoscaleMargin; 2328 if (margin != null) { 2329 if (opts.min == null) { 2330 min -= delta * margin; 2331 // make sure we don't go below zero if all values 2332 // are positive 2333 if (min < 0 && axis.datamin != null && axis.datamin >= 0) 2334 min = 0; 2335 } 2336 if (opts.max == null) { 2337 max += delta * margin; 2338 if (max > 0 && axis.datamax != null && axis.datamax <= 0) 2339 max = 0; 2340 } 2341 } 2342 } 2343 axis.min = min; 2344 axis.max = max; 2345 } 2346 2347 function setupTickGeneration(axis) { 2348 var opts = axis.options; 2349 2350 // estimate number of ticks 2351 var noTicks; 2352 if (typeof opts.ticks == "number" && opts.ticks > 0) 2353 noTicks = opts.ticks; 2354 else 2355 // heuristic based on the model a*sqrt(x) fitted to 2356 // some data points that seemed reasonable 2357 noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? surface.width : surface.height); 2358 2359 var delta = (axis.max - axis.min) / noTicks, 2360 dec = -Math.floor(Math.log(delta) / Math.LN10), 2361 maxDec = opts.tickDecimals; 2362 2363 if (maxDec != null && dec > maxDec) { 2364 dec = maxDec; 2365 } 2366 2367 var magn = Math.pow(10, -dec), 2368 norm = delta / magn, // norm is between 1.0 and 10.0 2369 size; 2370 2371 if (norm < 1.5) { 2372 size = 1; 2373 } else if (norm < 3) { 2374 size = 2; 2375 // special case for 2.5, requires an extra decimal 2376 if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { 2377 size = 2.5; 2378 ++dec; 2379 } 2380 } else if (norm < 7.5) { 2381 size = 5; 2382 } else { 2383 size = 10; 2384 } 2385 2386 size *= magn; 2387 2388 if (opts.minTickSize != null && size < opts.minTickSize) { 2389 size = opts.minTickSize; 2390 } 2391 2392 axis.delta = delta; 2393 axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec); 2394 axis.tickSize = opts.tickSize || size; 2395 2396 // Time mode was moved to a plug-in in 0.8, and since so many people use it 2397 // we'll add an especially friendly reminder to make sure they included it. 2398 2399 if (opts.mode == "time" && !axis.tickGenerator) { 2400 throw new Error("Time mode requires the flot.time plugin."); 2401 } 2402 2403 // Flot supports base-10 axes; any other mode else is handled by a plug-in, 2404 // like flot.time.js. 2405 2406 if (!axis.tickGenerator) { 2407 2408 axis.tickGenerator = function (axis) { 2409 2410 var ticks = [], 2411 start = floorInBase(axis.min, axis.tickSize), 2412 i = 0, 2413 v = Number.NaN, 2414 prev; 2415 2416 do { 2417 prev = v; 2418 v = start + i * axis.tickSize; 2419 ticks.push(v); 2420 ++i; 2421 } while (v < axis.max && v != prev); 2422 return ticks; 2423 }; 2424 2425 axis.tickFormatter = function (value, axis) { 2426 2427 var factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1; 2428 var formatted = "" + Math.round(value * factor) / factor; 2429 2430 // If tickDecimals was specified, ensure that we have exactly that 2431 // much precision; otherwise default to the value's own precision. 2432 2433 if (axis.tickDecimals != null) { 2434 var decimal = formatted.indexOf("."); 2435 var precision = decimal == -1 ? 0 : formatted.length - decimal - 1; 2436 if (precision < axis.tickDecimals) { 2437 return (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision); 2438 } 2439 } 2440 2441 return formatted; 2442 }; 2443 } 2444 2445 if ($.isFunction(opts.tickFormatter)) 2446 axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); }; 2447 2448 if (opts.alignTicksWithAxis != null) { 2449 var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1]; 2450 if (otherAxis && otherAxis.used && otherAxis != axis) { 2451 // consider snapping min/max to outermost nice ticks 2452 var niceTicks = axis.tickGenerator(axis); 2453 if (niceTicks.length > 0) { 2454 if (opts.min == null) 2455 axis.min = Math.min(axis.min, niceTicks[0]); 2456 if (opts.max == null && niceTicks.length > 1) 2457 axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]); 2458 } 2459 2460 axis.tickGenerator = function (axis) { 2461 // copy ticks, scaled to this axis 2462 var ticks = [], v, i; 2463 for (i = 0; i < otherAxis.ticks.length; ++i) { 2464 v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min); 2465 v = axis.min + v * (axis.max - axis.min); 2466 ticks.push(v); 2467 } 2468 return ticks; 2469 }; 2470 2471 // we might need an extra decimal since forced 2472 // ticks don't necessarily fit naturally 2473 if (!axis.mode && opts.tickDecimals == null) { 2474 var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1), 2475 ts = axis.tickGenerator(axis); 2476 2477 // only proceed if the tick interval rounded 2478 // with an extra decimal doesn't give us a 2479 // zero at end 2480 if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec)))) 2481 axis.tickDecimals = extraDec; 2482 } 2483 } 2484 } 2485 } 2486 2487 function setTicks(axis) { 2488 var oticks = axis.options.ticks, ticks = []; 2489 if (oticks == null || (typeof oticks == "number" && oticks > 0)) 2490 ticks = axis.tickGenerator(axis); 2491 else if (oticks) { 2492 if ($.isFunction(oticks)) 2493 // generate the ticks 2494 ticks = oticks(axis); 2495 else 2496 ticks = oticks; 2497 } 2498 2499 // clean up/labelify the supplied ticks, copy them over 2500 var i, v; 2501 axis.ticks = []; 2502 for (i = 0; i < ticks.length; ++i) { 2503 var label = null; 2504 var t = ticks[i]; 2505 if (typeof t == "object") { 2506 v = +t[0]; 2507 if (t.length > 1) 2508 label = t[1]; 2509 } 2510 else 2511 v = +t; 2512 if (label == null) 2513 label = axis.tickFormatter(v, axis); 2514 if (!isNaN(v)) 2515 axis.ticks.push({ v: v, label: label }); 2516 } 2517 } 2518 2519 function snapRangeToTicks(axis, ticks) { 2520 if (axis.options.autoscaleMargin && ticks.length > 0) { 2521 // snap to ticks 2522 if (axis.options.min == null) 2523 axis.min = Math.min(axis.min, ticks[0].v); 2524 if (axis.options.max == null && ticks.length > 1) 2525 axis.max = Math.max(axis.max, ticks[ticks.length - 1].v); 2526 } 2527 } 2528 2529 function draw() { 2530 2531 surface.clear(); 2532 2533 executeHooks(hooks.drawBackground, [ctx]); 2534 2535 var grid = options.grid; 2536 2537 // draw background, if any 2538 if (grid.show && grid.backgroundColor) 2539 drawBackground(); 2540 2541 if (grid.show && !grid.aboveData) { 2542 drawGrid(); 2543 } 2544 2545 for (var i = 0; i < series.length; ++i) { 2546 executeHooks(hooks.drawSeries, [ctx, series[i]]); 2547 drawSeries(series[i]); 2548 } 2549 2550 executeHooks(hooks.draw, [ctx]); 2551 2552 if (grid.show && grid.aboveData) { 2553 drawGrid(); 2554 } 2555 2556 surface.render(); 2557 2558 // A draw implies that either the axes or data have changed, so we 2559 // should probably update the overlay highlights as well. 2560 2561 triggerRedrawOverlay(); 2562 } 2563 2564 function extractRange(ranges, coord) { 2565 var axis, from, to, key, axes = allAxes(); 2566 2567 for (var i = 0; i < axes.length; ++i) { 2568 axis = axes[i]; 2569 if (axis.direction == coord) { 2570 key = coord + axis.n + "axis"; 2571 if (!ranges[key] && axis.n == 1) 2572 key = coord + "axis"; // support x1axis as xaxis 2573 if (ranges[key]) { 2574 from = ranges[key].from; 2575 to = ranges[key].to; 2576 break; 2577 } 2578 } 2579 } 2580 2581 // backwards-compat stuff - to be removed in future 2582 if (!ranges[key]) { 2583 axis = coord == "x" ? xaxes[0] : yaxes[0]; 2584 from = ranges[coord + "1"]; 2585 to = ranges[coord + "2"]; 2586 } 2587 2588 // auto-reverse as an added bonus 2589 if (from != null && to != null && from > to) { 2590 var tmp = from; 2591 from = to; 2592 to = tmp; 2593 } 2594 2595 return { from: from, to: to, axis: axis }; 2596 } 2597 2598 function drawBackground() { 2599 ctx.save(); 2600 ctx.translate(plotOffset.left, plotOffset.top); 2601 2602 ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)"); 2603 ctx.fillRect(0, 0, plotWidth, plotHeight); 2604 ctx.restore(); 2605 } 2606 2607 function drawGrid() { 2608 var i, axes, bw, bc; 2609 2610 ctx.save(); 2611 ctx.translate(plotOffset.left, plotOffset.top); 2612 2613 // draw markings 2614 var markings = options.grid.markings; 2615 if (markings) { 2616 if ($.isFunction(markings)) { 2617 axes = plot.getAxes(); 2618 // xmin etc. is backwards compatibility, to be 2619 // removed in the future 2620 axes.xmin = axes.xaxis.min; 2621 axes.xmax = axes.xaxis.max; 2622 axes.ymin = axes.yaxis.min; 2623 axes.ymax = axes.yaxis.max; 2624 2625 markings = markings(axes); 2626 } 2627 2628 for (i = 0; i < markings.length; ++i) { 2629 var m = markings[i], 2630 xrange = extractRange(m, "x"), 2631 yrange = extractRange(m, "y"); 2632 2633 // fill in missing 2634 if (xrange.from == null) 2635 xrange.from = xrange.axis.min; 2636 if (xrange.to == null) 2637 xrange.to = xrange.axis.max; 2638 if (yrange.from == null) 2639 yrange.from = yrange.axis.min; 2640 if (yrange.to == null) 2641 yrange.to = yrange.axis.max; 2642 2643 // clip 2644 if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max || 2645 yrange.to < yrange.axis.min || yrange.from > yrange.axis.max) 2646 continue; 2647 2648 xrange.from = Math.max(xrange.from, xrange.axis.min); 2649 xrange.to = Math.min(xrange.to, xrange.axis.max); 2650 yrange.from = Math.max(yrange.from, yrange.axis.min); 2651 yrange.to = Math.min(yrange.to, yrange.axis.max); 2652 2653 var xequal = xrange.from === xrange.to, 2654 yequal = yrange.from === yrange.to; 2655 2656 if (xequal && yequal) { 2657 continue; 2658 } 2659 2660 // then draw 2661 xrange.from = Math.floor(xrange.axis.p2c(xrange.from)); 2662 xrange.to = Math.floor(xrange.axis.p2c(xrange.to)); 2663 yrange.from = Math.floor(yrange.axis.p2c(yrange.from)); 2664 yrange.to = Math.floor(yrange.axis.p2c(yrange.to)); 2665 2666 if (xequal || yequal) { 2667 var lineWidth = m.lineWidth || options.grid.markingsLineWidth, 2668 subPixel = lineWidth % 2 ? 0.5 : 0; 2669 ctx.beginPath(); 2670 ctx.strokeStyle = m.color || options.grid.markingsColor; 2671 ctx.lineWidth = lineWidth; 2672 if (xequal) { 2673 ctx.moveTo(xrange.to + subPixel, yrange.from); 2674 ctx.lineTo(xrange.to + subPixel, yrange.to); 2675 } else { 2676 ctx.moveTo(xrange.from, yrange.to + subPixel); 2677 ctx.lineTo(xrange.to, yrange.to + subPixel); 2678 } 2679 ctx.stroke(); 2680 } else { 2681 ctx.fillStyle = m.color || options.grid.markingsColor; 2682 ctx.fillRect(xrange.from, yrange.to, 2683 xrange.to - xrange.from, 2684 yrange.from - yrange.to); 2685 } 2686 } 2687 } 2688 2689 // draw the ticks 2690 axes = allAxes(); 2691 bw = options.grid.borderWidth; 2692 2693 for (var j = 0; j < axes.length; ++j) { 2694 var axis = axes[j], box = axis.box, 2695 t = axis.tickLength, x, y, xoff, yoff; 2696 if (!axis.show || axis.ticks.length == 0) 2697 continue; 2698 2699 ctx.lineWidth = 1; 2700 2701 // find the edges 2702 if (axis.direction == "x") { 2703 x = 0; 2704 if (t == "full") 2705 y = (axis.position == "top" ? 0 : plotHeight); 2706 else 2707 y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0); 2708 } 2709 else { 2710 y = 0; 2711 if (t == "full") 2712 x = (axis.position == "left" ? 0 : plotWidth); 2713 else 2714 x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0); 2715 } 2716 2717 // draw tick bar 2718 if (!axis.innermost) { 2719 ctx.strokeStyle = axis.options.color; 2720 ctx.beginPath(); 2721 xoff = yoff = 0; 2722 if (axis.direction == "x") 2723 xoff = plotWidth + 1; 2724 else 2725 yoff = plotHeight + 1; 2726 2727 if (ctx.lineWidth == 1) { 2728 if (axis.direction == "x") { 2729 y = Math.floor(y) + 0.5; 2730 } else { 2731 x = Math.floor(x) + 0.5; 2732 } 2733 } 2734 2735 ctx.moveTo(x, y); 2736 ctx.lineTo(x + xoff, y + yoff); 2737 ctx.stroke(); 2738 } 2739 2740 // draw ticks 2741 2742 ctx.strokeStyle = axis.options.tickColor; 2743 2744 ctx.beginPath(); 2745 for (i = 0; i < axis.ticks.length; ++i) { 2746 var v = axis.ticks[i].v; 2747 2748 xoff = yoff = 0; 2749 2750 if (isNaN(v) || v < axis.min || v > axis.max 2751 // skip those lying on the axes if we got a border 2752 || (t == "full" 2753 && ((typeof bw == "object" && bw[axis.position] > 0) || bw > 0) 2754 && (v == axis.min || v == axis.max))) 2755 continue; 2756 2757 if (axis.direction == "x") { 2758 x = axis.p2c(v); 2759 yoff = t == "full" ? -plotHeight : t; 2760 2761 if (axis.position == "top") 2762 yoff = -yoff; 2763 } 2764 else { 2765 y = axis.p2c(v); 2766 xoff = t == "full" ? -plotWidth : t; 2767 2768 if (axis.position == "left") 2769 xoff = -xoff; 2770 } 2771 2772 if (ctx.lineWidth == 1) { 2773 if (axis.direction == "x") 2774 x = Math.floor(x) + 0.5; 2775 else 2776 y = Math.floor(y) + 0.5; 2777 } 2778 2779 ctx.moveTo(x, y); 2780 ctx.lineTo(x + xoff, y + yoff); 2781 } 2782 2783 ctx.stroke(); 2784 } 2785 2786 2787 // draw border 2788 if (bw) { 2789 // If either borderWidth or borderColor is an object, then draw the border 2790 // line by line instead of as one rectangle 2791 bc = options.grid.borderColor; 2792 if(typeof bw == "object" || typeof bc == "object") { 2793 if (typeof bw !== "object") { 2794 bw = {top: bw, right: bw, bottom: bw, left: bw}; 2795 } 2796 if (typeof bc !== "object") { 2797 bc = {top: bc, right: bc, bottom: bc, left: bc}; 2798 } 2799 2800 if (bw.top > 0) { 2801 ctx.strokeStyle = bc.top; 2802 ctx.lineWidth = bw.top; 2803 ctx.beginPath(); 2804 ctx.moveTo(0 - bw.left, 0 - bw.top/2); 2805 ctx.lineTo(plotWidth, 0 - bw.top/2); 2806 ctx.stroke(); 2807 } 2808 2809 if (bw.right > 0) { 2810 ctx.strokeStyle = bc.right; 2811 ctx.lineWidth = bw.right; 2812 ctx.beginPath(); 2813 ctx.moveTo(plotWidth + bw.right / 2, 0 - bw.top); 2814 ctx.lineTo(plotWidth + bw.right / 2, plotHeight); 2815 ctx.stroke(); 2816 } 2817 2818 if (bw.bottom > 0) { 2819 ctx.strokeStyle = bc.bottom; 2820 ctx.lineWidth = bw.bottom; 2821 ctx.beginPath(); 2822 ctx.moveTo(plotWidth + bw.right, plotHeight + bw.bottom / 2); 2823 ctx.lineTo(0, plotHeight + bw.bottom / 2); 2824 ctx.stroke(); 2825 } 2826 2827 if (bw.left > 0) { 2828 ctx.strokeStyle = bc.left; 2829 ctx.lineWidth = bw.left; 2830 ctx.beginPath(); 2831 ctx.moveTo(0 - bw.left/2, plotHeight + bw.bottom); 2832 ctx.lineTo(0- bw.left/2, 0); 2833 ctx.stroke(); 2834 } 2835 } 2836 else { 2837 ctx.lineWidth = bw; 2838 ctx.strokeStyle = options.grid.borderColor; 2839 ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw); 2840 } 2841 } 2842 2843 ctx.restore(); 2844 } 2845 2846 function drawAxisLabels() { 2847 2848 $.each(allAxes(), function (_, axis) { 2849 var box = axis.box, 2850 legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis", 2851 layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles, 2852 font = axis.options.font || "flot-tick-label tickLabel", 2853 tick, x, y, halign, valign; 2854 2855 // Remove text before checking for axis.show and ticks.length; 2856 // otherwise plugins, like flot-tickrotor, that draw their own 2857 // tick labels will end up with both theirs and the defaults. 2858 2859 surface.removeText(layer); 2860 2861 if (!axis.show || axis.ticks.length == 0) 2862 return; 2863 2864 for (var i = 0; i < axis.ticks.length; ++i) { 2865 2866 tick = axis.ticks[i]; 2867 if (!tick.label || tick.v < axis.min || tick.v > axis.max) 2868 continue; 2869 2870 if (axis.direction == "x") { 2871 halign = "center"; 2872 x = plotOffset.left + axis.p2c(tick.v); 2873 if (axis.position == "bottom") { 2874 y = box.top + box.padding; 2875 } else { 2876 y = box.top + box.height - box.padding; 2877 valign = "bottom"; 2878 } 2879 } else { 2880 valign = "middle"; 2881 y = plotOffset.top + axis.p2c(tick.v); 2882 if (axis.position == "left") { 2883 x = box.left + box.width - box.padding; 2884 halign = "right"; 2885 } else { 2886 x = box.left + box.padding; 2887 } 2888 } 2889 2890 surface.addText(layer, x, y, tick.label, font, null, null, halign, valign); 2891 } 2892 }); 2893 } 2894 2895 function drawSeries(series) { 2896 if (series.lines.show) 2897 drawSeriesLines(series); 2898 if (series.bars.show) 2899 drawSeriesBars(series); 2900 if (series.points.show) 2901 drawSeriesPoints(series); 2902 } 2903 2904 function drawSeriesLines(series) { 2905 function plotLine(datapoints, xoffset, yoffset, axisx, axisy) { 2906 var points = datapoints.points, 2907 ps = datapoints.pointsize, 2908 prevx = null, prevy = null; 2909 2910 ctx.beginPath(); 2911 for (var i = ps; i < points.length; i += ps) { 2912 var x1 = points[i - ps], y1 = points[i - ps + 1], 2913 x2 = points[i], y2 = points[i + 1]; 2914 2915 if (x1 == null || x2 == null) 2916 continue; 2917 2918 // clip with ymin 2919 if (y1 <= y2 && y1 < axisy.min) { 2920 if (y2 < axisy.min) 2921 continue; // line segment is outside 2922 // compute new intersection point 2923 x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; 2924 y1 = axisy.min; 2925 } 2926 else if (y2 <= y1 && y2 < axisy.min) { 2927 if (y1 < axisy.min) 2928 continue; 2929 x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; 2930 y2 = axisy.min; 2931 } 2932 2933 // clip with ymax 2934 if (y1 >= y2 && y1 > axisy.max) { 2935 if (y2 > axisy.max) 2936 continue; 2937 x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; 2938 y1 = axisy.max; 2939 } 2940 else if (y2 >= y1 && y2 > axisy.max) { 2941 if (y1 > axisy.max) 2942 continue; 2943 x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; 2944 y2 = axisy.max; 2945 } 2946 2947 // clip with xmin 2948 if (x1 <= x2 && x1 < axisx.min) { 2949 if (x2 < axisx.min) 2950 continue; 2951 y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; 2952 x1 = axisx.min; 2953 } 2954 else if (x2 <= x1 && x2 < axisx.min) { 2955 if (x1 < axisx.min) 2956 continue; 2957 y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; 2958 x2 = axisx.min; 2959 } 2960 2961 // clip with xmax 2962 if (x1 >= x2 && x1 > axisx.max) { 2963 if (x2 > axisx.max) 2964 continue; 2965 y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; 2966 x1 = axisx.max; 2967 } 2968 else if (x2 >= x1 && x2 > axisx.max) { 2969 if (x1 > axisx.max) 2970 continue; 2971 y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; 2972 x2 = axisx.max; 2973 } 2974 2975 if (x1 != prevx || y1 != prevy) 2976 ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset); 2977 2978 prevx = x2; 2979 prevy = y2; 2980 ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset); 2981 } 2982 ctx.stroke(); 2983 } 2984 2985 function plotLineArea(datapoints, axisx, axisy) { 2986 var points = datapoints.points, 2987 ps = datapoints.pointsize, 2988 bottom = Math.min(Math.max(0, axisy.min), axisy.max), 2989 i = 0, top, areaOpen = false, 2990 ypos = 1, segmentStart = 0, segmentEnd = 0; 2991 2992 // we process each segment in two turns, first forward 2993 // direction to sketch out top, then once we hit the 2994 // end we go backwards to sketch the bottom 2995 while (true) { 2996 if (ps > 0 && i > points.length + ps) 2997 break; 2998 2999 i += ps; // ps is negative if going backwards 3000 3001 var x1 = points[i - ps], 3002 y1 = points[i - ps + ypos], 3003 x2 = points[i], y2 = points[i + ypos]; 3004 3005 if (areaOpen) { 3006 if (ps > 0 && x1 != null && x2 == null) { 3007 // at turning point 3008 segmentEnd = i; 3009 ps = -ps; 3010 ypos = 2; 3011 continue; 3012 } 3013 3014 if (ps < 0 && i == segmentStart + ps) { 3015 // done with the reverse sweep 3016 ctx.fill(); 3017 areaOpen = false; 3018 ps = -ps; 3019 ypos = 1; 3020 i = segmentStart = segmentEnd + ps; 3021 continue; 3022 } 3023 } 3024 3025 if (x1 == null || x2 == null) 3026 continue; 3027 3028 // clip x values 3029 3030 // clip with xmin 3031 if (x1 <= x2 && x1 < axisx.min) { 3032 if (x2 < axisx.min) 3033 continue; 3034 y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; 3035 x1 = axisx.min; 3036 } 3037 else if (x2 <= x1 && x2 < axisx.min) { 3038 if (x1 < axisx.min) 3039 continue; 3040 y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; 3041 x2 = axisx.min; 3042 } 3043 3044 // clip with xmax 3045 if (x1 >= x2 && x1 > axisx.max) { 3046 if (x2 > axisx.max) 3047 continue; 3048 y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; 3049 x1 = axisx.max; 3050 } 3051 else if (x2 >= x1 && x2 > axisx.max) { 3052 if (x1 > axisx.max) 3053 continue; 3054 y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; 3055 x2 = axisx.max; 3056 } 3057 3058 if (!areaOpen) { 3059 // open area 3060 ctx.beginPath(); 3061 ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom)); 3062 areaOpen = true; 3063 } 3064 3065 // now first check the case where both is outside 3066 if (y1 >= axisy.max && y2 >= axisy.max) { 3067 ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max)); 3068 ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max)); 3069 continue; 3070 } 3071 else if (y1 <= axisy.min && y2 <= axisy.min) { 3072 ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min)); 3073 ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min)); 3074 continue; 3075 } 3076 3077 // else it's a bit more complicated, there might 3078 // be a flat maxed out rectangle first, then a 3079 // triangular cutout or reverse; to find these 3080 // keep track of the current x values 3081 var x1old = x1, x2old = x2; 3082 3083 // clip the y values, without shortcutting, we 3084 // go through all cases in turn 3085 3086 // clip with ymin 3087 if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) { 3088 x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; 3089 y1 = axisy.min; 3090 } 3091 else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) { 3092 x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; 3093 y2 = axisy.min; 3094 } 3095 3096 // clip with ymax 3097 if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) { 3098 x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; 3099 y1 = axisy.max; 3100 } 3101 else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) { 3102 x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; 3103 y2 = axisy.max; 3104 } 3105 3106 // if the x value was changed we got a rectangle 3107 // to fill 3108 if (x1 != x1old) { 3109 ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1)); 3110 // it goes to (x1, y1), but we fill that below 3111 } 3112 3113 // fill triangular section, this sometimes result 3114 // in redundant points if (x1, y1) hasn't changed 3115 // from previous line to, but we just ignore that 3116 ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1)); 3117 ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); 3118 3119 // fill the other rectangle if it's there 3120 if (x2 != x2old) { 3121 ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); 3122 ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2)); 3123 } 3124 } 3125 } 3126 3127 ctx.save(); 3128 ctx.translate(plotOffset.left, plotOffset.top); 3129 ctx.lineJoin = "round"; 3130 3131 var lw = series.lines.lineWidth, 3132 sw = series.shadowSize; 3133 // FIXME: consider another form of shadow when filling is turned on 3134 if (lw > 0 && sw > 0) { 3135 // draw shadow as a thick and thin line with transparency 3136 ctx.lineWidth = sw; 3137 ctx.strokeStyle = "rgba(0,0,0,0.1)"; 3138 // position shadow at angle from the mid of line 3139 var angle = Math.PI/18; 3140 plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis); 3141 ctx.lineWidth = sw/2; 3142 plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis); 3143 } 3144 3145 ctx.lineWidth = lw; 3146 ctx.strokeStyle = series.color; 3147 var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight); 3148 if (fillStyle) { 3149 ctx.fillStyle = fillStyle; 3150 plotLineArea(series.datapoints, series.xaxis, series.yaxis); 3151 } 3152 3153 if (lw > 0) 3154 plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis); 3155 ctx.restore(); 3156 } 3157 3158 function drawSeriesPoints(series) { 3159 function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) { 3160 var points = datapoints.points, ps = datapoints.pointsize; 3161 3162 for (var i = 0; i < points.length; i += ps) { 3163 var x = points[i], y = points[i + 1]; 3164 if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) 3165 continue; 3166 3167 ctx.beginPath(); 3168 x = axisx.p2c(x); 3169 y = axisy.p2c(y) + offset; 3170 if (symbol == "circle") 3171 ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false); 3172 else 3173 symbol(ctx, x, y, radius, shadow); 3174 ctx.closePath(); 3175 3176 if (fillStyle) { 3177 ctx.fillStyle = fillStyle; 3178 ctx.fill(); 3179 } 3180 ctx.stroke(); 3181 } 3182 } 3183 3184 ctx.save(); 3185 ctx.translate(plotOffset.left, plotOffset.top); 3186 3187 var lw = series.points.lineWidth, 3188 sw = series.shadowSize, 3189 radius = series.points.radius, 3190 symbol = series.points.symbol; 3191 3192 // If the user sets the line width to 0, we change it to a very 3193 // small value. A line width of 0 seems to force the default of 1. 3194 // Doing the conditional here allows the shadow setting to still be 3195 // optional even with a lineWidth of 0. 3196 3197 if( lw == 0 ) 3198 lw = 0.0001; 3199 3200 if (lw > 0 && sw > 0) { 3201 // draw shadow in two steps 3202 var w = sw / 2; 3203 ctx.lineWidth = w; 3204 ctx.strokeStyle = "rgba(0,0,0,0.1)"; 3205 plotPoints(series.datapoints, radius, null, w + w/2, true, 3206 series.xaxis, series.yaxis, symbol); 3207 3208 ctx.strokeStyle = "rgba(0,0,0,0.2)"; 3209 plotPoints(series.datapoints, radius, null, w/2, true, 3210 series.xaxis, series.yaxis, symbol); 3211 } 3212 3213 ctx.lineWidth = lw; 3214 ctx.strokeStyle = series.color; 3215 plotPoints(series.datapoints, radius, 3216 getFillStyle(series.points, series.color), 0, false, 3217 series.xaxis, series.yaxis, symbol); 3218 ctx.restore(); 3219 } 3220 3221 function drawBar(x, y, b, barLeft, barRight, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) { 3222 var left, right, bottom, top, 3223 drawLeft, drawRight, drawTop, drawBottom, 3224 tmp; 3225 3226 // in horizontal mode, we start the bar from the left 3227 // instead of from the bottom so it appears to be 3228 // horizontal rather than vertical 3229 if (horizontal) { 3230 drawBottom = drawRight = drawTop = true; 3231 drawLeft = false; 3232 left = b; 3233 right = x; 3234 top = y + barLeft; 3235 bottom = y + barRight; 3236 3237 // account for negative bars 3238 if (right < left) { 3239 tmp = right; 3240 right = left; 3241 left = tmp; 3242 drawLeft = true; 3243 drawRight = false; 3244 } 3245 } 3246 else { 3247 drawLeft = drawRight = drawTop = true; 3248 drawBottom = false; 3249 left = x + barLeft; 3250 right = x + barRight; 3251 bottom = b; 3252 top = y; 3253 3254 // account for negative bars 3255 if (top < bottom) { 3256 tmp = top; 3257 top = bottom; 3258 bottom = tmp; 3259 drawBottom = true; 3260 drawTop = false; 3261 } 3262 } 3263 3264 // clip 3265 if (right < axisx.min || left > axisx.max || 3266 top < axisy.min || bottom > axisy.max) 3267 return; 3268 3269 if (left < axisx.min) { 3270 left = axisx.min; 3271 drawLeft = false; 3272 } 3273 3274 if (right > axisx.max) { 3275 right = axisx.max; 3276 drawRight = false; 3277 } 3278 3279 if (bottom < axisy.min) { 3280 bottom = axisy.min; 3281 drawBottom = false; 3282 } 3283 3284 if (top > axisy.max) { 3285 top = axisy.max; 3286 drawTop = false; 3287 } 3288 3289 left = axisx.p2c(left); 3290 bottom = axisy.p2c(bottom); 3291 right = axisx.p2c(right); 3292 top = axisy.p2c(top); 3293 3294 // fill the bar 3295 if (fillStyleCallback) { 3296 c.fillStyle = fillStyleCallback(bottom, top); 3297 c.fillRect(left, top, right - left, bottom - top) 3298 } 3299 3300 // draw outline 3301 if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) { 3302 c.beginPath(); 3303 3304 // FIXME: inline moveTo is buggy with excanvas 3305 c.moveTo(left, bottom); 3306 if (drawLeft) 3307 c.lineTo(left, top); 3308 else 3309 c.moveTo(left, top); 3310 if (drawTop) 3311 c.lineTo(right, top); 3312 else 3313 c.moveTo(right, top); 3314 if (drawRight) 3315 c.lineTo(right, bottom); 3316 else 3317 c.moveTo(right, bottom); 3318 if (drawBottom) 3319 c.lineTo(left, bottom); 3320 else 3321 c.moveTo(left, bottom); 3322 c.stroke(); 3323 } 3324 } 3325 3326 function drawSeriesBars(series) { 3327 function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) { 3328 var points = datapoints.points, ps = datapoints.pointsize; 3329 3330 for (var i = 0; i < points.length; i += ps) { 3331 if (points[i] == null) 3332 continue; 3333 drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth); 3334 } 3335 } 3336 3337 ctx.save(); 3338 ctx.translate(plotOffset.left, plotOffset.top); 3339 3340 // FIXME: figure out a way to add shadows (for instance along the right edge) 3341 ctx.lineWidth = series.bars.lineWidth; 3342 ctx.strokeStyle = series.color; 3343 3344 var barLeft; 3345 3346 switch (series.bars.align) { 3347 case "left": 3348 barLeft = 0; 3349 break; 3350 case "right": 3351 barLeft = -series.bars.barWidth; 3352 break; 3353 default: 3354 barLeft = -series.bars.barWidth / 2; 3355 } 3356 3357 var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; 3358 plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, fillStyleCallback, series.xaxis, series.yaxis); 3359 ctx.restore(); 3360 } 3361 3362 function getFillStyle(filloptions, seriesColor, bottom, top) { 3363 var fill = filloptions.fill; 3364 if (!fill) 3365 return null; 3366 3367 if (filloptions.fillColor) 3368 return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); 3369 3370 var c = $.color.parse(seriesColor); 3371 c.a = typeof fill == "number" ? fill : 0.4; 3372 c.normalize(); 3373 return c.toString(); 3374 } 3375 3376 function insertLegend() { 3377 3378 if (options.legend.container != null) { 3379 $(options.legend.container).html(""); 3380 } else { 3381 placeholder.find(".legend").remove(); 3382 } 3383 3384 if (!options.legend.show) { 3385 return; 3386 } 3387 3388 var fragments = [], entries = [], rowStarted = false, 3389 lf = options.legend.labelFormatter, s, label; 3390 3391 // Build a list of legend entries, with each having a label and a color 3392 3393 for (var i = 0; i < series.length; ++i) { 3394 s = series[i]; 3395 if (s.label) { 3396 label = lf ? lf(s.label, s) : s.label; 3397 if (label) { 3398 entries.push({ 3399 label: label, 3400 color: s.color 3401 }); 3402 } 3403 } 3404 } 3405 3406 // Sort the legend using either the default or a custom comparator 3407 3408 if (options.legend.sorted) { 3409 if ($.isFunction(options.legend.sorted)) { 3410 entries.sort(options.legend.sorted); 3411 } else if (options.legend.sorted == "reverse") { 3412 entries.reverse(); 3413 } else { 3414 var ascending = options.legend.sorted != "descending"; 3415 entries.sort(function(a, b) { 3416 return a.label == b.label ? 0 : ( 3417 (a.label < b.label) != ascending ? 1 : -1 // Logical XOR 3418 ); 3419 }); 3420 } 3421 } 3422 3423 // Generate markup for the list of entries, in their final order 3424 3425 for (var i = 0; i < entries.length; ++i) { 3426 3427 var entry = entries[i]; 3428 3429 if (i % options.legend.noColumns == 0) { 3430 if (rowStarted) 3431 fragments.push('</tr>'); 3432 fragments.push('<tr>'); 3433 rowStarted = true; 3434 } 3435 3436 fragments.push( 3437 '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + entry.color + ';overflow:hidden"></div></div></td>' + 3438 '<td class="legendLabel">' + entry.label + '</td>' 3439 ); 3440 } 3441 3442 if (rowStarted) 3443 fragments.push('</tr>'); 3444 3445 if (fragments.length == 0) 3446 return; 3447 3448 var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>'; 3449 if (options.legend.container != null) 3450 $(options.legend.container).html(table); 3451 else { 3452 var pos = "", 3453 p = options.legend.position, 3454 m = options.legend.margin; 3455 if (m[0] == null) 3456 m = [m, m]; 3457 if (p.charAt(0) == "n") 3458 pos += 'top:' + (m[1] + plotOffset.top) + 'px;'; 3459 else if (p.charAt(0) == "s") 3460 pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;'; 3461 if (p.charAt(1) == "e") 3462 pos += 'right:' + (m[0] + plotOffset.right) + 'px;'; 3463 else if (p.charAt(1) == "w") 3464 pos += 'left:' + (m[0] + plotOffset.left) + 'px;'; 3465 var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder); 3466 if (options.legend.backgroundOpacity != 0.0) { 3467 // put in the transparent background 3468 // separately to avoid blended labels and 3469 // label boxes 3470 var c = options.legend.backgroundColor; 3471 if (c == null) { 3472 c = options.grid.backgroundColor; 3473 if (c && typeof c == "string") 3474 c = $.color.parse(c); 3475 else 3476 c = $.color.extract(legend, 'background-color'); 3477 c.a = 1; 3478 c = c.toString(); 3479 } 3480 var div = legend.children(); 3481 $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity); 3482 } 3483 } 3484 } 3485 3486 3487 // interactive features 3488 3489 var highlights = [], 3490 redrawTimeout = null; 3491 3492 // returns the data item the mouse is over, or null if none is found 3493 function findNearbyItem(mouseX, mouseY, seriesFilter) { 3494 var maxDistance = options.grid.mouseActiveRadius, 3495 smallestDistance = maxDistance * maxDistance + 1, 3496 item = null, foundPoint = false, i, j, ps; 3497 3498 for (i = series.length - 1; i >= 0; --i) { 3499 if (!seriesFilter(series[i])) 3500 continue; 3501 3502 var s = series[i], 3503 axisx = s.xaxis, 3504 axisy = s.yaxis, 3505 points = s.datapoints.points, 3506 mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster 3507 my = axisy.c2p(mouseY), 3508 maxx = maxDistance / axisx.scale, 3509 maxy = maxDistance / axisy.scale; 3510 3511 ps = s.datapoints.pointsize; 3512 // with inverse transforms, we can't use the maxx/maxy 3513 // optimization, sadly 3514 if (axisx.options.inverseTransform) 3515 maxx = Number.MAX_VALUE; 3516 if (axisy.options.inverseTransform) 3517 maxy = Number.MAX_VALUE; 3518 3519 if (s.lines.show || s.points.show) { 3520 for (j = 0; j < points.length; j += ps) { 3521 var x = points[j], y = points[j + 1]; 3522 if (x == null) 3523 continue; 3524 3525 // For points and lines, the cursor must be within a 3526 // certain distance to the data point 3527 if (x - mx > maxx || x - mx < -maxx || 3528 y - my > maxy || y - my < -maxy) 3529 continue; 3530 3531 // We have to calculate distances in pixels, not in 3532 // data units, because the scales of the axes may be different 3533 var dx = Math.abs(axisx.p2c(x) - mouseX), 3534 dy = Math.abs(axisy.p2c(y) - mouseY), 3535 dist = dx * dx + dy * dy; // we save the sqrt 3536 3537 // use <= to ensure last point takes precedence 3538 // (last generally means on top of) 3539 if (dist < smallestDistance) { 3540 smallestDistance = dist; 3541 item = [i, j / ps]; 3542 } 3543 } 3544 } 3545 3546 if (s.bars.show && !item) { // no other point can be nearby 3547 3548 var barLeft, barRight; 3549 3550 switch (s.bars.align) { 3551 case "left": 3552 barLeft = 0; 3553 break; 3554 case "right": 3555 barLeft = -s.bars.barWidth; 3556 break; 3557 default: 3558 barLeft = -s.bars.barWidth / 2; 3559 } 3560 3561 barRight = barLeft + s.bars.barWidth; 3562 3563 for (j = 0; j < points.length; j += ps) { 3564 var x = points[j], y = points[j + 1], b = points[j + 2]; 3565 if (x == null) 3566 continue; 3567 3568 // for a bar graph, the cursor must be inside the bar 3569 if (series[i].bars.horizontal ? 3570 (mx <= Math.max(b, x) && mx >= Math.min(b, x) && 3571 my >= y + barLeft && my <= y + barRight) : 3572 (mx >= x + barLeft && mx <= x + barRight && 3573 my >= Math.min(b, y) && my <= Math.max(b, y))) 3574 item = [i, j / ps]; 3575 } 3576 } 3577 } 3578 3579 if (item) { 3580 i = item[0]; 3581 j = item[1]; 3582 ps = series[i].datapoints.pointsize; 3583 3584 return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps), 3585 dataIndex: j, 3586 series: series[i], 3587 seriesIndex: i }; 3588 } 3589 3590 return null; 3591 } 3592 3593 function onMouseMove(e) { 3594 if (options.grid.hoverable) 3595 triggerClickHoverEvent("plothover", e, 3596 function (s) { return s["hoverable"] != false; }); 3597 } 3598 3599 function onMouseLeave(e) { 3600 if (options.grid.hoverable) 3601 triggerClickHoverEvent("plothover", e, 3602 function (s) { return false; }); 3603 } 3604 3605 function onClick(e) { 3606 triggerClickHoverEvent("plotclick", e, 3607 function (s) { return s["clickable"] != false; }); 3608 } 3609 3610 // trigger click or hover event (they send the same parameters 3611 // so we share their code) 3612 function triggerClickHoverEvent(eventname, event, seriesFilter) { 3613 var offset = eventHolder.offset(), 3614 canvasX = event.pageX - offset.left - plotOffset.left, 3615 canvasY = event.pageY - offset.top - plotOffset.top, 3616 pos = canvasToAxisCoords({ left: canvasX, top: canvasY }); 3617 3618 pos.pageX = event.pageX; 3619 pos.pageY = event.pageY; 3620 3621 var item = findNearbyItem(canvasX, canvasY, seriesFilter); 3622 3623 if (item) { 3624 // fill in mouse pos for any listeners out there 3625 item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left, 10); 3626 item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top, 10); 3627 } 3628 3629 if (options.grid.autoHighlight) { 3630 // clear auto-highlights 3631 for (var i = 0; i < highlights.length; ++i) { 3632 var h = highlights[i]; 3633 if (h.auto == eventname && 3634 !(item && h.series == item.series && 3635 h.point[0] == item.datapoint[0] && 3636 h.point[1] == item.datapoint[1])) 3637 unhighlight(h.series, h.point); 3638 } 3639 3640 if (item) 3641 highlight(item.series, item.datapoint, eventname); 3642 } 3643 3644 placeholder.trigger(eventname, [ pos, item ]); 3645 } 3646 3647 function triggerRedrawOverlay() { 3648 var t = options.interaction.redrawOverlayInterval; 3649 if (t == -1) { // skip event queue 3650 drawOverlay(); 3651 return; 3652 } 3653 3654 if (!redrawTimeout) 3655 redrawTimeout = setTimeout(drawOverlay, t); 3656 } 3657 3658 function drawOverlay() { 3659 redrawTimeout = null; 3660 3661 // draw highlights 3662 octx.save(); 3663 overlay.clear(); 3664 octx.translate(plotOffset.left, plotOffset.top); 3665 3666 var i, hi; 3667 for (i = 0; i < highlights.length; ++i) { 3668 hi = highlights[i]; 3669 3670 if (hi.series.bars.show) 3671 drawBarHighlight(hi.series, hi.point); 3672 else 3673 drawPointHighlight(hi.series, hi.point); 3674 } 3675 octx.restore(); 3676 3677 executeHooks(hooks.drawOverlay, [octx]); 3678 } 3679 3680 function highlight(s, point, auto) { 3681 if (typeof s == "number") 3682 s = series[s]; 3683 3684 if (typeof point == "number") { 3685 var ps = s.datapoints.pointsize; 3686 point = s.datapoints.points.slice(ps * point, ps * (point + 1)); 3687 } 3688 3689 var i = indexOfHighlight(s, point); 3690 if (i == -1) { 3691 highlights.push({ series: s, point: point, auto: auto }); 3692 3693 triggerRedrawOverlay(); 3694 } 3695 else if (!auto) 3696 highlights[i].auto = false; 3697 } 3698 3699 function unhighlight(s, point) { 3700 if (s == null && point == null) { 3701 highlights = []; 3702 triggerRedrawOverlay(); 3703 return; 3704 } 3705 3706 if (typeof s == "number") 3707 s = series[s]; 3708 3709 if (typeof point == "number") { 3710 var ps = s.datapoints.pointsize; 3711 point = s.datapoints.points.slice(ps * point, ps * (point + 1)); 3712 } 3713 3714 var i = indexOfHighlight(s, point); 3715 if (i != -1) { 3716 highlights.splice(i, 1); 3717 3718 triggerRedrawOverlay(); 3719 } 3720 } 3721 3722 function indexOfHighlight(s, p) { 3723 for (var i = 0; i < highlights.length; ++i) { 3724 var h = highlights[i]; 3725 if (h.series == s && h.point[0] == p[0] 3726 && h.point[1] == p[1]) 3727 return i; 3728 } 3729 return -1; 3730 } 3731 3732 function drawPointHighlight(series, point) { 3733 var x = point[0], y = point[1], 3734 axisx = series.xaxis, axisy = series.yaxis, 3735 highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(); 3736 3737 if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) 3738 return; 3739 3740 var pointRadius = series.points.radius + series.points.lineWidth / 2; 3741 octx.lineWidth = pointRadius; 3742 octx.strokeStyle = highlightColor; 3743 var radius = 1.5 * pointRadius; 3744 x = axisx.p2c(x); 3745 y = axisy.p2c(y); 3746 3747 octx.beginPath(); 3748 if (series.points.symbol == "circle") 3749 octx.arc(x, y, radius, 0, 2 * Math.PI, false); 3750 else 3751 series.points.symbol(octx, x, y, radius, false); 3752 octx.closePath(); 3753 octx.stroke(); 3754 } 3755 3756 function drawBarHighlight(series, point) { 3757 var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(), 3758 fillStyle = highlightColor, 3759 barLeft; 3760 3761 switch (series.bars.align) { 3762 case "left": 3763 barLeft = 0; 3764 break; 3765 case "right": 3766 barLeft = -series.bars.barWidth; 3767 break; 3768 default: 3769 barLeft = -series.bars.barWidth / 2; 3770 } 3771 3772 octx.lineWidth = series.bars.lineWidth; 3773 octx.strokeStyle = highlightColor; 3774 3775 drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, 3776 function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth); 3777 } 3778 3779 function getColorOrGradient(spec, bottom, top, defaultColor) { 3780 if (typeof spec == "string") 3781 return spec; 3782 else { 3783 // assume this is a gradient spec; IE currently only 3784 // supports a simple vertical gradient properly, so that's 3785 // what we support too 3786 var gradient = ctx.createLinearGradient(0, top, 0, bottom); 3787 3788 for (var i = 0, l = spec.colors.length; i < l; ++i) { 3789 var c = spec.colors[i]; 3790 if (typeof c != "string") { 3791 var co = $.color.parse(defaultColor); 3792 if (c.brightness != null) 3793 co = co.scale('rgb', c.brightness); 3794 if (c.opacity != null) 3795 co.a *= c.opacity; 3796 c = co.toString(); 3797 } 3798 gradient.addColorStop(i / (l - 1), c); 3799 } 3800 3801 return gradient; 3802 } 3803 } 3804 } 3805 3806 // Add the plot function to the top level of the jQuery object 3807 3808 $.plot = function(placeholder, data, options) { 3809 //var t0 = new Date(); 3810 var plot = new Plot($(placeholder), data, options, $.plot.plugins); 3811 //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime())); 3812 return plot; 3813 }; 3814 3815 $.plot.version = "0.8.3"; 3816 3817 $.plot.plugins = []; 3818 3819 // Also add the plot function as a chainable property 3820 3821 $.fn.plot = function(data, options) { 3822 return this.each(function() { 3823 $.plot(this, data, options); 3824 }); 3825 }; 3826 3827 // round to nearby lower multiple of base 3828 function floorInBase(n, base) { 3829 return base * Math.floor(n / base); 3830 } 3831 3832})(jQuery); 3833 3834/* Flot plugin for plotting textual data or categories. 3835 3836Copyright (c) 2007-2014 IOLA and Ole Laursen. 3837Licensed under the MIT license. 3838 3839Consider a dataset like [["February", 34], ["March", 20], ...]. This plugin 3840allows you to plot such a dataset directly. 3841 3842To enable it, you must specify mode: "categories" on the axis with the textual 3843labels, e.g. 3844 3845 $.plot("#placeholder", data, { xaxis: { mode: "categories" } }); 3846 3847By default, the labels are ordered as they are met in the data series. If you
3848need a different ordering, you can specify "categories" on the axis options 3849and list the categories there: 3850 3851 xaxis: { 3852 mode: "categories", 3853 categories: ["February", "March", "April"] 3854 } 3855 3856If you need to customize the distances between the categories, you can specify 3857"categories" as an object mapping labels to values 3858 3859 xaxis: { 3860 mode: "categories", 3861 categories: { "February": 1, "March": 3, "April": 4 } 3862 } 3863 3864If you don't specify all categories, the remaining categories will be numbered 3865from the max value plus 1 (with a spacing of 1 between each). 3866 3867Internally, the plugin works by transforming the input data through an auto- 3868generated mapping where the first category becomes 0, the second 1, etc. 3869Hence, a point like ["February", 34] becomes [0, 34] internally in Flot (this 3870is visible in hover and click events that return numbers rather than the 3871category labels). The plugin also overrides the tick generator to spit out the 3872categories as ticks instead of the values. 3873 3874If you need to map a value back to its label, the mapping is always accessible 3875as "categories" on the axis object, e.g. plot.getAxes().xaxis.categories. 3876 3877*/ 3878 3879(function ($) { 3880 var options = { 3881 xaxis: { 3882 categories: null 3883 }, 3884 yaxis: { 3885 categories: null 3886 } 3887 }; 3888 3889 function processRawData(plot, series, data, datapoints) { 3890 // if categories are enabled, we need to disable 3891 // auto-transformation to numbers so the strings are intact 3892 // for later processing 3893 3894 var xCategories = series.xaxis.options.mode == "categories", 3895 yCategories = series.yaxis.options.mode == "categories"; 3896 3897 if (!(xCategories || yCategories)) 3898 return; 3899 3900 var format = datapoints.format; 3901 3902 if (!format) { 3903 // FIXME: auto-detection should really not be defined here 3904 var s = series; 3905 format = []; 3906 format.push({ x: true, number: true, required: true }); 3907 format.push({ y: true, number: true, required: true }); 3908 3909 if (s.bars.show || (s.lines.show && s.lines.fill)) { 3910 var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero)); 3911 format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale }); 3912 if (s.bars.horizontal) { 3913 delete format[format.length - 1].y; 3914 format[format.length - 1].x = true; 3915 } 3916 } 3917 3918 datapoints.format = format; 3919 } 3920 3921 for (var m = 0; m < format.length; ++m) { 3922 if (format[m].x && xCategories) 3923 format[m].number = false; 3924 3925 if (format[m].y && yCategories) 3926 format[m].number = false; 3927 } 3928 } 3929 3930 function getNextIndex(categories) { 3931 var index = -1; 3932 3933 for (var v in categories) 3934 if (categories[v] > index) 3935 index = categories[v]; 3936 3937 return index + 1; 3938 } 3939 3940 function categoriesTickGenerator(axis) { 3941 var res = []; 3942 for (var label in axis.categories) { 3943 var v = axis.categories[label]; 3944 if (v >= axis.min && v <= axis.max) 3945 res.push([v, label]); 3946 } 3947 3948 res.sort(function (a, b) { return a[0] - b[0]; }); 3949 3950 return res; 3951 } 3952 3953 function setupCategoriesForAxis(series, axis, datapoints) { 3954 if (series[axis].options.mode != "categories") 3955 return; 3956 3957 if (!series[axis].categories) { 3958 // parse options 3959 var c = {}, o = series[axis].options.categories || {}; 3960 if ($.isArray(o)) { 3961 for (var i = 0; i < o.length; ++i) 3962 c[o[i]] = i; 3963 } 3964 else { 3965 for (var v in o) 3966 c[v] = o[v]; 3967 } 3968 3969 series[axis].categories = c; 3970 } 3971 3972 // fix ticks 3973 if (!series[axis].options.ticks) 3974 series[axis].options.ticks = categoriesTickGenerator; 3975 3976 transformPointsOnAxis(datapoints, axis, series[axis].categories); 3977 } 3978 3979 function transformPointsOnAxis(datapoints, axis, categories) { 3980 // go through the points, transforming them 3981 var points = datapoints.points, 3982 ps = datapoints.pointsize, 3983 format = datapoints.format, 3984 formatColumn = axis.charAt(0), 3985 index = getNextIndex(categories); 3986 3987 for (var i = 0; i < points.length; i += ps) { 3988 if (points[i] == null) 3989 continue; 3990 3991 for (var m = 0; m < ps; ++m) { 3992 var val = points[i + m]; 3993 3994 if (val == null || !format[m][formatColumn]) 3995 continue; 3996 3997 if (!(val in categories)) { 3998 categories[val] = index; 3999 ++index; 4000 } 4001 4002 points[i + m] = categories[val]; 4003 } 4004 } 4005 } 4006 4007 function processDatapoints(plot, series, datapoints) { 4008 setupCategoriesForAxis(series, "xaxis", datapoints); 4009 setupCategoriesForAxis(series, "yaxis", datapoints); 4010 } 4011 4012 function init(plot) { 4013 plot.hooks.processRawData.push(processRawData); 4014 plot.hooks.processDatapoints.push(processDatapoints); 4015 } 4016 4017 $.plot.plugins.push({ 4018 init: init, 4019 options: options, 4020 name: 'categories', 4021 version: '1.0' 4022 });
vendor: 7,382 bytes, lines 4023-4269
4023})(jQuery); 4024 4025/* Flot plugin for rendering pie charts. 4026 4027Copyright (c) 2007-2014 IOLA and Ole Laursen. 4028Licensed under the MIT license. 4029 4030The plugin assumes that each series has a single data value, and that each 4031value is a positive integer or zero. Negative numbers don't make sense for a 4032pie chart, and have unpredictable results. The values do NOT need to be 4033passed in as percentages; the plugin will calculate the total and per-slice 4034percentages internally. 4035 4036* Created by Brian Medendorp 4037 4038* Updated with contributions from btburnett3, Anthony Aragues and Xavi Ivars 4039 4040The plugin supports these options: 4041 4042 series: { 4043 pie: { 4044 show: true/false 4045 radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto' 4046 innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect 4047 startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result 4048 tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show) 4049 offset: { 4050 top: integer value to move the pie up or down 4051 left: integer value to move the pie left or right, or 'auto' 4052 }, 4053 stroke: { 4054 color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF') 4055 width: integer pixel width of the stroke 4056 }, 4057 label: { 4058 show: true/false, or 'auto' 4059 formatter: a user-defined function that modifies the text/style of the label text 4060 radius: 0-1 for percentage of fullsize, or a specified pixel length 4061 background: { 4062 color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000') 4063 opacity: 0-1 4064 }, 4065 threshold: 0-1 for the percentage value at which to hide labels (if they're too small) 4066 }, 4067 combine: { 4068 threshold: 0-1 for the percentage value at which to combine slices (if they're too small) 4069 color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined 4070 label: any text value of what the combined slice should be labeled 4071 } 4072 highlight: { 4073 opacity: 0-1 4074 } 4075 } 4076 } 4077 4078More detail and specific examples can be found in the included HTML file. 4079 4080*/ 4081 4082(function($) { 4083 4084 // Maximum redraw attempts when fitting labels within the plot 4085 4086 var REDRAW_ATTEMPTS = 10; 4087 4088 // Factor by which to shrink the pie when fitting labels within the plot 4089 4090 var REDRAW_SHRINK = 0.95; 4091 4092 function init(plot) { 4093 4094 var canvas = null, 4095 target = null, 4096 options = null, 4097 maxRadius = null, 4098 centerLeft = null, 4099 centerTop = null, 4100 processed = false, 4101 ctx = null; 4102 4103 // interactive variables 4104 4105 var highlights = []; 4106 4107 // add hook to determine if pie plugin in enabled, and then perform necessary operations 4108 4109 plot.hooks.processOptions.push(function(plot, options) { 4110 if (options.series.pie.show) { 4111 4112 options.grid.show = false; 4113 4114 // set labels.show 4115 4116 if (options.series.pie.label.show == "auto") { 4117 if (options.legend.show) { 4118 options.series.pie.label.show = false; 4119 } else { 4120 options.series.pie.label.show = true; 4121 } 4122 } 4123 4124 // set radius 4125 4126 if (options.series.pie.radius == "auto") { 4127 if (options.series.pie.label.show) { 4128 options.series.pie.radius = 3/4; 4129 } else { 4130 options.series.pie.radius = 1; 4131 } 4132 } 4133 4134 // ensure sane tilt 4135 4136 if (options.series.pie.tilt > 1) { 4137 options.series.pie.tilt = 1; 4138 } else if (options.series.pie.tilt < 0) { 4139 options.series.pie.tilt = 0; 4140 } 4141 } 4142 }); 4143 4144 plot.hooks.bindEvents.push(function(plot, eventHolder) { 4145 var options = plot.getOptions(); 4146 if (options.series.pie.show) { 4147 if (options.grid.hoverable) { 4148 eventHolder.unbind("mousemove").mousemove(onMouseMove); 4149 } 4150 if (options.grid.clickable) { 4151 eventHolder.unbind("click").click(onClick); 4152 } 4153 } 4154 }); 4155 4156 plot.hooks.processDatapoints.push(function(plot, series, data, datapoints) { 4157 var options = plot.getOptions(); 4158 if (options.series.pie.show) { 4159 processDatapoints(plot, series, data, datapoints); 4160 } 4161 }); 4162 4163 plot.hooks.drawOverlay.push(function(plot, octx) { 4164 var options = plot.getOptions(); 4165 if (options.series.pie.show) { 4166 drawOverlay(plot, octx); 4167 } 4168 }); 4169 4170 plot.hooks.draw.push(function(plot, newCtx) { 4171 var options = plot.getOptions(); 4172 if (options.series.pie.show) { 4173 draw(plot, newCtx); 4174 } 4175 }); 4176 4177 function processDatapoints(plot, series, datapoints) { 4178 if (!processed) { 4179 processed = true; 4180 canvas = plot.getCanvas(); 4181 target = $(canvas).parent(); 4182 options = plot.getOptions(); 4183 plot.setData(combine(plot.getData())); 4184 } 4185 } 4186 4187 function combine(data) { 4188 4189 var total = 0, 4190 combined = 0, 4191 numCombined = 0, 4192 color = options.series.pie.combine.color, 4193 newdata = []; 4194 4195 // Fix up the raw data from Flot, ensuring the data is numeric 4196 4197 for (var i = 0; i < data.length; ++i) { 4198 4199 var value = data[i].data; 4200 4201 // If the data is an array, we'll assume that it's a standard 4202 // Flot x-y pair, and are concerned only with the second value. 4203 4204 // Note how we use the original array, rather than creating a 4205 // new one; this is more efficient and preserves any extra data 4206 // that the user may have stored in higher indexes. 4207 4208 if ($.isArray(value) && value.length == 1) { 4209 value = value[0]; 4210 } 4211 4212 if ($.isArray(value)) { 4213 // Equivalent to $.isNumeric() but compatible with jQuery < 1.7 4214 if (!isNaN(parseFloat(value[1])) && isFinite(value[1])) { 4215 value[1] = +value[1]; 4216 } else { 4217 value[1] = 0; 4218 } 4219 } else if (!isNaN(parseFloat(value)) && isFinite(value)) { 4220 value = [1, +value]; 4221 } else { 4222 value = [1, 0]; 4223 } 4224 4225 data[i].data = [value]; 4226 } 4227 4228 // Sum up all the slices, so we can calculate percentages for each 4229 4230 for (var i = 0; i < data.length; ++i) { 4231 total += data[i].data[0][1]; 4232 } 4233 4234 // Count the number of slices with percentages below the combine 4235 // threshold; if it turns out to be just one, we won't combine. 4236 4237 for (var i = 0; i < data.length; ++i) { 4238 var value = data[i].data[0][1]; 4239 if (value / total <= options.series.pie.combine.threshold) { 4240 combined += value; 4241 numCombined++; 4242 if (!color) { 4243 color = data[i].color; 4244 } 4245 } 4246 } 4247 4248 for (var i = 0; i < data.length; ++i) { 4249 var value = data[i].data[0][1]; 4250 if (numCombined < 2 || value / total > options.series.pie.combine.threshold) { 4251 newdata.push( 4252 $.extend(data[i], { /* extend to allow keeping all other original data values 4253 and using them e.g. in labelFormatter. */ 4254 data: [[1, value]], 4255 color: data[i].color, 4256 label: data[i].label, 4257 angle: value * Math.PI * 2 / total, 4258 percent: value / (total / 100) 4259 }) 4260 ); 4261 } 4262 } 4263 4264 if (numCombined > 1) { 4265 newdata.push({ 4266 data: [[1, combined]], 4267 color: color, 4268 label: options.series.pie.combine.label, 4269 angle: combined * Math.PI * 2 / total,
4270 percent: combined / (total / 100) 4271 }); 4272 } 4273 4274 return newdata; 4275 } 4276 4277 function draw(plot, newCtx) { 4278 4279 if (!target) { 4280 return; // if no series were passed 4281 } 4282 4283 var canvasWidth = plot.getPlaceholder().width(), 4284 canvasHeight = plot.getPlaceholder().height(), 4285 legendWidth = target.children().filter(".legend").children().width() || 0; 4286 4287 ctx = newCtx; 4288 4289 // WARNING: HACK! REWRITE THIS CODE AS SOON AS POSSIBLE! 4290 4291 // When combining smaller slices into an 'other' slice, we need to 4292 // add a new series. Since Flot gives plugins no way to modify the 4293 // list of series, the pie plugin uses a hack where the first call 4294 // to processDatapoints results in a call to setData with the new 4295 // list of series, then subsequent processDatapoints do nothing. 4296 4297 // The plugin-global 'processed' flag is used to control this hack; 4298 // it starts out false, and is set to true after the first call to 4299 // processDatapoints. 4300 4301 // Unfortunately this turns future setData calls into no-ops; they 4302 // call processDatapoints, the flag is true, and nothing happens. 4303
vendor: 14,920 bytes, lines 4304-4801
4304 // To fix this we'll set the flag back to false here in draw, when 4305 // all series have been processed, so the next sequence of calls to 4306 // processDatapoints once again starts out with a slice-combine. 4307 // This is really a hack; in 0.9 we need to give plugins a proper 4308 // way to modify series before any processing begins. 4309 4310 processed = false; 4311 4312 // calculate maximum radius and center point 4313 4314 maxRadius = Math.min(canvasWidth, canvasHeight / options.series.pie.tilt) / 2; 4315 centerTop = canvasHeight / 2 + options.series.pie.offset.top; 4316 centerLeft = canvasWidth / 2; 4317 4318 if (options.series.pie.offset.left == "auto") { 4319 if (options.legend.position.match("w")) { 4320 centerLeft += legendWidth / 2; 4321 } else { 4322 centerLeft -= legendWidth / 2; 4323 } 4324 if (centerLeft < maxRadius) { 4325 centerLeft = maxRadius; 4326 } else if (centerLeft > canvasWidth - maxRadius) { 4327 centerLeft = canvasWidth - maxRadius; 4328 } 4329 } else { 4330 centerLeft += options.series.pie.offset.left; 4331 } 4332 4333 var slices = plot.getData(), 4334 attempts = 0; 4335 4336 // Keep shrinking the pie's radius until drawPie returns true, 4337 // indicating that all the labels fit, or we try too many times. 4338 4339 do { 4340 if (attempts > 0) { 4341 maxRadius *= REDRAW_SHRINK; 4342 } 4343 attempts += 1; 4344 clear(); 4345 if (options.series.pie.tilt <= 0.8) { 4346 drawShadow(); 4347 } 4348 } while (!drawPie() && attempts < REDRAW_ATTEMPTS) 4349 4350 if (attempts >= REDRAW_ATTEMPTS) { 4351 clear(); 4352 target.prepend("<div class='error'>Could not draw pie with labels contained inside canvas</div>"); 4353 } 4354 4355 if (plot.setSeries && plot.insertLegend) { 4356 plot.setSeries(slices); 4357 plot.insertLegend(); 4358 } 4359 4360 // we're actually done at this point, just defining internal functions at this point 4361 4362 function clear() { 4363 ctx.clearRect(0, 0, canvasWidth, canvasHeight); 4364 target.children().filter(".pieLabel, .pieLabelBackground").remove(); 4365 } 4366 4367 function drawShadow() { 4368 4369 var shadowLeft = options.series.pie.shadow.left; 4370 var shadowTop = options.series.pie.shadow.top; 4371 var edge = 10; 4372 var alpha = options.series.pie.shadow.alpha; 4373 var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; 4374 4375 if (radius >= canvasWidth / 2 - shadowLeft || radius * options.series.pie.tilt >= canvasHeight / 2 - shadowTop || radius <= edge) { 4376 return; // shadow would be outside canvas, so don't draw it 4377 } 4378 4379 ctx.save(); 4380 ctx.translate(shadowLeft,shadowTop); 4381 ctx.globalAlpha = alpha; 4382 ctx.fillStyle = "#000"; 4383 4384 // center and rotate to starting position 4385 4386 ctx.translate(centerLeft,centerTop); 4387 ctx.scale(1, options.series.pie.tilt); 4388 4389 //radius -= edge; 4390 4391 for (var i = 1; i <= edge; i++) { 4392 ctx.beginPath(); 4393 ctx.arc(0, 0, radius, 0, Math.PI * 2, false); 4394 ctx.fill(); 4395 radius -= i; 4396 } 4397 4398 ctx.restore(); 4399 } 4400 4401 function drawPie() { 4402 4403 var startAngle = Math.PI * options.series.pie.startAngle; 4404 var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; 4405 4406 // center and rotate to starting position 4407 4408 ctx.save(); 4409 ctx.translate(centerLeft,centerTop); 4410 ctx.scale(1, options.series.pie.tilt); 4411 //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera 4412 4413 // draw slices 4414 4415 ctx.save(); 4416 var currentAngle = startAngle; 4417 for (var i = 0; i < slices.length; ++i) { 4418 slices[i].startAngle = currentAngle; 4419 drawSlice(slices[i].angle, slices[i].color, true); 4420 } 4421 ctx.restore(); 4422 4423 // draw slice outlines 4424 4425 if (options.series.pie.stroke.width > 0) { 4426 ctx.save(); 4427 ctx.lineWidth = options.series.pie.stroke.width; 4428 currentAngle = startAngle; 4429 for (var i = 0; i < slices.length; ++i) { 4430 drawSlice(slices[i].angle, options.series.pie.stroke.color, false); 4431 } 4432 ctx.restore(); 4433 } 4434 4435 // draw donut hole 4436 4437 drawDonutHole(ctx); 4438 4439 ctx.restore(); 4440 4441 // Draw the labels, returning true if they fit within the plot 4442 4443 if (options.series.pie.label.show) { 4444 return drawLabels(); 4445 } else return true; 4446 4447 function drawSlice(angle, color, fill) { 4448 4449 if (angle <= 0 || isNaN(angle)) { 4450 return; 4451 } 4452 4453 if (fill) { 4454 ctx.fillStyle = color; 4455 } else { 4456 ctx.strokeStyle = color; 4457 ctx.lineJoin = "round"; 4458 } 4459 4460 ctx.beginPath(); 4461 if (Math.abs(angle - Math.PI * 2) > 0.000000001) { 4462 ctx.moveTo(0, 0); // Center of the pie 4463 } 4464 4465 //ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera 4466 ctx.arc(0, 0, radius,currentAngle, currentAngle + angle / 2, false); 4467 ctx.arc(0, 0, radius,currentAngle + angle / 2, currentAngle + angle, false); 4468 ctx.closePath(); 4469 //ctx.rotate(angle); // This doesn't work properly in Opera 4470 currentAngle += angle; 4471 4472 if (fill) { 4473 ctx.fill(); 4474 } else { 4475 ctx.stroke(); 4476 } 4477 } 4478 4479 function drawLabels() { 4480 4481 var currentAngle = startAngle; 4482 var radius = options.series.pie.label.radius > 1 ? options.series.pie.label.radius : maxRadius * options.series.pie.label.radius; 4483 4484 for (var i = 0; i < slices.length; ++i) { 4485 if (slices[i].percent >= options.series.pie.label.threshold * 100) { 4486 if (!drawLabel(slices[i], currentAngle, i)) { 4487 return false; 4488 } 4489 } 4490 currentAngle += slices[i].angle; 4491 } 4492 4493 return true; 4494 4495 function drawLabel(slice, startAngle, index) { 4496 4497 if (slice.data[0][1] == 0) { 4498 return true; 4499 } 4500 4501 // format label text 4502 4503 var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter; 4504 4505 if (lf) { 4506 text = lf(slice.label, slice); 4507 } else { 4508 text = slice.label; 4509 } 4510 4511 if (plf) { 4512 text = plf(text, slice); 4513 } 4514 4515 var halfAngle = ((startAngle + slice.angle) + startAngle) / 2; 4516 var x = centerLeft + Math.round(Math.cos(halfAngle) * radius); 4517 var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt; 4518 4519 var html = "<span class='pieLabel' id='pieLabel" + index + "' style='position:absolute;top:" + y + "px;left:" + x + "px;'>" + text + "</span>"; 4520 target.append(html); 4521 4522 var label = target.children("#pieLabel" + index); 4523 var labelTop = (y - label.height() / 2); 4524 var labelLeft = (x - label.width() / 2); 4525 4526 label.css("top", labelTop); 4527 label.css("left", labelLeft); 4528 4529 // check to make sure that the label is not outside the canvas 4530 4531 if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) { 4532 return false; 4533 } 4534 4535 if (options.series.pie.label.background.opacity != 0) { 4536 4537 // put in the transparent background separately to avoid blended labels and label boxes 4538 4539 var c = options.series.pie.label.background.color; 4540 4541 if (c == null) { 4542 c = slice.color; 4543 } 4544 4545 var pos = "top:" + labelTop + "px;left:" + labelLeft + "px;"; 4546 $("<div class='pieLabelBackground' style='position:absolute;width:" + label.width() + "px;height:" + label.height() + "px;" + pos + "background-color:" + c + ";'></div>") 4547 .css("opacity", options.series.pie.label.background.opacity) 4548 .insertBefore(label); 4549 } 4550 4551 return true; 4552 } // end individual label function 4553 } // end drawLabels function 4554 } // end drawPie function 4555 } // end draw function 4556 4557 // Placed here because it needs to be accessed from multiple locations 4558 4559 function drawDonutHole(layer) { 4560 if (options.series.pie.innerRadius > 0) { 4561 4562 // subtract the center 4563 4564 layer.save(); 4565 var innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius; 4566 layer.globalCompositeOperation = "destination-out"; // this does not work with excanvas, but it will fall back to using the stroke color 4567 layer.beginPath(); 4568 layer.fillStyle = options.series.pie.stroke.color; 4569 layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); 4570 layer.fill(); 4571 layer.closePath(); 4572 layer.restore(); 4573 4574 // add inner stroke 4575 4576 layer.save(); 4577 layer.beginPath(); 4578 layer.strokeStyle = options.series.pie.stroke.color; 4579 layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); 4580 layer.stroke(); 4581 layer.closePath(); 4582 layer.restore(); 4583 4584 // TODO: add extra shadow inside hole (with a mask) if the pie is tilted. 4585 } 4586 } 4587 4588 //-- Additional Interactive related functions -- 4589 4590 function isPointInPoly(poly, pt) { 4591 for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) 4592 ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1])) 4593 && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0]) 4594 && (c = !c); 4595 return c; 4596 } 4597 4598 function findNearbySlice(mouseX, mouseY) { 4599 4600 var slices = plot.getData(), 4601 options = plot.getOptions(), 4602 radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius, 4603 x, y; 4604 4605 for (var i = 0; i < slices.length; ++i) { 4606 4607 var s = slices[i]; 4608 4609 if (s.pie.show) { 4610 4611 ctx.save(); 4612 ctx.beginPath(); 4613 ctx.moveTo(0, 0); // Center of the pie 4614 //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here. 4615 ctx.arc(0, 0, radius, s.startAngle, s.startAngle + s.angle / 2, false); 4616 ctx.arc(0, 0, radius, s.startAngle + s.angle / 2, s.startAngle + s.angle, false); 4617 ctx.closePath(); 4618 x = mouseX - centerLeft; 4619 y = mouseY - centerTop; 4620 4621 if (ctx.isPointInPath) { 4622 if (ctx.isPointInPath(mouseX - centerLeft, mouseY - centerTop)) { 4623 ctx.restore(); 4624 return { 4625 datapoint: [s.percent, s.data], 4626 dataIndex: 0, 4627 series: s, 4628 seriesIndex: i 4629 }; 4630 } 4631 } else { 4632 4633 // excanvas for IE doesn;t support isPointInPath, this is a workaround. 4634 4635 var p1X = radius * Math.cos(s.startAngle), 4636 p1Y = radius * Math.sin(s.startAngle), 4637 p2X = radius * Math.cos(s.startAngle + s.angle / 4), 4638 p2Y = radius * Math.sin(s.startAngle + s.angle / 4), 4639 p3X = radius * Math.cos(s.startAngle + s.angle / 2), 4640 p3Y = radius * Math.sin(s.startAngle + s.angle / 2), 4641 p4X = radius * Math.cos(s.startAngle + s.angle / 1.5), 4642 p4Y = radius * Math.sin(s.startAngle + s.angle / 1.5), 4643 p5X = radius * Math.cos(s.startAngle + s.angle), 4644 p5Y = radius * Math.sin(s.startAngle + s.angle), 4645 arrPoly = [[0, 0], [p1X, p1Y], [p2X, p2Y], [p3X, p3Y], [p4X, p4Y], [p5X, p5Y]], 4646 arrPoint = [x, y]; 4647 4648 // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt? 4649 4650 if (isPointInPoly(arrPoly, arrPoint)) { 4651 ctx.restore(); 4652 return { 4653 datapoint: [s.percent, s.data], 4654 dataIndex: 0, 4655 series: s, 4656 seriesIndex: i 4657 }; 4658 } 4659 } 4660 4661 ctx.restore(); 4662 } 4663 } 4664 4665 return null; 4666 } 4667 4668 function onMouseMove(e) { 4669 triggerClickHoverEvent("plothover", e); 4670 } 4671 4672 function onClick(e) { 4673 triggerClickHoverEvent("plotclick", e); 4674 } 4675 4676 // trigger click or hover event (they send the same parameters so we share their code) 4677 4678 function triggerClickHoverEvent(eventname, e) { 4679 4680 var offset = plot.offset(); 4681 var canvasX = parseInt(e.pageX - offset.left); 4682 var canvasY = parseInt(e.pageY - offset.top); 4683 var item = findNearbySlice(canvasX, canvasY); 4684 4685 if (options.grid.autoHighlight) { 4686 4687 // clear auto-highlights 4688 4689 for (var i = 0; i < highlights.length; ++i) { 4690 var h = highlights[i]; 4691 if (h.auto == eventname && !(item && h.series == item.series)) { 4692 unhighlight(h.series); 4693 } 4694 } 4695 } 4696 4697 // highlight the slice 4698 4699 if (item) { 4700 highlight(item.series, eventname); 4701 } 4702 4703 // trigger any hover bind events 4704 4705 var pos = { pageX: e.pageX, pageY: e.pageY }; 4706 target.trigger(eventname, [pos, item]); 4707 } 4708 4709 function highlight(s, auto) { 4710 //if (typeof s == "number") { 4711 // s = series[s]; 4712 //} 4713 4714 var i = indexOfHighlight(s); 4715 4716 if (i == -1) { 4717 highlights.push({ series: s, auto: auto }); 4718 plot.triggerRedrawOverlay(); 4719 } else if (!auto) { 4720 highlights[i].auto = false; 4721 } 4722 } 4723 4724 function unhighlight(s) { 4725 if (s == null) { 4726 highlights = []; 4727 plot.triggerRedrawOverlay(); 4728 } 4729 4730 //if (typeof s == "number") { 4731 // s = series[s]; 4732 //} 4733 4734 var i = indexOfHighlight(s); 4735 4736 if (i != -1) { 4737 highlights.splice(i, 1); 4738 plot.triggerRedrawOverlay(); 4739 } 4740 } 4741 4742 function indexOfHighlight(s) { 4743 for (var i = 0; i < highlights.length; ++i) { 4744 var h = highlights[i]; 4745 if (h.series == s) 4746 return i; 4747 } 4748 return -1; 4749 } 4750 4751 function drawOverlay(plot, octx) { 4752 4753 var options = plot.getOptions(); 4754 4755 var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; 4756 4757 octx.save(); 4758 octx.translate(centerLeft, centerTop); 4759 octx.scale(1, options.series.pie.tilt); 4760 4761 for (var i = 0; i < highlights.length; ++i) { 4762 drawHighlight(highlights[i].series); 4763 } 4764 4765 drawDonutHole(octx); 4766 4767 octx.restore(); 4768 4769 function drawHighlight(series) { 4770 4771 if (series.angle <= 0 || isNaN(series.angle)) { 4772 return; 4773 } 4774 4775 //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString(); 4776 octx.fillStyle = "rgba(255, 255, 255, " + options.series.pie.highlight.opacity + ")"; // this is temporary until we have access to parseColor 4777 octx.beginPath(); 4778 if (Math.abs(series.angle - Math.PI * 2) > 0.000000001) { 4779 octx.moveTo(0, 0); // Center of the pie 4780 } 4781 octx.arc(0, 0, radius, series.startAngle, series.startAngle + series.angle / 2, false); 4782 octx.arc(0, 0, radius, series.startAngle + series.angle / 2, series.startAngle + series.angle, false); 4783 octx.closePath(); 4784 octx.fill(); 4785 } 4786 } 4787 } // end init (plugin body) 4788 4789 // define pie specific options and their default values 4790 4791 var options = { 4792 series: { 4793 pie: { 4794 show: false, 4795 radius: "auto", // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value) 4796 innerRadius: 0, /* for donut */ 4797 startAngle: 3/2, 4798 tilt: 1, 4799 shadow: { 4800 left: 5, // shadow left offset 4801 top: 15, // shadow top offset
4802 alpha: 0.02 // shadow alpha 4803 }, 4804 offset: { 4805 top: 0, 4806 left: "auto" 4807 }, 4808 stroke: { 4809 color: "#fff", 4810 width: 1 4811 }, 4812 label: { 4813 show: "auto", 4814 formatter: function(label, slice) { 4815 return "<div style='font-size:x-small;text-align:center;padding:2px;color:" + slice.color + ";'>" + label + "<br/>" + Math.round(slice.percent) + "%</div>"; 4816 }, // formatter function 4817 radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value) 4818 background: { 4819 color: null, 4820 opacity: 0 4821 }, 4822 threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow) 4823 }, 4824 combine: { 4825 threshold: -1, // percentage at which to combine little slices into one larger slice 4826 color: null, // color to give the new slice (auto-generated if null) 4827 label: "Other" // label to give the new slice 4828 }, 4829 highlight: { 4830 //color: "#fff", // will add this functionality once parseColor is available 4831 opacity: 0.5 4832 } 4833 } 4834 } 4835 }; 4836 4837 $.plot.plugins.push({ 4838 init: init, 4839 options: options, 4840 name: "pie", 4841 version: "1.1" 4842 }); 4843 4844})(jQuery); 4845 4846$(document).ready(function() { 4847 4848 $('.Form_newsletterSubscribe,' + 4849 '.PageArticle .FormRegisterNG,' + 4850 '.StageNewsletterSimple,' + 4851 '.PageRegister,' + 4852 '.StagePremiumPaywall' 4853 ).on('click', '.FormNLOptinPopup_open', function(e) { 4854 var parent = e.delegateTarget; 4855 $('.FormNLOptinPopup, .FormNLOptinPopup_overlay', parent).fadeIn(); 4856 4857 $('input', parent).each(function() { 4858 if ($(this).attr('name') === 'i_email') { 4859 var user_email = $(this).val(); 4860 if (user_email !== '' && user_email !== undefined) { 4861 var icon = "<i class=\"fas fa-envelope\"></i>"; 4862 $('.FormNLOptinPopup_email', parent).html(icon + user_email); 4863 } 4864 } 4865 }); 4866 4867 $('.FormNLOptinPopup_close-icon,' + 4868 '.FormNLOptinPopup_cancel,' + 4869 '.FormNLOptinPopup_overlay', parent).on('click', function(e) { 4870 $('.FormNLOptinPopup, .FormNLOptinPopup_overlay', parent).fadeOut(); 4871 }); 4872 4873 }); 4874 4875}); 4876 4877$(document).ready( function() { 4878 4879 function gA_on_Action(action, data) { 4880 if (data.indexOf('GoogleAnalytics_action') !== -1) { 4881 var url = window.location.href 4882 .split("?")[0] 4883 .split("#")[0]; 4884 url += '/user/registration/completed'; 4885 switch (action) { 4886 case '/user/registerng/register/': 4887 window.dfv_ga_vpageview(url); 4888 if (typeof window.sp_track_virtual_page_view === 'function') { 4889 window.sp_track_virtual_page_view(null, url); 4890 } 4891 break; 4892 default: 4893 } 4894 } 4895 } 4896 4897 function getLocationURL(url) { 4898 4899 const searchParams = new URLSearchParams(window.location.href); 4900 if (searchParams.has('redirect')) { 4901 return searchParams.get('redirect').split("#")[0]; 4902 } 4903 4904 return url.replace('?password=1&', '?') 4905 .replace('?password-en=1&', '?') 4906 .replace('?password=1', '') 4907 .replace('?password-en=1', '') 4908 .replace('&password=1', '') 4909 .replace('&password-en=1', '') 4910 .replace('?password', '?') 4911 .replace('?password-en', '?') 4912 .replace('&password', '') 4913 .replace('&password-en', '') 4914 .replace('?login=1', '?') 4915 .replace('?login-en=1', '?') 4916 .replace('&login=1', '') 4917 .replace('&login-en=1', '') 4918 .split("#")[0]; 4919 } 4920 4921 function sendCCSconversionToCMS(path, verifyhash, cceconversionid, info) { 4922 console.log('sendCCSconversionToCMS', path, verifyhash, cceconversionid, info); 4923 const xhr = new XMLHttpRequest(); 4924 xhr.open('POST', path); 4925 xhr.setRequestHeader('Content-Type', 'application/json'); 4926 xhr.onreadystatechange = () => { 4927 if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { 4928 console.log('cceconversion CMS OK'); 4929 } else if (xhr.readyState === XMLHttpRequest.DONE) { 4930 console.log('cceconversion CMS failed'); 4931 } 4932 }; 4933 const json = JSON.stringify({'i_verifyhash': verifyhash, 'i_cceconversionid':cceconversionid, 'i_info': info}); 4934 xhr.send(json); 4935 } 4936 4937 function pianoSendConversionEventAndGotoURL(data, url) { 4938 var cceconversionid = ''; 4939 document.querySelectorAll('#PianoConversionObject[data-piano-cceconversion-id]').forEach(function(element) {cceconversionid = element.getAttribute('data-piano-cceconversion-id');}); 4940 /* console.log('pianoSendConversionEvent "', cceconversionid, '" cX: ', typeof cX, 'cX.CCE', typeof cX.CCE); */ 4941 let verifyhash = ''; 4942 document.querySelectorAll('input[name=i_verifyhash]').forEach(function(element) {verifyhash = element.getAttribute('value');}); 4943 if (cceconversionid === ''|| verifyhash === '') { 4944 if (verifyhash === '') { 4945 verifyhash = 'no verifyhash'; 4946 } 4947 sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, 'NO', 'no-cceconversionid'); 4948 window.location = url; 4949 } 4950 console.log('sendCCSconversionToCMS'); 4951 sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, cceconversionid, 'start-sen
4951d-conversion-event'); 4952 if (typeof cX === 'undefined' || typeof cX.CCE === 'undefined') { 4953 sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, cceconversionid, 'error-no-cX-or-cXCCE'); 4954 window.location = url; 4955 } 4956 else { 4957 console.log('sendConversionEvent'); 4958 cX.CCE.callQueue.push(['sendConversionEvent', { 4959 'productId': cceconversionid, 4960 'funnelStep': 'convertProduct' 4961 }, { 4962 'callback': function (result) { 4963 console.log(result.httpStatus); // 200 4964 console.log(result.response); // {} 4965 let info = (result.httpStatus !== 200) ? 'error-api-response' : 'OK'; 4966 sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, cceconversionid, info); 4967 window.location = url; 4968 } 4969 }]); 4970 } 4971 } 4972 $('.FormRegisterNG').on('submit', '.FormRegisterNG_form', function(event) { 4973 const formRegisterNg = $(this).closest('.FormRegisterNG'); 4974 event.preventDefault(); 4975 var action = event.currentTarget.getAttribute('action'); 4976 var data = $( this ).serialize(); 4977 $.post( 4978 action, 4979 data, 4980 function(data) { 4981 gA_on_Action(action, data); 4982 var url = ''; 4983 let obj = null; 4984 try { 4985 obj = JSON.parse(data); 4986 switch (obj.step) { 4987 case 'thankyou': 4988 window.dataLayer.push({event: 'registration'}); 4989 formRegisterNg.html( obj.html ); 4990 window.location.href = '#formRegisterNG'; 4991 break; 4992 case 'auto_login': 4993 const searchParams = new URLSearchParams(window.location.href); 4994 console.log( searchParams.has('community') , searchParams.has('community', 1)); 4995 if ( searchParams.has('community') ) { 4996 window.location.href = '/community/'; 4997 break; 4998 } 4999 url = getLocationURL(obj.url); 5000 window.location.href = url; 5001 break; 5002 case 'auto_login_conversion': 5003 url = getLocationURL(obj.url); 5004 pianoSendConversionEventAndGotoURL(data, url); 5005 break; 5006 default: 5007 formRegisterNg.html( obj.html ); 5008 window.location.href = '#formRegisterNG'; 5009 } 5010 return true; 5011 } 5012 catch(e) { 5013 console.log('JSON.parse(data) failed, use html replace', data); 5014 } 5015 5016 if (data === 'auto_login') { 5017 url = getLocationURL(window.location.href); 5018 window.location.href = url; 5019 } else if (data === 'auto_login_conversion' ) { 5020 url = getLocationURL(window.location.href); 5021 pianoSendConversionEventAndGotoURL(data, url); 5022 } else { 5023 let innerHtml = $(data).hasClass('FormRegisterNG_wrapper') ? $(data) : $(data).find('.FormRegisterNG_wrapper'); 5024 if (innerHtml.length > 0) { 5025 formRegisterNg.html(innerHtml); 5026 } else { 5027 formRegisterNg.html(data); 5028 } 5029 window.location.href = '#formRegisterNG'; 5030 } 5031 } 5032 ); 5033 }); 5034 5035 $('.FormRegisterNG').on('click', function(event) { 5036 const formRegisterNg = $(this); 5037 if ($(event.target).hasClass('FormRegisterNG_control-showPassword')) { 5038 event.preventDefault(); 5039 var wdt = $('.FormRegisterNG_control-passwordField').css('width'); 5040 if ($('.FormRegisterNG_control-passwordField').attr('type') === 'password') { 5041 $('.FormRegisterNG_control-passwordField').attr('type', 'text'); 5042 if ($('a.FormRegisterNG_control-showPassword').text() === 'Show password') { 5043 $('a.FormRegisterNG_control-showPassword').text('Hide password'); 5044 } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Mostra password') { 5045 $('a.FormRegisterNG_control-showPassword').text('Inserire password'); 5046 } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Pokaż hasło') { 5047 $('a.FormRegisterNG_control-showPassword').text('Ukryj hasło'); 5048 } else { 5049 $('a.FormRegisterNG_control-showPassword').text('Passwort ausblenden'); 5050 } 5051 } else { 5052 $('.FormRegisterNG_control-passwordField').attr('type', 'password'); 5053 if ($('a.FormRegisterNG_control-showPassword').text() === 'Hide password') { 5054 $('a.FormRegisterNG_control-showPassword').text('Show password'); 5055 } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Inserire password') { 5056 $('a.FormRegisterNG_control-showPassword').text('Mostra password'); 5057 } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Ukryj hasło') { 5058 $('a.FormRegisterNG_control-showPassword').text('Pokaż hasło'); 5059 } else { 5060 $('a.FormRegisterNG_control-showPassword').text('Passwort einblenden'); 5061 } 5062 } 5063 $('.FormRegisterNG_control-passwordField').css('width', wdt); 5064 } else if (event.target.getAttribute('data-action')) { 5065 event.preventDefault(); 5066 var action = event.target.getAttribute('data-action'); 5067 var url = event.target.getAttribute('data-url'); 5068 data = 'url='+url; 5069 $.post( 5070 action, 5071 data, 5072 function(data) { 5073 gA_on_Action(action, data); 5074 formRegisterNg.html( data ); 5075 } 5076 ); 5077 } 5078 }); 5079 5080}); 5081 5082(function() { 5083 5084 if (typeof window.googletag === 'undefined') { 5085 window.googletag = { cmd: [] }; 5086 } 5087 5088 /* Event-Listener Adition iframe */ 5089 window.addEventListener('message',function(event) { 5090 const origin = window.location.origin; 5091 if(event.origin !== origin) return; 5092 5093 switch(event.data) { 5094 case 'bta': 5095 $(document).trigger('btaTeasering'); 5096 break; 5097 5098 default: 5099 return; 5100 } 5101 5102 },false); 5103 5104 5105 5106 'use strict'; 5107 5108 function insertAdvTag2(AdvTxt) { 5109 const taglines = document.querySelectorAll('.bta1Tagline, .bta2Tagline, .BTA-Artikeldetail-aSide-1 .Tagline, .BTA-Artikeldetail-aSide-2 .Tagline, .BTA-Artikeldetail-Stage-1 .Tagline, .BTA-Artikeldetail-Stage-2 .Tagline, .BTA-Artikeldetail-Stage-3 .Tagline'); 5110
5111 taglines.forEach(tagline => { 5112 const btaAdvTag = document.createElement('div'); 5113 btaAdvTag.className = 'AdvertNote'; 5114 btaAdvTag.textContent = AdvTxt; 5115 5116 /* btaAdvTag als erstes Kind des aktuellen Tagline-Elements einfügen */ 5117 tagline.insertBefore(btaAdvTag, tagline.firstChild); 5118 }); 5119 } 5120 5121 function insertAdvTag(AdvTxt, tagline) { 5122 5123 const btaAdvTag = document.createElement('div'); 5124 btaAdvTag.className = 'AdvertNote'; 5125 btaAdvTag.textContent = AdvTxt; 5126 5127 /* btaAdvTag als erstes Kind des aktuellen Tagline-Elements einfügen */ 5128 tagline.insertBefore(btaAdvTag, tagline.firstChild); 5129 5130 } 5131 5132 let btaAsideExists = false; 5133 let btaStageExists = false; 5134 5135 function setBtaStageMargin() { 5136 5137 5138 if (btaAsideExists) { 5139 const pageArticleContent = document.querySelector('.PageArticle_content'); 5140 if (!pageArticleContent) return; 5141 5142 const elAfterContent = pageArticleContent.nextElementSibling; 5143 if (elAfterContent) { 5144 const btaAsideDiv = document.querySelector('.btaAsideContainer'); 5145 5146 if (btaAsideDiv) { 5147 const computedStyle = getComputedStyle(btaAsideDiv); 5148 const btaAsideHeight = btaAsideDiv.offsetHeight + parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom); 5149 elAfterContent.style.marginTop = `${btaAsideHeight + 20}px`; 5150 } 5151 } 5152 } 5153 5154 } 5155 5156/* BTA-Aside */ 5157 5158 let isAsideListenerActive = false; 5159 5160 function positionAsideBta() { 5161 const leadEl = document.querySelector('.PageArticle_sticky'); 5162 const targetEl = document.querySelector('.btaAsideContainer'); 5163 5164 if (leadEl && targetEl) { 5165 /* hat leadEl "position: fixed" */ 5166 const leadComputedStyle = window.getComputedStyle(leadEl); 5167 const isLeadFixed = leadComputedStyle.position === 'fixed'; 5168 5169 let newTop; 5170 5171 if (isLeadFixed) { 5172 // wenn leadEl "fixed", dann positioniere targetEl relativ zum Viewport 5173 const leadRect = leadEl.getBoundingClientRect(); 5174 targetEl.style.position = 'fixed'; 5175 newTop = leadRect.bottom + 5; 5176 } else { 5177 // wenn leadEl nicht "fixed", dann positioniere targetEl relativ zum Dokument 5178 const leadOffsetTop = leadEl.offsetTop + leadEl.offsetHeight; 5179 targetEl.style.position = 'absolute'; 5180 newTop = leadOffsetTop + 5; 5181 } 5182 5183 targetEl.style.top = `${newTop}px`; 5184 5185 /* debugging */ 5186 /* 5187 console.log({ 5188 leadPosition: leadComputedStyle.position, 5189 leadBottom: leadEl.getBoundingClientRect().bottom, 5190 leadOffsetTop: leadEl.offsetTop, 5191 targetTop: targetEl.style.top, 5192 }); 5193 */ 5194 } 5195 } 5196 5197 function addAsideEventListeners() { 5198 if (!isAsideListenerActive) { 5199 window.addEventListener('resize', positionAsideBta); 5200 window.addEventListener('scroll', positionAsideBta); 5201 isAsideListenerActive = true; 5202 } 5203 } 5204 5205 $(document).on("btaTeasering", function(event){ 5206 // alle Elementen mit der Klasse "btaFrame" und dem Data-Attribut "ad_position" gleich "0" 5207 const bta1Els = document.querySelectorAll('.btaFrame[data-ad_position="bta1"]'); 5208 const bta2Els = document.querySelectorAll('.btaFrame[data-ad_position="bta2"]'); 5209 const bta3Els = document.querySelectorAll('.btaFrame[data-ad_position="bta3"]'); 5210 const bta4Els = document.querySelectorAll('.btaFrame[data-ad_position="bta4"]'); 5211 const bta5Els = document.querySelectorAll('.btaFrame[data-ad_position="bta5"]'); 5212 const bta6Els = document.querySelectorAll('.btaFrame[data-ad_position="bta6"]'); 5213 const bta7Els = document.querySelectorAll('.btaFrame[data-ad_position="bta7"]'); 5214 5215 if (bta1Els.length > 0) { 5216 const bta1Tagline = document.querySelector('.bta1Tagline'); 5217 const bta1Headline = document.querySelector('.bta1Headline'); 5218 const bta1href = document.querySelector('.bta1Url'); 5219 const bta1Text = document.querySelector('.BTA-Homepage-Aufmacher .ArticleTeaser_abstract'); 5220 5221 bta1Els.forEach(bta1El => { 5222 const bta_kicker = bta1El.getAttribute('data-kicker'); 5223 if (bta1Tagline && bta_kicker) { 5224 bta1Tagline.textContent = bta_kicker; 5225 } 5226 const bta_titel = bta1El.getAttribute('data-titel'); 5227 if (bta1Headline && bta_titel) { 5228 bta1Headline.textContent = bta_titel; 5229 } 5230 const bta_url = bta1El.getAttribute('data-targeturl'); 5231 if (bta1href && bta_url) { 5232 bta1href.href = bta_url; 5233 bta1href.setAttribute('target', '_blank'); 5234 } 5235 const bta_text = bta1El.getAttribute('data-text_content'); 5236 if (bta1Text) { 5237 bta1Text.textContent = bta_text; 5238 } 5239 insertAdvTag('Anzeige', bta1Tagline); 5240 }); 5241 5242 } 5243 5244 if (bta2Els.length > 0) { 5245 const bta2Tagline = document.querySelector('.bta2Tagline'); 5246 const bta2Headline = document.querySelector('.bta2Headline'); 5247 const bta2href = document.querySelector('.bta2Url'); 5248
5249 bta2Els.forEach(bta2El => { 5250 const bta_kicker = bta2El.getAttribute('data-kicker'); 5251 if (bta2Tagline && bta_kicker) { 5252 bta2Tagline.textContent = bta_kicker; 5253 } 5254 const bta_titel = bta2El.getAttribute('data-titel'); 5255 if (bta2Headline && bta_titel) { 5256 bta2Headline.textContent = bta_titel; 5257 } 5258 const bta_url = bta2El.getAttribute('data-targeturl'); 5259 if (bta2href && bta_url) { 5260 bta2href.href = bta_url; 5261 } 5262 }); 5263 insertAdvTag('Anzeige', bta2Tagline); 5264 } 5265 5266 5267 if (bta3Els.length > 0) { 5268 const bta3Tagline = document.querySelector('.BTA-Artikeldetail-aSide-1 .Tagline'); 5269 const bta3Headline = document.querySelector('.BTA-Artikeldetail-aSide-1 .Headline'); 5270 const bta3href = document.querySelector('.BTA-Artikeldetail-aSide-1 .btaAside1Link'); 5271 5272 bta3Els.forEach(bta3El => { 5273 const bta_kicker = bta3El.getAttribute('data-kicker'); 5274 if (bta3Tagline && bta_kicker) { 5275 bta3Tagline.textContent = bta_kicker; 5276 } 5277 const bta_titel = bta3El.getAttribute('data-titel'); 5278 if (bta3Headline && bta_titel) { 5279 bta3Headline.textContent = bta_titel; 5280 } 5281 const bta_url = bta3El.getAttribute('data-targeturl'); 5282 if (bta3href && bta_url) { 5283 bta3href.href = bta_url; 5284 } 5285 5286 /* Position bei Änderungen aktualisieren */ 5287 addAsideEventListeners(); 5288 5289 /* Initiale Positionierung */ 5290 document.addEventListener('DOMContentLoaded', positionAsideBta); 5291 btaAsideExists = true; 5292 insertAdvTag('Anzeige', bta3Tagline); 5293 5294 }); 5295 } else { 5296 const btaAsideContainer = document.querySelector('.btaAsideContainer'); 5297 if (btaAsideContainer && (bta4Els.length < 1) ) { 5298 btaAsideContainer.style.display = 'none'; 5299 } 5300 } 5301 5302 if (bta4Els.length > 0) { 5303 const bta4Tagline = document.querySelector('.BTA-Artikeldetail-aSide-2 .Tagline'); 5304 const bta4Headline = document.querySelector('.BTA-Artikeldetail-aSide-2 .Headline'); 5305 const bta4href = document.querySelector('.BTA-Artikeldetail-aSide-2 .btaAside2Link'); 5306 5307 bta4Els.forEach(bta4El => { 5308 const bta_kicker = bta4El.getAttribute('data-kicker'); 5309 if (bta4Tagline && bta_kicker) { 5310 bta4Tagline.textContent = bta_kicker; 5311 } 5312 const bta_titel = bta4El.getAttribute('data-titel'); 5313 if (bta4Headline && bta_titel) { 5314 bta4Headline.textContent = bta_titel; 5315 } 5316 const bta_url = bta4El.getAttribute('data-targeturl'); 5317 if (bta4href && bta_url) { 5318 bta4href.href = bta_url; 5319 } 5320 5321 addAsideEventListeners(); 5322 5323 /* Initiale Positionierung */ 5324 document.addEventListener('DOMContentLoaded', positionAsideBta); 5325 btaAsideExists = true; 5326 insertAdvTag('Anzeige', bta4Tagline); 5327 }); 5328 } else { 5329 const btaAsideContainer = document.querySelector('.btaAsideContainer'); 5330 if (btaAsideContainer && (bta3Els.length < 1)) { 5331 btaAsideContainer.style.display = 'none'; 5332 } 5333 } 5334 5335 if (bta5Els.length > 0) { 5336 btaStageExists = true; 5337 const bta5Tagline = document.querySelector('.BTA-Artikeldetail-Stage-1 .Tagline'); 5338 const bta5Headline = document.querySelector('.BTA-Artikeldetail-Stage-1 .Headline'); 5339 const bta5hrefs = document.querySelectorAll('.BTA-Artikeldetail-Stage-1 a.ArticleTeaser_link'); 5340 const bta5Text = document.querySelector('.BTA-Artikeldetail-Stage-1 .ArticleTeaser_abstract a.ArticleTeaser_link'); 5341 5342 bta5Els.forEach(bta5El => { 5343 const bta_kicker = bta5El.getAttribute('data-kicker'); 5344 if (bta5Tagline && bta_kicker) { 5345 bta5Tagline.textContent = bta_kicker; 5346 } 5347 const bta_titel = bta5El.getAttribute('data-titel'); 5348 if (bta5Headline && bta_titel) { 5349 bta5Headline.textContent = bta_titel; 5350 } 5351 bta5hrefs.forEach(bta5href => { 5352 const bta_url = bta5El.getAttribute('data-targeturl'); 5353 if (bta_url) { 5354 bta5href.href = bta_url; 5355 bta5href.setAttribute('target', '_blank'); 5356 } 5357 }); 5358 const bta_text = bta5El.getAttribute('data-text_content'); 5359 if (bta5Text) { 5360 bta5Text.textContent = bta_text; 5361 } 5362 setBtaFrameHeight(bta5El); 5363 insertAdvTag('Anzeige', bta5Tagline); 5364 }); 5365 5366 } 5367 5368 if (bta6Els.length > 0) { 5369 btaStageExists = true; 5370 const bta6Tagline = document.querySelector('.BTA-Artikeldetail-Stage-2 .Tagline'); 5371 const bta6Headline = document.querySelector('.BTA-Artikeldetail-Stage-2 .Headline'); 5372 const bta6hrefs = document.querySelectorAll('.BTA-Artikeldetail-Stage-2 a.ArticleTeaser_link'); 5373 const bta6Text = document.querySelector('.BTA-Artikeldetail-Stage-2 .ArticleTeaser_abstract a.ArticleTeaser_link'); 5374
5375 bta6Els.forEach(bta6El => { 5376 const bta_kicker = bta6El.getAttribute('data-kicker'); 5377 if (bta6Tagline && bta_kicker) { 5378 bta6Tagline.textContent = bta_kicker; 5379 } 5380 const bta_titel = bta6El.getAttribute('data-titel'); 5381 if (bta6Headline && bta_titel) { 5382 bta6Headline.textContent = bta_titel; 5383 } 5384 bta6hrefs.forEach(bta6href => { 5385 const bta_url = bta6El.getAttribute('data-targeturl'); 5386 if (bta_url) { 5387 bta6href.href = bta_url; 5388 bta6href.setAttribute('target', '_blank'); 5389 } 5390 }); 5391 const bta_text = bta6El.getAttribute('data-text_content'); 5392 if (bta6Text) { 5393 bta6Text.textContent = bta_text; 5394 } 5395 setBtaFrameHeight(bta6El); 5396 insertAdvTag('Anzeige', bta6Tagline); 5397 }); 5398 } 5399 5400 if (bta7Els.length > 0) { 5401 btaStageExists = true; 5402 const bta7Tagline = document.querySelector('.BTA-Artikeldetail-Stage-3 .Tagline'); 5403 const bta7Headline = document.querySelector('.BTA-Artikeldetail-Stage-3 .Headline'); 5404 const bta7hrefs = document.querySelectorAll('.BTA-Artikeldetail-Stage-3 a.ArticleTeaser_link'); 5405 const bta7Text = document.querySelector('.BTA-Artikeldetail-Stage-3 .ArticleTeaser_abstract a.ArticleTeaser_link'); 5406 5407 bta7Els.forEach(bta7El => { 5408 const bta_kicker = bta7El.getAttribute('data-kicker'); 5409 if (bta7Tagline && bta_kicker) { 5410 bta7Tagline.textContent = bta_kicker; 5411 } 5412 const bta_titel = bta7El.getAttribute('data-titel'); 5413 if (bta7Headline && bta_titel) { 5414 bta7Headline.textContent = bta_titel; 5415 } 5416 bta7hrefs.forEach(bta7href => { 5417 const bta_url = bta7El.getAttribute('data-targeturl'); 5418 if (bta_url) { 5419 bta7href.href = bta_url; 5420 bta7href.setAttribute('target', '_blank'); 5421 } 5422 }); 5423 const bta_text = bta7El.getAttribute('data-text_content'); 5424 if (bta7Text) { 5425 bta7Text.textContent = bta_text; 5426 } 5427 setBtaFrameHeight(bta7El); 5428 insertAdvTag('Anzeige', bta7Tagline); 5429 }); 5430 } 5431 5432 setBtaStageMargin(); 5433 eraseEmptyStageArticles(); 5434 5435 5436 5437 }); /* end btaTeasering */ 5438 5439 5440 function isStageSlotFilled(slotElement) { 5441 if (!slotElement) return false; 5442 5443 // Echte Anzeige vorhanden 5444 const adIframe = slotElement.querySelector('iframe'); 5445 if (adIframe) { 5446 return adIframe.offsetHeight > 0 || adIframe.dataset.loadComplete === 'true'; 5447 } 5448 5449 // GAM-Container ohne iframe -> nur als gefuellt werten, wenn sichtbar > 0 5450 const gamContainer = slotElement.querySelector('div[id$="__container__"]'); 5451 if (gamContainer) { 5452 return gamContainer.offsetHeight > 0; 5453 } 5454 5455 return false; 5456 } 5457 5458 5459 function eraseEmptyStageArticles() { 5460 const btaStageSection = document.querySelector('.StageAdvertNativeTextAds'); 5461 5462 if (btaStageSection) { 5463 const stageElements = btaStageSection.querySelectorAll('[id^="renderSlot_BTA-Artikeldetail-Stage-"]'); 5464 let hiddenArticles = 0; 5465 stageElements.forEach((element) => { 5466 const isFilled = isStageSlotFilled(element); 5467 if (!isFilled) { 5468 const articleElement = element.closest('article'); 5469 if (articleElement) { 5470 articleElement.style.display = 'none'; 5471 articleElement.classList.add('noDisplay'); 5472 hiddenArticles++; 5473 5474 } else { 5475 5476 } 5477 } 5478 }); 5479 5480 if (hiddenArticles === 2) { 5481 layoutSingleArticle(); 5482 } 5483 5484 } 5485 } 5486 5487 function layoutSingleArticle() { 5488 window.onload = () => { 5489 console.log('Seite vollständig geladen'); 5490 5491 setTimeout(() => { 5492 const singleArticleEl = Array.from(document.querySelectorAll('[class*="BTA-Artikeldetail-Stage-"]')).find(element => { 5493 const style = window.getComputedStyle(element); 5494 return (style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0') && 5495 !element.classList.contains('noDisplay'); 5496 }); 5497 5498 if (singleArticleEl) { 5499 const anchorTag = singleArticleEl.querySelector('a.ArticleTeaser_imgWrapper'); 5500 if (anchorTag) { 5501 anchorTag.style.float = 'left'; 5502 anchorTag.style.marginRight = '1em'; 5503 } 5504 } else { 5505 console.log('Kein sichtbares Element gefunden.'); 5506 } 5507 }, 150); 5508 }; 5509 5510 5511 } 5512 5513 /* in BTA-Bühne Höhe des iFrames an img anpassen */ 5514 function setBtaFrameHeight(btaFrame) { 5515 if (btaFrame) { 5516 btaFrame.onload = function() { 5517 const btaFrameDocument = btaFrame.contentDocument || btaFrame.contentWindow.document; 5518 const bannerImage = btaFrameDocument.getElementById('banner_image'); 5519 if (bannerImage) { 5520 const bannerHeight = bannerImage.offsetHeight; 5521 5522 requestAnimationFrame(() => { 5523 btaFrame.style.height = bannerHeight + 'px'; 5524 }); 5525 } else { 5526 console.error('Das <img>-Element mit der ID "banner_image" wurde im btaFrame nicht gefunden.'); 5527 } 5528 }; 5529 } 5530 } 5531 5532 /* 5533 START 5534 check ob bta-Bühne leer ist, dann nicht anzeigen 5535 */ 5536 function waitForLoad() { 5537 return new Promise((resolve) => { 5538 window.onload = resolve; 5539 }); 5540 } 5541 5542 function waitForAdditionalTime(ms) { 5543 return new Promise((resolve) => setTimeout(resolve, ms)); 5544 } 5545 5546 waitForLoad().then(() => { 5547 return waitForAdditionalTime(1000); 5548 }).then(() => { 5549 const bta5Els = document.querySelector('.btaFrame[data-ad_position="bta5"]'); 5550 const bta6Els = document.querySelector('.btaFrame[data-ad_position="bta6"]'); 5551 const bta7Els = document.querySelector('.btaFrame[data-ad_position="bta7"]'); 5552 5553 if (!bta5Els && !bta6Els && !bta7Els) { 5554 const btaStageSection = document.querySelector('.StageAdvertNativeTextAds'); 5555 if (btaStageSection) { 5556 btaStageSection.style.display = 'none'; 5557 } 5558 } 5559 }); 5560 /* 5561 END 5562 check ob bta-Bühne leer ist, dann nicht anzeigen 5563 */ 5564 5565 5566 5567})(); 5568 5569 5570/* Event-Listener Adition iframe */ 5571if (typeof window.googletag === 'undefined') { 5572 window.googletag = { cmd: [] }; 5573} 5574 5575window.addEventListener('message',function(event) { 5576 const origin = window.location.origin; 5577 if(event.origin !== origin) return; 5578 5579 let currentUrl = window.location.href; 5580 5581 let be_domainsInsertAdvTextDiv = [ 5582 'iz.de', 5583 'handelextra.pl', 5584 'how-green-works.de', 5585 'foodservice24.pl', 5586 'horizont.net', 5587 'mmponline.pl', 5588 'lebensmittelzeitung.net', 5589 'tw-media.com', 5590 'pebbles.dfv-is.de', 5591 'fibers-in-process.de', 5592 'umweltwirtschaft.com', 5593 'wwt-online.de', 5594 'changement-magazin.de', 5595 'zoe-online.org' 5596 ]; 5597 5598 let be_domainsAddSliderControl = ['ahgz.at', 'lebensmittelzeitung.net']; 5599 5600 let be_domainsContainerClass = { 5601 'default': 'PageFrame', 5602 'the-spin-off.com' : 'container', 5603 'horizont.net' : 'SiteHeader', 5604 'dfv-is.de' : 'SiteHeader', 5605 'fibers-in-process.de' : 'SiteHeader', 5606 'umweltwirtschaft.com' : 'SiteHeader', 5607 'wwt-online.de' : 'SiteHeader', 5608 'changement-magazin.de' : 'SiteHeader', 5609 'zoe-online.org' : 'SiteHeader' 5610 }; 5611 5612 let be_domainsWideLayout = [ 5613 'horizont.net', 5614 'mmponline.pl', 5615 'dfv-is.de', 5616 'fibers-in-process.de', 5617 'umweltwirtschaft.com', 5618 'wwt-online.de', 5619 'changement-magazin.de', 5620 'zoe-online.org' 5621 ]; 5622 5623 function be_isDomainInUrl(domainsArray, currentUrl) { 5624 return domainsArray.some(domain => currentUrl.includes(domain)); 5625 } 5626 5627 let wideLayout = false;
5628 if (be_isDomainInUrl(be_domainsWideLayout, currentUrl)) { 5629 wideLayout = true; 5630 } 5631 5632 let be_containerClass; 5633 const matchingKey = Object.keys(be_domainsContainerClass).find(key => currentUrl.includes(key)); 5634 5635 if (matchingKey) { 5636 be_containerClass = be_domainsContainerClass[matchingKey]; 5637 } else { 5638 be_containerClass = be_domainsContainerClass['default']; 5639 } 5640 5641 switch(event.data) { 5642 5643 case 'textAd': $(document).trigger('textAd'); 5644 break; 5645 /* 5646 case 'teadsResize': 5647 $(document).trigger('teadsResize'); 5648 break; 5649 5650 */ 5651 case 'parallax': 5652 if (be_isDomainInUrl(be_domainsInsertAdvTextDiv, currentUrl)) { 5653 $(document).trigger('insertAdvTextDiv'); 5654 } 5655 $(document).trigger('parallax'); 5656 break; 5657 case 'bannerinit': 5658 //$(document).trigger('resizeIframe'); 5659 $(document).trigger('advertOnImage'); 5660 $(document).trigger('clsAlignSuperbanner'); 5661 $(document).trigger('clsAlignBillboard'); 5662 $(document).trigger('BillboardHeight'); 5663 5664 5665 if (be_isDomainInUrl(be_domainsAddSliderControl,currentUrl)) { 5666 $(document).trigger('adSliderControl'); 5667 } 5668 if (be_isDomainInUrl(be_domainsInsertAdvTextDiv, currentUrl)) { 5669 $(document).trigger('insertAdvTextDiv'); 5670 } 5671 break; 5672 case 'singlebanner': 5673 $(document).trigger('clsAlignSuperbanner'); 5674 $(document).trigger('clsAlignBillboard'); 5675 break; 5676 case 'halfpage': 5677 $(document).trigger('halfpage', [be_containerClass]); 5678 break; 5679 case 'floorAd': 5680 $(document).trigger('floorAd'); 5681 //$(document).trigger('resizeIframe'); 5682 break; 5683 /* 5684 case 'html5floorAd': 5685 $(document).trigger('html5floorAd'); 5686 break; 5687 case 'HTML5sitebar': 5688 $(document).trigger('html5sitebar'); 5689 break; 5690 */ 5691 case 'layerAd': 5692 $(document).trigger('layerAd'); 5693 break; 5694 5695 case 'bridgeAd': 5696 $(document).trigger('alignSkyscraperLeft'); 5697 $(document).trigger('alignSkyscraperRight'); 5698 $(document).trigger('bridgeAd'); 5699 break; 5700 case 'bridgeAdSticky': 5701 $(document).trigger('alignSkyscraperLeft'); 5702 $(document).trigger('alignSkyscraperRight'); 5703 $(document).trigger('bridgeAdSticky'); 5704 $(document).trigger('billboardSticky'); 5705 break; 5706 5707 case 'bridgeAdComp': 5708 $(document).trigger('bridgeAdComp'); 5709 break; 5710 5711 case 'fullWidthBillboard': 5712 $(document).trigger('fullWidthBillboard'); 5713 break; 5714 5715 case 'valueAd': 5716 $(document).trigger('valueAd'); 5717 break; 5718 /* 5719 case 'exitintent': 5720 $(document).trigger('exitintent'); 5721 break; 5722 case 'background': 5723 $(document).trigger('changeBackgroundColor'); 5724 break; 5725 case 'backgroundclick': 5726 $(document).trigger('isBackgroundClick'); 5727 break; 5728 case 'counterAd': 5729 $(document).trigger('counterAd'); 5730 break; 5731 case 'centerFrame': $(document).trigger('centerIframe'); 5732 break; 5733 case 'blockadvertisement': 5734 $(document).trigger('blockadvertisement'); 5735 break; 5736 case 'wallpapercolor': 5737 $(document).trigger('wallpapercolor'); 5738 break; 5739 */ 5740 case 'sitebar': 5741 case 'sitebarHTML5': 5742 $(document).trigger('sitebar', [wideLayout]); 5743 break; 5744 case 'sitebar-switch': 5745 $(document).trigger('sitebar-switch', [be_domainsContainerClass, wideLayout]); 5746 break; 5747 case 'sitebarLeft': 5748 $(document).trigger('sitebarLeft', [wideLayout]); 5749 break; 5750 case 'pushdown': 5751 case 'pushdown2': 5752 case 'pushdown3': 5753 case 'pushdown4': 5754 case 'pushdown5': 5755 case 'pushdown6': 5756 case 'pushdown7': 5757 const elementclass = event.data; 5758 $(document).trigger('pushdown', [elementclass]); 5759 break; 5760 case 'parallax_outstream': 5761 $(document).trigger('parallax_outstream'); 5762 break; 5763 case 'dynamic_sitebar': 5764 $(document).trigger('dynamic_sitebar'); 5765 break; 5766 case 'billboardSticky': 5767 $(document).trigger('billboardSticky'); 5768 break; 5769 case 'dfvSolutionAd': 5770 $(document).trigger('dfvSolutionAd'); 5771 break; 5772 case 'welcomeVideo': 5773 $(document).trigger('welcomeAdVideo'); break; 5774 case 'welcomeVideoMobil': 5775 $(document).trigger('welcomeAdVideoMobil'); break; 5776 case 'welcomeImage': 5777 $(document).trigger('welcomeAdImage'); break; 5778 case 'welcomeImageMobil': 5779 $(document).trigger('welcomeAdImageMobil'); break; 5780 case 'understitial': 5781 $(document).trigger('understitial'); 5782 break; 5783 case 'bbreminder': 5784 $(document).trigger('bbReminder'); 5785 break; 5786 case 'fadeoutadvertisement': 5787 $(document).trigger('fadeoutadvertisement'); 5788 break; 5789 default: 5790 return; 5791 } 5792 5793},false); 5794 5795/** 5796 * billboardHeight 5797 * billboard pushdown - margin bottom / overflow hidden 5798 */ 5799$(document).one('billboardHeight', function() {
5800 const slots = document.querySelectorAll('#renderSlot_Billboard, #renderSlot_Mobil-Billboard'); 5801 5802 slots.forEach(slot => { 5803 let banner_div = slot.querySelector('div'); 5804 if (banner_div) { 5805 const checkStyleInterval = setInterval(() => { 5806 if (banner_div.getAttribute('style')) { 5807 banner_div.style.marginBottom = '20px'; 5808 if (slot.offsetHeight < 290) { /* CLS */ 5809 slot.style.marginBottom = '20px'; 5810 } 5811 slot.style.overflow = 'hidden'; 5812 clearInterval(checkStyleInterval); 5813 } 5814 }, 100); 5815 } else { 5816 const observer = new MutationObserver((mutationsList, observer) => { 5817 mutationsList.forEach(mutation => { 5818 if (mutation.type === 'childList') { 5819 banner_div = slot.querySelector('div'); 5820 if (banner_div) { 5821 const checkStyleInterval = setInterval(() => { 5822 if (banner_div.getAttribute('style')) { 5823 banner_div.style.marginBottom = '20px'; 5824 if (slot.offsetHeight < 290) { /* CLS */ 5825 slot.style.marginBottom = '20px'; 5826 } 5827 slot.style.overflow = 'hidden'; 5828 clearInterval(checkStyleInterval); 5829 } 5830 }, 100); 5831 observer.disconnect(); 5832 } 5833 } 5834 }); 5835 }); 5836 observer.observe(slot, { childList: true, subtree: true }); 5837 } 5838 }); 5839}); 5840 5841/** 5842 * billboardSticky 5843 */ 5844$(document).on('billboardSticky', function() { 5845 const slot = document.querySelector('#renderSlot_Billboard, #renderSlot_Mobil-Billboard'); 5846 if (!slot) return; 5847 5848 const billboardIframe = document.querySelector('.billboardSticky'); 5849 const stickyHeader = document.querySelector('.SiteHeaderSticky'); 5850 5851 const stickyHeaderHeight = stickyHeader ? stickyHeader.offsetHeight : 0; 5852 const billboardPositionTop = slot.getBoundingClientRect().top + window.scrollY; 5853 5854 const parentMarginTop = billboardIframe ? parseFloat(getComputedStyle(billboardIframe.parentNode).marginTop) : 0; 5855 let billboardStickyOffsetTop = stickyHeaderHeight + 5; 5856 billboardStickyOffsetTop += (Math.sign(parentMarginTop) === -1) ? Math.abs(parentMarginTop) : -Math.abs(parentMarginTop); 5857 5858 // Banner-ID aus iframe.id erzeugen (zwischen erstem und zweitem "/") 5859 const idParts = billboardIframe.id.split('/'); 5860 let bId = idParts[1] || 'default'; 5861 const lsKey = 'stickyBillboard_' + bId; 5862 let sTimer = null; 5863 let ticking = false; 5864 let animationFrameId = null; 5865 5866 const scrollDuration = 300; 5867 5868 // LocalStorage prüfen 5869 const lsValue = localStorage.getItem(lsKey); 5870 if (lsValue) { 5871 const expireDate = JSON.parse(lsValue).expireAt; 5872 if (expireDate >= Date.now()) return; 5873 else localStorage.removeItem(lsKey); 5874 } 5875 5876 function animateSlot(from, to, duration) { 5877 let startTime = null; 5878 function animate(time) { 5879 if (!startTime) startTime = time; 5880 const progress = Math.min((time - startTime) / duration, 1); 5881 slot.style.top = from + (to - from) * progress + 'px'; 5882 if (progress < 1) animationFrameId = requestAnimationFrame(animate); 5883 else animationFrameId = null; 5884 } 5885 animationFrameId = requestAnimationFrame(animate); 5886 } 5887 5888 function handleScroll() { 5889 const scrollTop = window.scrollY; 5890 5891 if (scrollTop > billboardPositionTop) { 5892 if (!slot.classList.contains('isStickyBillboard') && !sTimer && !localStorage.getItem(lsKey)) { 5893 slot.classList.add('isStickyBillboard'); 5894 slot.style.position = 'fixed'; 5895 slot.style.top = billboardStickyOffsetTop + 'px'; 5896 slot.style.zIndex = 999; 5897 5898 sTimer = setTimeout(() => { 5899 animateSlot(billboardStickyOffsetTop, -600, 3000); 5900 sTimer = null; 5901 const expireAt = Date.now() + 60000 * 1440; 5902 localStorage.setItem(lsKey, JSON.stringify({ expireAt })); 5903 }, 2000); 5904 } 5905 } else { 5906 if (sTimer) { 5907 clearTimeout(sTimer); 5908 sTimer = null; 5909 } 5910 if (animationFrameId) { 5911 cancelAnimationFrame(animationFrameId); 5912 animationFrameId = null; 5913 } 5914 const currentTop = parseFloat(getComputedStyle(slot).top) || 0; 5915 animateSlot(currentTop, 0, scrollDuration); 5916 slot.classList.remove('isStickyBillboard'); 5917 slot.style.position = ''; 5918 } 5919 5920 ticking = false;
5921 } 5922 5923 window.addEventListener('scroll', function() { 5924 if (!ticking) { 5925 window.requestAnimationFrame(handleScroll); 5926 ticking = true; 5927 } 5928 }); 5929}); 5930 5931 5932 5933/** 5934 * parallax 5935 */ 5936$(document).on("parallax", function(event){ 5937 'use strict'; 5938 const htmlTag = document.getElementsByTagName('html')[0]; 5939 const peephole = $(".parallax").parent().parent(); 5940 const parallax_div = $(".parallax").parent(); 5941 const parallax_iframe = $(".parallax"); 5942 5943 const peephole_width = peephole.width(); 5944 const peephole_height = peephole.height(); 5945 5946 const bgcolor = parallax_iframe.data("bgcolor"); 5947 const parallax_ratio = parallax_iframe.data("height") / parallax_iframe.data("width"); 5948 5949 htmlTag.classList.add('Ad_setZindex'); /* Workaround für Safari < v15 */ 5950 5951 let viewportHeight = window.innerHeight - $(".SiteHeaderSticky").outerHeight(true); 5952 if (window.innerWidth < 768) { 5953 viewportHeight = window.innerHeight; 5954 } 5955 if (parallax_iframe.data("width") >= parallax_div.width()){ 5956 parallax_iframe.height( parallax_div.width() * parallax_ratio); 5957 } 5958 5959 let ad_top = parseInt(viewportHeight - parallax_iframe.height()) / 2; 5960 const parallax_height_diff = Math.abs(viewportHeight - parallax_iframe.height()) * parallax_ratio; 5961 const parallax_width_diff = Math.floor(parallax_height_diff); 5962 5963 if ((parallax_iframe.data("height") >= viewportHeight) || (ad_top < parseInt($(".SiteHeaderSticky").outerHeight(true)))) { 5964 ad_top = $(".SiteHeaderSticky").outerHeight(true) +"px"; 5965 } 5966 5967 peephole.height(viewportHeight); 5968 peephole.css("position","relative");
5969 peephole.prepend('<span class=\"Ad_parallax-borderTop\" style=\"width: ' + peephole_width + 'px;\"></span>'); /*Chrome-Render-Fix*/ 5970 5971 parallax_div.css('width', peephole_width + 'px'); 5972 parallax_div.css("height",viewportHeight); 5973 if (bgcolor) { 5974 parallax_div.css("background-color", bgcolor); 5975 } 5976 parallax_div.addClass('Ad_parallax-innerWrapper'); 5977 parallax_div.css('margin', '0 auto'); 5978 parallax_iframe.height(viewportHeight); 5979 const parallax_width = parallax_div.height() / parallax_ratio; 5980 5981 if ((peephole_height > viewportHeight) && (window.innerWidth < 768)) { 5982 parallax_iframe.width(parallax_width-parallax_width_diff); 5983 } else { 5984 parallax_iframe.width(parallax_width); 5985 } 5986 5987 if (parallax_width > peephole_width) { 5988 parallax_iframe.width(peephole_width); 5989 } 5990 5991 if (parallax_div.width() - parallax_iframe.width() > 48 ){ 5992 parallax_iframe.css("margin-left", ((parallax_div.width() - parallax_iframe.width()) / 2) + "px"); 5993 } else { 5994 parallax_iframe.css("margin-left", "0px"); 5995 } 5996 parallax_iframe.css("position","fixed"); 5997 parallax_iframe.css("bottom",ad_top); 5998 parallax_iframe.css("top",ad_top); 5999 6000}); 6001 6002/** 6003 * textAd 6004 */ 6005$(document).one("textAd", function() { 6006 $("iframe.textAd").each(function() { 6007 6008 const $iframe = $(this); 6009 6010 $.each(this.attributes, function() { 6011 if(this.name.startsWith('data-')) { 6012 /* console.log(this.name + ': ' + $iframe.attr(this.name)); */ 6013 } 6014 }); 6015 6016 // Füge ein leeres DIV direkt unter das nächste Elternelement mit id^="renderSlot_" 6017 const $container = $iframe.closest('[id^="renderSlot_"]'); 6018 if ($container.length) { 6019 $('<div class="AnzHelper"></div>').insertBefore($container.children().first()); 6020 } 6021 6022 const headline = $iframe.attr("data-headline") || ""; 6023 const text = $iframe.attr("data-text") || ""; 6024 const imgPos = ($iframe.attr("data-img-pos") || "top").toLowerCase(); 6025 const moreButton = $iframe.attr("data-more_button") === "ja"; 6026 const buttonText = $iframe.attr("data-button_text") || "Mehr"; 6027 const clickUrl = $iframe.attr("data-clickurl") || "#"; 6028 const centerAd = $iframe.attr("data-center_ad") === "1"; 6029 const marginTop = parseInt($iframe.attr("data-margin-top") || "0", 10); 6030 6031 const $textWrapper = $("<div class=\"ArticleTeaser_content\"><div class='textAd-text-wrapper ArticleTeaser_content'></div></div>") 6032 .css({ 6033 "line-height": "1.4em", 6034 "white-space": "normal", 6035 "font-family": "inherit", 6036 "font-size": "16px", 6037 "text-align": centerAd ? "center" : "left", 6038 "margin-top": `${marginTop}px` 6039 }) 6040 .html(` 6041 <h2 class="Headline ArticleTeaser_headline TextAdHeadLine">${headline}</h2> 6042 <div class="ArticleTeaser_abstract TextAdContent">${text}</div> 6043 `); 6044 6045 if (moreButton) { 6046 const btn = document.createElement("a"); 6047 btn.href = clickUrl; 6048 btn.target = "_blank"; 6049 btn.innerHTML = buttonText; 6050 btn.className = "ReadMore ArticleTeaser_readMore"; 6051 btn.setAttribute("data-pw-ev", "arena-more"); 6052 6053 //$textWrapper[0].appendChild(btn); 6054 $textWrapper.append(btn); 6055 } 6056 6057 if (imgPos === "left") { 6058 const $parent = $iframe.parent(); 6059 $parent.css({ 6060 display: "flex", 6061 "align-items": "flex-start", 6062 "gap": "16px" 6063 }); 6064 6065 // Responsive Mobile: auf kleinen Bildschirmen Block-Layout 6066 if (window.innerWidth <= 480) { 6067 $parent.css({ display: "block" }); 6068 } 6069 6070 $iframe.after($textWrapper); 6071 } else if (imgPos === "right") { 6072 const $parent = $iframe.parent(); 6073 $parent.css({ 6074 display: "flex", 6075 "align-items": "flex-start", 6076 "gap": "16px" 6077 }); 6078 $iframe.before($textWrapper); 6079 } else if (imgPos === "top") { 6080 $iframe.after($textWrapper); 6081 } else if (imgPos === "bottom") { 6082 $iframe.before($textWrapper); 6083 } 6084 }); 6085}); 6086 6087/** 6088 * resizeIframe 6089 */ 6090 6091const be_onGptSlotRenderEnded = function(event) { 6092 const $slot = $('#' + event.slot.getSlotElementId()); 6093 const $iframe = $slot.find('iframe'); 6094 if (event.isEmpty || $iframe.length === 0) return; 6095 6096 /** --- Check, wenn iFrame mit data-is-safeframe-Attribut, dann Parent-Element margin-bottom setzen (mit Retry) --- **/ 6097 function setSafeFrameMargin($slot, retries = 3, delay = 300) { 6098 const $safeFrame = $slot.find('iframe[data-is-safeframe]'); 6099 if ($safeFrame.length > 0) { 6100 $safeFrame.parent().css('margin-bottom', '1rem'); 6101 } else if (retries > 0) { 6102 setTimeout(function() { 6103 setSafeFrameMargin($slot, retries - 1, delay); 6104 }, delay); 6105 } 6106 } 6107 setSafeFrameMargin($slot); 6108 6109 /** --- NEU: FLUID CHECK ---// Prüfen, ob die Größe "fluid" ist. Falls ja, nichts am Iframe schrauben. */ 6110 if (event.size === 'fluid' || (Array.isArray(event.size) && event.size[0] === 0)) { return; } 6111 6112 const w = event.size[0], h = event.size[1], ratio = h / w; 6113 const isFloorAd = $slot.hasClass('Ad-FloorAd') || $slot.closest('.Ad-FloorAd').length > 0; 6114 6115 const adjustAdSize = function () { 6116 const containerWidth = $slot.parent().width() || 0; 6117 const viewportWidth = $(window).width() - 15; 6118 const adPosition = String($iframe.data('ad_position') || '').toLowerCase(); 6119 const isBtaStageSlot = ['bta5', 'bta6', 'bta7'].includes(adPosition); 6120 6121 // Nicht-FloorAds nur am Viewport begrenzen, da Parent-Container oft schmaler sind. 6122 const availableSpace = isFloorAd ? Math.min(containerWidth, viewportWidth) : viewportWidth; 6123 6124 if (!isBtaStageSlot) { 6125 const targetWidth = w > availableSpace ? availableSpace : w; 6126 const targetHeight = w > availableSpace ? (availableSpace * ratio) : h; 6127 6128 $iframe.css({ 6129 'width': targetWidth + 'px', 6130 'max-width': 'none', 6131 'height': targetHeight + 'px', 6132 'display': 'block' 6133 }); 6134 } 6135 6136 // Zentrierung für Bühne (nicht FloorAd) 6137 if (!isFloorAd) { 6138 $iframe.css({'margin-left': 'auto', 'margin-right': 'auto'}); 6139 } 6140 6141 function isValidPxValue(val) { 6142 return val && !["0", "NULL", ""].includes(val); 6143 } 6144 6145 const pxLeftValue = $iframe.data('pxleft'); 6146 if (isValidPxValue(pxLeftValue)) { 6147 $iframe.css('margin-left', pxLeftValue + 'px'); 6148 } 6149 6150 const pxRightValue = $iframe.data('pxright'); 6151 if (isValidPxValue(pxRightValue)) { 6152 $iframe.css('margin-right', pxRightValue + 'px'); 6153 } 6154 6155 }; 6156 6157 const injectStyles = function() { 6158 try { 6159 const doc = $iframe[0].contentDocument || $iframe[0].contentWindow.document; 6160 if (doc && !doc.getElementById('ad-res-style')) { 6161 const style = doc.createElement('style'); 6162 style.id = 'ad-res-style'; 6163 style.innerHTML = 'img, canvas { max-width: 100% !important; height: auto !important; display: block; margin: 0 auto; } body { margin: 0; padding: 0; }'; 6164 doc.head.appendChild(style); 6165 } 6166 } catch (e) {} 6167 }; 6168 6169 adjustAdSize(); 6170 injectStyles(); 6171 $iframe.on('load', injectStyles); 6172 $(window).off('resize.' + event.slot.getSlotElementId()).on('resize.' + event.slot.getSlotElementId(), adjustAdSize); 6173 6174 // Fallback: Auf manchen Seiten wird insertAdvTextDiv zu frueh getriggert. 6175 // Wenn der Billboard-Slot jetzt da ist, aber noch kein Ad_text hat, erneut triggern.
6176 if ($slot.is('#renderSlot_Billboard, #renderSlot_Mobil-Billboard') && $slot.find('.Ad_text').length === 0) { 6177 setTimeout(function() { 6178 $(document).trigger('insertAdvTextDiv'); 6179 }, 0); 6180 } 6181 6182 if ($slot.closest('.slick-track').length) { $('.SliderBannerArticleDetail_dots').show(); } 6183}; 6184 6185if (window.googletag && typeof window.googletag.pubads === 'function' && 6186 typeof window.googletag.pubads().addEventListener === 'function') { 6187 window.googletag.pubads().addEventListener('slotRenderEnded', be_onGptSlotRenderEnded); 6188} else if (window.googletag && Array.isArray(window.googletag.cmd)) { 6189 window.googletag.cmd.push(function() { 6190 if (window.googletag && typeof window.googletag.pubads === 'function' && 6191 typeof window.googletag.pubads().addEventListener === 'function') { 6192 window.googletag.pubads().addEventListener('slotRenderEnded', be_onGptSlotRenderEnded); 6193 } 6194 }); 6195} 6196 6197/** 6198 * adSliderControl 6199 */ 6200$(document).one("adSliderControl", function(event) { 6201 /** 6202 * Nur geschaltete Banner in Banner-Slider auf Artikelseite zeigen. 6203 * Wenn es nur einen geschalteten Banner gibt, dann wird Auto-Slide deaktiviert 6204 * und zum Slide mit dem Banner gesprungen. Sind beide Banner vorhanden, 6205 * wird der Auto-Slide des Sliders wieder aktiviert. 6206 * 6207 * Eine Umsetzung mit sowohl "unslick" als auch "slickRemove" funktionierte nicht, 6208 * da dann alle Werbemittel nicht mehr sichtbar waren. Auch vornherein den Slider nur 6209 * anzuwenden, wenn es mehr als einen Banner gibt, hatte nicht funktioniert, da das Banner-JS bereits 6210 * verarbeitet war. 6211 */ 6212 'use strict'; 6213 const bannerSlider = '.SliderBannerArticleDetail'; 6214 const bannerSliderDots = bannerSlider + '_dots'; 6215 const slideSelectors = ['slick-slide00', 'slick-slide01']; 6216 const slideState = []; 6217 6218 $(bannerSliderDots).css('display', 'none'); 6219 $(bannerSlider).slick('slickPause'); 6220 $(bannerSlider).slick('slickGoTo', 0); /* Slider refreshen, damit Slides aufrufbar sind */ 6221 6222 const waitForEl = function (slideSelectors, callback) { 6223 const startTimeInMs = Date.now(); 6224 6225 for (let i = 0; i < slideSelectors.length; i++) { 6226 const selectorObj = document.getElementById(slideSelectors[i]); 6227 if (selectorObj && selectorObj.children.length && selectorObj.children[0].tagName === 'DIV') { 6228 slideState[i] = 1; 6229 } else { 6230 slideState[i] = 0; 6231 } 6232 } 6233 6234 if (slideState[0] === 1 && slideState[1] === 0) { 6235 $(bannerSlider).slick('slickGoTo', 0); 6236 callback(); 6237 return; 6238 } else if (slideState[0] === 0 && slideState[1] === 1) { 6239 $(bannerSlider).slick('slickGoTo', 1); 6240 callback(); 6241 return; 6242 } else if (slideState[0] === 1 && slideState[1] === 1) { 6243 $(bannerSlider).slick('slickPlay'); 6244 $(bannerSliderDots + ' li').css('padding-left', '0'); 6245 $(bannerSliderDots).css('display', 'block'); 6246 callback(); 6247 return; 6248 } else { 6249 setTimeout(function () { 6250 if (Date.now() - startTimeInMs > 10000) { 6251 /*Callback spätestens nach 10 Sekunden abbrechen */ 6252 return; 6253 } 6254 waitForEl(slideSelectors, callback); 6255 }, 10); 6256 } 6257 }; 6258 6259 waitForEl(slideSelectors, function() {}); 6260 6261}); 6262 6263/** 6264 * halfpage 6265 */ 6266$(document).on("halfpage", function(event, be_containerClass){ 6267 6268 /* 6269 const $iframes = $("iframe.halfpage"); 6270 6271 $iframes.each(function(){ 6272 const slot = $(this).parent().parent(); 6273 slot.css("width","300px"); 6274 }); 6275 */ 6276 6277 function halfpageResize() { 6278 /* Class-Name für sitebarContainer und .page-footer entsprechend einsetzen */ 6279 const halfpageContainer = '.Ad-skyscraper-right'; 6280 6281 const stageWidth = $("." + be_containerClass).width(); 6282 let halfpageSpace = ($(this).width() - stageWidth) / 2; 6283 halfpageSpace = Math.floor(halfpageSpace) -15; 6284 6285 if ($(halfpageContainer + ' iframe.responsiveFrame').data("width") > halfpageSpace ) { 6286 $(halfpageContainer + ' iframe.responsiveFrame').width(halfpageSpace); 6287 } 6288 6289 const halfpageAd = $('.halfpage').parent().parent(); 6290 const halfpage = $('.halfpage'); 6291 const halfpage_width = halfpage.data('width'); 6292 6293 if (halfpage_width > halfpageSpace ) { 6294 halfpage.width(halfpageSpace); 6295 halfpageAd.css("width",halfpageSpace+"px"); 6296 halfpage.css("width",halfpageSpace+"px"); 6297 6298 $(document).ready(function(){ 6299 const halfpageDOM = halfpage.contents(); 6300 halfpageDOM.find("iframe").css("width", halfpageSpace+"px"); 6301 const currWinHeight = $(window).height(); 6302 halfpageDOM.find("iframe").css("max-height", currWinHeight+"px"); 6303 }); 6304 } 6305 } 6306 6307 const halfpageAd = $('.halfpage').parent().parent(); 6308 const halfpage = $('.halfpage'); 6309 6310 const halfpage_width = halfpage.data('width'); 6311 halfpageAd.css("width",halfpage_width+'px'); 6312 halfpageAd.css("max-width",halfpage_width+'px'); 6313 6314 const halfpage_fixed = halfpage.data('fixed'); 6315 if (halfpage_fixed != 'false') { 6316 halfpageAd.css("position","fixed"); 6317 } 6318 6319 /* Resize halfpage when the window is resized */ 6320 $( window ).resize( function() { 6321 halfpageResize(); 6322 /* Resize to fix halfpage on page load. */ 6323 }).resize(); 6324 6325}
6325); 6326 6327 6328/** 6329 * floorAd 6330 */ 6331$(document).on('floorAd', function(event) { 6332 //console.log('[DEBUG] floorAd Event ausgelöst:', event); 6333 6334 const floorAd = $('.floorAd').parent().parent(); 6335 const floorAdIframe = $('.floorAd'); 6336 const floorAdIframeContent = $('.floorAd').contents(); 6337 const scroll_pos = floorAdIframe.data('display-at-pixel'); 6338 const display_on_scroll = floorAdIframe.data('display-on-scroll'); 6339 let isHidden = false; 6340 6341 /* 6342 console.log('[DEBUG] floorAd Variablen:', { 6343 floorAd, 6344 floorAdIframe, 6345 floorAdIframeContent, 6346 scroll_pos, 6347 display_on_scroll, 6348 center_ad, 6349 }); 6350 */ 6351 6352 floorAd.css('z-index', floorAdIframe.data('zindex')); 6353 if (display_on_scroll === "1" || display_on_scroll === 1 || display_on_scroll === true) { 6354 //console.log('[DEBUG] floorAd wird nur beim Scrollen angezeigt.'); 6355 floorAd.css('display', 'none'); 6356 } 6357 6358 floorAd.css('position', 'fixed'); 6359 floorAd.css('bottom', '0'); 6360 //floorAd.css('min-height', '90px'); // Fallback-Mindesthöhe 6361 6362 // Dynamische Höhe anhand des Bildes im iFrame setzen 6363 function setFloorAdHeightFromImage() { 6364 try { 6365 var iframe = floorAdIframe.get(0); 6366 if (!iframe || !iframe.contentWindow || !iframe.contentDocument) return; 6367 var doc = iframe.contentDocument || iframe.contentWindow.document; 6368 var img = doc.querySelector('img'); 6369 if (img && img.complete) { 6370 var imgHeight = img.naturalHeight || img.height; 6371 if (imgHeight > 0) { 6372 floorAd.height(imgHeight); 6373 floorAdIframe.height(imgHeight); 6374 } 6375 } else if (img) { 6376 img.addEventListener('load', function() { 6377 var imgHeight = img.naturalHeight || img.height; 6378 if (imgHeight > 0) { 6379 floorAd.height(imgHeight); 6380 floorAdIframe.height(imgHeight); 6381 } 6382 }); 6383 } 6384 } catch (e) { 6385 // Cross-Origin: keine Aktion möglich 6386 } 6387 } 6388 6389 // Nach dem Laden des iFrames prüfen 6390 floorAdIframe.on('load', function() { 6391 setFloorAdHeightFromImage(); 6392 }); 6393 // Falls das iFrame schon geladen ist 6394 setFloorAdHeightFromImage(); 6395 6396 $(window).on('resize', function() { 6397 $('#renderSlot_Layer-Ad, #renderSlot_Layer-Ad > div, #renderSlot_Layer-Ad iframe').css({ 6398 width: '100%', 6399 minWidth: 0, 6400 maxWidth: '100vw', 6401 boxSizing: 'border-box' 6402 }); 6403 }).trigger('resize'); 6404 6405 if (display_on_scroll == 1 || display_on_scroll === true) { 6406 window.onscroll = function() { 6407 if (window && !isHidden) { 6408 var currentScroll = window.pageYOffset !== undefined ? window.pageYOffset : document.documentElement.scrollTop; 6409 if (currentScroll > scroll_pos) { 6410 $(floorAd).fadeIn("slow"); 6411 } else if (currentScroll < scroll_pos) { 6412 $(floorAd).fadeOut("slow"); 6413 } 6414 } 6415 }; 6416 } 6417 6418 floorAdIframeContent.find('.CloseAd').click(function() { 6419 $(floorAd).fadeOut('slow'); 6420 isHidden = true; 6421 }); 6422 6423}); 6424 6425 6426/** 6427 * layerAd 6428 */ 6429$(document).on('layerAd', function(event) { 6430 const layerAd = $('.layerAd').parent().parent(); 6431 const layerAdWrapper = $('.layerAd').parent(); 6432 const layerAdIframe = $('.layerAd'); 6433 const ad_close_time = layerAdIframe.data('ad-close-time'); 6434 6435 const bg_color = layerAdIframe.data('bgcolor'); 6436 const bg_opacity = layerAdIframe.data('bgopacity'); 6437 6438 const align_banner = layerAdIframe.data('align'); 6439 const vertical_px_offset = layerAdIframe.data('vertical-px-offset'); 6440 const vertical_pos = layerAdIframe.data('vertical-pos'); 6441 const horizontal_px_offset = layerAdIframe.data('horizontal-px-offset'); 6442 const horizontal_pos = layerAdIframe.data('horizontal-pos'); 6443 6444 function convertHex(hex,opacity){ 6445 hex = hex.replace('#',''); 6446 r = parseInt(hex.substring(0,2), 16); 6447 g = parseInt(hex.substring(2,4), 16); 6448 b = parseInt(hex.substring(4,6), 16); 6449 6450 return 'rgba(' + r + ',' + g + ',' + b + ',' + opacity / 100 + ')'; 6451 } 6452 6453 const bgColor_rgb = convertHex(bg_color, bg_opacity); 6454 6455 layerAd.css('width', '100%'); 6456 layerAd.css('height', '100%'); 6457 layerAd.css('background', bgColor_rgb); 6458 layerAd.css('position', 'fixed'); 6459 layerAd.css('top', '0'); 6460 layerAd.css('left', '0'); 6461 layerAd.css('z-index', '12000'); 6462 6463 layerAd.css('display', 'flex'); 6464 layerAd.css('display', '-webkit-box'); 6465 layerAd.css('display', '-webkit-flex'); 6466 layerAd.css('display', '-ms-flexbox'); 6467 6468 layerAd.css('-webkit-box-align', 'center'); 6469 layerAd.css('-webkit-align-items', 'center'); 6470 layerAd.css('-ms-flex-align', 'center'); 6471 layerAd.css('align-items', 'center'); 6472 6473 layerAd.css('-webkit-box-pack', 'center');
6474 layerAd.css('-webkit-justify-content', 'center'); 6475 layerAd.css('-ms-flex-pack', 'center'); 6476 layerAd.css('justify-content', 'center'); 6477 6478 6479 layerAd.css('z-index', '12000'); 6480 6481 layerAdWrapper.css('position', 'absolute'); 6482 layerAdWrapper.prepend("<div class='layer_close' style='z-index: 13000; position:absolute; color: #ffffff; top:0; right:0;'><i title =\"schließen\" class=\"fa fa-close fa-2x\"></i></div>"); 6483 6484 layerAdWrapper.css('margin', 'auto'); 6485 6486 if (align_banner == 1) { 6487 if (vertical_pos == 'bottom') { 6488 layerAdWrapper.css('margin-bottom', vertical_px_offset+'px'); 6489 } else { 6490 layerAdWrapper.css('margin-top', vertical_px_offset+'px'); 6491 } 6492 if (horizontal_pos == 'left') { 6493 layerAdWrapper.css('margin-left', horizontal_px_offset+'px'); 6494 } else { 6495 layerAdWrapper.css('margin-right', horizontal_px_offset+'px'); 6496 } 6497 } 6498 6499 function showLayerAd() { 6500 layerAd.show(); 6501 } 6502 6503 function closeLayerAd() { 6504 layerAd.hide(); 6505 } 6506 6507 if (ad_close_time > 0){ 6508 setTimeout(function(){closeLayerAd();}, ad_close_time*1000); 6509 } 6510 6511 $( ".layer_close" ).click(function() { 6512 layerAd.hide(); 6513 }); 6514}); 6515 6516/** 6517 * exitintent 6518 */ 6519$(document).one("exitintent", function(event){ 6520 $( "html" ).one( "mouseleave", function() { 6521 $("#LayerModal").addClass("show"); 6522 }); 6523}); 6524 6525/** 6526 * changeBackgroundColor 6527 */ 6528$(document).on('changeBackgroundColor',function(event){ 6529 const iframe = $('.fireplace'), 6530 bg_color = iframe.data('bgcolor'); 6531 $(".Body").css('background-color', bg_color); 6532}); 6533 6534/** 6535 * isBackgroundClick 6536 * On Background click go to clickurl 6537 */ 6538$(document).on('isBackgroundClick',function(event){ 6539 6540 $("#usercentrics-root").click(function(event ) { 6541 event.stopPropagation(); 6542 }); 6543 6544 $(".PageFrame").click(function(event ) { 6545 event.stopPropagation(); 6546 }); 6547 6548 $("#uc-center-container").click(function(event ) { 6549 event.stopPropagation(); 6550 }); 6551 6552 $(".Body").click(function() { 6553 const iframe = $('.bgclickplace'); 6554 const clickurl = iframe.data('clickurl'); 6555 window.open(clickurl, '_blank'); 6556 }); 6557}); 6558 6559/** 6560 * counterAd 6561 */ 6562$(document).one('counterAd', function(event) { 6563 const counterAd = $('.counterAd').parent().parent(); 6564 const counterAdIframe = $('.counterAd'); 6565 6566 const pl_id = counterAdIframe.data('contentunit'); 6567 const clickurl = counterAdIframe.data('clickurl'); 6568 const enddatum = counterAdIframe.data('enddatum'); 6569 const counterimage = counterAdIframe.data('counterimage'); 6570 const layout = counterAdIframe.data('layout'); 6571 6572 let countertext = ''; 6573 6574 countertext = countertext + '<div id=\"'+pl_id+'\" class="noanzeige" width=\"300\" height=\"300\">\n'; 6575 countertext = countertext + ' <div>\n' ; 6576 countertext = countertext + ' <a target=\"_blank\" href=\"'+clickurl+'\">\n'; 6577 if(typeof layout !== 'undefined' && layout === 'image') { 6578 countertext = countertext + ' <img src=\"' + counterimage + '\" title=\"\" alt=\"\" border=\"0\" width=\"300\" height=\"150\"/>\n'; 6579 } 6580 countertext = countertext + ' </a>\n'; 6581 countertext = countertext + ' <div class=\"banner_counter\" border=\"0\" width=\"300\" height=\"150\" style=\"max-width: 300px !important;\"> \n'; 6582 countertext = countertext + ' <span id=\"clockline\"></span>\n'; 6583 countertext = countertext + ' <div id=\"banner_counter\"></div>\n'; 6584 countertext = countertext + ' <div id=\"name_time_block\">\n'; 6585 countertext = countertext + ' <span class=\"name_time\">Tage</span>\n'; 6586 countertext = countertext + ' <span class=\"name_time\">Stunden</span>\n'; 6587 countertext = countertext + ' <span class=\"name_time\">Minuten</span>\n'; 6588 countertext = countertext + ' </div>\n'; 6589 countertext = countertext + ' </div> \n'; 6590 countertext = countertext + ' \n'; 6591 countertext = countertext + ' </div>\n'; 6592 countertext = countertext + '\n'; 6593 countertext = countertext + '</div>\n'; 6594 counterAd.append(countertext); 6595 if(typeof layout !== 'undefined' && layout === 'image'){ 6596 counterAdIframe.css("display","none"); 6597 } 6598 counterAd.css('margin-top', '10px'); 6599 $('.noanzeige').not(':first').remove(); 6600 if(typeof jQuery == "function"){ 6601 $(function() { 6602 $(document).trigger( "counter", enddatum); 6603 }); 6604 } 6605 6606 $( counterAd ).closest('div').next().find('.line').removeClass("line"); 6607}); 6608 6609/** 6610 * counter 6611 */ 6612$(document).on("counter", function(event, endtime){ 6613 6614 /* Datum mit Punkt */ 6615 let iso_end_date; 6616 if (endtime.match(/\./) ) { 6617 let iso_end_dateArr = endtime.split("."); 6618 6619 /* Umwandlung in Iso-Format */ 6620 if (iso_end_dateArr[2] < 100) iso_end_dateArr[2] = "20" + iso_end_dateArr[2]; 6621 iso_end_date = iso_end_dateArr[2] + "-" + iso_end_dateArr[0] + "-" +iso_end_dateArr[1]; 6622 6623 /* Datum im Iso-Format, z.B. 2020-11-09 */ 6624 } else { 6625 iso_end_date = endtime; 6626 } 6627 6628 const end = new Date(iso_end_date); 6629 6630 const _second = 1000; 6631 const _minute = _second * 60; 6632 const _hour = _minute * 60; 6633 const _day = _hour * 24; 6634 let timer; 6635 6636 function showRemaining() { 6637 const now = new Date(); 6638 now.setHours(now.getHours() +1); 6639 6640 const distance = end - now; 6641 if (distance < 0) { 6642 6643 clearInterval(timer); 6644 document.getElementById('banner_counter').innerHTML = '<span class="time">0</span> '; 6645 document.getElementById('banner_counter').innerHTML += '<span class="time">0</span> '; 6646 document.getElementById('banner_counter').innerHTML += '<span class="time">0</span> '; 6647 return; 6648 } 6649 const days = Math.floor(distance / _day); 6650 const hours = Math.floor((distance % _day) / _hour); 6651 const minutes = Math.floor((distance % _hour) / _minute); 6652 6653 document.getElementById('banner_counter').innerHTML = '<span class="time">' + days + '</span> '; 6654 document.getElementById('banner_counter').innerHTML += '<span class="time">' + hours + '</span> '; 6655 document.getElementById('banner_counter').innerHTML += '<span class="time">' + minutes + '</span> '; 6656 6657 } 6658 timer = setInterval(showRemaining, 1000); 6659 6660}); 6661 6662/** 6663 * centerIframe 6664 */ 6665$(document).on('centerIframe', function(event){ 6666 const iframe = $('.centeredFrame'), 6667 container = iframe.parent(); 6668 6669 container.css('display', 'flex'); 6670 container.css('flex-flow','column'); 6671 iframe.css('align-self','center'); 6672}); 6673 6674/** 6675 * blockadvertisement 6676 */ 6677$(document).on("blockadvertisement", function(event){ 6678 6679 const iframe = $('.blockadvertisement'); 6680 let container = iframe.parent(); 6681 container.css("display","none"); 6682}); 6683 6684/** 6685 * wallpapercolor 6686 * Einfärben des body für Wallpaper 6687 */ 6688$(document).on("wallpapercolor", function(event){ 6689 6690 const iframe = $('.wallpaper_banner'); 6691 const wallpapercolor = iframe.data("wallpapercolor"); 6692 $('body').css("background-color",wallpapercolor); 6693 6694}); 6695 6696/** 6697 * advertOnImage 6698 */ 6699$(document).one("advertOnImage", function(event){ 6700 const slot = $('[id^="renderSlot_Rectangle-Online-Specials"]'); 6701 if (slot.hasClass("Ad-mediumRectangleStageTeaserAdvert")) { 6702 if (slot.children('div').length > 0) { 6703 slot.parent().css('padding', '5px'); 6704 slot.parent().css('background-color', '#fff'); 6705 } 6706 6707 } 6708 6709}); 6710 6711/** 6712 * be_sitebarResize 6713 */ 6714function be_sitebarResize(wideLayout, sitebarBid) { 6715 const browser_scrollbar_width = 0; 6716 let offsetLeft = 460; 6717 let outerWidth = 980; 6718 const sitebarContainer = '.Ad-skyscraper-right'; 6719 if (($('.SiteFooter').length) && (!wideLayout)) { 6720 offsetLeft = $('.SiteFooter').offset().left + browser_scrollbar_width; 6721 outerWidth = $('.SiteFooter').outerWidth(); 6722 } else if (($('.PageGallery').length) && (!wideLayout)) { 6723 offsetLeft = $('.PageGallery').offset().left + browser_scrollbar_width; 6724 outerWidth = $('.PageGallery').outerWidth(); 6725 } 6726 if (wideLayout === true) { 6727 let siteHeader = document.querySelector('.SiteHeader') || document.querySelector('.SiteHeaderSticky_firstLine-inner'); 6728 if (siteHeader) { 6729 let rect = siteHeader.getBoundingClientRect(); 6730 offsetLeft = rect.left + browser_scrollbar_width; 6731 6732 let siteHeaderStyles = window.getComputedStyle(siteHeader); 6733 outerWidth = parseFloat(siteHeaderStyles.getPropertyValue('width')); 6734 } 6735 } 6736 6737 let rightOffset = $(this).width() - (offsetLeft + outerWidth); 6738 rightOffset = Math.floor(rightOffset); 6739 6740 if ($(sitebarContainer + ' iframe.responsiveFrame').data("width") > rightOffset ) { 6741 $(sitebarContainer + ' iframe.responsiveFrame').width(rightOffset); 6742 } 6743 6744 const iframeEl = document.querySelector('iframe.sitebar'); 6745 let iFrameElDocument = iframeEl.contentDocument || iframeEl.contentWindow.document; 6746 let imgSitebar = iFrameElDocument.getElementById("sitebar"+sitebarBid); 6747 let imgSky = iFrameElDocument.getElementById("sky"+sitebarBid); 6748 const offsetLowLmt = 135; 6749 const offsetUpLmt = 215; 6750 6751 if (imgSky && imgSitebar) { 6752 if ((offsetLeft >= offsetLowLmt) && (offsetLeft < offsetUpLmt)) { 6753 imgSitebar.style.display = "none"; 6754 imgSky.style.display = "inline"; 6755 } else if (offsetLeft >= offsetUpLmt) { 6756 imgSitebar.style.display = "inline"; 6757 imgSky.style.display = "none"; 6758 } 6759 else if (offsetLeft < offsetLowLmt) { 6760 imgSitebar.style.display = "none"; 6761 imgSky.style.display = "none"; 6762 } 6763 } 6764 6765 6766 const sitebarAd = $('.sitebar').parent().parent(); 6767 const sitebar = $('.sitebar'); 6768 const sitebar_width = sitebar.data('width'); 6769 6770 6771 if (sitebar_width > rightOffset ) { 6772 sitebar.width(rightOffset); 6773 sitebarAd.css("width",rightOffset+"px"); 6774 sitebar.css("width",rightOffset+"px"); 6775 6776 $(document).ready(function(){ 6777 const sitebarDOM = sitebar.contents(); 6778 sitebarDOM.find("iframe").css("width", rightOffset+"px"); 6779 const currWinHeight = $(window).height(); 6780 sitebarDOM.find("iframe").css("max-height", currWinHeight+"px"); 6781 }); 6782 } 6783} 6784 6785/** 6786 * sitebar 6787 */ 6788$(document).on('sitebar',function(event, wideLayout) { 6789 const sitebarAd = $('.sitebar').parent().parent(); 6790 const sitebar = $('.sitebar'); 6791 const sitebarBid = sitebar[0].getAttribute("data-bid"); 6792 const sbAdMarginTop = sitebar[0].getAttribute("data-margintop"); 6793 if (sbAdMarginTop !== "0" && sbAdMarginTop !== "NULL") { 6794 sitebarAd.css("margin-top",sbAdMarginTop+'px'); 6795 } 6796 6797 if ( sitebar.data('bgcolor') ) { 6798 const bg_color = sitebar.data('bgcolor'); 6799 if (bg_color.startsWith("#")) { 6800 document.getElementsByTagName('body')[0].style.backgroundColor = bg_color; 6801 } 6802 } 6803 6804 const sitebar_width = sitebar.data('width'); 6805 sitebarAd.css("width",sitebar_width+'px'); 6806 sitebarAd.css("max-width",sitebar_width+'px'); 6807 sitebar.css("max-height",'100vh'); 6808 6809 const sitebar_fixed = sitebar.data('fixed'); 6810 if (sitebar_fixed != 'false') { 6811 sitebarAd.css("position","fixed"); 6812 } 6813 6814 /* Resize sitebar when the window is resized */ 6815 $( window ).resize( function() { 6816 be_sitebarResize(wideLayout, sitebarBid); 6817 /* Resize to fix sitebar on page load. */ 6818 }).resize(); 6819 6820}
6820); 6821 6822/** 6823 * be_sitebarLeftResize 6824 */ 6825function be_sitebarLeftResize(wideLayout, sitebarBid) { 6826 const browser_scrollbar_width = 15; 6827 let offsetLeft = 460; 6828 let outerWidth = 980; 6829 const sitebarLeftContainer = '.Ad-skyscraper-left'; 6830 if (($('.SiteFooter').length) && (!wideLayout)) { 6831 offsetLeft = $('.SiteFooter').offset().left + browser_scrollbar_width; 6832 outerWidth = $('.SiteFooter').outerWidth(); 6833 } else if (($('.PageGallery').length) && (!wideLayout)) { 6834 offsetLeft = $('.PageGallery').offset().left + browser_scrollbar_width; 6835 outerWidth = $('.PageGallery').outerWidth(); 6836 } 6837 if (wideLayout === true) { 6838 let siteHeader = document.querySelector('.SiteHeader') || document.querySelector('.SiteHeaderSticky_firstLine-inner'); 6839 if (siteHeader) { 6840 let rect = siteHeader.getBoundingClientRect(); 6841 offsetLeft = rect.left + browser_scrollbar_width; 6842 6843 let siteHeaderStyles = window.getComputedStyle(siteHeader); 6844 outerWidth = parseFloat(siteHeaderStyles.getPropertyValue('width')); 6845 } 6846 } 6847 6848 let leftOffset = offsetLeft; 6849 leftOffset = Math.round(leftOffset); 6850 6851 if ($(sitebarLeftContainer + ' iframe.responsiveFrame').data("width") > leftOffset ) { 6852 $(sitebarLeftContainer + ' iframe.responsiveFrame').width(leftOffset); 6853 } 6854 6855 const iframeElLeft = document.querySelector('iframe.sitebarLeft'); 6856 let iFrameElLeftDocument = iframeElLeft.contentDocument || iframeElLeft.contentWindow.document; 6857 let imgSitebar = iFrameElLeftDocument.getElementById("sitebar"+sitebarBid); 6858 let imgSky = iFrameElLeftDocument.getElementById("sky"+sitebarBid); 6859 const offsetLowLmt = 140; 6860 const offsetUpLmt = 320; 6861 6862 if (imgSky && imgSitebar) { 6863 if ((offsetLeft >= offsetLowLmt) && (offsetLeft < offsetUpLmt)) { 6864 imgSitebar.style.display = "none"; 6865 imgSky.style.display = "inline"; 6866 } else if (offsetLeft >= offsetUpLmt) { 6867 imgSitebar.style.display = "inline"; 6868 imgSky.style.display = "none"; 6869 } 6870 else if (offsetLeft < offsetLowLmt) { 6871 imgSitebar.style.display = "none"; 6872 imgSky.style.display = "none"; 6873 } 6874 } 6875 6876 6877 const sitebarAd = $('.sitebarLeft').parent().parent(); 6878 const sitebar = $('.sitebarLeft'); 6879 const sitebar_width = sitebar.data('width'); 6880 const hideWidth = (sitebar.data('hidewidth') !== undefined ? sitebar.data('hidewidth') : 0) + 15; 6881 6882 if (leftOffset <= hideWidth) { 6883 sitebarAd.css('display', 'none'); 6884 return; 6885 } else { 6886 sitebarAd.css('display', 'block'); 6887 } 6888 6889 6890 let sidebarLeftMargin = Math.round(leftOffset); 6891 sitebarAd.css("margin-left","0px"); 6892 let currSitebar_width = sitebarAd[0].offsetWidth; 6893 6894 if (sitebar_width >= leftOffset ) { 6895 leftOffset = leftOffset-browser_scrollbar_width; 6896 6897 sitebar.width(leftOffset); 6898 sitebarAd.css("width",leftOffset+"px"); 6899 sitebar.css("width",leftOffset+"px"); 6900 6901 $(document).ready(function(){ 6902 const sitebarDOM = sitebar.contents(); 6903 sitebarDOM.find("iframe").css("width", leftOffset+"px"); 6904 const currWinHeight = $(window).height(); 6905 sitebarDOM.find("iframe").css("max-height", currWinHeight+"px"); 6906 }); 6907 } else if (sitebar_width < leftOffset) { 6908 let sbMarginLeft = leftOffset - browser_scrollbar_width - sitebar_width; 6909 6910 sitebarAd.css("width",sitebar_width+"px"); 6911 sitebar.css("width",sitebar_width+"px"); 6912 sitebarAd.css("margin-left",sbMarginLeft+"px"); 6913 } 6914} 6915 6916/** 6917 * sitebarLeft 6918 */ 6919$(document).on('sitebarLeft',function(event, wideLayout) { 6920 const sitebarLeftAd = $('.sitebarLeft').parent().parent(); 6921 const sitebarLeft = $('.sitebarLeft'); 6922 const sitebarLeftBid = sitebarLeft[0].getAttribute("data-bid"); 6923 const leftSitebarSlot = document.getElementById("renderSlot_Skyscraper-links"); 6924 leftSitebarSlot.classList.add("leftSitebarSlot"); 6925 6926 const sitebarLeft_width = sitebarLeft.data('width'); 6927 sitebarLeftAd.css("width",sitebarLeft_width+'px'); 6928 sitebarLeftAd.css("max-width",sitebarLeft_width+'px'); 6929 6930 const sitebarLeft_fixed = sitebarLeft.data('fixed'); 6931 if (sitebarLeft_fixed != 'false') { 6932 sitebarLeftAd.css("position","fixed"); 6933 } 6934 6935 const sbAdLeftMarginTop = sitebarLeft[0].getAttribute("data-margintop"); 6936 if (sbAdLeftMarginTop !== "0" && sbAdLeftMarginTop !== "NULL") { 6937 sitebarLeftAd.css("margin-top",sbAdLeftMarginTop+'px'); 6938 } 6939 6940 /* Resize sitebarLeft when the window is resized */ 6941 $( window ).resize( function() { 6942 be_sitebarLeftResize(wideLayout, sitebarLeftBid); 6943 /* Resize to fix sitebar on page load. */ 6944 }).resize(); 6945 6946 window.addEventListener('load', function() { 6947 be_sitebarLeftResize(wideLayout, sitebarLeftBid); 6948 }); 6949 6950 window.onload = function() { 6951 be_sitebarLeftResize(wideLayout, sitebarLeftBid); 6952 }; 6953 6954 6955}); 6956 6957/** 6958 * teadsResize 6959 * teads Videos 6960 */ 6961$(document).on('teadsResize',function(event){ 6962 const iframe = $('.video_ad'), 6963 aspect_ratio = 1.7, 6964 wrapper = iframe.parent(); 6965 6966 iframe.height(iframe.width()/aspect_ratio); 6967 6968 wrapper.css('display', 'flex'); 6969 wrapper.css('flex-flow','column'); 6970 iframe.css('align-self','center'); 6971}); 6972 6973/** 6974 * pushdown 6975 */ 6976$(document).on("pushdown", function(event, elementclass){ 6977 6978 const pushdown_iframe = $("." + elementclass); 6979 const pushdown_container = pushdown_iframe.parent(); 6980 6981 const ad_height = pushdown_iframe.data("height"); 6982 const ad_width = pushdown_iframe.data("width"); 6983 const ad_margin_bottom = parseInt(pushdown_container.css("height")) - ad_height; 6984 const pushdownheight = pushdown_iframe.data("pushdownheight") + ad_margin_bottom; 6985 const pushdowntime = pushdown_iframe.data("pushdowntime"); /* Dauer der Animation */ 6986 const closingtime = pushdown_iframe.data("closingtime") * 1000; /* Initiales Einfahren */ 6987 const pushdown_center_ad = pushdown_iframe.data("center_ad"); 6988 const pushdown_func = pushdown_iframe.data("pushdown-func") ? 1 : 0; 6989 const no_initialpushdown = pushdown_iframe.data("no_initialpushdown") ? 1 : 0; 6990 6991 /* Werbemittel zentrieren */ 6992 if(pushdown_center_ad == 1){ 6993 pushdown_container.css("text-align","center"); 6994 } 6995 6996 if(pushdown_func == 0){ 6997 6998 /* prevent too large iFrame-height on smaller stage */ 6999 let pushdown_iframeWidth = pushdown_iframe[0].clientWidth; 7000 let pushdownRatio = ad_height / ad_width;
7001 let pushdownHeight = Math.ceil(pushdown_iframeWidth * pushdownRatio); 7002 pushdown_iframe.css("height",pushdownHeight + "px"); 7003 7004 return; 7005 } 7006 7007 /* Nutzer-Handling */ 7008 pushdown_iframe.on("mouseover", function(event){ 7009 clearTimeout(waiting_for_closing); 7010 $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, '1', pushdownheight]); 7011 7012 pushdown_iframe.one("mouseout", function(event){ 7013 $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, '1', ad_height]); 7014 }); 7015 }); 7016 7017 /* Initiales Ausfahren */ 7018 if(no_initialpushdown != 1) { 7019 $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, pushdowntime, pushdownheight]); 7020 } 7021 7022 /* Einfahren nach initialem Ausfahren */ 7023 let waiting_for_closing = window.setTimeout(function(){ 7024 $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, pushdowntime, ad_height]); 7025 }, closingtime); 7026 7027}); 7028 7029/** 7030 * pushdown-animation 7031 */ 7032$(document).on("pushdown-animation", function(event, pushdown_container, pushdown_iframe, movingtime, newheight){ 7033 7034 pushdown_container.css({ 7035 height : newheight, 7036 WebkitTransition : 'height ' + movingtime + 's ease-in-out', 7037 MozTransition : 'height ' + movingtime + 's ease-in-out', 7038 MsTransition : 'height ' + movingtime + 's ease-in-out', 7039 OTransition : 'height ' + movingtime + 's ease-in-out', 7040 transition : 'height ' + movingtime + 's ease-in-out' 7041 }); 7042 pushdown_iframe.css({ 7043 height : newheight, 7044 WebkitTransition : 'height ' + movingtime + 's ease-in-out', 7045 MozTransition : 'height ' + movingtime + 's ease-in-out', 7046 MsTransition : 'height ' + movingtime + 's ease-in-out', 7047 OTransition : 'height ' + movingtime + 's ease-in-out', 7048 transition : 'height ' + movingtime + 's ease-in-out' 7049 }); 7050}); 7051 7052/** 7053 * parallax_outstream 7054 */ 7055$(document).on("parallax_outstream", function(event){ 7056 const iframe = $('.parallax_outstream'); 7057 const container = iframe.parent(); 7058 container.attr("id","parallax_outstream"); 7059 iframe.css("height","0px"); 7060 iframe.css("width","0px"); 7061}); 7062 7063/** 7064 * dynamic_sitebar 7065 */ 7066$(document).on("dynamic_sitebar", function(event){ 7067 const iframe = $('.dynamic_sitebar'); 7068 const container = iframe.parent(); 7069 const dynamic_space = ($('.PageFrame').outerWidth(true) - $('.PageFrame').outerWidth()) / 2; 7070 container.css("width", dynamic_space +"px"); 7071 container.css("position","fixed"); 7072}); 7073 7074/** 7075 * insertAdvTextDiv 7076 * 7077 * "Anzeige"-Position und Border an Werbemittelgroesse positionieren/anpassen 7078 */ 7079$(document).on("insertAdvTextDiv", function(event) { 7080 const $iframes = $('[id^="renderSlot_"] iframe'); 7081 let el = $('<div class="Ad_text"></div>'); 7082 7083 $iframes.each(function () { 7084 if ($(this).data("width") == '1') { 7085 $(this).parent('div').css('height', '0'); 7086 return; 7087 } 7088 7089 const slot = $(this).parent().parent(); 7090 if ($(this).parent().parent().length) { 7091 if (slot.attr('id').match(/renderSlot_(Super*|Sky*|Rectangle-Gal|Mobil-Rectangle-Gal)/)) { 7092 return; 7093 } 7094 } else { 7095 return; 7096 } 7097 if (slot.parent().length && slot.parent().hasClass() ){ 7098 if(slot.parent().attr('class').match(/slick-track/)){ 7099 /* SliderBannerArticleDetail_dots nur einblenden, wenn auch was geschaltet ist */ 7100 $('.SliderBannerArticleDetail_dots').css('display', 'block'); 7101 } 7102 } 7103 7104 let ad_text_div = $(this).parent().find('.Ad_text'); 7105 let ad_text_parallax_div = $(this).parent().parent().find('.Ad_text'); 7106 7107 ad_text_div.css('margin', ''); 7108 if ($(this).hasClass('parallax')) { 7109 7110 if(!ad_text_parallax_div.length > 0){ 7111 $(this).parent().parent('div').prepend(el); 7112 ad_text_parallax_div = $(this).parent().parent().find('.Ad_text'); 7113 } 7114 ad_text_parallax_div.css("margin", "0 auto"); 7115 ad_text_parallax_div.css("width", '100%'); 7116 if ($(this).data("ad_text_bgc")) { 7117 ad_text_parallax_div.css("background-color", $(this).data("ad_text_bgc")); 7118 } 7119 if ($(this).data("ad_text_margintop")) { 7120 ad_text_parallax_div.css("margin-top", $(this).data("ad_text_margintop")); 7121 } 7122 if ($(this).data("ad_text_maxheight")) { 7123 ad_text_parallax_div.css("max-height", $(this).data("ad_text_maxheight")); 7124 } 7125 if ($(this).data("ad_text_noborder")) { 7126 ad_text_parallax_div.addClass('html5BannerBefore'); 7127 } 7128 ad_text_parallax_div.css("z-index", '10'); 7129 } else { 7130 if (!ad_text_div.length > 0) { 7131 $(this).parent('div').prepend(el); 7132 ad_text_div = $(this).parent().find('.Ad_text'); 7133 } 7134 if (slot.attr('id').match(/renderSlot_(Rectangle-Aufmacher)/)) { 7135 ad_text_div.css("width", '100%'); 7136 } else { 7137 const dataWidthRaw = $(this).data('width'); 7138 const dataWidth = (dataWidthRaw !== undefined && dataWidthRaw !== null) ? String(dataWidthRaw).trim() : ''; 7139 const widthAttr = parseInt($(this).attr('width'), 10) || 0; 7140 const cssWidth = parseInt($(this).css('width'), 10) || 0; 7141 const effectiveWidth = (dataWidth && dataWidth !== 'NULL' && dataWidth !== '0') ? dataWidth : (widthAttr || cssWidth || 0); 7142 7143 ad_text_div.css('width', /^\d+$/.test(String(effectiveWidth)) ? (effectiveWidth + 'px') : effectiveWidth); 7144 ad_text_div.css("margin", "0 auto"); 7145 } 7146 7147 } 7148 7149 if (/[^-]?width\s?:\s?100%/.test($(this).attr('style'))) { 7150 ad_text_div.css("margin", "0 auto"); 7151 } 7152 el = el.clone(); 7153 }); 7154}); 7155 7156/** 7157 * fadeoutadvertisement 7158 * Hierüber kann eine Platzierung animiert ausgeblendet werden 7159 */ 7160$(document).on("fadeoutadvertisement", function(event){ 7161 7162 const iframe = $('.fadeoutadvertisement'); 7163 let container = iframe.parent(); 7164 container.animate({ 7165 height: "0px" 7166 }, 2000, function() { 7167 container.css("display","none"); 7168 }); 7169 7170}); 7171 7172/**
7173 * be_reduceBackgroundOpacity 7174 * @param element 7175 * @param opacity 7176 */ 7177function be_reduceBackgroundOpacity(element, opacity) { 7178 let backgroundColor = element.style.backgroundColor; 7179 if (backgroundColor.substring(0, 4) === "rgba") { 7180 /* if rgba format is already used, just update the alpha value */ 7181 backgroundColor = backgroundColor.replace(/[^,]+(?=\))/, opacity); 7182 } else { 7183 /* convert hexadecimal or RGB format to rgba format and add alpha value */ 7184 let r = 0, g = 0, b = 0; 7185 if (backgroundColor.substring(0, 1) === "#") { 7186 /* convert hexadecimal to RGB */ 7187 const hex = backgroundColor.substring(1); 7188 r = parseInt(hex.substring(0, 2), 16); 7189 g = parseInt(hex.substring(2, 4), 16); 7190 b = parseInt(hex.substring(4, 6), 16); 7191 } else if (backgroundColor.substring(0, 3) === "rgb") { 7192 /* extract RGB values from comma-separated string */ 7193 const values = backgroundColor.match(/\d+/g); 7194 r = parseInt(values[0]); 7195 g = parseInt(values[1]); 7196 b = parseInt(values[2]); 7197 } 7198 /* convert RGB to rgba */ 7199 backgroundColor = "rgba(" + r + ", " + g + ", " + b + ", " + opacity + ")"; 7200 } 7201 element.style.backgroundColor = backgroundColor; 7202} 7203 7204/** 7205 * be_changeBGColor 7206 * @param element 7207 * @param color1 7208 * @param color2 7209 * @param mixVal 7210 */ 7211function be_changeBGColor(element, color1, color2, mixVal) { 7212 const hexToRgb = function (hex) { 7213 const r = parseInt(hex.slice(1, 3), 16); 7214 const g = parseInt(hex.slice(3, 5), 16); 7215 const b = parseInt(hex.slice(5, 7), 16); 7216 7217 return [r, g, b]; 7218 }; 7219 7220 const rgbToHex = function (rgb) { 7221 const componentToHex = function (component) { 7222 const hex = component.toString(); 7223 return hex.length == 1 ? "0" + hex : hex; 7224 }; 7225 7226 const r = componentToHex(rgb[0]); 7227 const g = componentToHex(rgb[1]); 7228 const b = componentToHex(rgb[2]); 7229 7230 return "#" + r + g + b; 7231 }; 7232 7233 const color1Rgb = hexToRgb(color1); 7234 const color2Rgb = hexToRgb(color2); 7235 7236 const r = Math.round((1 - mixVal) * color1Rgb[0] + mixVal * color2Rgb[0]); 7237 const g = Math.round((1 - mixVal) * color1Rgb[1] + mixVal * color2Rgb[1]); 7238 const b = Math.round((1 - mixVal) * color1Rgb[2] + mixVal * color2Rgb[2]); 7239 7240 element.style.backgroundColor = rgbToHex([r, g, b]); 7241} 7242 7243/** 7244 * be_rgbToHex 7245 * @param rgb 7246 * @returns {string} 7247 */ 7248function be_rgbToHex(rgb) { 7249 /* Liefert nur die Ziffern 0-9 und a-f */ 7250 function hex(x) { 7251 return ("0" + parseInt(x).toString(16)).slice(-2); 7252 } 7253 7254 /* Konvertiere den RGB-String in eine Array */ 7255 const rgbArray = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); 7256 /* Wandle die RGB-Werte in Hexadezimalwerte um */ 7257 return "#" + hex(rgbArray[1]) + hex(rgbArray[2]) + hex(rgbArray[3]); 7258} 7259 7260/** 7261 * welcomeAdVideo 7262 * WelcomeAd mit Video-URL, wird beim Scrollen ausgeblendet, hat Close-Button 7263 */ 7264$(document).on('welcomeAdVideo', function(event) { 7265 7266 let welcomeAdIframe = $('.welcomeFrame'); 7267 let wcVideoSrc = welcomeAdIframe.data('videosrc'); 7268 let wcVideoCodecs = welcomeAdIframe.data('videocodecs'); 7269 let wcBgColor = welcomeAdIframe.data('bgcolor'); 7270 let wcClickUrl = welcomeAdIframe.data('clickurl'); 7271 let wcStageMarginTop = welcomeAdIframe.data('stagemargintop'); 7272 let wcMuteButton = welcomeAdIframe.data('mutebutton'); 7273 let bodyEl = document.getElementsByTagName("BODY")[0]; 7274 let superbannerAd = document.getElementById('renderSlot_Superbanner'); 7275 let defaultBgColor = window.getComputedStyle(document.body).getPropertyValue('background-color'); 7276 defaultBgColor = be_rgbToHex(defaultBgColor); 7277 if(wcBgColor != 'default') { 7278 bodyEl.style.backgroundColor = wcBgColor; 7279 } 7280 let bgEl = document.createElement("div"); 7281 const stageEl = document.querySelector('.PageFrame'); 7282 bgEl.classList.add("wcVideo"); 7283 let videoEl = document.createElement("video"); 7284 videoEl.setAttribute("preload", "auto"); 7285 videoEl.setAttribute("loop", ""); 7286 //videoEl.setAttribute("autoplay", ""); 7287 videoEl.setAttribute("muted", ""); 7288 videoEl.classList.add("wcVideoTag"); 7289 7290 let wcCloseButton = document.createElement("button"); 7291 let closeBtnTxt = welcomeAdIframe.data('closebtntxt'); 7292 let wcCloseButtonText = closeBtnTxt != 'default' ? closeBtnTxt : 'schließen'; 7293 wcCloseButton.classList.add("wcCloseButton"); 7294 wcCloseButton.prepend(wcCloseButtonText); 7295 7296 let playBtnTxt = welcomeAdIframe.data('playbtntxt'); 7297 let pauseBtnTxt = welcomeAdIframe.data('pausebtntxt'); 7298
7299 bgEl.prepend(videoEl); 7300 bodyEl.prepend(wcCloseButton); 7301 7302 if (playBtnTxt != 'default') { 7303 let wcPlayButton = document.createElement("button"); 7304 let wcPlayButtonText = welcomeAdIframe.data('playbtntxt'); 7305 let wcPauseButtonText = welcomeAdIframe.data('pausebtntxt'); 7306 wcPlayButton.classList.add("wcPlayButton"); 7307 wcPlayButton.prepend(wcPlayButtonText); 7308 bodyEl.prepend(wcPlayButton); 7309 } 7310 7311 if (wcMuteButton) { 7312 let wcMuteButtonEl = document.createElement("button"); 7313 wcMuteButtonEl.classList.add("wcMuteButton"); 7314 let wcMuteButtonElText = "<i class='fa fa-volume-off fa-2x'> </i>"; 7315 wcMuteButtonEl.innerHTML = wcMuteButtonElText; 7316 bodyEl.prepend(wcMuteButtonEl); 7317 7318 } 7319 7320 let sourceEl = document.createElement("source"); 7321 sourceEl.setAttribute("src", wcVideoSrc); 7322 sourceEl.setAttribute("type", "video/mp4"); 7323 sourceEl.setAttribute("codecs", wcVideoCodecs); 7324 7325 videoEl.prepend(sourceEl); 7326 bodyEl.prepend(bgEl); 7327 7328 function playWcVideo() { 7329 videoEl.play(); 7330 } 7331 7332 function pauseWcVideo() { 7333 videoEl.pause(); 7334 } 7335 7336 function toggleWcVideo() { 7337 if(wcVideo.paused){ 7338 wcVideo.play(); 7339 if (wcPlayButton) { 7340 wcPlayButton.className = "wcPauseButton"; 7341 if (playBtnTxt != 'default') { 7342 let wcPauseButtonText = welcomeAdIframe.data('pausebtntxt'); 7343 wcPlayButton.innerText = wcPauseButtonText; 7344 } 7345 7346 } 7347 }else{ 7348 wcVideo.pause(); 7349 if (wcPlayButton) { 7350 wcPlayButton.className = "wcPlayButton"; 7351 if (playBtnTxt != 'default') { 7352 let wcPlayButtonText = welcomeAdIframe.data('playbtntxt'); 7353 wcPlayButton.innerText = wcPlayButtonText; 7354 } 7355 } 7356 } 7357 7358 /* 7359 if(wcVideo.muted){ 7360 wcVideo.muted = false; 7361 }else{ 7362 wcVideo.muted = true; 7363 } 7364 */ 7365 } 7366 7367 function toggleMuteButton() { 7368 if (wcVideo.muted) { 7369 wcVideo.muted = false; 7370 wcMuteButtonEl.classList.add("wcMuteOn"); 7371 wcMuteButtonEl.classList.remove("wcMuteOff"); 7372 wcMuteButtonEl.innerHTML = "<i class='fa fa-volume-up fa-2x'> </i>"; 7373 } else { 7374 wcVideo.muted = true; 7375 wcMuteButtonEl.classList.add("wcMuteOff"); 7376 wcMuteButtonEl.classList.remove("wcMuteOn"); 7377 wcMuteButtonEl.innerHTML = "<i class='fa fa-volume-off fa-2x'> </i>"; 7378 } 7379 } 7380 7381 let wcVideo = document.getElementsByClassName("wcVideoTag")[0]; 7382 wcVideo.addEventListener("click", toggleWcVideo); 7383 wcVideo.muted = true; 7384 wcVideo.autoplay = true; 7385 7386 7387 let wcPlayButton = document.querySelector(".wcPlayButton"); 7388 wcPlayButton.innerText = pauseBtnTxt; 7389 7390 if (wcPlayButton) { 7391 wcPlayButton.addEventListener("click", toggleWcVideo); 7392 } 7393 7394 let wcPauseButton = document.querySelector(".wcPauseButton"); 7395 if (wcPauseButton) { 7396 wcPauseButton.addEventListener("click", toggleWcVideo); 7397 } 7398 7399 let wcMuteButtonEl = document.querySelector(".wcMuteButton"); 7400 if (wcMuteButtonEl) { 7401 wcMuteButtonEl.addEventListener("click", toggleMuteButton); 7402 } 7403 7404 /* clickable background -> */ 7405 const wcMouseOverHandler = function (event) { 7406 if (event.target === document.body) { 7407 document.body.style.cursor = 'pointer'; 7408 } 7409 }; 7410 document.addEventListener('mouseover', wcMouseOverHandler); 7411 7412 const wcMouseOutHandler = function (event) { 7413 if (event.target === document.body) { 7414 document.body.style.cursor = 'auto'; 7415 } 7416 }; 7417 document.addEventListener('mouseout', wcMouseOutHandler); 7418 7419 const clickHandler = function (event) { 7420 if (event.target === document.body) { 7421 window.open(wcClickUrl, '_blank'); 7422 } 7423 }; 7424 document.addEventListener('click', clickHandler); 7425 /* <- clickable background */ 7426 7427 function fadeOutOnScroll(element, stageEl) { 7428 if (!element || !stageEl) { 7429 return; 7430 } 7431 7432 let distanceToTop = window.pageYOffset + element.getBoundingClientRect().top; 7433 const elementHeight = element.offsetHeight; 7434 const scrollTop = document.documentElement.scrollTop; 7435 7436 let opacity = 1; 7437 distanceToTop = 0; 7438 element.style.position = 'fixed'; 7439 7440 if (scrollTop > distanceToTop) { 7441 opacity = 1 - (scrollTop - distanceToTop) / elementHeight; 7442 opacity = (opacity < 0) ? 0 : opacity; 7443 opacity = (opacity > 0.95) ? 1 : opacity; 7444 } 7445 7446 if (opacity >= 0) { 7447 element.style.opacity = opacity;
7448 /* be_reduceBackgroundOpacity(superbannerAd, opacity); */ 7449 if(wcBgColor != 'default') { 7450 be_changeBGColor(bodyEl, defaultBgColor, wcBgColor, opacity); 7451 } 7452 } 7453 } 7454 7455 function scrollHandler() { 7456 fadeOutOnScroll(wcVideo, bgEl); 7457 } 7458 7459 window.addEventListener('scroll', scrollHandler, {passive: true}); 7460 7461 /** 7462 * Close Button 7463 */ 7464 function closeWcVideo() { 7465 wcVideo.remove(); 7466 bodyEl.style.backgroundColor = defaultBgColor; 7467 superbannerAd.firstElementChild.remove(); 7468 wcCloseButton.remove(); 7469 if (wcPlayButton) { 7470 wcPlayButton.remove(); 7471 } 7472 if (wcMuteButtonEl) { 7473 wcMuteButtonEl.remove(); 7474 } 7475 window.removeEventListener('scroll', scrollHandler, {passive: true}); 7476 document.removeEventListener('click', clickHandler); 7477 document.removeEventListener('mouseover', wcMouseOverHandler); 7478 document.removeEventListener('mouseout', wcMouseOutHandler); 7479 stageEl.style.transition = 'margin 1s'; 7480 stageEl.style.marginTop = '0px'; 7481 } 7482 7483 wcCloseButton.addEventListener("click", closeWcVideo); 7484 7485 /* wait until bg-video is available */ 7486 let wcInterval = setInterval(function() { 7487 document.getElementById("renderSlot_Superbanner").style.height = "0"; 7488 if (videoEl) { 7489 clearInterval(wcInterval); 7490 let OriginalStageMarginTop = wcStageMarginTop; 7491 let videoElStyle = getComputedStyle(videoEl); 7492 let videoElHeight = parseInt(videoElStyle.height); 7493 let videoElOrigHeight = videoEl.naturalHeight; 7494 videoElOrigHeight = videoElOrigHeight || welcomeAdIframe.data('height'); 7495 if (videoElHeight > videoElOrigHeight) { 7496 7497 videoElHeight = videoElOrigHeight; 7498 } 7499 7500 let videoElRatio = (videoElHeight / videoElOrigHeight).toFixed(2); 7501 let StageMarginTop = Math.round(OriginalStageMarginTop * videoElRatio); 7502 7503 stageEl.style.marginTop = StageMarginTop+'px'; 7504 } 7505 clearInterval(wcInterval); 7506 }, 200); 7507 7508}); 7509 7510/** 7511 * welcomeAdImage 7512 * WelcomeAd mit Hintergrund-Image, wird beim Scrollen ausgeblendet, hat Close-Button 7513 */ 7514$(document).on('welcomeAdImage', function(event) { 7515 7516 let welcomeAd = $('.welcomeFrame').parent().parent(); 7517 let welcomeAdIframe = $('.welcomeFrame'); 7518 let wcBgColor = welcomeAdIframe.data('bgcolor'); 7519 let wcClickUrl = welcomeAdIframe.data('clickurl'); 7520 let bodyEl = document.getElementsByTagName("BODY")[0]; 7521 let superbannerAd = document.getElementById('renderSlot_Superbanner'); 7522 let defaultBgColor = window.getComputedStyle(document.body).getPropertyValue('background-color'); 7523 defaultBgColor = be_rgbToHex(defaultBgColor); 7524 7525 if(wcBgColor != 'default') { 7526 bodyEl.style.backgroundColor = wcBgColor; 7527 } 7528 let bgEl = document.createElement("div"); 7529 const stageEl = document.querySelector('.PageFrame'); 7530 7531 bgEl.classList.add("wcBgImage"); 7532 let imgEl = document.createElement("img"); 7533 imgEl.classList.add("wcBgImageTag"); 7534 7535 let wcCloseButton = document.createElement("button"); 7536 let closeBtnTxt = welcomeAdIframe.data('closebtntxt'); 7537 let wcCloseButtonText = closeBtnTxt != 'default' ? closeBtnTxt : 'schließen'; 7538 7539 wcCloseButton.classList.add("wcCloseButton"); 7540 wcCloseButton.prepend(wcCloseButtonText); 7541 7542 bgEl.prepend(imgEl); 7543 bodyEl.prepend(wcCloseButton); 7544 7545 let bgImgSource = welcomeAdIframe.data('bgimagesrc'); 7546 7547 imgEl.setAttribute('src',bgImgSource); 7548 bodyEl.prepend(bgEl); 7549 7550 /* clickable background -> */ 7551 const wcMouseOverHandler = function (event) { 7552 if (event.target === document.body) { 7553 document.body.style.cursor = 'pointer'; 7554 } 7555 }; 7556 document.addEventListener('mouseover', wcMouseOverHandler); 7557 7558 const wcMouseOutHandler = function (event) { 7559 if (event.target === document.body) { 7560 document.body.style.cursor = 'auto'; 7561 } 7562 }; 7563 document.addEventListener('mouseout', wcMouseOutHandler); 7564 7565 const clickHandler = function (event) { 7566 if (event.target === document.body) { 7567 window.open(wcClickUrl, '_blank'); 7568 } 7569 }; 7570 document.addEventListener('click', clickHandler); 7571 /* <- clickable background */ 7572 7573 /* Superbanner in Hintergrund und sticky -> */ 7574 superbannerAd.classList.add("wcfixedSuperbanner"); 7575 const stageElStyles = window.getComputedStyle(stageEl); 7576 const stageElMarginTop = stageElStyles.getPropertyValue('margin-top'); 7577 stageEl.style.marginTop = superbannerAd.offsetHeight+'px'; 7578 /* 7579 * Calculation of the distance from the stage to the top of the screen 7580 * in a fixed ratio of 1080 (width of background image) to 520 (original distance from stage to top of screen) 7581 */ 7582 let wcInterval2 = setInterval(function() { 7583 7584 if (imgEl) { 7585 clearInterval(wcInterval2); 7586 7587 let imgElStyle = getComputedStyle(imgEl); 7588 let imgElCurrHeight = parseInt(imgElStyle.height); 7589 7590 let imgHeight = 520; 7591 let imgElOrigHeight = 1080; 7592 let imgElRatio = (imgHeight / imgElOrigHeight).toFixed(2); 7593 let StageMarginTop = Math.round(imgElCurrHeight * imgElRatio); 7594 7595 stageEl.style.marginTop = StageMarginTop+'px'; 7596 } 7597 clearInterval(wcInterval2); 7598 }, 200); 7599 7600 7601 /* <- Superbanner in Hintergrund und sticky */ 7602 7603 /* clickable superbanner -> */ 7604 7605 superbannerAd.addEventListener('mouseover', function() { 7606 superbannerAd.style.cursor = 'pointer'; 7607 }); 7608 7609 superbannerAd.addEventListener('mouseout', function() { 7610 superbannerAd.style.cursor = 'auto'; 7611 }); 7612 7613 superbannerAd.addEventListener('click', function() { 7614 window.open(wcClickUrl, '_blank'); 7615 }); 7616 /* <- clickable superbanner */ 7617 7618 function fadeOutOnScroll(element, stageEl) { 7619 if (!element || !stageEl) { 7620 return; 7621 } 7622 7623 let distanceToTop = window.pageYOffset + element.getBoundingClientRect().top; 7624 const elementHeight = element.offsetHeight; 7625 const scrollTop = document.documentElement.scrollTop; 7626 7627 let opacity = 1; 7628 distanceToTop = 0; 7629 element.style.position = 'fixed'; 7630 7631 if (scrollTop > distanceToTop) { 7632 opacity = 1 - (scrollTop - distanceToTop) / elementHeight; 7633 opacity = (opacity < 0) ? 0 : opacity; 7634 opacity = (opacity > 0.95) ? 1 : opacity; 7635 } 7636 7637 if (opacity >= 0) { 7638 element.style.opacity = opacity;
7639 /* be_reduceBackgroundOpacity(superbannerAd, opacity); */ 7640 if(wcBgColor != 'default') { 7641 be_changeBGColor(bodyEl, defaultBgColor, wcBgColor, opacity); 7642 } 7643 } 7644 } 7645 7646 function scrollHandler() { 7647 fadeOutOnScroll(bgEl, stageEl); 7648 } 7649 7650 window.addEventListener('scroll', scrollHandler, {passive: true}); 7651 7652 /* 7653 * Close Button 7654 */ 7655 function closewcBgImage() { 7656 bgEl.remove(); 7657 bodyEl.style.backgroundColor = defaultBgColor; 7658 superbannerAd.firstElementChild.remove(); 7659 wcCloseButton.remove(); 7660 window.removeEventListener('scroll', scrollHandler, {passive: true}); 7661 document.removeEventListener('click', clickHandler); 7662 document.removeEventListener('mouseover', wcMouseOverHandler); 7663 document.removeEventListener('mouseout', wcMouseOutHandler); 7664 stageEl.style.transition = "margin-top 0.5s ease"; 7665 stageEl.style.marginTop = stageElMarginTop; 7666 } 7667 7668 wcCloseButton.addEventListener("click", closewcBgImage); 7669 7670}); 7671 7672/** 7673 * welcomeAdVideoMobil 7674 * WelcomeAd mit Video-URL für Mobil, hat Close-Button 7675 */ 7676$(document).on('welcomeAdVideoMobil', function(event) { 7677 7678 let welcomeAdIframe = document.getElementById('welcomeFrameMobil'); 7679 7680 let bodyEl = document.getElementsByTagName("BODY")[0]; 7681 let superbannerAd = document.getElementById('renderSlot_Mobil-Superbanner'); 7682 7683 let wcCloseButton = document.createElement("button"); 7684 let closeBtnTxt = welcomeAdIframe.getAttribute('data-closebtntxt'); 7685 let wcCloseButtonText = closeBtnTxt != 'default' ? closeBtnTxt : 'schließen'; 7686 wcCloseButton.classList.add("wcCloseButtonMobil"); 7687 wcCloseButton.prepend(wcCloseButtonText); 7688 7689 bodyEl.prepend(wcCloseButton); 7690 7691 let adHeight = superbannerAd.clientHeight; 7692 7693 welcomeAdIframe.style.position = "fixed"; 7694 welcomeAdIframe.style.zIndex = "-1"; 7695 superbannerAd.style.height = adHeight+"px"; 7696 7697 wcCloseButton.style.top = adHeight-35+"px"; 7698 7699 7700 /* 7701 * Create Video Tag 7702 */ 7703 let bgEl = document.createElement("div"); 7704 bgEl.classList.add("wcVideo"); 7705 bgEl.classList.add("wcMobil"); 7706 7707 let videoEl = document.createElement("video"); 7708 videoEl.setAttribute("preload", "auto"); 7709 videoEl.setAttribute("loop", ""); 7710 videoEl.setAttribute("muted", ""); 7711 videoEl.setAttribute("id", "wcVideoTag"); 7712 videoEl.classList.add("wcVideoTag"); 7713 7714 let wcVideoSrc = welcomeAdIframe.getAttribute('data-videosrc'); 7715 let wcVideoCodecs = welcomeAdIframe.getAttribute('data-videocodecs'); 7716 let sourceEl = document.createElement("source"); 7717 sourceEl.setAttribute("src", wcVideoSrc); 7718 sourceEl.setAttribute("type", "video/mp4"); 7719 sourceEl.setAttribute("codecs", wcVideoCodecs); 7720 7721 videoEl.prepend(sourceEl); 7722 bgEl.prepend(videoEl); 7723 bodyEl.prepend(bgEl); 7724 7725 7726 7727 /* 7728 * Close Button 7729 */ 7730 function closeWcVideo() { 7731 superbannerAd.remove(); 7732 wcCloseButton.remove(); 7733 wcPlayButton.remove(); 7734 } 7735 7736 wcCloseButton.addEventListener("click", closeWcVideo); 7737 7738 7739 /* 7740 * Play/Stop Button 7741 */ 7742 let wcPlayBtnTxt = welcomeAdIframe.getAttribute('data-playbtntxt'); 7743 let wcPauseBtnTxt = welcomeAdIframe.getAttribute('data-pausebtntxt'); 7744 7745 let wcPlayButton = document.createElement("button"); 7746 wcPlayButton.classList.add("wcPlayButtonMobil"); 7747 wcPlayButton.prepend(wcPlayBtnTxt); 7748 bodyEl.prepend(wcPlayButton); 7749 7750 wcPlayButton.style.top = adHeight-35+"px"; 7751 7752 wcPlayButton.addEventListener("click", toggleWcVideo); 7753 7754 let wcVideo = document.getElementById('wcVideo'); 7755 wcVideo = videoEl; 7756 7757 function toggleWcVideo() { 7758 if(wcVideo.paused){ 7759 wcVideo.play(); 7760 if (wcPlayButton) { 7761 wcPlayButton.className = "wcPauseButtonMobil"; 7762 if (wcPlayBtnTxt != 'default') { 7763 wcPlayButton.innerText = wcPauseBtnTxt; 7764 } 7765 7766 } 7767 }else{ 7768 wcVideo.pause(); 7769 if (wcPlayButton) { 7770 wcPlayButton.className = "wcPlayButtonMobil"; 7771 if (wcPlayBtnTxt != 'default') { 7772 wcPlayButton.innerText = wcPlayBtnTxt; 7773 } 7774 } 7775 } 7776 7777 /* 7778 if(wcVideo.muted){ 7779 wcVideo.muted = false; 7780 }else{ 7781 wcVideo.muted = true; 7782 } 7783 */ 7784 } 7785 7786}); 7787 7788 7789/** 7790 * alignSkyscraperLeft 7791 */ 7792$(document).one("alignSkyscraperLeft", function(event){
7793 if ($("#renderSlot_Skyscraper-links > div > iframe").length){ 7794 let leftSkyEl = document.getElementById("renderSlot_Skyscraper-links"); 7795 7796 7797 if($("#renderSlot_Skyscraper-links > div > iframe").length){ 7798 7799 let elementSkyLeft = document.querySelector('.Ad-skyscraper-left'); 7800 if(!elementSkyLeft) return; 7801 let style = window.getComputedStyle(elementSkyLeft); 7802 let marginLeftSkyLeft = parseFloat(style.getPropertyValue('margin-left')); 7803 7804 const bannerFrame = $("#renderSlot_Skyscraper-links > div > iframe"); 7805 let bannerFrameWidth = bannerFrame.data("width"); 7806 let bannerFrameHeight = bannerFrame.data('height'); 7807 let bannerFrameZIndex = bannerFrame.data('z-index'); 7808 7809 if(bannerFrameWidth){ 7810 let offset = bannerFrameWidth - Math.abs(marginLeftSkyLeft); 7811 offset = Math.abs(offset); 7812 if(offset <= 20){ /* wenn versucht wurde durch css Abstand zur Bühne herzustellen */ 7813 bannerFrameWidth = bannerFrameWidth + offset; 7814 } 7815 $("#renderSlot_Skyscraper-links").css("margin-left", "-" + bannerFrameWidth + "px"); 7816 $("#renderSlot_Skyscraper-links").css("width", bannerFrameWidth + "px"); 7817 $("#renderSlot_Skyscraper-links > div > iframe").css("height", bannerFrameHeight + "px"); 7818 } 7819 if(bannerFrameZIndex){ 7820 $('#renderSlot_Skyscraper-links').css('z-index', bannerFrameZIndex); 7821 } 7822 } 7823 } 7824 7825}); 7826 7827/** 7828 * alignSkyscraperRight 7829 * Positioniert den rechten Skyscraper so, dass sein linker Rand am rechten Rand der Bühne (.PageFrame) anliegt. 7830 * Sitebar wird ausgeschlossen 7831 */ 7832$(document).one("alignSkyscraperRight", function(event){ 7833 var selector = "#renderSlot_Skyscraper-rechts iframe"; 7834 var maxTries = 10; 7835 var tryCount = 0; 7836 function tryAlign() { 7837 var bannerFrame = $(selector); 7838 //console.log('[DEBUG] Versuch', tryCount+1, 'Gefundene iFrames:', bannerFrame.length, bannerFrame); 7839 if (bannerFrame.length) { 7840 7841 var bannerFrameWidth = bannerFrame.data("width"); 7842 var marginTop = bannerFrame.data("margin-top"); 7843 var marginBottom = bannerFrame.data("margin-bottom"); 7844 var marginLeft = bannerFrame.data("margin-left"); 7845 var marginRight = bannerFrame.data("margin-right"); 7846 //console.log('[DEBUG] data-width:', bannerFrameWidth, 'marginTop:', marginTop, 'marginBottom:', marginBottom, 'marginLeft:', marginLeft, 'marginRight:', marginRight); 7847 var $pageFrame = $('.PageFrame'); 7848 if (bannerFrameWidth && $pageFrame.length) { 7849 var pageFrameRight = $pageFrame.offset().left + $pageFrame.outerWidth(); 7850 var $skyContainer = $("#renderSlot_Skyscraper-rechts"); 7851 // Position berechnen: linker Rand des Skyscrapers = rechter Rand der Bühne 7852 var newLeft = pageFrameRight; 7853 var cssProps = { 7854 position: 'absolute', 7855 left: newLeft + 'px', 7856 width: bannerFrameWidth + 'px', 7857 'margin-left': 0 7858 }; 7859 // Margin-Attribute aus dem Template 7860 if (typeof marginTop !== 'undefined' && marginTop !== null && marginTop !== '' && marginTop !== '0') { 7861 cssProps['margin-top'] = marginTop + 'px'; 7862 } 7863 if (typeof marginBottom !== 'undefined' && marginBottom !== null && marginBottom !== '' && marginBottom !== '0') { 7864 cssProps['margin-bottom'] = marginBottom + 'px'; 7865 } 7866 if (typeof marginLeft !== 'undefined' && marginLeft !== null && marginLeft !== '' && marginLeft !== '0') { 7867 cssProps['margin-left'] = marginLeft + 'px'; 7868 } 7869 if (typeof marginRight !== 'undefined' && marginRight !== null && marginRight !== '' && marginRight !== '0') { 7870 cssProps['margin-right'] = marginRight + 'px'; 7871 } 7872 $skyContainer.css(cssProps); 7873 console.log('[DEBUG] Skyscraper rechts positioniert:', cssProps); 7874 } else { 7875 //console.warn('[DEBUG] Kein data-width oder keine .PageFrame gefunden!'); 7876 } 7877 } else if (++tryCount < maxTries) { 7878 setTimeout(tryAlign, 100); 7879 } else { 7880 //console.warn('[DEBUG] Kein iFrame gefunden für Selector nach', maxTries, 'Versuchen:', selector); 7881 } 7882 } 7883 tryAlign(); 7884}); 7885 7886/** 7887 * bridgeAd 7888 */ 7889$(document).on("bridgeAd", function(event){ 7890 const bA_iframe = document.querySelector('.bridgeAdFrame'); 7891 const bA_renderSlot = document.querySelector('.Ad-billboard'); 7892 bA_renderSlot.classList.add('bridgeAdSlot'); 7893}); 7894 7895/** 7896 * bridgeAdSticky 7897 */ 7898$(document).on("bridgeAdSticky", function(event){ 7899 const bA_iframe = document.querySelector('.bridgeAdFrame'); 7900 const bA_renderSlot = document.querySelector('.Ad-billboard'); 7901 bA_renderSlot.classList.add('bridgeAdSlot'); 7902 bA_iframe.classList.add('billboardSticky'); 7903}); 7904 7905/** 7906 * Rechts-Ausrichtung 7907 * wird inbridgeAdComp aufgerufen, nachdem Skyscraper iFrame mit Grafik gefüllt wurde 7908 */ 7909$(document).on("alignSkyscraperRightBridgeAd", function(event) { 7910 var selector = ".Ad-skyscraper-right iframe.CompFrame"; 7911 var maxTries = 15; 7912 var tryCount = 0; 7913 7914 function tryAlign() { 7915 var $bannerFrame = $(selector).first();
7916 var $billboard = $('#renderSlot_Billboard'); 7917 7918 if ($bannerFrame.length && $billboard.length) { 7919 var bannerFrameWidth = parseFloat($bannerFrame.attr("data-width")); 7920 if (!bannerFrameWidth) { 7921 if (++tryCount < maxTries) setTimeout(tryAlign, 100); 7922 return; 7923 } 7924 7925 var $skyContainer = $bannerFrame.closest('.Ad-skyscraper-right'); 7926 var billboardRect = $billboard[0].getBoundingClientRect(); 7927 var finalLeft = billboardRect.right; 7928 7929 var cssProps = { 7930 'position': 'fixed', 7931 // 'top': billboardRect.top + 'px', // Bei Bedarf aktivieren für vertikale Billboard-Bindung 7932 'left': finalLeft + 'px', 7933 'right': 'auto', 7934 'width': bannerFrameWidth + 'px', 7935 'margin': '0', 7936 'transform': 'none', 7937 'z-index': '100' 7938 }; 7939 7940 // Optionaler Margin-Top aus dem iFrame 7941 var mTop = parseFloat($bannerFrame.attr("data-margin-top")); 7942 if (mTop) cssProps['top'] = (billboardRect.top + mTop) + 'px'; 7943 7944 $skyContainer.css(cssProps); 7945 } else if (++tryCount < maxTries) { 7946 setTimeout(tryAlign, 100); 7947 } 7948 } 7949 tryAlign(); 7950}); 7951 7952/** 7953 * Links-Ausrichtung 7954 * wird in bridgeAdComp aufgerufen, nachdem Skyscraper iFrame mit Grafik gefüllt wurde 7955 */ 7956$(document).on("alignSkyscraperLeftBridgeAd", function(event) { 7957 var selector = ".Ad-skyscraper-left iframe.CompFrame"; 7958 var maxTries = 15; 7959 var tryCount = 0; 7960 7961 function tryAlign() { 7962 var $bannerFrame = $(selector).first(); 7963 var $billboard = $('#renderSlot_Billboard'); 7964 7965 if ($bannerFrame.length && $billboard.length) { 7966 var bannerFrameWidth = parseFloat($bannerFrame.attr("data-width")); 7967 if (!bannerFrameWidth) { 7968 if (++tryCount < maxTries) setTimeout(tryAlign, 100); 7969 return; 7970 } 7971 7972 var $skyContainer = $bannerFrame.closest('.Ad-skyscraper-left'); 7973 var billboardRect = $billboard[0].getBoundingClientRect(); 7974 var finalLeft = billboardRect.left - bannerFrameWidth; 7975 7976 var cssProps = { 7977 'position': 'fixed', 7978 // 'top': billboardRect.top + 'px', // Bei Bedarf aktivieren für vertikale Billboard-Bindung 7979 'left': finalLeft + 'px', 7980 'right': 'auto', 7981 'width': bannerFrameWidth + 'px', 7982 'margin': '0', 7983 'transform': 'none', 7984 'z-index': '100' 7985 }; 7986 7987 var mTop = parseFloat($bannerFrame.attr("data-margin-top")); 7988 if (mTop) cssProps['top'] = (billboardRect.top + mTop) + 'px'; 7989 7990 $skyContainer.css(cssProps); 7991 } else if (++tryCount < maxTries) { 7992 setTimeout(tryAlign, 100); 7993 } 7994 } 7995 tryAlign(); 7996}); 7997 7998$(document).on('valueAd', function() { 7999 const valueAdFrame = document.querySelector('#renderSlot_Billboard iframe.valueAdFrame, #renderSlot_Mobil-Billboard iframe.valueAdFrame, iframe.valueAdFrame'); 8000 if (!valueAdFrame) return; 8001 8002 const bgImage = valueAdFrame.getAttribute('data-bgimage') || ''; 8003 const bgColor = valueAdFrame.getAttribute('data-bgcolor') || ''; 8004 if (bgImage && bgImage.indexOf('[%') === -1) { 8005 document.body.style.backgroundImage = 'url("' + bgImage + '")'; 8006 document.body.style.backgroundRepeat = 'no-repeat'; 8007 document.body.style.backgroundPosition = 'center top'; 8008 } 8009 if (bgColor && bgColor.indexOf('[%') === -1) { 8010 document.body.style.backgroundColor = bgColor; 8011 } 8012 8013 const billboardSlot = valueAdFrame.closest('#renderSlot_Billboard, #renderSlot_Mobil-Billboard'); 8014 if (billboardSlot) { 8015 // Bei ValueAd darf seitlich kein Padding bleiben, damit Sky direkt am Billboard anliegt. 8016 billboardSlot.style.paddingLeft = '0px'; 8017 billboardSlot.style.paddingRight = '0px'; 8018 } 8019 8020 if (valueAdFrame.parentElement) { 8021 valueAdFrame.parentElement.style.paddingLeft = '0px'; 8022 valueAdFrame.parentElement.style.paddingRight = '0px'; 8023 } 8024 8025 // Vorhandene BridgeAd-Logik wiederverwenden: ValueAd-iframe als Quelle markieren. 8026 valueAdFrame.classList.add('bridgeAdFrame'); 8027 8028 const imgLeft = valueAdFrame.getAttribute('data-img_left') || ''; 8029 const imgRight = valueAdFrame.getAttribute('data-img_right') || ''; 8030 if (!imgLeft && !imgRight) return; 8031 if (imgLeft.indexOf('[%') !== -1 && imgRight.indexOf('[%') !== -1) return; 8032 8033 $(document).trigger('bridgeAdComp'); 8034}); 8035 8036 8037/** 8038 * bridgeAdComp 8039 * Hauptfunktion: Bridge-Ad Kompatibilität 8040 */ 8041$(document).on("bridgeAdComp", function(event) { 8042 const bA_iframe = document.querySelector('.bridgeAdFrame'); 8043 if (!bA_iframe) return; 8044 8045 const skyRight_Slot = document.querySelector('.Ad-skyscraper-right'); 8046 const skyLeft_Slot = document.querySelector('.Ad-skyscraper-left'); 8047 const commonClickUrl = bA_iframe.dataset.click_url; 8048 8049 const setupSkyscraper = (slot, imgUrl, linkUrl, eventName) => { 8050 if (!slot || !imgUrl) return; 8051 8052 const googleDiv = Array.from(slot.querySelectorAll('div')) 8053 .find(div => div.id && div.id.startsWith('google_ads_iframe_')); 8054 8055 if (googleDiv) { 8056 const imgLoader = new Image(); 8057 imgLoader.src = imgUrl; 8058 8059 imgLoader.onload = function() {
8060 const realWidth = imgLoader.naturalWidth; 8061 const realHeight = imgLoader.naturalHeight; 8062 8063 googleDiv.innerHTML = ''; 8064 let customFrame = document.createElement('iframe'); 8065 customFrame.classList.add('responsiveFrame', 'CompFrame'); 8066 customFrame.dataset.width = realWidth; 8067 customFrame.dataset.height = realHeight; 8068 8069 Object.assign(customFrame.style, { 8070 width: '100%', 8071 maxWidth: `${realWidth}px`, 8072 height: 'auto', 8073 aspectRatio: `${realWidth} / ${realHeight}`, 8074 border: 'none', 8075 display: 'block' 8076 }); 8077 8078 customFrame.src = 'about:blank'; 8079 googleDiv.appendChild(customFrame); 8080 8081 const finalizeFrame = () => { 8082 try { 8083 const doc = customFrame.contentDocument || customFrame.contentWindow.document; 8084 if (doc) { 8085 doc.open(); 8086 // Einbau des Links um das Bild herum 8087 doc.write(` 8088 <!DOCTYPE html> 8089 <html> 8090 <body style="margin:0;padding:0;overflow:hidden;"> 8091 <a href="${linkUrl || '#'}" target="_blank" style="display:block;text-decoration:none;outline:none;"> 8092 <img src="${imgUrl}" style="width:100%;display:block;border:none;-webkit-user-drag:none;" /> 8093 </a> 8094 </body> 8095 </html> 8096 `); 8097 doc.close(); 8098 8099 setTimeout(() => { 8100 $(document).trigger(eventName); 8101 console.log(`[DEBUG] ${eventName} mit Link ausgeführt`); 8102 }, 10); 8103 } 8104 } catch (e) { 8105 console.error("Fehler beim Finalisieren des iFrames:", e); 8106 } 8107 }; 8108 8109 if (customFrame.contentDocument && customFrame.contentDocument.readyState === 'complete') { 8110 finalizeFrame(); 8111 } else { 8112 customFrame.onload = finalizeFrame; 8113 } 8114 }; 8115 } 8116 }; 8117 8118 setupSkyscraper( 8119 skyRight_Slot, 8120 bA_iframe.dataset.img_right, 8121 // bA_iframe.dataset.click_right, 8122 commonClickUrl, 8123 "alignSkyscraperRightBridgeAd" 8124 ); 8125 8126 setupSkyscraper( 8127 skyLeft_Slot, 8128 bA_iframe.dataset.img_left, 8129 // bA_iframe.dataset.click_left, 8130 commonClickUrl, 8131 "alignSkyscraperLeftBridgeAd" 8132 ); 8133}); 8134 8135/** 8136 * Magnet-Effekt bei Resize 8137 */ 8138$(window).on('resize', function() { 8139 if ($('.Ad-skyscraper-right iframe.CompFrame').length) $(document).trigger("alignSkyscraperRightBridgeAd"); 8140 if ($('.Ad-skyscraper-left iframe.CompFrame').length) $(document).trigger("alignSkyscraperLeftBridgeAd"); 8141}); 8142 8143/** 8144 * fullWidthBillboard 8145 */ 8146$(document).on("fullWidthBillboard", function(event){ 8147 const fw_renderSlot = document.querySelector('#renderSlot_Billboard'); 8148 fw_renderSlot.classList.add('fullWidthBillboard'); 8149}); 8150 8151/** 8152 * billboardSticky 8153 */ 8154$(document).on('billboardSticky', function(){ 8155 const slot = $('#renderSlot_Billboard, #renderSlot_Mobil-Billboard'); 8156 const billboardAdIframe = $('.billboardSticky'); 8157 const stickyHeaderHeight = $('.SiteHeaderSticky').height(); 8158 8159 const billboardPositionTop = slot.offset().top; 8160 const billboardMarginTop = parseFloat(billboardAdIframe.parent().css('margin-top')); 8161 let billboardStickyOffsetTop = stickyHeaderHeight + 5; 8162 let sTimer = 0; 8163 if (Math.sign(billboardMarginTop) === -1) { 8164 billboardStickyOffsetTop = billboardStickyOffsetTop + Math.abs(billboardMarginTop); 8165 } else { 8166 billboardStickyOffsetTop = billboardStickyOffsetTop - Math.abs(billboardMarginTop); 8167 } 8168 8169 const bId = String(billboardAdIframe.data('bannerid')); 8170 const lsKey = 'stickyBillboard_' + bId; 8171 const lsValue = localStorage.getItem(lsKey); 8172 8173 if (lsValue !== null) { 8174 const expireDate = JSON.parse(lsValue).expireAt; 8175 if (expireDate < new Date().getTime()) { 8176 localStorage.removeItem(lsKey); 8177 } else { 8178 return false; 8179 } 8180 } 8181 8182 if ($('.PageFrame').height() > 2000) { 8183 $(window).scroll(function () { 8184 if ($(window).scrollTop() > billboardPositionTop) { 8185 if (localStorage.getItem(lsKey) === null && !sTimer && !slot.hasClass('isStickyBillboard')) { 8186 slot.css({top: billboardStickyOffsetTop + 'px'}); 8187 slot.addClass('isStickyBillboard'); 8188 8189 sTimer = setTimeout(function () { 8190 slot.css({'zIndex': 998}); 8191 slot.animate({'top': -600}, 3000, function () { 8192 }); 8193 sTimer = 0; 8194 const expireAt = new Date(new Date().getTime() + (60000 * 1440)).getTime(); 8195 localStorage.setItem(lsKey, JSON.stringify({expireAt: expireAt})); 8196 }, 2000); 8197 } 8198 } else { 8199 if (sTimer) { 8200 clearTimeout(sTimer); 8201 sTimer = 0; 8202 } 8203 slot.css({top: '0px'}); 8204 slot.removeClass('isStickyBillboard'); 8205 } 8206 }); 8207 } 8208}); 8209 8210 8211window.googletag = window.googletag || { cmd: [] }; 8212function initPremiumPaywallExpandOnAnker(get_status) { 8213 var url; 8214 var anker_exists; 8215 8216 url = window.location.href; 8217 anker_exists = url.indexOf("#formRegisterNG"); 8218 8219 if ( anker_exists >= 0) { 8220 if (get_status !== true) { 8221 $('.FormRegisterNG_secondWrapper').addClass('isExpanded'); 8222 } else { 8223 return true; 8224 } 8225 } 8226} 8227 8228function getQueryVariable(variable) { 8229 var query = window.location.search.substring(1); 8230 var vars = query.split("&"); 8231 for (var i=0;i<vars.length;i++) { 8232 var pair = vars[i].split("="); 8233 if (pair[0] == variable) { 8234 return pair[1]; 8235 } 8236 } 8237 return ""; 8238} 8239 8240function fillForm(field_id,value, formID) { 8241 $('#'+formID + ' #'+field_id).val(decodeURIComponent(value)); 8242} 8243 8244function initPremiumPaywallToggle() { 8245 var is_expanded; 8246 is_expanded = initPremiumPaywallExpandOnAnker(true); 8247 8248 // Diese Variablen dürfen per Get an die Reg-Bühne übergeben werden 8249 var allowed_get_params = ['email', 'firstname', 'lastname']; 8250 8251 // Werte holen für formFillers und Formular vorbelegen
8252 allowed_get_params.forEach( function(entry) { 8253 form_val = getQueryVariable(entry); 8254 if (form_val.length > 0) { 8255 fillForm('i_' + entry, form_val, 'nl_order_single_form' ) 8256 } 8257 }); 8258 8259 8260 if ( is_expanded || $('.FormRegisterNG_secondWrapper').hasClass('isExpanded') ) { 8261 $('.FormRegisterNG_toggleButton-arrows').css('transform', 'rotate(180deg)'); 8262 } 8263 8264 $('.StagePremiumPaywall .FormRegisterNG_firstWrapper').click(function() { 8265 var paywall = '.FormRegisterNG_secondWrapper'; 8266 8267 if ( $(paywall+':visible').length === 0 ) { 8268 $(paywall).slideDown(225); 8269 $('.FormRegisterNG_toggleButton').addClass('isActive'); 8270 $('.FormRegisterNG_toggleButton-arrows').css('transform', 'rotate(180deg)'); 8271 } else if ( $(paywall+':visible').length > 0) { 8272 $(paywall).slideUp(225); 8273 $('.FormRegisterNG_toggleButton').removeClass('isActive'); 8274 $('.FormRegisterNG_toggleButton-arrows').css('transform', 'rotate(0deg)'); 8275 } 8276 }); 8277} 8278 8279$(document).ready( function() { 8280 initPremiumPaywallToggle(); 8281 initPremiumPaywallExpandOnAnker(false); 8282}); 8283 8284!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):"undefined"!=typeof exports?module.exports=i(require("jquery")):i(jQuery)}(function(i){"use strict";var e=window.Slick||{};(e=function(){var e=0;return function(t,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(t),appendDots:i(t),arrows:!0,asNavFor:null,prevArrow:'<button class="slick-prev" aria-label="Previous" type="button">Previous</button>',nextArrow:'<button class="slick-next" aria-label="Next" type="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(e,t){return i('<button type="button" />').text(t+1)},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},n.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden="hidden",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(t),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange="visibilitychange",n.windowWidth=0,n.windowTimer=null,s=i(t).data("slick")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,void 0!==document.mozHidden?(n.hidden="mozHidden",n.visibilityChange="mozvisibilitychange"):void 0!==document.webkitHidden&&(n.hidden="webkitHidden",n.visibilityChange="webkitvisibilitychange"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=e++,n.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}}()).prototype.activateADA=function(){this.$slideTrack.find(".slick-active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if("boolean"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),"number"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):!0===o?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr("data-slick-index",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),!0===s.options.rtl&&!1===s.options.vertical&&(e=-e),!1===s.transformsEnabled?!1===s.options.vertical?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):!1===s.cssTransitions?(!0===s.options.rtl&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),!1===s.options.vertical?(o[s.animType]="translate("+i+"px, 0px)",s.$slideTrack.css(o)):(o[s.animType]="translate(0px,"+i+"px)",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),!1===s.options.vertical?o[s.animType]="translate3d("+e+"px, 0px, 0px)":o[s.animType]="translate3d(0px,"+e+"px, 0px)",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this.getNavTarget();null!==t&&"object"==typeof t&&t.each(function(){var t=i(this).slick("getSlick");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};!1===e.options.fade?t[e.transitionType]=e.transformType+" "+e.options.speed+"ms "+e.options.cssEase:t[e.transitionType]="opacity "+e.options.speed+"ms "+e.options.cssEase,!1===e.options.fade?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(!1===i.options.infinite&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1==0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;!0===e.options.arrows&&(e.$prevArrow=i(e.options.prevArrow).addClass("slick-arrow"),e.$nextArrow=i(e.options.nextArrow).addClass("slick-arrow"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),e.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),!0!==e.options.infinite&&e.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):e.$prevArrow.add(e.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},e.prototype.buildDots=function(){var e,t,o=this;if(!0===o.options.dots){for(o.$slider.addClass("slick-dotted"),t=i("<ul />").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i("<li />").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find("li").first().addClass("slick-active")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+":not(.slick-cloned)").addClass("slick-slide"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr("data-slick-index",e).data("originalStyling",i(t).attr("style")||"")}),e.$slider.addClass("slick-slider"),e.$slideTrack=0===e.slideCount?i('<div class="slick-track"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class="slick-track"/>').parent(),e.$list=e.$slideTrack.wrap('<div class="slick-list"/>').parent(),e.$slideTrack.css("opacity",0),!0!==e.options.centerMode&&!0!==e.options.swipeToSlide||(e.options.slidesToScroll=1),i("img[data-lazy]",e.$slider).not("[src]").addClass("slick-loading"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses("number"==typeof e.currentSlide?e.currentSlide:0),!0===e.options.draggable&&e.$list.addClass("draggable")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.o
vendor: 3,442 bytes, line 8284
8284ptions.rows>1){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement("div");for(e=0;e<l.options.rows;e++){var a=document.createElement("div");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+"%",display:"inline-block"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if("window"===r.respondTo?n=a:"slider"===r.respondTo?n=d:"min"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(!1===r.originalSettings.mobileFirst?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,"unslick"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,"unslick"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||!1===l||r.$slider.trigger("breakpoint",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is("a")&&e.preventDefault(),l.is("li")||(l=l.closest("li")),n=r.slideCount%r.options.slidesToScroll!=0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case"previous":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case"next":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case"index":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger("focus");break;default:return}},e.prototype.checkNavigable=function(i){var e,t;if(e=this.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var o in e){if(i<e[o]){i=t;break}t=e[o]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i("li",e.$dots).off("click.slick",e.changeSlide).off("mouseenter.slick",i.proxy(e.interrupt,e,!0)).off("mouseleave.slick",i.proxy(e.interrupt,e,!1)),!0===e.options.accessibility&&e.$dots.off("keydown.slick",e.keyHandler)),e.$slider.off("focus.slick blur.slick"),!0===e.options.arrows&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off("click.slick",e.changeSlide),e.$nextArrow&&e.$nextArrow.off("click.slick",e.changeSlide),!0===e.options.accessibility&&(e.$prevArrow&&e.$prevArrow.off("keydown.slick",e.keyHandler),e.$nextArrow&&e.$nextArrow.off("keydown.slick",e.keyHandler))),e.$list.off("touchstart.slick mousedown.slick",e.swipeHandler),e.$list.off("touchmove.slick mousemove.slick",e.swipeHandler),e.$list.off("touchend.slick mouseup.slick",e.swipeHandler),e.$list.off("touchcancel.slick mouseleave.
8284slick",e.swipeHandler),e.$list.off("click.slick",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),!0===e.options.accessibility&&e.$list.off("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().off("click.slick",e.selectHandler),i(window).off("orientationchange.slick.slick-"+e.instanceUid,e.orientationChange),i(window).off("resize.slick.slick-"+e.instanceUid,e.resize),i("[draggable!=true]",e.$slideTrack).off("dragstart",e.preventDefault),i(window).off("load.slick.slick-"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off("mouseenter.slick",i.proxy(e.interrupt,e,!0)),e.$list.off("mouseleave.slick",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>1&&((i=e.$slides.children().children()).removeAttr("style"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){!1===this.shouldClick&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(".slick-cloned",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){i(this).attr("style",i(this).data("originalStyling"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass("slick-slider"),t.$slider.removeClass("slick-initialized"),t.$slider.removeClass("slick-dotted"),t.unslicked=!0,e||t.$slider.trigger("destroy",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]="",!1===e.options.fade?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;!1===t.cssTransitions?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;!1===e.cssTransitions?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off("focus.slick blur.slick").on("focus.slick blur.slick","*",function(t){t.stopImmediatePropagation();var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&(e.focussed=o.is(":focus"),e.autoPlay())},0)})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){return this.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(!0===i.options.infinite)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(!0===i.options.centerMode)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),!0===n.options.infinite?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,!0===n.options.vertical&&!0===n.options.centerMode&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!=0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),!0===n.options.centerMode&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:!0===n.options.centerMode&&!0===n.options.infinite?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:!0===n.options.centerMode&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=!1===n.options.vertical?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,!0===n.options.variableWidth&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,!0===n.options.centerMode&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow+1),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){return this.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(!1===e.options.infinite?i=e.slideCount:(t=-1*e.options.slidesToScroll,o=-1*e.options.slidesToScroll,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o=this;return t=!0===o.options.centerMode?o.slideWidth*Math.floor(o.options.slidesToShow/2):0,!0===o.options.swipeToSlide?(o.$slideTrack.find(".slick-slide").each(function(s,n){if(n.offsetLeft-t+i(n).outerWidth()/2>-1*o.swipeLeft)return e=n,!1}),Math.abs(i(e).attr("data-slick-index")-o.currentSlide)||1):o.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){this.changeSlide({data:{message:"index",index:
8284parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass("slick-initialized")||(i(t.$slider).addClass("slick-initialized"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger("init",[t]),!0===t.options.accessibility&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(".slick-cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(".slick-cloned")).each(function(t){var s=o.indexOf(t);i(this).attr({role:"tabpanel",id:"slick-slide"+e.instanceUid+t,tabindex:-1}),-1!==s&&i(this).attr({"aria-describedby":"slick-slide-control"+e.instanceUid+s})}),e.$dots.attr("role","tablist").find("li").each(function(s){var n=o[s];i(this).attr({role:"presentation"}),i(this).find("button").first().attr({role:"tab",id:"slick-slide-control"+e.instanceUid+s,"aria-controls":"slick-slide"+e.instanceUid+n,"aria-label":s+1+" of "+t,"aria-selected":null,tabindex:"-1"})}).eq(e.currentSlide).find("button").attr({"aria-selected":"true",tabindex:"0"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.$slides.eq(s).attr("tabindex",0);e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off("click.slick").on("click.slick",{message:"previous"},i.changeSlide),i.$nextArrow.off("click.slick").on("click.slick",{message:"next"},i.changeSlide),!0===i.options.accessibility&&(i.$prevArrow.on("keydown.slick",i.keyHandler),i.$nextArrow.on("keydown.slick",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;!0===e.options.dots&&(i("li",e.$dots).on("click.slick",{message:"index"},e.changeSlide),!0===e.options.accessibility&&e.$dots.on("keydown.slick",e.keyHandler)),!0===e.options.dots&&!0===e.options.pauseOnDotsHover&&i("li",e.$dots).on("mouseenter.slick",i.proxy(e.interrupt,e,!0)).on("mouseleave.slick",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on("mouseenter.slick",i.proxy(e.interrupt,e,!0)),e.$list.on("mouseleave.slick",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on("touchstart.slick mousedown.slick",{action:"start"},e.swipeHandler),e.$list.on("touchmove.slick mousemove.slick",{action:"move"},e.swipeHandler),e.$list.on("touchend.slick mouseup.slick",{action:"end"}
8284,e.swipeHandler),e.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},e.swipeHandler),e.$list.on("click.slick",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),!0===e.options.accessibility&&e.$list.on("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().on("click.slick",e.selectHandler),i(window).on("orientationchange.slick.slick-"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on("resize.slick.slick-"+e.instanceUid,i.proxy(e.resize,e)),i("[draggable!=true]",e.$slideTrack).on("dragstart",e.preventDefault),i(window).on("load.slick.slick-"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),!0===i.options.dots&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===i.keyCode&&!0===e.options.accessibility?e.changeSlide({data:{message:!0===e.options.rtl?"next":"previous"}}):39===i.keyCode&&!0===e.options.accessibility&&e.changeSlide({data:{message:!0===e.options.rtl?"previous":"next"}}))},e.prototype.lazyLoad=function(){function e(e){i("img[data-lazy]",e).each(function(){var e=i(this),t=i(this).attr("data-lazy"),o=i(this).attr("data-srcset"),s=i(this).attr("data-sizes")||n.$slider.attr("data-sizes"),r=document.createElement("img");r.onload=function(){e.animate({opacity:0}
vendor: 5,619 bytes, line 8284
8284,100,function(){o&&(e.attr("srcset",o),s&&e.attr("sizes",s)),e.attr("src",t).animate({opacity:1},200,function(){e.removeAttr("data-lazy data-srcset data-sizes").removeClass("slick-loading")}),n.$slider.trigger("lazyLoaded",[n,e,t])})},r.onerror=function(){e.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),n.$slider.trigger("lazyLoadError",[n,e,t])},r.src=t})}var t,o,s,n=this;if(!0===n.options.centerMode?!0===n.options.infinite?s=(o=n.currentSlide+(n.options.slidesToShow/2+1))+n.options.slidesToShow+2:(o=Math.max(0,n.currentSlide-(n.options.slidesToShow/2+1)),s=n.options.slidesToShow/2+1+2+n.currentSlide):(o=n.options.infinite?n.options.slidesToShow+n.currentSlide:n.currentSlide,s=Math.ceil(o+n.options.slidesToShow),!0===n.options.fade&&(o>0&&o--,s<=n.slideCount&&s++)),t=n.$slider.find(".slick-slide").slice(o,s),"anticipated"===n.options.lazyLoad)for(var r=o-1,l=s,d=n.$slider.find(".slick-slide"),a=0;a<n.options.slidesToScroll;a++)r<0&&(r=n.slideCount-1),t=(t=t.add(d.eq(r))).add(d.eq(l)),r--,l++;e(t),n.slideCount<=n.options.slidesToShow?e(n.$slider.find(".slick-slide")):n.currentSlide>=n.slideCount-n.options.slidesToShow?e(n.$slider.find(".slick-cloned").slice(0,n.options.slidesToShow)):0===n.currentSlide&&e(n.$slider.find(".slick-cloned").slice(-1*n.options.slidesToShow))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass("slick-loading"),i.initUI(),"progressive"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){this.changeSlide({data:{message:"next"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;t.unslicked||(t.$slider.trigger("afterChange",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),!0===t.options.accessibility&&(t.initADA(),t.options.focusOnChange&&i(t.$slides.get(t.currentSlide)).attr("tabindex",0).focus()))},e.prototype.prev=e.prototype.slickPrev=function(){this.changeSlide({data:{message:"previous"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i("img[data-lazy]",l.$slider);d.length?(t=d.first(),o=t.attr("data-lazy"),s=t.attr("data-srcset"),n=t.attr("data-sizes")||l.$slider.attr("data-sizes"),(r=document.createElement("img")).onload=function(){s&&(t.attr("srcset",s),n&&t.attr("sizes",n)),t.attr("src",o).removeAttr("data-lazy data-srcset data-sizes").removeClass("slick-loading"),!0===l.options.adaptiveHeight&&l.setPosition(),l.$slider.trigger("lazyLoaded",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),l.$slider.trigger("lazyLoadError",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger("allImagesLoaded",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:"index",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if("array"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||"window";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass("slick-slide"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().on("click.slick",e.selectHandler),e.setSlideClasses("number"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger("reInit",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;if(i="boolean"==typeof i?!0===(e=i)?0:o.slideCount-1:!0===e?--i:i,o.slideCount<1||i<0||i>o.slideCount-1)return!1;o.unload(),!0===t?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,o.reinit()},e.prototype.setCSS=function(i){var e,t,o=this,s={};
8284!0===o.options.rtl&&(i=-i),e="left"==o.positionProp?Math.ceil(i)+"px":"0px",t="top"==o.positionProp?Math.ceil(i)+"px":"0px",s[o.positionProp]=i,!1===o.transformsEnabled?o.$slideTrack.css(s):(s={},!1===o.cssTransitions?(s[o.animType]="translate("+e+", "+t+")",o.$slideTrack.css(s)):(s[o.animType]="translate3d("+e+", "+t+", 0px)",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;!1===i.options.vertical?!0===i.options.centerMode&&i.$list.css({padding:"0px "+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),!0===i.options.centerMode&&i.$list.css({padding:i.options.centerPadding+" 0px"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),!1===i.options.vertical&&!1===i.options.variableWidth?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(".slick-slide").length))):!0===i.options.variableWidth?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(".slick-slide").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();!1===i.options.variableWidth&&i.$slideTrack.children(".slick-slide").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,!0===t.options.rtl?i(s).css({position:"relative",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}
8284):i(s).css({position:"relative",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css("height",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if("object"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n="multiple"):"string"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],"responsive"===arguments[0]&&"array"===i.type(arguments[1])?n="responsive":void 0!==arguments[1]&&(n="single")),"single"===n)r.options[o]=s;else if("multiple"===n)i.each(o,function(i,e){r.options[i]=e});else if("responsive"===n)for(t in s)if("array"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),!1===i.options.fade?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger("setPosition",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=!0===i.options.vertical?"top":"left","top"===i.positionProp?i.$slider.addClass("slick-vertical"):i.$slider.removeClass("slick-vertical"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||!0===i.options.useCSS&&(i.cssTransitions=!0),i.options.fade&&("number"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType="OTransform",i.transformType="-o-transform",i.transitionType="OTransition",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType="MozTransform",i.transformType="-moz-transform",i.transitionType="MozTransition",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType="webkitTransform",i.transformType="-webkit-transform",i.transitionType="webkitTransition",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType="msTransform",i.transformType="-ms-transform",i.transitionType="msTransition",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&!1!==i.animType&&(i.animType="transform",i.transformType="transform",i.transitionType="transition"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&!1!==i.animType},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),n.$slides.eq(i).addClass("slick-current"),!0===n.options.centerMode){var r=n.options.slidesToShow%2==0?1:0;e=Math.floor(n.options.slidesToShow/2),!0===n.options.infinite&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass("slick-active").attr("aria-hidden","false"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass("slick-active").attr("aria-hidden","false")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass("slick-center"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass("slick-center")),n.$slides.eq(i).addClass("slick-center")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):t.length<=n.options.slidesToShow?t.addClass("slick-active").attr("aria-hidden","false"):(s=n.slideCount%n.options.slidesToShow,o=!0===n.options.infinite?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass("slick-active").attr("aria-hidden","false"):t.slice(o,o+n.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"));"ondemand"!==n.options.lazyLoad&&"anticipated"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(!0===s.options.fade&&(s.options.centerMode=!1),!0===s.options.infinite&&!1===s.options.fade&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=!0===s.options.centerMode?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr("id","").attr("data-slick-index",t-s.slideCount).prependTo(s.$slideTrack).addClass("slick-cloned");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr("id","").attr("data-slick-index",t+s.slideCount).appendTo(s.$slideTrack).addClass("slick-cloned");s.$slideTrack.find(".slick-cloned").find("[id]").each(function(){i(this).attr("id","")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(".slick-slide")?i(e.target):i(e.target).parents(".slick-slide"),s=parseInt(o.attr("data-slick-index"));s||(s=0),t.slideCount<=t.options.slidesToShow?t.slideHandler(s,!1,!0):t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(!0===a.animating&&!0===a.options.waitForAnimate||!0===a.options.fade&&a.currentSlide===i))if(!1===e&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,!1===a.options.infinite&&!1===a.options.centerMode&&(i<0||i>a.getDotCount()*a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else if(!1===a.options.infinite&&!0===a.options.centerMode&&(i<0||i>a.slideCount-a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else{if(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!=0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+
8284o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!=0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger("beforeChange",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=(l=a.getNavTarget()).slick("getSlick")).slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide),a.updateDots(),a.updateArrows(),!0===a.options.fade)return!0!==t?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight();!0!==t?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)}},e.prototype.startLoad=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),!0===i.options.dots&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass("slick-loading")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),(o=Math.round(180*t/Math.PI))<0&&(o=360-Math.abs(o)),o<=45&&o>=0?!1===s.options.rtl?"left":"right":o<=360&&o>=315?!1===s.options.rtl?"left":"right":o>=135&&o<=225?!1===s.options.rtl?"right":"left":!0===s.options.verticalSwiping?o>=35&&o<=135?"down":"up":"vertical"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(!0===o.touchObject.edgeHit&&o.$slider.trigger("edge",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case"left":case"down":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case"right":case"up":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}"vertical"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger("swipe",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(!1===e.options.swipe||"ontouchend"in document&&!1===e.options.swipe||!1===e.options.draggable&&-1!==i.type.indexOf("mouse")))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,!0===e.options.verticalSwiping&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case"start":e.swipeStart(i);break;case"move":e.swipeMove(i);break;case"end":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(!0===l.options.verticalSwiping&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(!1===l.options.rtl?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),!0===l.options.verticalSwiping&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,!1===l.options.infinite&&(0===l.currentSlide&&"right"===t||l.currentSlide>=l.getDotCount()&&"left"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),!1===l.options.vertical?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,!0===l.options.verticalSwiping&&(l.swipeLeft=e+o*s),!0!==l.options.fade&&!1!==l.options.touchMove&&(!0===l.animating?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;if(t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow)return t.touchObject={},!1;void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,t.dragging=!0},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(".slick-cloned",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")}
8284,e.prototype.unslick=function(i){var e=this;e.$slider.trigger("unslick",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i=this;Math.floor(i.options.slidesToShow/2),!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&!i.options.infinite&&(i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===i.currentSlide?(i.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-i.options.slidesToShow&&!1===i.options.centerMode?(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-1&&!0===i.options.centerMode&&(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find("li").removeClass("slick-active").end(),i.$dots.find("li").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass("slick-active"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if("object"==typeof s||void 0===s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),void 0!==t)return t;return o}}); 8285 8286$().ready(function() { 8287 8288 $('#comments').on("click", ".ev-comment-reply, .ev-comment-edit", function() { 8289 var cmtempl = $('.cm_template_form').clone(); 8290 cmtempl.show(); 8291 var parent_cm_id = $(this).closest('.ArticleComment_item').find('.comments-anchor').attr('data-cmid'); 8292 var parent_level = $(this).closest('.ArticleComment_item').attr('data-level'); 8293 cmtempl.find('.cm_parent_id').val(parent_cm_id); 8294 cmtempl.find('.parent_level').val(parent_level); 8295 $(this).after(cmtempl); 8296 console.log(cmtempl); 8297 cmtempl.find("textarea").focus(); 8298 if ($(this).hasClass('ev-comment-edit')) { 8299 var $cm_content = $(this).closest('.ArticleComment_block').find(".ArticleComment_content p"); 8300 cmtempl.find("textarea").val($cm_content.text()); 8301 $cm_content.hide(); 8302 cmtempl.find('.button-cm-send').val('Änderungen absenden'); 8303 } 8304 $(".ev-comment-reply, .ev-comment-edit").hide(); 8305 }); 8306 8307 8308 $('#comments').on("click", ".button-cm-cancel", function() { 8309 if (confirm("Wollen Sie die Eingabe wirklich abbrechen?")) { 8310 $(".ev-comment-reply, .ev-comment-edit, .ArticleComment_content p").show(); 8311 $(this).closest('section').remove(); 8312 } 8313 return false; 8314 }); 8315 8316 // -- Kommentar per Ajax 8317 $('#comments').on('click', '.button-cm-send', function() { 8318 var settings = { 8319 ajaxUrl : "/comments/ajax-comments.php", 8320 } 8321 var cmtempl = $(this).closest('section'); 8322 var $li_closest = $(this).closest('.ArticleComment_item'); 8323 var $cm_content = $(this).closest('.ArticleComment_item') 8324 .children('.ArticleComment_block') 8325 .find(".ArticleComment_content p"); 8326 $.ajax({ 8327 type: "POST", 8328 async: true, 8329 url: settings.ajaxUrl, 8330 dataType: 'json', 8331 data: $(this).closest('form').serialize() + "&OK=1" 8332 }).done(function(data) { 8333 if (data['mode'] == 'edit') { 8334 $cm_content.text(cmtempl.find("textarea").val()); 8335 $cm_content.show(); 8336 } else { 8337 $li_closest.children('.ArticleComment_children').append(data['listtext']); 8338 } 8339 $(".ev-comment-reply, .ev-comment-edit").show(); 8340 cmtempl.remove(); 8341 }).fail(function() { 8342 alert('Ihre Eingabe konnte nicht gespeichert werden.'); 8343 }); 8344 return false; 8345 }); 8346 8347}); 8348 8349 8350/** 8351 * Swiper 12.0.3 8352 * Most modern mobile touch slider and framework with hardware accelerated transitions 8353 * https://swiperjs.com 8354 * 8355 * Copyright 2014-2025 Vladimir Kharlampidi 8356 * 8357 * Released under the MIT License 8358 * 8359 * Released on: October 21, 2025 8360 */ 8361 8362var Swiper = (function () { 8363 'use strict'; 8364 8365 /** 8366 * SSR Window 5.0.1 8367 * Better handling for window object in SSR environment 8368 * https://github.com/nolimits4web/ssr-window 8369 * 8370 * Copyright 2025, Vladimir Kharlampidi 8371 * 8372 * Licensed under MIT 8373 * 8374 * Released on: June 27, 2025 8375 */ 8376 /* eslint-disable no-param-reassign */ 8377 function isObject$1(obj) { 8378 return obj !== null && typeof obj === 'object' && 'constructor' in obj && obj.constructor === Object; 8379 } 8380 function extend$1(target = {}, src = {}) { 8381 const noExtend = ['__proto__', 'constructor', 'prototype'];
vendor: 5,054 bytes, lines 8382-8580
8382 Object.keys(src).filter(key => noExtend.indexOf(key) < 0).forEach(key => { 8383 if (typeof target[key] === 'undefined') target[key] = src[key];else if (isObject$1(src[key]) && isObject$1(target[key]) && Object.keys(src[key]).length > 0) { 8384 extend$1(target[key], src[key]); 8385 } 8386 }); 8387 } 8388 const ssrDocument = { 8389 body: {}, 8390 addEventListener() {}, 8391 removeEventListener() {}, 8392 activeElement: { 8393 blur() {}, 8394 nodeName: '' 8395 }, 8396 querySelector() { 8397 return null; 8398 }, 8399 querySelectorAll() { 8400 return []; 8401 }, 8402 getElementById() { 8403 return null; 8404 }, 8405 createEvent() { 8406 return { 8407 initEvent() {} 8408 }; 8409 }, 8410 createElement() { 8411 return { 8412 children: [], 8413 childNodes: [], 8414 style: {}, 8415 setAttribute() {}, 8416 getElementsByTagName() { 8417 return []; 8418 } 8419 }; 8420 }, 8421 createElementNS() { 8422 return {}; 8423 }, 8424 importNode() { 8425 return null; 8426 }, 8427 location: { 8428 hash: '', 8429 host: '', 8430 hostname: '', 8431 href: '', 8432 origin: '', 8433 pathname: '', 8434 protocol: '', 8435 search: '' 8436 } 8437 }; 8438 function getDocument() { 8439 const doc = typeof document !== 'undefined' ? document : {}; 8440 extend$1(doc, ssrDocument); 8441 return doc; 8442 } 8443 const ssrWindow = { 8444 document: ssrDocument, 8445 navigator: { 8446 userAgent: '' 8447 }, 8448 location: { 8449 hash: '', 8450 host: '', 8451 hostname: '', 8452 href: '', 8453 origin: '', 8454 pathname: '', 8455 protocol: '', 8456 search: '' 8457 }, 8458 history: { 8459 replaceState() {}, 8460 pushState() {}, 8461 go() {}, 8462 back() {} 8463 }, 8464 CustomEvent: function CustomEvent() { 8465 return this; 8466 }, 8467 addEventListener() {}, 8468 removeEventListener() {}, 8469 getComputedStyle() { 8470 return { 8471 getPropertyValue() { 8472 return ''; 8473 } 8474 }; 8475 }, 8476 Image() {}, 8477 Date() {}, 8478 screen: {}, 8479 setTimeout() {}, 8480 clearTimeout() {}, 8481 matchMedia() { 8482 return {}; 8483 }, 8484 requestAnimationFrame(callback) { 8485 if (typeof setTimeout === 'undefined') { 8486 callback(); 8487 return null; 8488 } 8489 return setTimeout(callback, 0); 8490 }, 8491 cancelAnimationFrame(id) { 8492 if (typeof setTimeout === 'undefined') { 8493 return; 8494 } 8495 clearTimeout(id); 8496 } 8497 }; 8498 function getWindow() { 8499 const win = typeof window !== 'undefined' ? window : {}; 8500 extend$1(win, ssrWindow); 8501 return win; 8502 } 8503 8504 function classesToTokens(classes = '') { 8505 return classes.trim().split(' ').filter(c => !!c.trim()); 8506 } 8507 8508 function deleteProps(obj) { 8509 const object = obj; 8510 Object.keys(object).forEach(key => { 8511 try { 8512 object[key] = null; 8513 } catch (e) { 8514 // no getter for object 8515 } 8516 try { 8517 delete object[key]; 8518 } catch (e) { 8519 // something got wrong 8520 } 8521 }); 8522 } 8523 function nextTick(callback, delay = 0) { 8524 return setTimeout(callback, delay); 8525 } 8526 function now() { 8527 return Date.now(); 8528 } 8529 function getComputedStyle$1(el) { 8530 const window = getWindow(); 8531 let style; 8532 if (window.getComputedStyle) { 8533 style = window.getComputedStyle(el, null); 8534 } 8535 if (!style && el.currentStyle) { 8536 style = el.currentStyle; 8537 } 8538 if (!style) { 8539 style = el.style; 8540 } 8541 return style; 8542 } 8543 function getTranslate(el, axis = 'x') { 8544 const window = getWindow(); 8545 let matrix; 8546 let curTransform; 8547 let transformMatrix; 8548 const curStyle = getComputedStyle$1(el); 8549 if (window.WebKitCSSMatrix) { 8550 curTransform = curStyle.transform || curStyle.webkitTransform; 8551 if (curTransform.split(',').length > 6) { 8552 curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', '); 8553 } 8554 // Some old versions of Webkit choke when 'none' is passed; pass 8555 // empty string instead in this case 8556 transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform); 8557 } else { 8558 transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,'); 8559 matrix = transformMatrix.toString().split(','); 8560 } 8561 if (axis === 'x') { 8562 // Latest Chrome and webkits Fix 8563 if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41; 8564 // Crazy IE10 Matrix 8565 else if (matrix.length === 16) curTransform = parseFloat(matrix[12]); 8566 // Normal Browsers 8567 else curTransform = parseFloat(matrix[4]); 8568 } 8569 if (axis === 'y') { 8570 // Latest Chrome and webkits Fix 8571 if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42; 8572 // Crazy IE10 Matrix 8573 else if (matrix.length === 16) curTransform = parseFloat(matrix[13]); 8574 // Normal Browsers 8575 else curTransform = parseFloat(matrix[5]); 8576 } 8577 return curTransform || 0; 8578 } 8579 function isObject(o) { 8580 return typeof o === 'object' && o !== null && o.constructor && Ob
vendor: 9,136 bytes, lines 8580-8844
8580ject.prototype.toString.call(o).slice(8, -1) === 'Object'; 8581 } 8582 function isNode(node) { 8583 // eslint-disable-next-line 8584 if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') { 8585 return node instanceof HTMLElement; 8586 } 8587 return node && (node.nodeType === 1 || node.nodeType === 11); 8588 } 8589 function extend(...args) { 8590 const to = Object(args[0]); 8591 const noExtend = ['__proto__', 'constructor', 'prototype']; 8592 for (let i = 1; i < args.length; i += 1) { 8593 const nextSource = args[i]; 8594 if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) { 8595 const keysArray = Object.keys(Object(nextSource)).filter(key => noExtend.indexOf(key) < 0); 8596 for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) { 8597 const nextKey = keysArray[nextIndex]; 8598 const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); 8599 if (desc !== undefined && desc.enumerable) { 8600 if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) { 8601 if (nextSource[nextKey].__swiper__) { 8602 to[nextKey] = nextSource[nextKey]; 8603 } else { 8604 extend(to[nextKey], nextSource[nextKey]); 8605 } 8606 } else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) { 8607 to[nextKey] = {}; 8608 if (nextSource[nextKey].__swiper__) { 8609 to[nextKey] = nextSource[nextKey]; 8610 } else { 8611 extend(to[nextKey], nextSource[nextKey]); 8612 } 8613 } else { 8614 to[nextKey] = nextSource[nextKey]; 8615 } 8616 } 8617 } 8618 } 8619 } 8620 return to; 8621 } 8622 function setCSSProperty(el, varName, varValue) { 8623 el.style.setProperty(varName, varValue); 8624 } 8625 function animateCSSModeScroll({ 8626 swiper, 8627 targetPosition, 8628 side 8629 }) { 8630 const window = getWindow(); 8631 const startPosition = -swiper.translate; 8632 let startTime = null; 8633 let time; 8634 const duration = swiper.params.speed; 8635 swiper.wrapperEl.style.scrollSnapType = 'none'; 8636 window.cancelAnimationFrame(swiper.cssModeFrameID); 8637 const dir = targetPosition > startPosition ? 'next' : 'prev'; 8638 const isOutOfBound = (current, target) => { 8639 return dir === 'next' && current >= target || dir === 'prev' && current <= target; 8640 }; 8641 const animate = () => { 8642 time = new Date().getTime(); 8643 if (startTime === null) { 8644 startTime = time; 8645 } 8646 const progress = Math.max(Math.min((time - startTime) / duration, 1), 0); 8647 const easeProgress = 0.5 - Math.cos(progress * Math.PI) / 2; 8648 let currentPosition = startPosition + easeProgress * (targetPosition - startPosition); 8649 if (isOutOfBound(currentPosition, targetPosition)) { 8650 currentPosition = targetPosition; 8651 } 8652 swiper.wrapperEl.scrollTo({ 8653 [side]: currentPosition 8654 }); 8655 if (isOutOfBound(currentPosition, targetPosition)) { 8656 swiper.wrapperEl.style.overflow = 'hidden'; 8657 swiper.wrapperEl.style.scrollSnapType = ''; 8658 setTimeout(() => { 8659 swiper.wrapperEl.style.overflow = ''; 8660 swiper.wrapperEl.scrollTo({ 8661 [side]: currentPosition 8662 }); 8663 }); 8664 window.cancelAnimationFrame(swiper.cssModeFrameID); 8665 return; 8666 } 8667 swiper.cssModeFrameID = window.requestAnimationFrame(animate); 8668 }; 8669 animate(); 8670 } 8671 function getSlideTransformEl(slideEl) { 8672 return slideEl.querySelector('.swiper-slide-transform') || slideEl.shadowRoot && slideEl.shadowRoot.querySelector('.swiper-slide-transform') || slideEl; 8673 } 8674 function elementChildren(element, selector = '') { 8675 const window = getWindow(); 8676 const children = [...element.children]; 8677 if (window.HTMLSlotElement && element instanceof HTMLSlotElement) { 8678 children.push(...element.assignedElements()); 8679 } 8680 if (!selector) { 8681 return children; 8682 } 8683 return children.filter(el => el.matches(selector)); 8684 } 8685 function elementIsChildOfSlot(el, slot) { 8686 // Breadth-first search through all parent's children and assigned elements 8687 const elementsQueue = [slot]; 8688 while (elementsQueue.length > 0) { 8689 const elementToCheck = elementsQueue.shift(); 8690 if (el === elementToCheck) { 8691 return true; 8692 } 8693 elementsQueue.push(...elementToCheck.children, ...(elementToCheck.shadowRoot ? elementToCheck.shadowRoot.children : []), ...(elementToCheck.assignedElements ? elementToCheck.assignedElements() : [])); 8694 } 8695 } 8696 function elementIsChildOf(el, parent) { 8697 const window = getWindow(); 8698 let isChild = parent.contains(el); 8699 if (!isChild && window.HTMLSlotElement && parent instanceof HTMLSlotElement) { 8700 const children = [...parent.assignedElements()]; 8701 isChild = children.includes(el); 8702 if (!isChild) { 8703 isChild = elementIsChildOfSlot(el, parent); 8704 } 8705 } 8706 return isChild; 8707 } 8708 function showWarning(text) { 8709 try { 8710 console.warn(text); 8711 return; 8712 } catch (err) { 8713 // err 8714 } 8715 } 8716 function createElement(tag, classes = []) { 8717 const el = document.createElement(tag); 8718 el.classList.add(...(Array.isArray(classes) ? classes : classesToTokens(classes))); 8719 return el; 8720 } 8721 function elementOffset(el) { 8722 const window = getWindow(); 8723 const document = getDocument(); 8724 const box = el.getBoundingClientRect(); 8725 const body = document.body; 8726 const clientTop = el.clientTop || body.clientTop || 0; 8727 const clientLeft = el.clientLeft || body.clientLeft || 0; 8728 const scrollTop = el === window ? window.scrollY : el.scrollTop; 8729 const scrollLeft = el === window ? window.scrollX : el.scrollLeft; 8730 return { 8731 top: box.top + scrollTop - clientTop, 8732 left: box.left + scrollLeft - clientLeft 8733 }; 8734 } 8735 function elementPrevAll(el, selector) { 8736 const prevEls = []; 8737 while (el.previousElementSibling) { 8738 const prev = el.previousElementSibling; // eslint-disable-line 8739 if (selector) { 8740 if (prev.matches(selector)) prevEls.push(prev); 8741 } else prevEls.push(prev); 8742 el = prev; 8743 } 8744 return prevEls; 8745 } 8746 function elementNextAll(el, selector) { 8747 const nextEls = []; 8748 while (el.nextElementSibling) { 8749 const next = el.nextElementSibling; // eslint-disable-line 8750 if (selector) { 8751 if (next.matches(selector)) nextEls.push(next); 8752 } else nextEls.push(next); 8753 el = next; 8754 } 8755 return nextEls; 8756 } 8757 function elementStyle(el, prop) { 8758 const window = getWindow(); 8759 return window.getComputedStyle(el, null).getPropertyValue(prop); 8760 } 8761 function elementIndex(el) { 8762 let child = el; 8763 let i; 8764 if (child) { 8765 i = 0; 8766 // eslint-disable-next-line 8767 while ((child = child.previousSibling) !== null) { 8768 if (child.nodeType === 1) i += 1; 8769 } 8770 return i; 8771 } 8772 return undefined; 8773 } 8774 function elementParents(el, selector) { 8775 const parents = []; // eslint-disable-line 8776 let parent = el.parentElement; // eslint-disable-line 8777 while (parent) { 8778 if (selector) { 8779 if (parent.matches(selector)) parents.push(parent); 8780 } else { 8781 parents.push(parent); 8782 } 8783 parent = parent.parentElement; 8784 } 8785 return parents; 8786 } 8787 function elementTransitionEnd(el, callback) { 8788 function fireCallBack(e) { 8789 if (e.target !== el) return; 8790 callback.call(el, e); 8791 el.removeEventListener('transitionend', fireCallBack); 8792 } 8793 if (callback) { 8794 el.addEventListener('transitionend', fireCallBack); 8795 } 8796 } 8797 function elementOuterSize(el, size, includeMargins) { 8798 const window = getWindow(); 8799 if (includeMargins) { 8800 return el[size === 'width' ? 'offsetWidth' : 'offsetHeight'] + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-right' : 'margin-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-left' : 'margin-bottom')); 8801 } 8802 return el.offsetWidth; 8803 } 8804 function makeElementsArray(el) { 8805 return (Array.isArray(el) ? el : [el]).filter(e => !!e); 8806 } 8807 function getRotateFix(swiper) { 8808 return v => { 8809 if (Math.abs(v) > 0 && swiper.browser && swiper.browser.need3dFix && Math.abs(v) % 90 === 0) { 8810 return v + 0.001; 8811 } 8812 return v; 8813 }; 8814 } 8815 function setInnerHTML(el, html = '') { 8816 if (typeof trustedTypes !== 'undefined') { 8817 el.innerHTML = trustedTypes.createPolicy('html', { 8818 createHTML: s => s 8819 }).createHTML(html); 8820 } else { 8821 el.innerHTML = html; 8822 } 8823 } 8824 8825 let support; 8826 function calcSupport() { 8827 const window = getWindow(); 8828 const document = getDocument(); 8829 return { 8830 smoothScroll: document.documentElement && document.documentElement.style && 'scrollBehavior' in document.documentElement.style, 8831 touch: !!('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch) 8832 }; 8833 } 8834 function getSupport() { 8835 if (!support) { 8836 support = calcSupport(); 8837 } 8838 return support; 8839 } 8840 8841 let deviceCached; 8842 function calcDevice({ 8843 userAgent 8844 } = {}) {
vendor: 13,243 bytes, lines 8845-9232
8845 const support = getSupport(); 8846 const window = getWindow(); 8847 const platform = window.navigator.platform; 8848 const ua = userAgent || window.navigator.userAgent; 8849 const device = { 8850 ios: false, 8851 android: false 8852 }; 8853 const screenWidth = window.screen.width; 8854 const screenHeight = window.screen.height; 8855 const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line 8856 let ipad = ua.match(/(iPad)(?!\1).*OS\s([\d_]+)/); 8857 const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/); 8858 const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/); 8859 const windows = platform === 'Win32'; 8860 let macos = platform === 'MacIntel'; 8861 8862 // iPadOs 13 fix 8863 const iPadScreens = ['1024x1366', '1366x1024', '834x1194', '1194x834', '834x1112', '1112x834', '768x1024', '1024x768', '820x1180', '1180x820', '810x1080', '1080x810']; 8864 if (!ipad && macos && support.touch && iPadScreens.indexOf(`${screenWidth}x${screenHeight}`) >= 0) { 8865 ipad = ua.match(/(Version)\/([\d.]+)/); 8866 if (!ipad) ipad = [0, 1, '13_0_0']; 8867 macos = false; 8868 } 8869 8870 // Android 8871 if (android && !windows) { 8872 device.os = 'android'; 8873 device.android = true; 8874 } 8875 if (ipad || iphone || ipod) { 8876 device.os = 'ios'; 8877 device.ios = true; 8878 } 8879 8880 // Export object 8881 return device; 8882 } 8883 function getDevice(overrides = {}) { 8884 if (!deviceCached) { 8885 deviceCached = calcDevice(overrides); 8886 } 8887 return deviceCached; 8888 } 8889 8890 let browser; 8891 function calcBrowser() { 8892 const window = getWindow(); 8893 const device = getDevice(); 8894 let needPerspectiveFix = false; 8895 function isSafari() { 8896 const ua = window.navigator.userAgent.toLowerCase(); 8897 return ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0; 8898 } 8899 if (isSafari()) { 8900 const ua = String(window.navigator.userAgent); 8901 if (ua.includes('Version/')) { 8902 const [major, minor] = ua.split('Version/')[1].split(' ')[0].split('.').map(num => Number(num)); 8903 needPerspectiveFix = major < 16 || major === 16 && minor < 2; 8904 } 8905 } 8906 const isWebView = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent); 8907 const isSafariBrowser = isSafari(); 8908 const need3dFix = isSafariBrowser || isWebView && device.ios; 8909 return { 8910 isSafari: needPerspectiveFix || isSafariBrowser, 8911 needPerspectiveFix, 8912 need3dFix, 8913 isWebView 8914 }; 8915 } 8916 function getBrowser() { 8917 if (!browser) { 8918 browser = calcBrowser(); 8919 } 8920 return browser; 8921 } 8922 8923 function Resize({ 8924 swiper, 8925 on, 8926 emit 8927 }) { 8928 const window = getWindow(); 8929 let observer = null; 8930 let animationFrame = null; 8931 const resizeHandler = () => { 8932 if (!swiper || swiper.destroyed || !swiper.initialized) return; 8933 emit('beforeResize'); 8934 emit('resize'); 8935 }; 8936 const createObserver = () => { 8937 if (!swiper || swiper.destroyed || !swiper.initialized) return; 8938 observer = new ResizeObserver(entries => { 8939 animationFrame = window.requestAnimationFrame(() => { 8940 const { 8941 width, 8942 height 8943 } = swiper; 8944 let newWidth = width; 8945 let newHeight = height; 8946 entries.forEach(({ 8947 contentBoxSize, 8948 contentRect, 8949 target 8950 }) => { 8951 if (target && target !== swiper.el) return; 8952 newWidth = contentRect ? contentRect.width : (contentBoxSize[0] || contentBoxSize).inlineSize; 8953 newHeight = contentRect ? contentRect.height : (contentBoxSize[0] || contentBoxSize).blockSize; 8954 }); 8955 if (newWidth !== width || newHeight !== height) { 8956 resizeHandler(); 8957 } 8958 }); 8959 }); 8960 observer.observe(swiper.el); 8961 }; 8962 const removeObserver = () => { 8963 if (animationFrame) { 8964 window.cancelAnimationFrame(animationFrame); 8965 } 8966 if (observer && observer.unobserve && swiper.el) { 8967 observer.unobserve(swiper.el); 8968 observer = null; 8969 } 8970 }; 8971 const orientationChangeHandler = () => { 8972 if (!swiper || swiper.destroyed || !swiper.initialized) return; 8973 emit('orientationchange'); 8974 }; 8975 on('init', () => { 8976 if (swiper.params.resizeObserver && typeof window.ResizeObserver !== 'undefined') { 8977 createObserver(); 8978 return; 8979 } 8980 window.addEventListener('resize', resizeHandler); 8981 window.addEventListener('orientationchange', orientationChangeHandler); 8982 }); 8983 on('destroy', () => { 8984 removeObserver(); 8985 window.removeEventListener('resize', resizeHandler); 8986 window.removeEventListener('orientationchange', orientationChangeHandler); 8987 }); 8988 } 8989 8990 function Observer({ 8991 swiper, 8992 extendParams, 8993 on, 8994 emit 8995 }) { 8996 const observers = []; 8997 const window = getWindow(); 8998 const attach = (target, options = {}) => { 8999 const ObserverFunc = window.MutationObserver || window.WebkitMutationObserver; 9000 const observer = new ObserverFunc(mutations => { 9001 // The observerUpdate event should only be triggered 9002 // once despite the number of mutations. Additional 9003 // triggers are redundant and are very costly 9004 if (swiper.__preventObserver__) return; 9005 if (mutations.length === 1) { 9006 emit('observerUpdate', mutations[0]); 9007 return; 9008 } 9009 const observerUpdate = function observerUpdate() { 9010 emit('observerUpdate', mutations[0]); 9011 }; 9012 if (window.requestAnimationFrame) { 9013 window.requestAnimationFrame(observerUpdate); 9014 } else { 9015 window.setTimeout(observerUpdate, 0); 9016 } 9017 }); 9018 observer.observe(target, { 9019 attributes: typeof options.attributes === 'undefined' ? true : options.attributes, 9020 childList: swiper.isElement || (typeof options.childList === 'undefined' ? true : options).childList, 9021 characterData: typeof options.characterData === 'undefined' ? true : options.characterData 9022 }); 9023 observers.push(observer); 9024 }; 9025 const init = () => { 9026 if (!swiper.params.observer) return; 9027 if (swiper.params.observeParents) { 9028 const containerParents = elementParents(swiper.hostEl); 9029 for (let i = 0; i < containerParents.length; i += 1) { 9030 attach(containerParents[i]); 9031 } 9032 } 9033 // Observe container 9034 attach(swiper.hostEl, { 9035 childList: swiper.params.observeSlideChildren 9036 }); 9037 9038 // Observe wrapper 9039 attach(swiper.wrapperEl, { 9040 attributes: false 9041 }); 9042 }; 9043 const destroy = () => { 9044 observers.forEach(observer => { 9045 observer.disconnect(); 9046 }); 9047 observers.splice(0, observers.length); 9048 }; 9049 extendParams({ 9050 observer: false, 9051 observeParents: false, 9052 observeSlideChildren: false 9053 }); 9054 on('init', init); 9055 on('destroy', destroy); 9056 } 9057 9058 /* eslint-disable no-underscore-dangle */ 9059 9060 var eventsEmitter = { 9061 on(events, handler, priority) { 9062 const self = this; 9063 if (!self.eventsListeners || self.destroyed) return self; 9064 if (typeof handler !== 'function') return self; 9065 const method = priority ? 'unshift' : 'push'; 9066 events.split(' ').forEach(event => { 9067 if (!self.eventsListeners[event]) self.eventsListeners[event] = []; 9068 self.eventsListeners[event][method](handler); 9069 }); 9070 return self; 9071 }, 9072 once(events, handler, priority) { 9073 const self = this; 9074 if (!self.eventsListeners || self.destroyed) return self; 9075 if (typeof handler !== 'function') return self; 9076 function onceHandler(...args) { 9077 self.off(events, onceHandler); 9078 if (onceHandler.__emitterProxy) { 9079 delete onceHandler.__emitterProxy; 9080 } 9081 handler.apply(self, args); 9082 } 9083 onceHandler.__emitterProxy = handler; 9084 return self.on(events, onceHandler, priority); 9085 }, 9086 onAny(handler, priority) { 9087 const self = this; 9088 if (!self.eventsListeners || self.destroyed) return self; 9089 if (typeof handler !== 'function') return self; 9090 const method = priority ? 'unshift' : 'push'; 9091 if (self.eventsAnyListeners.indexOf(handler) < 0) { 9092 self.eventsAnyListeners[method](handler); 9093 } 9094 return self; 9095 }, 9096 offAny(handler) { 9097 const self = this; 9098 if (!self.eventsListeners || self.destroyed) return self; 9099 if (!self.eventsAnyListeners) return self; 9100 const index = self.eventsAnyListeners.indexOf(handler); 9101 if (index >= 0) { 9102 self.eventsAnyListeners.splice(index, 1); 9103 } 9104 return self; 9105 }, 9106 off(events, handler) { 9107 const self = this; 9108 if (!self.eventsListeners || self.destroyed) return self; 9109 if (!self.eventsListeners) return self; 9110 events.split(' ').forEach(event => { 9111 if (typeof handler === 'undefined') { 9112 self.eventsListeners[event] = []; 9113 } else if (self.eventsListeners[event]) { 9114 self.eventsListeners[event].forEach((eventHandler, index) => { 9115 if (eventHandler === handler || eventHandler.__emitterProxy && eventHandler.__emitterProxy === handler) { 9116 self.eventsListeners[event].splice(index, 1); 9117 } 9118 }); 9119 } 9120 }); 9121 return self; 9122 }, 9123 emit(...args) { 9124 const self = this; 9125 if (!self.eventsListeners || self.destroyed) return self; 9126 if (!self.eventsListeners) return self; 9127 let events; 9128 let data; 9129 let context; 9130 if (typeof args[0] === 'string' || Array.isArray(args[0])) { 9131 events = args[0]; 9132 data = args.slice(1, args.length); 9133 context = self; 9134 } else { 9135 events = args[0].events; 9136 data = args[0].data; 9137 context = args[0].context || self; 9138 } 9139 data.unshift(context); 9140 const eventsArray = Array.isArray(events) ? events : events.split(' '); 9141 eventsArray.forEach(event => { 9142 if (self.eventsAnyListeners && self.eventsAnyListeners.length) { 9143 self.eventsAnyListeners.forEach(eventHandler => { 9144 eventHandler.apply(context, [event, ...data]); 9145 }); 9146 } 9147 if (self.eventsListeners && self.eventsListeners[event]) { 9148 self.eventsListeners[event].forEach(eventHandler => { 9149 eventHandler.apply(context, data); 9150 }); 9151 } 9152 }); 9153 return self; 9154 } 9155 }; 9156 9157 function updateSize() { 9158 const swiper = this; 9159 let width; 9160 let height; 9161 const el = swiper.el; 9162 if (typeof swiper.params.width !== 'undefined' && swiper.params.width !== null) { 9163 width = swiper.params.width; 9164 } else { 9165 width = el.clientWidth; 9166 } 9167 if (typeof swiper.params.height !== 'undefined' && swiper.params.height !== null) { 9168 height = swiper.params.height; 9169 } else { 9170 height = el.clientHeight; 9171 } 9172 if (width === 0 && swiper.isHorizontal() || height === 0 && swiper.isVertical()) { 9173 return; 9174 } 9175 9176 // Subtract paddings 9177 width = width - parseInt(elementStyle(el, 'padding-left') || 0, 10) - parseInt(elementStyle(el, 'padding-right') || 0, 10); 9178 height = height - parseInt(elementStyle(el, 'padding-top') || 0, 10) - parseInt(elementStyle(el, 'padding-bottom') || 0, 10); 9179 if (Number.isNaN(width)) width = 0; 9180 if (Number.isNaN(height)) height = 0; 9181 Object.assign(swiper, { 9182 width, 9183 height, 9184 size: swiper.isHorizontal() ? width : height 9185 }); 9186 } 9187 9188 function updateSlides() { 9189 const swiper = this; 9190 function getDirectionPropertyValue(node, label) { 9191 return parseFloat(node.getPropertyValue(swiper.getDirectionLabel(label)) || 0); 9192 } 9193 const params = swiper.params; 9194 const { 9195 wrapperEl, 9196 slidesEl, 9197 rtlTranslate: rtl, 9198 wrongRTL 9199 } = swiper; 9200 const isVirtual = swiper.virtual && params.virtual.enabled; 9201 const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length; 9202 const slides = elementChildren(slidesEl, `.${swiper.params.slideClass}, swiper-slide`); 9203 const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length; 9204 let snapGrid = []; 9205 const slidesGrid = []; 9206 const slidesSizesGrid = []; 9207 let offsetBefore = params.slidesOffsetBefore; 9208 if (typeof offsetBefore === 'function') { 9209 offsetBefore = params.slidesOffsetBefore.call(swiper); 9210 } 9211 let offsetAfter = params.slidesOffsetAfter; 9212 if (typeof offsetAfter === 'function') { 9213 offsetAfter = params.slidesOffsetAfter.call(swiper); 9214 } 9215 const previousSnapGridLength = swiper.snapGrid.length; 9216 const previousSlidesGridLength = swiper.slidesGrid.length; 9217 const swiperSize = swiper.size - offsetBefore - offsetAfter; 9218 let spaceBetween = params.spaceBetween; 9219 let slidePosition = -offsetBefore; 9220 let prevSlideSize = 0; 9221 let index = 0; 9222 if (typeof swiperSize === 'undefined') { 9223 return; 9224 } 9225 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { 9226 spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize; 9227 } else if (typeof spaceBetween === 'string') { 9228 spaceBetween = parseFloat(spaceBetween); 9229 } 9230 swiper.virtualSize = -spaceBetween - offsetBefore - offsetAfter; 9231 9232 // reset margins
vendor: 5,708 bytes, lines 9233-9363
9233 slides.forEach(slideEl => { 9234 if (rtl) { 9235 slideEl.style.marginLeft = ''; 9236 } else { 9237 slideEl.style.marginRight = ''; 9238 } 9239 slideEl.style.marginBottom = ''; 9240 slideEl.style.marginTop = ''; 9241 }); 9242 9243 // reset cssMode offsets 9244 if (params.centeredSlides && params.cssMode) { 9245 setCSSProperty(wrapperEl, '--swiper-centered-offset-before', ''); 9246 setCSSProperty(wrapperEl, '--swiper-centered-offset-after', ''); 9247 } 9248 const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid; 9249 if (gridEnabled) { 9250 swiper.grid.initSlides(slides); 9251 } else if (swiper.grid) { 9252 swiper.grid.unsetSlides(); 9253 } 9254 9255 // Calc slides 9256 let slideSize; 9257 const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => { 9258 return typeof params.breakpoints[key].slidesPerView !== 'undefined'; 9259 }).length > 0; 9260 for (let i = 0; i < slidesLength; i += 1) { 9261 slideSize = 0; 9262 const slide = slides[i]; 9263 if (slide) { 9264 if (gridEnabled) { 9265 swiper.grid.updateSlide(i, slide, slides); 9266 } 9267 if (elementStyle(slide, 'display') === 'none') continue; // eslint-disable-line 9268 } 9269 9270 if (isVirtual && params.slidesPerView === 'auto') { 9271 if (params.virtual.slidesPerViewAutoSlideSize) { 9272 slideSize = params.virtual.slidesPerViewAutoSlideSize; 9273 } 9274 if (slideSize && slide) { 9275 if (params.roundLengths) slideSize = Math.floor(slideSize); 9276 slide.style[swiper.getDirectionLabel('width')] = `${slideSize}px`; 9277 } 9278 } else if (params.slidesPerView === 'auto') { 9279 if (shouldResetSlideSize) { 9280 slide.style[swiper.getDirectionLabel('width')] = ``; 9281 } 9282 const slideStyles = getComputedStyle(slide); 9283 const currentTransform = slide.style.transform; 9284 const currentWebKitTransform = slide.style.webkitTransform; 9285 if (currentTransform) { 9286 slide.style.transform = 'none'; 9287 } 9288 if (currentWebKitTransform) { 9289 slide.style.webkitTransform = 'none'; 9290 } 9291 if (params.roundLengths) { 9292 slideSize = swiper.isHorizontal() ? elementOuterSize(slide, 'width', true) : elementOuterSize(slide, 'height', true); 9293 } else { 9294 // eslint-disable-next-line 9295 const width = getDirectionPropertyValue(slideStyles, 'width'); 9296 const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left'); 9297 const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right'); 9298 const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left'); 9299 const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right'); 9300 const boxSizing = slideStyles.getPropertyValue('box-sizing'); 9301 if (boxSizing && boxSizing === 'border-box') { 9302 slideSize = width + marginLeft + marginRight; 9303 } else { 9304 const { 9305 clientWidth, 9306 offsetWidth 9307 } = slide; 9308 slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth); 9309 } 9310 } 9311 if (currentTransform) { 9312 slide.style.transform = currentTransform; 9313 } 9314 if (currentWebKitTransform) { 9315 slide.style.webkitTransform = currentWebKitTransform; 9316 } 9317 if (params.roundLengths) slideSize = Math.floor(slideSize); 9318 } else { 9319 slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView; 9320 if (params.roundLengths) slideSize = Math.floor(slideSize); 9321 if (slide) { 9322 slide.style[swiper.getDirectionLabel('width')] = `${slideSize}px`; 9323 } 9324 } 9325 if (slide) { 9326 slide.swiperSlideSize = slideSize; 9327 } 9328 slidesSizesGrid.push(slideSize); 9329 if (params.centeredSlides) { 9330 slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween; 9331 if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween; 9332 if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween; 9333 if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0; 9334 if (params.roundLengths) slidePosition = Math.floor(slidePosition); 9335 if (index % params.slidesPerGroup === 0) snapGrid.push(slidePosition); 9336 slidesGrid.push(slidePosition); 9337 } else { 9338 if (params.roundLengths) slidePosition = Math.floor(slidePosition); 9339 if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition); 9340 slidesGrid.push(slidePosition); 9341 slidePosition = slidePosition + slideSize + spaceBetween; 9342 } 9343 swiper.virtualSize += slideSize + spaceBetween; 9344 prevSlideSize = slideSize; 9345 index += 1; 9346 } 9347 swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter; 9348 if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) { 9349 wrapperEl.style.width = `${swiper.virtualSize + spaceBetween}px`; 9350 } 9351 if (params.setWrapperSize) { 9352 wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`; 9353 } 9354 if (gridEnabled) { 9355 swiper.grid.updateWrapperSize(slideSize, snapGrid); 9356 } 9357 9358 // Remove last grid elements depending on width 9359 if (!params.centeredSlides) { 9360 const newSlidesGrid = []; 9361 for (let i = 0; i < snapGrid.length; i += 1) { 9362 let slidesGridItem = snapGrid[i]; 9363 if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
vendor: 1,485 bytes, lines 9364-9399
9364 if (snapGrid[i] <= swiper.virtualSize - swiperSize) { 9365 newSlidesGrid.push(slidesGridItem); 9366 } 9367 } 9368 snapGrid = newSlidesGrid; 9369 if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) { 9370 snapGrid.push(swiper.virtualSize - swiperSize); 9371 } 9372 } 9373 if (isVirtual && params.loop) { 9374 const size = slidesSizesGrid[0] + spaceBetween; 9375 if (params.slidesPerGroup > 1) { 9376 const groups = Math.ceil((swiper.virtual.slidesBefore + swiper.virtual.slidesAfter) / params.slidesPerGroup); 9377 const groupSize = size * params.slidesPerGroup; 9378 for (let i = 0; i < groups; i += 1) { 9379 snapGrid.push(snapGrid[snapGrid.length - 1] + groupSize); 9380 } 9381 } 9382 for (let i = 0; i < swiper.virtual.slidesBefore + swiper.virtual.slidesAfter; i += 1) { 9383 if (params.slidesPerGroup === 1) { 9384 snapGrid.push(snapGrid[snapGrid.length - 1] + size); 9385 } 9386 slidesGrid.push(slidesGrid[slidesGrid.length - 1] + size); 9387 swiper.virtualSize += size; 9388 } 9389 } 9390 if (snapGrid.length === 0) snapGrid = [0]; 9391 if (spaceBetween !== 0) { 9392 const key = swiper.isHorizontal() && rtl ? 'marginLeft' : swiper.getDirectionLabel('marginRight'); 9393 slides.filter((_, slideIndex) => { 9394 if (!params.cssMode || params.loop) return true; 9395 if (slideIndex === slides.length - 1) { 9396 return false; 9397 } 9398 return true; 9399 }
vendor: 65,509 bytes, lines 9399-11145
9399).forEach(slideEl => { 9400 slideEl.style[key] = `${spaceBetween}px`; 9401 }); 9402 } 9403 if (params.centeredSlides && params.centeredSlidesBounds) { 9404 let allSlidesSize = 0; 9405 slidesSizesGrid.forEach(slideSizeValue => { 9406 allSlidesSize += slideSizeValue + (spaceBetween || 0); 9407 }); 9408 allSlidesSize -= spaceBetween; 9409 const maxSnap = allSlidesSize > swiperSize ? allSlidesSize - swiperSize : 0; 9410 snapGrid = snapGrid.map(snap => { 9411 if (snap <= 0) return -offsetBefore; 9412 if (snap > maxSnap) return maxSnap + offsetAfter; 9413 return snap; 9414 }); 9415 } 9416 if (params.centerInsufficientSlides) { 9417 let allSlidesSize = 0; 9418 slidesSizesGrid.forEach(slideSizeValue => { 9419 allSlidesSize += slideSizeValue + (spaceBetween || 0); 9420 }); 9421 allSlidesSize -= spaceBetween; 9422 const offsetSize = (offsetBefore || 0) + (offsetAfter || 0); 9423 if (allSlidesSize + offsetSize < swiperSize) { 9424 const allSlidesOffset = (swiperSize - allSlidesSize - offsetSize) / 2; 9425 snapGrid.forEach((snap, snapIndex) => { 9426 snapGrid[snapIndex] = snap - allSlidesOffset; 9427 }); 9428 slidesGrid.forEach((snap, snapIndex) => { 9429 slidesGrid[snapIndex] = snap + allSlidesOffset; 9430 }); 9431 } 9432 } 9433 Object.assign(swiper, { 9434 slides, 9435 snapGrid, 9436 slidesGrid, 9437 slidesSizesGrid 9438 }); 9439 if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) { 9440 setCSSProperty(wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`); 9441 setCSSProperty(wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`); 9442 const addToSnapGrid = -swiper.snapGrid[0]; 9443 const addToSlidesGrid = -swiper.slidesGrid[0]; 9444 swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid); 9445 swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid); 9446 } 9447 if (slidesLength !== previousSlidesLength) { 9448 swiper.emit('slidesLengthChange'); 9449 } 9450 if (snapGrid.length !== previousSnapGridLength) { 9451 if (swiper.params.watchOverflow) swiper.checkOverflow(); 9452 swiper.emit('snapGridLengthChange'); 9453 } 9454 if (slidesGrid.length !== previousSlidesGridLength) { 9455 swiper.emit('slidesGridLengthChange'); 9456 } 9457 if (params.watchSlidesProgress) { 9458 swiper.updateSlidesOffset(); 9459 } 9460 swiper.emit('slidesUpdated'); 9461 if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) { 9462 const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`; 9463 const hasClassBackfaceClassAdded = swiper.el.classList.contains(backFaceHiddenClass); 9464 if (slidesLength <= params.maxBackfaceHiddenSlides) { 9465 if (!hasClassBackfaceClassAdded) swiper.el.classList.add(backFaceHiddenClass); 9466 } else if (hasClassBackfaceClassAdded) { 9467 swiper.el.classList.remove(backFaceHiddenClass); 9468 } 9469 } 9470 } 9471 9472 function updateAutoHeight(speed) { 9473 const swiper = this; 9474 const activeSlides = []; 9475 const isVirtual = swiper.virtual && swiper.params.virtual.enabled; 9476 let newHeight = 0; 9477 let i; 9478 if (typeof speed === 'number') { 9479 swiper.setTransition(speed); 9480 } else if (speed === true) { 9481 swiper.setTransition(swiper.params.speed); 9482 } 9483 const getSlideByIndex = index => { 9484 if (isVirtual) { 9485 return swiper.slides[swiper.getSlideIndexByData(index)]; 9486 } 9487 return swiper.slides[index]; 9488 }; 9489 // Find slides currently in view 9490 if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) { 9491 if (swiper.params.centeredSlides) { 9492 (swiper.visibleSlides || []).forEach(slide => { 9493 activeSlides.push(slide); 9494 }); 9495 } else { 9496 for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) { 9497 const index = swiper.activeIndex + i; 9498 if (index > swiper.slides.length && !isVirtual) break; 9499 activeSlides.push(getSlideByIndex(index)); 9500 } 9501 } 9502 } else { 9503 activeSlides.push(getSlideByIndex(swiper.activeIndex)); 9504 } 9505 9506 // Find new height from highest slide in view 9507 for (i = 0; i < activeSlides.length; i += 1) { 9508 if (typeof activeSlides[i] !== 'undefined') { 9509 const height = activeSlides[i].offsetHeight; 9510 newHeight = height > newHeight ? height : newHeight; 9511 } 9512 } 9513 9514 // Update Height 9515 if (newHeight || newHeight === 0) swiper.wrapperEl.style.height = `${newHeight}px`; 9516 } 9517 9518 function updateSlidesOffset() { 9519 const swiper = this; 9520 const slides = swiper.slides; 9521 // eslint-disable-next-line 9522 const minusOffset = swiper.isElement ? swiper.isHorizontal() ? swiper.wrapperEl.offsetLeft : swiper.wrapperEl.offsetTop : 0; 9523 for (let i = 0; i < slides.length; i += 1) { 9524 slides[i].swiperSlideOffset = (swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop) - minusOffset - swiper.cssOverflowAdjustment(); 9525 } 9526 } 9527 9528 const toggleSlideClasses$1 = (slideEl, condition, className) => { 9529 if (condition && !slideEl.classList.contains(className)) { 9530 slideEl.classList.add(className); 9531 } else if (!condition && slideEl.classList.contains(className)) { 9532 slideEl.classList.remove(className); 9533 } 9534 }; 9535 function updateSlidesProgress(translate = this && this.translate || 0) { 9536 const swiper = this; 9537 const params = swiper.params; 9538 const { 9539 slides, 9540 rtlTranslate: rtl, 9541 snapGrid 9542 } = swiper; 9543 if (slides.length === 0) return; 9544 if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset(); 9545 let offsetCenter = -translate; 9546 if (rtl) offsetCenter = translate; 9547 swiper.visibleSlidesIndexes = []; 9548 swiper.visibleSlides = []; 9549 let spaceBetween = params.spaceBetween; 9550 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { 9551 spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiper.size; 9552 } else if (typeof spaceBetween === 'string') { 9553 spaceBetween = parseFloat(spaceBetween); 9554 } 9555 for (let i = 0; i < slides.length; i += 1) { 9556 const slide = slides[i]; 9557 let slideOffset = slide.swiperSlideOffset; 9558 if (params.cssMode && params.centeredSlides) { 9559 slideOffset -= slides[0].swiperSlideOffset; 9560 } 9561 const slideProgress = (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + spaceBetween); 9562 const originalSlideProgress = (offsetCenter - snapGrid[0] + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + spaceBetween); 9563 const slideBefore = -(offsetCenter - slideOffset); 9564 const slideAfter = slideBefore + swiper.slidesSizesGrid[i]; 9565 const isFullyVisible = slideBefore >= 0 && slideBefore <= swiper.size - swiper.slidesSizesGrid[i]; 9566 const isVisible = slideBefore >= 0 && slideBefore < swiper.size - 1 || slideAfter > 1 && slideAfter <= swiper.size || slideBefore <= 0 && slideAfter >= swiper.size; 9567 if (isVisible) { 9568 swiper.visibleSlides.push(slide); 9569 swiper.visibleSlidesIndexes.push(i); 9570 } 9571 toggleSlideClasses$1(slide, isVisible, params.slideVisibleClass); 9572 toggleSlideClasses$1(slide, isFullyVisible, params.slideFullyVisibleClass); 9573 slide.progress = rtl ? -slideProgress : slideProgress; 9574 slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress; 9575 } 9576 } 9577 9578 function updateProgress(translate) { 9579 const swiper = this; 9580 if (typeof translate === 'undefined') { 9581 const multiplier = swiper.rtlTranslate ? -1 : 1; 9582 // eslint-disable-next-line 9583 translate = swiper && swiper.translate && swiper.translate * multiplier || 0; 9584 } 9585 const params = swiper.params; 9586 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate(); 9587 let { 9588 progress, 9589 isBeginning, 9590 isEnd, 9591 progressLoop 9592 } = swiper; 9593 const wasBeginning = isBeginning; 9594 const wasEnd = isEnd; 9595 if (translatesDiff === 0) { 9596 progress = 0; 9597 isBeginning = true; 9598 isEnd = true; 9599 } else { 9600 progress = (translate - swiper.minTranslate()) / translatesDiff; 9601 const isBeginningRounded = Math.abs(translate - swiper.minTranslate()) < 1; 9602 const isEndRounded = Math.abs(translate - swiper.maxTranslate()) < 1; 9603 isBeginning = isBeginningRounded || progress <= 0; 9604 isEnd = isEndRounded || progress >= 1; 9605 if (isBeginningRounded) progress = 0; 9606 if (isEndRounded) progress = 1; 9607 } 9608 if (params.loop) { 9609 const firstSlideIndex = swiper.getSlideIndexByData(0); 9610 const lastSlideIndex = swiper.getSlideIndexByData(swiper.slides.length - 1); 9611 const firstSlideTranslate = swiper.slidesGrid[firstSlideIndex]; 9612 const lastSlideTranslate = swiper.slidesGrid[lastSlideIndex]; 9613 const translateMax = swiper.slidesGrid[swiper.slidesGrid.length - 1]; 9614 const translateAbs = Math.abs(translate); 9615 if (translateAbs >= firstSlideTranslate) { 9616 progressLoop = (translateAbs - firstSlideTranslate) / translateMax; 9617 } else { 9618 progressLoop = (translateAbs + translateMax - lastSlideTranslate) / translateMax; 9619 } 9620 if (progressLoop > 1) progressLoop -= 1; 9621 } 9622 Object.assign(swiper, { 9623 progress, 9624 progressLoop, 9625 isBeginning, 9626 isEnd 9627 }); 9628 if (params.watchSlidesProgress || params.centeredSlides && params.autoHeight) swiper.updateSlidesProgress(translate); 9629 if (isBeginning && !wasBeginning) { 9630 swiper.emit('reachBeginning toEdge'); 9631 } 9632 if (isEnd && !wasEnd) { 9633 swiper.emit('reachEnd toEdge'); 9634 } 9635 if (wasBeginning && !isBeginning || wasEnd && !isEnd) { 9636 swiper.emit('fromEdge'); 9637 } 9638 swiper.emit('progress', progress); 9639 } 9640 9641 const toggleSlideClasses = (slideEl, condition, className) => { 9642 if (condition && !slideEl.classList.contains(className)) { 9643 slideEl.classList.add(className); 9644 } else if (!condition && slideEl.classList.contains(className)) { 9645 slideEl.classList.remove(className); 9646 } 9647 }; 9648 function updateSlidesClasses() { 9649 const swiper = this; 9650 const { 9651 slides, 9652 params, 9653 slidesEl, 9654 activeIndex 9655 } = swiper; 9656 const isVirtual = swiper.virtual && params.virtual.enabled; 9657 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 9658 const getFilteredSlide = selector => { 9659 return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0]; 9660 }; 9661 let activeSlide; 9662 let prevSlide; 9663 let nextSlide; 9664 if (isVirtual) { 9665 if (params.loop) { 9666 let slideIndex = activeIndex - swiper.virtual.slidesBefore; 9667 if (slideIndex < 0) slideIndex = swiper.virtual.slides.length + slideIndex; 9668 if (slideIndex >= swiper.virtual.slides.length) slideIndex -= swiper.virtual.slides.length; 9669 activeSlide = getFilteredSlide(`[data-swiper-slide-index="${slideIndex}"]`); 9670 } else { 9671 activeSlide = getFilteredSlide(`[data-swiper-slide-index="${activeIndex}"]`); 9672 } 9673 } else { 9674 if (gridEnabled) { 9675 activeSlide = slides.find(slideEl => slideEl.column === activeIndex); 9676 nextSlide = slides.find(slideEl => slideEl.column === activeIndex + 1); 9677 prevSlide = slides.find(slideEl => slideEl.column === activeIndex - 1); 9678 } else { 9679 activeSlide = slides[activeIndex]; 9680 } 9681 } 9682 if (activeSlide) { 9683 if (!gridEnabled) { 9684 // Next Slide 9685 nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0]; 9686 if (params.loop && !nextSlide) { 9687 nextSlide = slides[0]; 9688 } 9689 9690 // Prev Slide 9691 prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0]; 9692 if (params.loop && !prevSlide === 0) { 9693 prevSlide = slides[slides.length - 1]; 9694 } 9695 } 9696 } 9697 slides.forEach(slideEl => { 9698 toggleSlideClasses(slideEl, slideEl === activeSlide, params.slideActiveClass); 9699 toggleSlideClasses(slideEl, slideEl === nextSlide, params.slideNextClass); 9700 toggleSlideClasses(slideEl, slideEl === prevSlide, params.slidePrevClass); 9701 }); 9702 swiper.emitSlidesClasses(); 9703 } 9704 9705 const processLazyPreloader = (swiper, imageEl) => { 9706 if (!swiper || swiper.destroyed || !swiper.params) return; 9707 const slideSelector = () => swiper.isElement ? `swiper-slide` : `.${swiper.params.slideClass}`; 9708 const slideEl = imageEl.closest(slideSelector()); 9709 if (slideEl) { 9710 let lazyEl = slideEl.querySelector(`.${swiper.params.lazyPreloaderClass}`); 9711 if (!lazyEl && swiper.isElement) { 9712 if (slideEl.shadowRoot) { 9713 lazyEl = slideEl.shadowRoot.querySelector(`.${swiper.params.lazyPreloaderClass}`); 9714 } else { 9715 // init later 9716 requestAnimationFrame(() => { 9717 if (slideEl.shadowRoot) { 9718 lazyEl = slideEl.shadowRoot.querySelector(`.${swiper.params.lazyPreloaderClass}`); 9719 if (lazyEl) lazyEl.remove(); 9720 } 9721 }); 9722 } 9723 } 9724 if (lazyEl) lazyEl.remove(); 9725 } 9726 }; 9727 const unlazy = (swiper, index) => { 9728 if (!swiper.slides[index]) return; 9729 const imageEl = swiper.slides[index].querySelector('[loading="lazy"]'); 9730 if (imageEl) imageEl.removeAttribute('loading'); 9731 }; 9732 const preload = swiper => { 9733 if (!swiper || swiper.destroyed || !swiper.params) return; 9734 let amount = swiper.params.lazyPreloadPrevNext; 9735 const len = swiper.slides.length; 9736 if (!len || !amount || amount < 0) return; 9737 amount = Math.min(amount, len); 9738 const slidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(swiper.params.slidesPerView); 9739 const activeIndex = swiper.activeIndex; 9740 if (swiper.params.grid && swiper.params.grid.rows > 1) { 9741 const activeColumn = activeIndex; 9742 const preloadColumns = [activeColumn - amount]; 9743 preloadColumns.push(...Array.from({ 9744 length: amount 9745 }).map((_, i) => { 9746 return activeColumn + slidesPerView + i; 9747 })); 9748 swiper.slides.forEach((slideEl, i) => { 9749 if (preloadColumns.includes(slideEl.column)) unlazy(swiper, i); 9750 }); 9751 return; 9752 } 9753 const slideIndexLastInView = activeIndex + slidesPerView - 1; 9754 if (swiper.params.rewind || swiper.params.loop) { 9755 for (let i = activeIndex - amount; i <= slideIndexLastInView + amount; i += 1) { 9756 const realIndex = (i % len + len) % len; 9757 if (realIndex < activeIndex || realIndex > slideIndexLastInView) unlazy(swiper, realIndex); 9758 } 9759 } else { 9760 for (let i = Math.max(activeIndex - amount, 0); i <= Math.min(slideIndexLastInView + amount, len - 1); i += 1) { 9761 if (i !== activeIndex && (i > slideIndexLastInView || i < activeIndex)) { 9762 unlazy(swiper, i); 9763 } 9764 } 9765 } 9766 }; 9767 9768 function getActiveIndexByTranslate(swiper) { 9769 const { 9770 slidesGrid, 9771 params 9772 } = swiper; 9773 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate; 9774 let activeIndex; 9775 for (let i = 0; i < slidesGrid.length; i += 1) { 9776 if (typeof slidesGrid[i + 1] !== 'undefined') { 9777 if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - (slidesGrid[i + 1] - slidesGrid[i]) / 2) { 9778 activeIndex = i; 9779 } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) { 9780 activeIndex = i + 1; 9781 } 9782 } else if (translate >= slidesGrid[i]) { 9783 activeIndex = i; 9784 } 9785 } 9786 // Normalize slideIndex 9787 if (params.normalizeSlideIndex) { 9788 if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0; 9789 } 9790 return activeIndex; 9791 } 9792 function updateActiveIndex(newActiveIndex) { 9793 const swiper = this; 9794 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate; 9795 const { 9796 snapGrid, 9797 params, 9798 activeIndex: previousIndex, 9799 realIndex: previousRealIndex, 9800 snapIndex: previousSnapIndex 9801 } = swiper; 9802 let activeIndex = newActiveIndex; 9803 let snapIndex; 9804 const getVirtualRealIndex = aIndex => { 9805 let realIndex = aIndex - swiper.virtual.slidesBefore; 9806 if (realIndex < 0) { 9807 realIndex = swiper.virtual.slides.length + realIndex; 9808 } 9809 if (realIndex >= swiper.virtual.slides.length) { 9810 realIndex -= swiper.virtual.slides.length; 9811 } 9812 return realIndex; 9813 }; 9814 if (typeof activeIndex === 'undefined') { 9815 activeIndex = getActiveIndexByTranslate(swiper); 9816 } 9817 if (snapGrid.indexOf(translate) >= 0) { 9818 snapIndex = snapGrid.indexOf(translate); 9819 } else { 9820 const skip = Math.min(params.slidesPerGroupSkip, activeIndex); 9821 snapIndex = skip + Math.floor((activeIndex - skip) / params.slidesPerGroup); 9822 } 9823 if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1; 9824 if (activeIndex === previousIndex && !swiper.params.loop) { 9825 if (snapIndex !== previousSnapIndex) { 9826 swiper.snapIndex = snapIndex; 9827 swiper.emit('snapIndexChange'); 9828 } 9829 return; 9830 } 9831 if (activeIndex === previousIndex && swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) { 9832 swiper.realIndex = getVirtualRealIndex(activeIndex); 9833 return; 9834 } 9835 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 9836 9837 // Get real index 9838 let realIndex; 9839 if (swiper.virtual && params.virtual.enabled && params.loop) { 9840 realIndex = getVirtualRealIndex(activeIndex); 9841 } else if (gridEnabled) { 9842 const firstSlideInColumn = swiper.slides.find(slideEl => slideEl.column === activeIndex); 9843 let activeSlideIndex = parseInt(firstSlideInColumn.getAttribute('data-swiper-slide-index'), 10); 9844 if (Number.isNaN(activeSlideIndex)) { 9845 activeSlideIndex = Math.max(swiper.slides.indexOf(firstSlideInColumn), 0); 9846 } 9847 realIndex = Math.floor(activeSlideIndex / params.grid.rows); 9848 } else if (swiper.slides[activeIndex]) { 9849 const slideIndex = swiper.slides[activeIndex].getAttribute('data-swiper-slide-index'); 9850 if (slideIndex) { 9851 realIndex = parseInt(slideIndex, 10); 9852 } else { 9853 realIndex = activeIndex; 9854 } 9855 } else { 9856 realIndex = activeIndex; 9857 } 9858 Object.assign(swiper, { 9859 previousSnapIndex, 9860 snapIndex, 9861 previousRealIndex, 9862 realIndex, 9863 previousIndex, 9864 activeIndex 9865 }); 9866 if (swiper.initialized) { 9867 preload(swiper); 9868 } 9869 swiper.emit('activeIndexChange'); 9870 swiper.emit('snapIndexChange'); 9871 if (swiper.initialized || swiper.params.runCallbacksOnInit) { 9872 if (previousRealIndex !== realIndex) { 9873 swiper.emit('realIndexChange'); 9874 } 9875 swiper.emit('slideChange'); 9876 } 9877 } 9878 9879 function updateClickedSlide(el, path) { 9880 const swiper = this; 9881 const params = swiper.params; 9882 let slide = el.closest(`.${params.slideClass}, swiper-slide`); 9883 if (!slide && swiper.isElement && path && path.length > 1 && path.includes(el)) { 9884 [...path.slice(path.indexOf(el) + 1, path.length)].forEach(pathEl => { 9885 if (!slide && pathEl.matches && pathEl.matches(`.${params.slideClass}, swiper-slide`)) { 9886 slide = pathEl; 9887 } 9888 }); 9889 } 9890 let slideFound = false; 9891 let slideIndex; 9892 if (slide) { 9893 for (let i = 0; i < swiper.slides.length; i += 1) { 9894 if (swiper.slides[i] === slide) { 9895 slideFound = true; 9896 slideIndex = i; 9897 break; 9898 } 9899 } 9900 } 9901 if (slide && slideFound) { 9902 swiper.clickedSlide = slide; 9903 if (swiper.virtual && swiper.params.virtual.enabled) { 9904 swiper.clickedIndex = parseInt(slide.getAttribute('data-swiper-slide-index'), 10); 9905 } else { 9906 swiper.clickedIndex = slideIndex; 9907 } 9908 } else { 9909 swiper.clickedSlide = undefined; 9910 swiper.clickedIndex = undefined; 9911 return; 9912 } 9913 if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) { 9914 swiper.slideToClickedSlide(); 9915 } 9916 } 9917 9918 var update = { 9919 updateSize, 9920 updateSlides, 9921 updateAutoHeight, 9922 updateSlidesOffset, 9923 updateSlidesProgress, 9924 updateProgress, 9925 updateSlidesClasses, 9926 updateActiveIndex, 9927 updateClickedSlide 9928 }; 9929 9930 function getSwiperTranslate(axis = this.isHorizontal() ? 'x' : 'y') { 9931 const swiper = this; 9932 const { 9933 params, 9934 rtlTranslate: rtl, 9935 translate, 9936 wrapperEl 9937 } = swiper; 9938 if (params.virtualTranslate) { 9939 return rtl ? -translate : translate; 9940 } 9941 if (params.cssMode) { 9942 return translate; 9943 } 9944 let currentTranslate = getTranslate(wrapperEl, axis); 9945 currentTranslate += swiper.cssOverflowAdjustment(); 9946 if (rtl) currentTranslate = -currentTranslate; 9947 return currentTranslate || 0; 9948 } 9949 9950 function setTranslate(translate, byController) { 9951 const swiper = this; 9952 const { 9953 rtlTranslate: rtl, 9954 params, 9955 wrapperEl, 9956 progress 9957 } = swiper; 9958 let x = 0; 9959 let y = 0; 9960 const z = 0; 9961 if (swiper.isHorizontal()) { 9962 x = rtl ? -translate : translate; 9963 } else { 9964 y = translate; 9965 } 9966 if (params.roundLengths) { 9967 x = Math.floor(x); 9968 y = Math.floor(y); 9969 } 9970 swiper.previousTranslate = swiper.translate; 9971 swiper.translate = swiper.isHorizontal() ? x : y; 9972 if (params.cssMode) { 9973 wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y; 9974 } else if (!params.virtualTranslate) { 9975 if (swiper.isHorizontal()) { 9976 x -= swiper.cssOverflowAdjustment(); 9977 } else { 9978 y -= swiper.cssOverflowAdjustment(); 9979 } 9980 wrapperEl.style.transform = `translate3d(${x}px, ${y}px, ${z}px)`; 9981 } 9982 9983 // Check if we need to update progress 9984 let newProgress; 9985 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate(); 9986 if (translatesDiff === 0) { 9987 newProgress = 0; 9988 } else { 9989 newProgress = (translate - swiper.minTranslate()) / translatesDiff; 9990 } 9991 if (newProgress !== progress) { 9992 swiper.updateProgress(translate); 9993 } 9994 swiper.emit('setTranslate', swiper.translate, byController); 9995 } 9996 9997 function minTranslate() { 9998 return -this.snapGrid[0]; 9999 } 10000 10001 function maxTranslate() { 10002 return -this.snapGrid[this.snapGrid.length - 1]; 10003 } 10004 10005 function translateTo(translate = 0, speed = this.params.speed, runCallbacks = true, translateBounds = true, internal) { 10006 const swiper = this; 10007 const { 10008 params, 10009 wrapperEl 10010 } = swiper; 10011 if (swiper.animating && params.preventInteractionOnTransition) { 10012 return false; 10013 } 10014 const minTranslate = swiper.minTranslate(); 10015 const maxTranslate = swiper.maxTranslate(); 10016 let newTranslate; 10017 if (translateBounds && translate > minTranslate) newTranslate = minTranslate;else if (translateBounds && translate < maxTranslate) newTranslate = maxTranslate;else newTranslate = translate; 10018 10019 // Update progress 10020 swiper.updateProgress(newTranslate); 10021 if (params.cssMode) { 10022 const isH = swiper.isHorizontal(); 10023 if (speed === 0) { 10024 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate; 10025 } else { 10026 if (!swiper.support.smoothScroll) { 10027 animateCSSModeScroll({ 10028 swiper, 10029 targetPosition: -newTranslate, 10030 side: isH ? 'left' : 'top' 10031 }); 10032 return true; 10033 } 10034 wrapperEl.scrollTo({ 10035 [isH ? 'left' : 'top']: -newTranslate, 10036 behavior: 'smooth' 10037 }); 10038 } 10039 return true; 10040 } 10041 if (speed === 0) { 10042 swiper.setTransition(0); 10043 swiper.setTranslate(newTranslate); 10044 if (runCallbacks) { 10045 swiper.emit('beforeTransitionStart', speed, internal); 10046 swiper.emit('transitionEnd'); 10047 } 10048 } else { 10049 swiper.setTransition(speed); 10050 swiper.setTranslate(newTranslate); 10051 if (runCallbacks) { 10052 swiper.emit('beforeTransitionStart', speed, internal); 10053 swiper.emit('transitionStart'); 10054 } 10055 if (!swiper.animating) { 10056 swiper.animating = true; 10057 if (!swiper.onTranslateToWrapperTransitionEnd) { 10058 swiper.onTranslateToWrapperTransitionEnd = function transitionEnd(e) { 10059 if (!swiper || swiper.destroyed) return; 10060 if (e.target !== this) return; 10061 swiper.wrapperEl.removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd); 10062 swiper.onTranslateToWrapperTransitionEnd = null; 10063 delete swiper.onTranslateToWrapperTransitionEnd; 10064 swiper.animating = false; 10065 if (runCallbacks) { 10066 swiper.emit('transitionEnd'); 10067 } 10068 }; 10069 } 10070 swiper.wrapperEl.addEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd); 10071 } 10072 } 10073 return true; 10074 } 10075 10076 var translate = { 10077 getTranslate: getSwiperTranslate, 10078 setTranslate, 10079 minTranslate, 10080 maxTranslate, 10081 translateTo 10082 }; 10083 10084 function setTransition(duration, byController) { 10085 const swiper = this; 10086 if (!swiper.params.cssMode) { 10087 swiper.wrapperEl.style.transitionDuration = `${duration}ms`; 10088 swiper.wrapperEl.style.transitionDelay = duration === 0 ? `0ms` : ''; 10089 } 10090 swiper.emit('setTransition', duration, byController); 10091 } 10092 10093 function transitionEmit({ 10094 swiper, 10095 runCallbacks, 10096 direction, 10097 step 10098 }) { 10099 const { 10100 activeIndex, 10101 previousIndex 10102 } = swiper; 10103 let dir = direction; 10104 if (!dir) { 10105 if (activeIndex > previousIndex) dir = 'next';else if (activeIndex < previousIndex) dir = 'prev';else dir = 'reset'; 10106 } 10107 swiper.emit(`transition${step}`); 10108 if (runCallbacks && dir === 'reset') { 10109 swiper.emit(`slideResetTransition${step}`); 10110 } else if (runCallbacks && activeIndex !== previousIndex) { 10111 swiper.emit(`slideChangeTransition${step}`); 10112 if (dir === 'next') { 10113 swiper.emit(`slideNextTransition${step}`); 10114 } else { 10115 swiper.emit(`slidePrevTransition${step}`); 10116 } 10117 } 10118 } 10119 10120 function transitionStart(runCallbacks = true, direction) { 10121 const swiper = this; 10122 const { 10123 params 10124 } = swiper; 10125 if (params.cssMode) return; 10126 if (params.autoHeight) { 10127 swiper.updateAutoHeight(); 10128 } 10129 transitionEmit({ 10130 swiper, 10131 runCallbacks, 10132 direction, 10133 step: 'Start' 10134 }); 10135 } 10136 10137 function transitionEnd(runCallbacks = true, direction) { 10138 const swiper = this; 10139 const { 10140 params 10141 } = swiper; 10142 swiper.animating = false; 10143 if (params.cssMode) return; 10144 swiper.setTransition(0); 10145 transitionEmit({ 10146 swiper, 10147 runCallbacks, 10148 direction, 10149 step: 'End' 10150 }); 10151 } 10152 10153 var transition = { 10154 setTransition, 10155 transitionStart, 10156 transitionEnd 10157 }; 10158 10159 function slideTo(index = 0, speed, runCallbacks = true, internal, initial) { 10160 if (typeof index === 'string') { 10161 index = parseInt(index, 10); 10162 } 10163 const swiper = this; 10164 let slideIndex = index; 10165 if (slideIndex < 0) slideIndex = 0; 10166 const { 10167 params, 10168 snapGrid, 10169 slidesGrid, 10170 previousIndex, 10171 activeIndex, 10172 rtlTranslate: rtl, 10173 wrapperEl, 10174 enabled 10175 } = swiper; 10176 if (!enabled && !internal && !initial || swiper.destroyed || swiper.animating && params.preventInteractionOnTransition) { 10177 return false; 10178 } 10179 if (typeof speed === 'undefined') { 10180 speed = swiper.params.speed; 10181 } 10182 const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex); 10183 let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup); 10184 if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1; 10185 const translate = -snapGrid[snapIndex]; 10186 // Normalize slideIndex 10187 if (params.normalizeSlideIndex) { 10188 for (let i = 0; i < slidesGrid.length; i += 1) { 10189 const normalizedTranslate = -Math.floor(translate * 100); 10190 const normalizedGrid = Math.floor(slidesGrid[i] * 100); 10191 const normalizedGridNext = Math.floor(slidesGrid[i + 1] * 100); 10192 if (typeof slidesGrid[i + 1] !== 'undefined') { 10193 if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext - (normalizedGridNext - normalizedGrid) / 2) { 10194 slideIndex = i; 10195 } else if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext) { 10196 slideIndex = i + 1; 10197 } 10198 } else if (normalizedTranslate >= normalizedGrid) { 10199 slideIndex = i; 10200 } 10201 } 10202 } 10203 // Directions locks 10204 if (swiper.initialized && slideIndex !== activeIndex) { 10205 if (!swiper.allowSlideNext && (rtl ? translate > swiper.translate && translate > swiper.minTranslate() : translate < swiper.translate && translate < swiper.minTranslate())) { 10206 return false; 10207 } 10208 if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) { 10209 if ((activeIndex || 0) !== slideIndex) { 10210 return false; 10211 } 10212 } 10213 } 10214 if (slideIndex !== (previousIndex || 0) && runCallbacks) { 10215 swiper.emit('beforeSlideChangeStart'); 10216 } 10217 10218 // Update progress 10219 swiper.updateProgress(translate); 10220 let direction; 10221 if (slideIndex > activeIndex) direction = 'next';else if (slideIndex < activeIndex) direction = 'prev';else direction = 'reset'; 10222 10223 // initial virtual 10224 const isVirtual = swiper.virtual && swiper.params.virtual.enabled; 10225 const isInitialVirtual = isVirtual && initial; 10226 // Update Index 10227 if (!isInitialVirtual && (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate)) { 10228 swiper.updateActiveIndex(slideIndex); 10229 // Update Height 10230 if (params.autoHeight) { 10231 swiper.updateAutoHeight(); 10232 } 10233 swiper.updateSlidesClasses(); 10234 if (params.effect !== 'slide') { 10235 swiper.setTranslate(translate); 10236 } 10237 if (direction !== 'reset') { 10238 swiper.transitionStart(runCallbacks, direction); 10239 swiper.transitionEnd(runCallbacks, direction); 10240 } 10241 return false; 10242 } 10243 if (params.cssMode) { 10244 const isH = swiper.isHorizontal(); 10245 const t = rtl ? translate : -translate; 10246 if (speed === 0) { 10247 if (isVirtual) { 10248 swiper.wrapperEl.style.scrollSnapType = 'none'; 10249 swiper._immediateVirtual = true; 10250 } 10251 if (isVirtual && !swiper._cssModeVirtualInitialSet && swiper.params.initialSlide > 0) { 10252 swiper._cssModeVirtualInitialSet = true; 10253 requestAnimationFrame(() => { 10254 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t; 10255 }); 10256 } else { 10257 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t; 10258 } 10259 if (isVirtual) { 10260 requestAnimationFrame(() => { 10261 swiper.wrapperEl.style.scrollSnapType = ''; 10262 swiper._immediateVirtual = false; 10263 }); 10264 } 10265 } else { 10266 if (!swiper.support.smoothScroll) { 10267 animateCSSModeScroll({ 10268 swiper, 10269 targetPosition: t, 10270 side: isH ? 'left' : 'top' 10271 }); 10272 return true; 10273 } 10274 wrapperEl.scrollTo({ 10275 [isH ? 'left' : 'top']: t, 10276 behavior: 'smooth' 10277 }); 10278 } 10279 return true; 10280 } 10281 const browser = getBrowser(); 10282 const isSafari = browser.isSafari; 10283 if (isVirtual && !initial && isSafari && swiper.isElement) { 10284 swiper.virtual.update(false, false, slideIndex); 10285 } 10286 swiper.setTransition(speed); 10287 swiper.setTranslate(translate); 10288 swiper.updateActiveIndex(slideIndex); 10289 swiper.updateSlidesClasses(); 10290 swiper.emit('beforeTransitionStart', speed, internal); 10291 swiper.transitionStart(runCallbacks, direction); 10292 if (speed === 0) { 10293 swiper.transitionEnd(runCallbacks, direction); 10294 } else if (!swiper.animating) { 10295 swiper.animating = true; 10296 if (!swiper.onSlideToWrapperTransitionEnd) { 10297 swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) { 10298 if (!swiper || swiper.destroyed) return; 10299 if (e.target !== this) return; 10300 swiper.wrapperEl.removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd); 10301 swiper.onSlideToWrapperTransitionEnd = null; 10302 delete swiper.onSlideToWrapperTransitionEnd; 10303 swiper.transitionEnd(runCallbacks, direction); 10304 }; 10305 } 10306 swiper.wrapperEl.addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd); 10307 } 10308 return true; 10309 } 10310 10311 function slideToLoop(index = 0, speed, runCallbacks = true, internal) { 10312 if (typeof index === 'string') { 10313 const indexAsNumber = parseInt(index, 10); 10314 index = indexAsNumber; 10315 } 10316 const swiper = this; 10317 if (swiper.destroyed) return; 10318 if (typeof speed === 'undefined') { 10319 speed = swiper.params.speed; 10320 } 10321 const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1; 10322 let newIndex = index; 10323 if (swiper.params.loop) { 10324 if (swiper.virtual && swiper.params.virtual.enabled) { 10325 // eslint-disable-next-line 10326 newIndex = newIndex + swiper.virtual.slidesBefore; 10327 } else { 10328 let targetSlideIndex; 10329 if (gridEnabled) { 10330 const slideIndex = newIndex * swiper.params.grid.rows; 10331 targetSlideIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column; 10332 } else { 10333 targetSlideIndex = swiper.getSlideIndexByData(newIndex); 10334 } 10335 const cols = gridEnabled ? Math.ceil(swiper.slides.length / swiper.params.grid.rows) : swiper.slides.length; 10336 const { 10337 centeredSlides, 10338 slidesOffsetBefore, 10339 slidesOffsetAfter 10340 } = swiper.params; 10341 const bothDirections = centeredSlides || !!slidesOffsetBefore || !!slidesOffsetAfter; 10342 let slidesPerView = swiper.params.slidesPerView; 10343 if (slidesPerView === 'auto') { 10344 slidesPerView = swiper.slidesPerViewDynamic(); 10345 } else { 10346 slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10)); 10347 if (bothDirections && slidesPerView % 2 === 0) { 10348 slidesPerView = slidesPerView + 1; 10349 } 10350 } 10351 let needLoopFix = cols - targetSlideIndex < slidesPerView; 10352 if (bothDirections) { 10353 needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2); 10354 } 10355 if (internal && bothDirections && swiper.params.slidesPerView !== 'auto' && !gridEnabled) { 10356 needLoopFix = false; 10357 } 10358 if (needLoopFix) { 10359 const direction = bothDirections ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev'; 10360 swiper.loopFix({ 10361 direction, 10362 slideTo: true, 10363 activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1, 10364 slideRealIndex: direction === 'next' ? swiper.realIndex : undefined 10365 }); 10366 } 10367 if (gridEnabled) { 10368 const slideIndex = newIndex * swiper.params.grid.rows; 10369 newIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column; 10370 } else { 10371 newIndex = swiper.getSlideIndexByData(newIndex); 10372 } 10373 } 10374 } 10375 requestAnimationFrame(() => { 10376 swiper.slideTo(newIndex, speed, runCallbacks, internal); 10377 }); 10378 return swiper; 10379 } 10380 10381 /* eslint no-unused-vars: "off" */ 10382 function slideNext(speed, runCallbacks = true, internal) { 10383 const swiper = this; 10384 const { 10385 enabled, 10386 params, 10387 animating 10388 } = swiper; 10389 if (!enabled || swiper.destroyed) return swiper; 10390 if (typeof speed === 'undefined') { 10391 speed = swiper.params.speed; 10392 } 10393 let perGroup = params.slidesPerGroup; 10394 if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) { 10395 perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1); 10396 } 10397 const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup; 10398 const isVirtual = swiper.virtual && params.virtual.enabled; 10399 if (params.loop) { 10400 if (animating && !isVirtual && params.loopPreventsSliding) return false; 10401 swiper.loopFix({ 10402 direction: 'next' 10403 }); 10404 // eslint-disable-next-line 10405 swiper._clientLeft = swiper.wrapperEl.clientLeft; 10406 if (swiper.activeIndex === swiper.slides.length - 1 && params.cssMode) { 10407 requestAnimationFrame(() => { 10408 swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal); 10409 }); 10410 return true; 10411 } 10412 } 10413 if (params.rewind && swiper.isEnd) { 10414 return swiper.slideTo(0, speed, runCallbacks, internal); 10415 } 10416 return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal); 10417 } 10418 10419 /* eslint no-unused-vars: "off" */ 10420 function slidePrev(speed, runCallbacks = true, internal) { 10421 const swiper = this; 10422 const { 10423 params, 10424 snapGrid, 10425 slidesGrid, 10426 rtlTranslate, 10427 enabled, 10428 animating 10429 } = swiper; 10430 if (!enabled || swiper.destroyed) return swiper; 10431 if (typeof speed === 'undefined') { 10432 speed = swiper.params.speed; 10433 } 10434 const isVirtual = swiper.virtual && params.virtual.enabled; 10435 if (params.loop) { 10436 if (animating && !isVirtual && params.loopPreventsSliding) return false; 10437 swiper.loopFix({ 10438 direction: 'prev' 10439 }); 10440 // eslint-disable-next-line 10441 swiper._clientLeft = swiper.wrapperEl.clientLeft; 10442 } 10443 const translate = rtlTranslate ? swiper.translate : -swiper.translate; 10444 function normalize(val) { 10445 if (val < 0) return -Math.floor(Math.abs(val)); 10446 return Math.floor(val); 10447 } 10448 const normalizedTranslate = normalize(translate); 10449 const normalizedSnapGrid = snapGrid.map(val => normalize(val)); 10450 const isFreeMode = params.freeMode && params.freeMode.enabled; 10451 let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1]; 10452 if (typeof prevSnap === 'undefined' && (params.cssMode || isFreeMode)) { 10453 let prevSnapIndex; 10454 snapGrid.forEach((snap, snapIndex) => { 10455 if (normalizedTranslate >= snap) { 10456 // prevSnap = snap; 10457 prevSnapIndex = snapIndex; 10458 } 10459 }); 10460 if (typeof prevSnapIndex !== 'undefined') { 10461 prevSnap = isFreeMode ? snapGrid[prevSnapIndex] : snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex]; 10462 } 10463 } 10464 let prevIndex = 0; 10465 if (typeof prevSnap !== 'undefined') { 10466 prevIndex = slidesGrid.indexOf(prevSnap); 10467 if (prevIndex < 0) prevIndex = swiper.activeIndex - 1; 10468 if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) { 10469 prevIndex = prevIndex - swiper.slidesPerViewDynamic('previous', true) + 1; 10470 prevIndex = Math.max(prevIndex, 0); 10471 } 10472 } 10473 if (params.rewind && swiper.isBeginning) { 10474 const lastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1; 10475 return swiper.slideTo(lastIndex, speed, runCallbacks, internal); 10476 } else if (params.loop && swiper.activeIndex === 0 && params.cssMode) { 10477 requestAnimationFrame(() => { 10478 swiper.slideTo(prevIndex, speed, runCallbacks, internal); 10479 }); 10480 return true; 10481 } 10482 return swiper.slideTo(prevIndex, speed, runCallbacks, internal); 10483 } 10484 10485 /* eslint no-unused-vars: "off" */ 10486 function slideReset(speed, runCallbacks = true, internal) { 10487 const swiper = this; 10488 if (swiper.destroyed) return; 10489 if (typeof speed === 'undefined') { 10490 speed = swiper.params.speed; 10491 } 10492 return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal); 10493 } 10494 10495 /* eslint no-unused-vars: "off" */ 10496 function slideToClosest(speed, runCallbacks = true, internal, threshold = 0.5) { 10497 const swiper = this; 10498 if (swiper.destroyed) return; 10499 if (typeof speed === 'undefined') { 10500 speed = swiper.params.speed; 10501 } 10502 let index = swiper.activeIndex; 10503 const skip = Math.min(swiper.params.slidesPerGroupSkip, index); 10504 const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup); 10505 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate; 10506 if (translate >= swiper.snapGrid[snapIndex]) { 10507 // The current translate is on or after the current snap index, so the choice 10508 // is between the current index and the one after it. 10509 const currentSnap = swiper.snapGrid[snapIndex]; 10510 const nextSnap = swiper.snapGrid[snapIndex + 1]; 10511 if (translate - currentSnap > (nextSnap - currentSnap) * threshold) { 10512 index += swiper.params.slidesPerGroup; 10513 } 10514 } else { 10515 // The current translate is before the current snap index, so the choice 10516 // is between the current index and the one before it. 10517 const prevSnap = swiper.snapGrid[snapIndex - 1]; 10518 const currentSnap = swiper.snapGrid[snapIndex]; 10519 if (translate - prevSnap <= (currentSnap - prevSnap) * threshold) { 10520 index -= swiper.params.slidesPerGroup; 10521 } 10522 } 10523 index = Math.max(index, 0); 10524 index = Math.min(index, swiper.slidesGrid.length - 1); 10525 return swiper.slideTo(index, speed, runCallbacks, internal); 10526 } 10527 10528 function slideToClickedSlide() { 10529 const swiper = this; 10530 if (swiper.destroyed) return; 10531 const { 10532 params, 10533 slidesEl 10534 } = swiper; 10535 const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView; 10536 let slideToIndex = swiper.getSlideIndexWhenGrid(swiper.clickedIndex); 10537 let realIndex; 10538 const slideSelector = swiper.isElement ? `swiper-slide` : `.${params.slideClass}`; 10539 const isGrid = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1; 10540 if (params.loop) { 10541 if (swiper.animating) return; 10542 realIndex = parseInt(swiper.clickedSlide.getAttribute('data-swiper-slide-index'), 10); 10543 if (params.centeredSlides) { 10544 swiper.slideToLoop(realIndex); 10545 } else if (slideToIndex > (isGrid ? (swiper.slides.length - slidesPerView) / 2 - (swiper.params.grid.rows - 1) : swiper.slides.length - slidesPerView)) { 10546 swiper.loopFix(); 10547 slideToIndex = swiper.getSlideIndex(elementChildren(slidesEl, `${slideSelector}[data-swiper-slide-index="${realIndex}"]`)[0]); 10548 nextTick(() => { 10549 swiper.slideTo(slideToIndex); 10550 }); 10551 } else { 10552 swiper.slideTo(slideToIndex); 10553 } 10554 } else { 10555 swiper.slideTo(slideToIndex); 10556 } 10557 } 10558 10559 var slide = { 10560 slideTo, 10561 slideToLoop, 10562 slideNext, 10563 slidePrev, 10564 slideReset, 10565 slideToClosest, 10566 slideToClickedSlide 10567 }; 10568 10569 function loopCreate(slideRealIndex, initial) { 10570 const swiper = this; 10571 const { 10572 params, 10573 slidesEl 10574 } = swiper; 10575 if (!params.loop || swiper.virtual && swiper.params.virtual.enabled) return; 10576 const initSlides = () => { 10577 const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`); 10578 slides.forEach((el, index) => { 10579 el.setAttribute('data-swiper-slide-index', index); 10580 }); 10581 }; 10582 const clearBlankSlides = () => { 10583 const slides = elementChildren(slidesEl, `.${params.slideBlankClass}`); 10584 slides.forEach(el => { 10585 el.remove(); 10586 }); 10587 if (slides.length > 0) { 10588 swiper.recalcSlides(); 10589 swiper.updateSlides(); 10590 } 10591 }; 10592 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 10593 if (params.loopAddBlankSlides && (params.slidesPerGroup > 1 || gridEnabled)) { 10594 clearBlankSlides(); 10595 } 10596 const slidesPerGroup = params.slidesPerGroup * (gridEnabled ? params.grid.rows : 1); 10597 const shouldFillGroup = swiper.slides.length % slidesPerGroup !== 0; 10598 const shouldFillGrid = gridEnabled && swiper.slides.length % params.grid.rows !== 0; 10599 const addBlankSlides = amountOfSlides => { 10600 for (let i = 0; i < amountOfSlides; i += 1) { 10601 const slideEl = swiper.isElement ? createElement('swiper-slide', [params.slideBlankClass]) : createElement('div', [params.slideClass, params.slideBlankClass]); 10602 swiper.slidesEl.append(slideEl); 10603 } 10604 }; 10605 if (shouldFillGroup) { 10606 if (params.loopAddBlankSlides) { 10607 const slidesToAdd = slidesPerGroup - swiper.slides.length % slidesPerGroup; 10608 addBlankSlides(slidesToAdd); 10609 swiper.recalcSlides(); 10610 swiper.updateSlides(); 10611 } else { 10612 showWarning('Swiper Loop Warning: The number of slides is not even to slidesPerGroup, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)'); 10613 } 10614 initSlides(); 10615 } else if (shouldFillGrid) { 10616 if (params.loopAddBlankSlides) { 10617 const slidesToAdd = params.grid.rows - swiper.slides.length % params.grid.rows; 10618 addBlankSlides(slidesToAdd); 10619 swiper.recalcSlides(); 10620 swiper.updateSlides(); 10621 } else { 10622 showWarning('Swiper Loop Warning: The number of slides is not even to grid.rows, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)'); 10623 } 10624 initSlides(); 10625 } else { 10626 initSlides(); 10627 } 10628 const bothDirections = params.centeredSlides || !!params.slidesOffsetBefore || !!params.slidesOffsetAfter; 10629 swiper.loopFix({ 10630 slideRealIndex, 10631 direction: bothDirections ? undefined : 'next', 10632 initial 10633 }); 10634 } 10635 10636 function loopFix({ 10637 slideRealIndex, 10638 slideTo = true, 10639 direction, 10640 setTranslate, 10641 activeSlideIndex, 10642 initial, 10643 byController, 10644 byMousewheel 10645 } = {}) { 10646 const swiper = this; 10647 if (!swiper.params.loop) return; 10648 swiper.emit('beforeLoopFix'); 10649 const { 10650 slides, 10651 allowSlidePrev, 10652 allowSlideNext, 10653 slidesEl, 10654 params 10655 } = swiper; 10656 const { 10657 centeredSlides, 10658 slidesOffsetBefore, 10659 slidesOffsetAfter, 10660 initialSlide 10661 } = params; 10662 const bothDirections = centeredSlides || !!slidesOffsetBefore || !!slidesOffsetAfter; 10663 swiper.allowSlidePrev = true; 10664 swiper.allowSlideNext = true; 10665 if (swiper.virtual && params.virtual.enabled) { 10666 if (slideTo) { 10667 if (!bothDirections && swiper.snapIndex === 0) { 10668 swiper.slideTo(swiper.virtual.slides.length, 0, false, true); 10669 } else if (bothDirections && swiper.snapIndex < params.slidesPerView) { 10670 swiper.slideTo(swiper.virtual.slides.length + swiper.snapIndex, 0, false, true); 10671 } else if (swiper.snapIndex === swiper.snapGrid.length - 1) { 10672 swiper.slideTo(swiper.virtual.slidesBefore, 0, false, true); 10673 } 10674 } 10675 swiper.allowSlidePrev = allowSlidePrev; 10676 swiper.allowSlideNext = allowSlideNext; 10677 swiper.emit('loopFix'); 10678 return; 10679 } 10680 let slidesPerView = params.slidesPerView; 10681 if (slidesPerView === 'auto') { 10682 slidesPerView = swiper.slidesPerViewDynamic(); 10683 } else { 10684 slidesPerView = Math.ceil(parseFloat(params.slidesPerView, 10)); 10685 if (bothDirections && slidesPerView % 2 === 0) { 10686 slidesPerView = slidesPerView + 1; 10687 } 10688 } 10689 const slidesPerGroup = params.slidesPerGroupAuto ? slidesPerView : params.slidesPerGroup; 10690 let loopedSlides = bothDirections ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2)) : slidesPerGroup; 10691 if (loopedSlides % slidesPerGroup !== 0) { 10692 loopedSlides += slidesPerGroup - loopedSlides % slidesPerGroup; 10693 } 10694 loopedSlides += params.loopAdditionalSlides; 10695 swiper.loopedSlides = loopedSlides; 10696 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 10697 if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) { 10698 showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters'); 10699 } else if (gridEnabled && params.grid.fill === 'row') { 10700 showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`'); 10701 } 10702 const prependSlidesIndexes = []; 10703 const appendSlidesIndexes = []; 10704 const cols = gridEnabled ? Math.ceil(slides.length / params.grid.rows) : slides.length; 10705 const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !bothDirections; 10706 let activeIndex = isInitialOverflow ? initialSlide : swiper.activeIndex; 10707 if (typeof activeSlideIndex === 'undefined') { 10708 activeSlideIndex = swiper.getSlideIndex(slides.find(el => el.classList.contains(params.slideActiveClass))); 10709 } else { 10710 activeIndex = activeSlideIndex; 10711 } 10712 const isNext = direction === 'next' || !direction; 10713 const isPrev = direction === 'prev' || !direction; 10714 let slidesPrepended = 0; 10715 let slidesAppended = 0; 10716 const activeColIndex = gridEnabled ? slides[activeSlideIndex].column : activeSlideIndex; 10717 const activeColIndexWithShift = activeColIndex + (bothDirections && typeof setTranslate === 'undefined' ? -slidesPerView / 2 + 0.5 : 0); 10718 // prepend last slides before start 10719 if (activeColIndexWithShift < loopedSlides) { 10720 slidesPrepended = Math.max(loopedSlides - activeColIndexWithShift, slidesPerGroup); 10721 for (let i = 0; i < loopedSlides - activeColIndexWithShift; i += 1) { 10722 const index = i - Math.floor(i / cols) * cols; 10723 if (gridEnabled) { 10724 const colIndexToPrepend = cols - index - 1; 10725 for (let i = slides.length - 1; i >= 0; i -= 1) { 10726 if (slides[i].column === colIndexToPrepend) prependSlidesIndexes.push(i); 10727 } 10728 // slides.forEach((slide, slideIndex) => { 10729 // if (slide.column === colIndexToPrepend) prependSlidesIndexes.push(slideIndex); 10730 // }); 10731 } else { 10732 prependSlidesIndexes.push(cols - index - 1); 10733 } 10734 } 10735 } else if (activeColIndexWithShift + slidesPerView > cols - loopedSlides) { 10736 slidesAppended = Math.max(activeColIndexWithShift - (cols - loopedSlides * 2), slidesPerGroup); 10737 if (isInitialOverflow) { 10738 slidesAppended = Math.max(slidesAppended, slidesPerView - cols + initialSlide + 1); 10739 } 10740 for (let i = 0; i < slidesAppended; i += 1) { 10741 const index = i - Math.floor(i / cols) * cols; 10742 if (gridEnabled) { 10743 slides.forEach((slide, slideIndex) => { 10744 if (slide.column === index) appendSlidesIndexes.push(slideIndex); 10745 }); 10746 } else { 10747 appendSlidesIndexes.push(index); 10748 } 10749 } 10750 } 10751 swiper.__preventObserver__ = true; 10752 requestAnimationFrame(() => { 10753 swiper.__preventObserver__ = false; 10754 }); 10755 if (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) { 10756 if (appendSlidesIndexes.includes(activeSlideIndex)) { 10757 appendSlidesIndexes.splice(appendSlidesIndexes.indexOf(activeSlideIndex), 1); 10758 } 10759 if (prependSlidesIndexes.includes(activeSlideIndex)) { 10760 prependSlidesIndexes.splice(prependSlidesIndexes.indexOf(activeSlideIndex), 1); 10761 } 10762 } 10763 if (isPrev) { 10764 prependSlidesIndexes.forEach(index => { 10765 slides[index].swiperLoopMoveDOM = true; 10766 slidesEl.prepend(slides[index]); 10767 slides[index].swiperLoopMoveDOM = false; 10768 }); 10769 } 10770 if (isNext) { 10771 appendSlidesIndexes.forEach(index => { 10772 slides[index].swiperLoopMoveDOM = true; 10773 slidesEl.append(slides[index]); 10774 slides[index].swiperLoopMoveDOM = false; 10775 }); 10776 } 10777 swiper.recalcSlides(); 10778 if (params.slidesPerView === 'auto') { 10779 swiper.updateSlides(); 10780 } else if (gridEnabled && (prependSlidesIndexes.length > 0 && isPrev || appendSlidesIndexes.length > 0 && isNext)) { 10781 swiper.slides.forEach((slide, slideIndex) => { 10782 swiper.grid.updateSlide(slideIndex, slide, swiper.slides); 10783 }); 10784 } 10785 if (params.watchSlidesProgress) { 10786 swiper.updateSlidesOffset(); 10787 } 10788 if (slideTo) { 10789 if (prependSlidesIndexes.length > 0 && isPrev) { 10790 if (typeof slideRealIndex === 'undefined') { 10791 const currentSlideTranslate = swiper.slidesGrid[activeIndex]; 10792 const newSlideTranslate = swiper.slidesGrid[activeIndex + slidesPrepended]; 10793 const diff = newSlideTranslate - currentSlideTranslate; 10794 if (byMousewheel) { 10795 swiper.setTranslate(swiper.translate - diff); 10796 } else { 10797 swiper.slideTo(activeIndex + Math.ceil(slidesPrepended), 0, false, true); 10798 if (setTranslate) { 10799 swiper.touchEventsData.startTranslate = swiper.touchEventsData.startTranslate - diff; 10800 swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff; 10801 } 10802 } 10803 } else { 10804 if (setTranslate) { 10805 const shift = gridEnabled ? prependSlidesIndexes.length / params.grid.rows : prependSlidesIndexes.length; 10806 swiper.slideTo(swiper.activeIndex + shift, 0, false, true); 10807 swiper.touchEventsData.currentTranslate = swiper.translate; 10808 } 10809 } 10810 } else if (appendSlidesIndexes.length > 0 && isNext) { 10811 if (typeof slideRealIndex === 'undefined') { 10812 const currentSlideTranslate = swiper.slidesGrid[activeIndex]; 10813 const newSlideTranslate = swiper.slidesGrid[activeIndex - slidesAppended]; 10814 const diff = newSlideTranslate - currentSlideTranslate; 10815 if (byMousewheel) { 10816 swiper.setTranslate(swiper.translate - diff); 10817 } else { 10818 swiper.slideTo(activeIndex - slidesAppended, 0, false, true); 10819 if (setTranslate) { 10820 swiper.touchEventsData.startTranslate = swiper.touchEventsData.startTranslate - diff; 10821 swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff; 10822 } 10823 } 10824 } else { 10825 const shift = gridEnabled ? appendSlidesIndexes.length / params.grid.rows : appendSlidesIndexes.length; 10826 swiper.slideTo(swiper.activeIndex - shift, 0, false, true); 10827 } 10828 } 10829 } 10830 swiper.allowSlidePrev = allowSlidePrev; 10831 swiper.allowSlideNext = allowSlideNext; 10832 if (swiper.controller && swiper.controller.control && !byController) { 10833 const loopParams = { 10834 slideRealIndex, 10835 direction, 10836 setTranslate, 10837 activeSlideIndex, 10838 byController: true 10839 }; 10840 if (Array.isArray(swiper.controller.control)) { 10841 swiper.controller.control.forEach(c => { 10842 if (!c.destroyed && c.params.loop) c.loopFix({ 10843 ...loopParams, 10844 slideTo: c.params.slidesPerView === params.slidesPerView ? slideTo : false 10845 }); 10846 }); 10847 } else if (swiper.controller.control instanceof swiper.constructor && swiper.controller.control.params.loop) { 10848 swiper.controller.control.loopFix({ 10849 ...loopParams, 10850 slideTo: swiper.controller.control.params.slidesPerView === params.slidesPerView ? slideTo : false 10851 }); 10852 } 10853 } 10854 swiper.emit('loopFix'); 10855 } 10856 10857 function loopDestroy() { 10858 const swiper = this; 10859 const { 10860 params, 10861 slidesEl 10862 } = swiper; 10863 if (!params.loop || !slidesEl || swiper.virtual && swiper.params.virtual.enabled) return; 10864 swiper.recalcSlides(); 10865 const newSlidesOrder = []; 10866 swiper.slides.forEach(slideEl => { 10867 const index = typeof slideEl.swiperSlideIndex === 'undefined' ? slideEl.getAttribute('data-swiper-slide-index') * 1 : slideEl.swiperSlideIndex; 10868 newSlidesOrder[index] = slideEl; 10869 }); 10870 swiper.slides.forEach(slideEl => { 10871 slideEl.removeAttribute('data-swiper-slide-index'); 10872 }); 10873 newSlidesOrder.forEach(slideEl => { 10874 slidesEl.append(slideEl); 10875 }); 10876 swiper.recalcSlides(); 10877 swiper.slideTo(swiper.realIndex, 0); 10878 } 10879 10880 var loop = { 10881 loopCreate, 10882 loopFix, 10883 loopDestroy 10884 }; 10885 10886 function setGrabCursor(moving) { 10887 const swiper = this; 10888 if (!swiper.params.simulateTouch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) return; 10889 const el = swiper.params.touchEventsTarget === 'container' ? swiper.el : swiper.wrapperEl; 10890 if (swiper.isElement) { 10891 swiper.__preventObserver__ = true; 10892 } 10893 el.style.cursor = 'move'; 10894 el.style.cursor = moving ? 'grabbing' : 'grab'; 10895 if (swiper.isElement) { 10896 requestAnimationFrame(() => { 10897 swiper.__preventObserver__ = false; 10898 }); 10899 } 10900 } 10901 10902 function unsetGrabCursor() { 10903 const swiper = this; 10904 if (swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) { 10905 return; 10906 } 10907 if (swiper.isElement) { 10908 swiper.__preventObserver__ = true; 10909 } 10910 swiper[swiper.params.touchEventsTarget === 'container' ? 'el' : 'wrapperEl'].style.cursor = ''; 10911 if (swiper.isElement) { 10912 requestAnimationFrame(() => { 10913 swiper.__preventObserver__ = false; 10914 }); 10915 } 10916 } 10917 10918 var grabCursor = { 10919 setGrabCursor, 10920 unsetGrabCursor 10921 }; 10922 10923 // Modified from https://stackoverflow.com/questions/54520554/custom-element-getrootnode-closest-function-crossing-multiple-parent-shadowd 10924 function closestElement(selector, base = this) { 10925 function __closestFrom(el) { 10926 if (!el || el === getDocument() || el === getWindow()) return null; 10927 if (el.assignedSlot) el = el.assignedSlot; 10928 const found = el.closest(selector); 10929 if (!found && !el.getRootNode) { 10930 return null; 10931 } 10932 return found || __closestFrom(el.getRootNode().host); 10933 } 10934 return __closestFrom(base); 10935 } 10936 function preventEdgeSwipe(swiper, event, startX) { 10937 const window = getWindow(); 10938 const { 10939 params 10940 } = swiper; 10941 const edgeSwipeDetection = params.edgeSwipeDetection; 10942 const edgeSwipeThreshold = params.edgeSwipeThreshold; 10943 if (edgeSwipeDetection && (startX <= edgeSwipeThreshold || startX >= window.innerWidth - edgeSwipeThreshold)) { 10944 if (edgeSwipeDetection === 'prevent') { 10945 event.preventDefault(); 10946 return true; 10947 } 10948 return false; 10949 } 10950 return true; 10951 } 10952 function onTouchStart(event) { 10953 const swiper = this; 10954 const document = getDocument(); 10955 let e = event; 10956 if (e.originalEvent) e = e.originalEvent; 10957 const data = swiper.touchEventsData; 10958 if (e.type === 'pointerdown') { 10959 if (data.pointerId !== null && data.pointerId !== e.pointerId) { 10960 return; 10961 } 10962 data.pointerId = e.pointerId; 10963 } else if (e.type === 'touchstart' && e.targetTouches.length === 1) { 10964 data.touchId = e.targetTouches[0].identifier; 10965 } 10966 if (e.type === 'touchstart') { 10967 // don't proceed touch event 10968 preventEdgeSwipe(swiper, e, e.targetTouches[0].pageX); 10969 return; 10970 } 10971 const { 10972 params, 10973 touches, 10974 enabled 10975 } = swiper; 10976 if (!enabled) return; 10977 if (!params.simulateTouch && e.pointerType === 'mouse') return; 10978 if (swiper.animating && params.preventInteractionOnTransition) { 10979 return; 10980 } 10981 if (!swiper.animating && params.cssMode && params.loop) { 10982 swiper.loopFix(); 10983 } 10984 let targetEl = e.target; 10985 if (params.touchEventsTarget === 'wrapper') { 10986 if (!elementIsChildOf(targetEl, swiper.wrapperEl)) return; 10987 } 10988 if ('which' in e && e.which === 3) return; 10989 if ('button' in e && e.button > 0) return; 10990 if (data.isTouched && data.isMoved) return; 10991 10992 // change target el for shadow root component 10993 const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== ''; 10994 // eslint-disable-next-line 10995 const eventPath = e.composedPath ? e.composedPath() : e.path; 10996 if (swipingClassHasValue && e.target && e.target.shadowRoot && eventPath) { 10997 targetEl = eventPath[0]; 10998 } 10999 const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`; 11000 const isTargetShadow = !!(e.target && e.target.shadowRoot); 11001 11002 // use closestElement for shadow root element to get the actual closest for nested shadow root element 11003 if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, targetEl) : targetEl.closest(noSwipingSelector))) { 11004 swiper.allowClick = true; 11005 return; 11006 } 11007 if (params.swipeHandler) { 11008 if (!targetEl.closest(params.swipeHandler)) return; 11009 } 11010 touches.currentX = e.pageX; 11011 touches.currentY = e.pageY; 11012 const startX = touches.currentX; 11013 const startY = touches.currentY; 11014 11015 // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore 11016 11017 if (!preventEdgeSwipe(swiper, e, startX)) { 11018 return; 11019 } 11020 Object.assign(data, { 11021 isTouched: true, 11022 isMoved: false, 11023 allowTouchCallbacks: true, 11024 isScrolling: undefined, 11025 startMoving: undefined 11026 }); 11027 touches.startX = startX; 11028 touches.startY = startY; 11029 data.touchStartTime = now(); 11030 swiper.allowClick = true; 11031 swiper.updateSize(); 11032 swiper.swipeDirection = undefined; 11033 if (params.threshold > 0) data.allowThresholdMove = false; 11034 let preventDefault = true; 11035 if (targetEl.matches(data.focusableElements)) { 11036 preventDefault = false; 11037 if (targetEl.nodeName === 'SELECT') { 11038 data.isTouched = false; 11039 } 11040 } 11041 if (document.activeElement && document.activeElement.matches(data.focusableElements) && document.activeElement !== targetEl && (e.pointerType === 'mouse' || e.pointerType !== 'mouse' && !targetEl.matches(data.focusableElements))) { 11042 document.activeElement.blur(); 11043 } 11044 const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault; 11045 if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !targetEl.isContentEditable) { 11046 e.preventDefault(); 11047 } 11048 if (params.freeMode && params.freeMode.enabled && swiper.freeMode && swiper.animating && !params.cssMode) { 11049 swiper.freeMode.onTouchStart(); 11050 } 11051 swiper.emit('touchStart', e); 11052 } 11053 11054 function onTouchMove(event) { 11055 const document = getDocument(); 11056 const swiper = this; 11057 const data = swiper.touchEventsData; 11058 const { 11059 params, 11060 touches, 11061 rtlTranslate: rtl, 11062 enabled 11063 } = swiper; 11064 if (!enabled) return; 11065 if (!params.simulateTouch && event.pointerType === 'mouse') return; 11066 let e = event; 11067 if (e.originalEvent) e = e.originalEvent; 11068 if (e.type === 'pointermove') { 11069 if (data.touchId !== null) return; // return from pointer if we use touch 11070 const id = e.pointerId; 11071 if (id !== data.pointerId) return; 11072 } 11073 let targetTouch; 11074 if (e.type === 'touchmove') { 11075 targetTouch = [...e.changedTouches].find(t => t.identifier === data.touchId); 11076 if (!targetTouch || targetTouch.identifier !== data.touchId) return; 11077 } else { 11078 targetTouch = e; 11079 } 11080 if (!data.isTouched) { 11081 if (data.startMoving && data.isScrolling) { 11082 swiper.emit('touchMoveOpposite', e); 11083 } 11084 return; 11085 } 11086 const pageX = targetTouch.pageX; 11087 const pageY = targetTouch.pageY; 11088 if (e.preventedByNestedSwiper) { 11089 touches.startX = pageX; 11090 touches.startY = pageY; 11091 return; 11092 } 11093 if (!swiper.allowTouchMove) { 11094 if (!e.target.matches(data.focusableElements)) { 11095 swiper.allowClick = false; 11096 } 11097 if (data.isTouched) { 11098 Object.assign(touches, { 11099 startX: pageX, 11100 startY: pageY, 11101 currentX: pageX, 11102 currentY: pageY 11103 }); 11104 data.touchStartTime = now(); 11105 } 11106 return; 11107 } 11108 if (params.touchReleaseOnEdges && !params.loop) { 11109 if (swiper.isVertical()) { 11110 // Vertical 11111 if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper.translate >= swiper.minTranslate()) { 11112 data.isTouched = false; 11113 data.isMoved = false; 11114 return; 11115 } 11116 } else if (rtl && (pageX > touches.startX && -swiper.translate <= swiper.maxTranslate() || pageX < touches.startX && -swiper.translate >= swiper.minTranslate())) { 11117 return; 11118 } else if (!rtl && (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX && swiper.translate >= swiper.minTranslate())) { 11119 return; 11120 } 11121 } 11122 if (document.activeElement && document.activeElement.matches(data.focusableElements) && document.activeElement !== e.target && e.pointerType !== 'mouse') { 11123 document.activeElement.blur(); 11124 } 11125 if (document.activeElement) { 11126 if (e.target === document.activeElement && e.target.matches(data.focusableElements)) { 11127 data.isMoved = true; 11128 swiper.allowClick = false; 11129 return; 11130 } 11131 } 11132 if (data.allowTouchCallbacks) { 11133 swiper.emit('touchMove', e); 11134 } 11135 touches.previousX = touches.currentX; 11136 touches.previousY = touches.currentY; 11137 touches.currentX = pageX; 11138 touches.currentY = pageY; 11139 const diffX = touches.currentX - touches.startX; 11140 const diffY = touches.currentY - touches.startY; 11141 if (swiper.params.threshold && Math.sqrt(diffX ** 2 + diffY ** 2) < swiper.params.threshold) return; 11142 if (typeof data.isScrolling === 'undefined') { 11143 let touchAngle; 11144 if (swiper.isHorizontal() && touches.currentY === touches.startY || swiper.isVertical() && touches.currentX === touches.startX) { 11145 data.isScrolling = false;
vendor: 8,243 bytes, lines 11146-11351
11146 } else { 11147 // eslint-disable-next-line 11148 if (diffX * diffX + diffY * diffY >= 25) { 11149 touchAngle = Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180 / Math.PI; 11150 data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : 90 - touchAngle > params.touchAngle; 11151 } 11152 } 11153 } 11154 if (data.isScrolling) { 11155 swiper.emit('touchMoveOpposite', e); 11156 } 11157 if (typeof data.startMoving === 'undefined') { 11158 if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) { 11159 data.startMoving = true; 11160 } 11161 } 11162 if (data.isScrolling || e.type === 'touchmove' && data.preventTouchMoveFromPointerMove) { 11163 data.isTouched = false; 11164 return; 11165 } 11166 if (!data.startMoving) { 11167 return; 11168 } 11169 swiper.allowClick = false; 11170 if (!params.cssMode && e.cancelable) { 11171 e.preventDefault(); 11172 } 11173 if (params.touchMoveStopPropagation && !params.nested) { 11174 e.stopPropagation(); 11175 } 11176 let diff = swiper.isHorizontal() ? diffX : diffY; 11177 let touchesDiff = swiper.isHorizontal() ? touches.currentX - touches.previousX : touches.currentY - touches.previousY; 11178 if (params.oneWayMovement) { 11179 diff = Math.abs(diff) * (rtl ? 1 : -1); 11180 touchesDiff = Math.abs(touchesDiff) * (rtl ? 1 : -1); 11181 } 11182 touches.diff = diff; 11183 diff *= params.touchRatio; 11184 if (rtl) { 11185 diff = -diff; 11186 touchesDiff = -touchesDiff; 11187 } 11188 const prevTouchesDirection = swiper.touchesDirection; 11189 swiper.swipeDirection = diff > 0 ? 'prev' : 'next'; 11190 swiper.touchesDirection = touchesDiff > 0 ? 'prev' : 'next'; 11191 const isLoop = swiper.params.loop && !params.cssMode; 11192 const allowLoopFix = swiper.touchesDirection === 'next' && swiper.allowSlideNext || swiper.touchesDirection === 'prev' && swiper.allowSlidePrev; 11193 if (!data.isMoved) { 11194 if (isLoop && allowLoopFix) { 11195 swiper.loopFix({ 11196 direction: swiper.swipeDirection 11197 }); 11198 } 11199 data.startTranslate = swiper.getTranslate(); 11200 swiper.setTransition(0); 11201 if (swiper.animating) { 11202 const evt = new window.CustomEvent('transitionend', { 11203 bubbles: true, 11204 cancelable: true, 11205 detail: { 11206 bySwiperTouchMove: true 11207 } 11208 }); 11209 swiper.wrapperEl.dispatchEvent(evt); 11210 } 11211 data.allowMomentumBounce = false; 11212 // Grab Cursor 11213 if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) { 11214 swiper.setGrabCursor(true); 11215 } 11216 swiper.emit('sliderFirstMove', e); 11217 } 11218 let loopFixed; 11219 new Date().getTime(); 11220 if (params._loopSwapReset !== false && data.isMoved && data.allowThresholdMove && prevTouchesDirection !== swiper.touchesDirection && isLoop && allowLoopFix && Math.abs(diff) >= 1) { 11221 Object.assign(touches, { 11222 startX: pageX, 11223 startY: pageY, 11224 currentX: pageX, 11225 currentY: pageY, 11226 startTranslate: data.currentTranslate 11227 }); 11228 data.loopSwapReset = true; 11229 data.startTranslate = data.currentTranslate; 11230 return; 11231 } 11232 swiper.emit('sliderMove', e); 11233 data.isMoved = true; 11234 data.currentTranslate = diff + data.startTranslate; 11235 let disableParentSwiper = true; 11236 let resistanceRatio = params.resistanceRatio; 11237 if (params.touchReleaseOnEdges) { 11238 resistanceRatio = 0; 11239 } 11240 if (diff > 0) { 11241 if (isLoop && allowLoopFix && !loopFixed && data.allowThresholdMove && data.currentTranslate > (params.centeredSlides ? swiper.minTranslate() - swiper.slidesSizesGrid[swiper.activeIndex + 1] - (params.slidesPerView !== 'auto' && swiper.slides.length - params.slidesPerView >= 2 ? swiper.slidesSizesGrid[swiper.activeIndex + 1] + swiper.params.spaceBetween : 0) - swiper.params.spaceBetween : swiper.minTranslate())) { 11242 swiper.loopFix({ 11243 direction: 'prev', 11244 setTranslate: true, 11245 activeSlideIndex: 0 11246 }); 11247 } 11248 if (data.currentTranslate > swiper.minTranslate()) { 11249 disableParentSwiper = false; 11250 if (params.resistance) { 11251 data.currentTranslate = swiper.minTranslate() - 1 + (-swiper.minTranslate() + data.startTranslate + diff) ** resistanceRatio; 11252 } 11253 } 11254 } else if (diff < 0) { 11255 if (isLoop && allowLoopFix && !loopFixed && data.allowThresholdMove && data.currentTranslate < (params.centeredSlides ? swiper.maxTranslate() + swiper.slidesSizesGrid[swiper.slidesSizesGrid.length - 1] + swiper.params.spaceBetween + (params.slidesPerView !== 'auto' && swiper.slides.length - params.slidesPerView >= 2 ? swiper.slidesSizesGrid[swiper.slidesSizesGrid.length - 1] + swiper.params.spaceBetween : 0) : swiper.maxTranslate())) { 11256 swiper.loopFix({ 11257 direction: 'next', 11258 setTranslate: true, 11259 activeSlideIndex: swiper.slides.length - (params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10))) 11260 }); 11261 } 11262 if (data.currentTranslate < swiper.maxTranslate()) { 11263 disableParentSwiper = false; 11264 if (params.resistance) { 11265 data.currentTranslate = swiper.maxTranslate() + 1 - (swiper.maxTranslate() - data.startTranslate - diff) ** resistanceRatio; 11266 } 11267 } 11268 } 11269 if (disableParentSwiper) { 11270 e.preventedByNestedSwiper = true; 11271 } 11272 11273 // Directions locks 11274 if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) { 11275 data.currentTranslate = data.startTranslate; 11276 } 11277 if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) { 11278 data.currentTranslate = data.startTranslate; 11279 } 11280 if (!swiper.allowSlidePrev && !swiper.allowSlideNext) { 11281 data.currentTranslate = data.startTranslate; 11282 } 11283 11284 // Threshold 11285 if (params.threshold > 0) { 11286 if (Math.abs(diff) > params.threshold || data.allowThresholdMove) { 11287 if (!data.allowThresholdMove) { 11288 data.allowThresholdMove = true; 11289 touches.startX = touches.currentX; 11290 touches.startY = touches.currentY; 11291 data.currentTranslate = data.startTranslate; 11292 touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY; 11293 return; 11294 } 11295 } else { 11296 data.currentTranslate = data.startTranslate; 11297 return; 11298 } 11299 } 11300 if (!params.followFinger || params.cssMode) return; 11301 11302 // Update active index in free mode 11303 if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) { 11304 swiper.updateActiveIndex(); 11305 swiper.updateSlidesClasses(); 11306 } 11307 if (params.freeMode && params.freeMode.enabled && swiper.freeMode) { 11308 swiper.freeMode.onTouchMove(); 11309 } 11310 // Update progress 11311 swiper.updateProgress(data.currentTranslate); 11312 // Update translate 11313 swiper.setTranslate(data.currentTranslate); 11314 } 11315 11316 function onTouchEnd(event) { 11317 const swiper = this; 11318 const data = swiper.touchEventsData; 11319 let e = event; 11320 if (e.originalEvent) e = e.originalEvent; 11321 let targetTouch; 11322 const isTouchEvent = e.type === 'touchend' || e.type === 'touchcancel'; 11323 if (!isTouchEvent) { 11324 if (data.touchId !== null) return; // return from pointer if we use touch 11325 if (e.pointerId !== data.pointerId) return; 11326 targetTouch = e; 11327 } else { 11328 targetTouch = [...e.changedTouches].find(t => t.identifier === data.touchId); 11329 if (!targetTouch || targetTouch.identifier !== data.touchId) return; 11330 } 11331 if (['pointercancel', 'pointerout', 'pointerleave', 'contextmenu'].includes(e.type)) { 11332 const proceed = ['pointercancel', 'contextmenu'].includes(e.type) && (swiper.browser.isSafari || swiper.browser.isWebView); 11333 if (!proceed) { 11334 return; 11335 } 11336 } 11337 data.pointerId = null; 11338 data.touchId = null; 11339 const { 11340 params, 11341 touches, 11342 rtlTranslate: rtl, 11343 slidesGrid, 11344 enabled 11345 } = swiper; 11346 if (!enabled) return; 11347 if (!params.simulateTouch && e.pointerType === 'mouse') return; 11348 if (data.allowTouchCallbacks) { 11349 swiper.emit('touchEnd', e); 11350 } 11351 data.allowTouchCallbacks = false;
vendor: 4,775 bytes, lines 11352-11483
11352 if (!data.isTouched) { 11353 if (data.isMoved && params.grabCursor) { 11354 swiper.setGrabCursor(false); 11355 } 11356 data.isMoved = false; 11357 data.startMoving = false; 11358 return; 11359 } 11360 11361 // Return Grab Cursor 11362 if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) { 11363 swiper.setGrabCursor(false); 11364 } 11365 11366 // Time diff 11367 const touchEndTime = now(); 11368 const timeDiff = touchEndTime - data.touchStartTime; 11369 11370 // Tap, doubleTap, Click 11371 if (swiper.allowClick) { 11372 const pathTree = e.path || e.composedPath && e.composedPath(); 11373 swiper.updateClickedSlide(pathTree && pathTree[0] || e.target, pathTree); 11374 swiper.emit('tap click', e); 11375 if (timeDiff < 300 && touchEndTime - data.lastClickTime < 300) { 11376 swiper.emit('doubleTap doubleClick', e); 11377 } 11378 } 11379 data.lastClickTime = now(); 11380 nextTick(() => { 11381 if (!swiper.destroyed) swiper.allowClick = true; 11382 }); 11383 if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 && !data.loopSwapReset || data.currentTranslate === data.startTranslate && !data.loopSwapReset) { 11384 data.isTouched = false; 11385 data.isMoved = false; 11386 data.startMoving = false; 11387 return; 11388 } 11389 data.isTouched = false; 11390 data.isMoved = false; 11391 data.startMoving = false; 11392 let currentPos; 11393 if (params.followFinger) { 11394 currentPos = rtl ? swiper.translate : -swiper.translate; 11395 } else { 11396 currentPos = -data.currentTranslate; 11397 } 11398 if (params.cssMode) { 11399 return; 11400 } 11401 if (params.freeMode && params.freeMode.enabled) { 11402 swiper.freeMode.onTouchEnd({ 11403 currentPos 11404 }); 11405 return; 11406 } 11407 11408 // Find current slide 11409 const swipeToLast = currentPos >= -swiper.maxTranslate() && !swiper.params.loop; 11410 let stopIndex = 0; 11411 let groupSize = swiper.slidesSizesGrid[0]; 11412 for (let i = 0; i < slidesGrid.length; i += i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup) { 11413 const increment = i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup; 11414 if (typeof slidesGrid[i + increment] !== 'undefined') { 11415 if (swipeToLast || currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) { 11416 stopIndex = i; 11417 groupSize = slidesGrid[i + increment] - slidesGrid[i]; 11418 } 11419 } else if (swipeToLast || currentPos >= slidesGrid[i]) { 11420 stopIndex = i; 11421 groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2]; 11422 } 11423 } 11424 let rewindFirstIndex = null; 11425 let rewindLastIndex = null; 11426 if (params.rewind) { 11427 if (swiper.isBeginning) { 11428 rewindLastIndex = params.virtual && params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1; 11429 } else if (swiper.isEnd) { 11430 rewindFirstIndex = 0; 11431 } 11432 } 11433 // Find current slide size 11434 const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize; 11435 const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup; 11436 if (timeDiff > params.longSwipesMs) { 11437 // Long touches 11438 if (!params.longSwipes) { 11439 swiper.slideTo(swiper.activeIndex); 11440 return; 11441 } 11442 if (swiper.swipeDirection === 'next') { 11443 if (ratio >= params.longSwipesRatio) swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);else swiper.slideTo(stopIndex); 11444 } 11445 if (swiper.swipeDirection === 'prev') { 11446 if (ratio > 1 - params.longSwipesRatio) { 11447 swiper.slideTo(stopIndex + increment); 11448 } else if (rewindLastIndex !== null && ratio < 0 && Math.abs(ratio) > params.longSwipesRatio) { 11449 swiper.slideTo(rewindLastIndex); 11450 } else { 11451 swiper.slideTo(stopIndex); 11452 } 11453 } 11454 } else { 11455 // Short swipes 11456 if (!params.shortSwipes) { 11457 swiper.slideTo(swiper.activeIndex); 11458 return; 11459 } 11460 const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl); 11461 if (!isNavButtonTarget) { 11462 if (swiper.swipeDirection === 'next') { 11463 swiper.slideTo(rewindFirstIndex !== null ? rewindFirstIndex : stopIndex + increment); 11464 } 11465 if (swiper.swipeDirection === 'prev') { 11466 swiper.slideTo(rewindLastIndex !== null ? rewindLastIndex : stopIndex); 11467 } 11468 } else if (e.target === swiper.navigation.nextEl) { 11469 swiper.slideTo(stopIndex + increment); 11470 } else { 11471 swiper.slideTo(stopIndex); 11472 } 11473 } 11474 } 11475 11476 function onResize() { 11477 const swiper = this; 11478 const { 11479 params, 11480 el 11481 } = swiper; 11482 if (el && el.offsetWidth === 0) return; 11483
vendor: 6,853 bytes, lines 11484-11706
11484 // Breakpoints 11485 if (params.breakpoints) { 11486 swiper.setBreakpoint(); 11487 } 11488 11489 // Save locks 11490 const { 11491 allowSlideNext, 11492 allowSlidePrev, 11493 snapGrid 11494 } = swiper; 11495 const isVirtual = swiper.virtual && swiper.params.virtual.enabled; 11496 11497 // Disable locks on resize 11498 swiper.allowSlideNext = true; 11499 swiper.allowSlidePrev = true; 11500 swiper.updateSize(); 11501 swiper.updateSlides(); 11502 swiper.updateSlidesClasses(); 11503 const isVirtualLoop = isVirtual && params.loop; 11504 if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides && !isVirtualLoop) { 11505 swiper.slideTo(swiper.slides.length - 1, 0, false, true); 11506 } else { 11507 if (swiper.params.loop && !isVirtual) { 11508 swiper.slideToLoop(swiper.realIndex, 0, false, true); 11509 } else { 11510 swiper.slideTo(swiper.activeIndex, 0, false, true); 11511 } 11512 } 11513 if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) { 11514 clearTimeout(swiper.autoplay.resizeTimeout); 11515 swiper.autoplay.resizeTimeout = setTimeout(() => { 11516 if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) { 11517 swiper.autoplay.resume(); 11518 } 11519 }, 500); 11520 } 11521 // Return locks after resize 11522 swiper.allowSlidePrev = allowSlidePrev; 11523 swiper.allowSlideNext = allowSlideNext; 11524 if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) { 11525 swiper.checkOverflow(); 11526 } 11527 } 11528 11529 function onClick(e) { 11530 const swiper = this; 11531 if (!swiper.enabled) return; 11532 if (!swiper.allowClick) { 11533 if (swiper.params.preventClicks) e.preventDefault(); 11534 if (swiper.params.preventClicksPropagation && swiper.animating) { 11535 e.stopPropagation(); 11536 e.stopImmediatePropagation(); 11537 } 11538 } 11539 } 11540 11541 function onScroll() { 11542 const swiper = this; 11543 const { 11544 wrapperEl, 11545 rtlTranslate, 11546 enabled 11547 } = swiper; 11548 if (!enabled) return; 11549 swiper.previousTranslate = swiper.translate; 11550 if (swiper.isHorizontal()) { 11551 swiper.translate = -wrapperEl.scrollLeft; 11552 } else { 11553 swiper.translate = -wrapperEl.scrollTop; 11554 } 11555 // eslint-disable-next-line 11556 if (swiper.translate === 0) swiper.translate = 0; 11557 swiper.updateActiveIndex(); 11558 swiper.updateSlidesClasses(); 11559 let newProgress; 11560 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate(); 11561 if (translatesDiff === 0) { 11562 newProgress = 0; 11563 } else { 11564 newProgress = (swiper.translate - swiper.minTranslate()) / translatesDiff; 11565 } 11566 if (newProgress !== swiper.progress) { 11567 swiper.updateProgress(rtlTranslate ? -swiper.translate : swiper.translate); 11568 } 11569 swiper.emit('setTranslate', swiper.translate, false); 11570 } 11571 11572 function onLoad(e) { 11573 const swiper = this; 11574 processLazyPreloader(swiper, e.target); 11575 if (swiper.params.cssMode || swiper.params.slidesPerView !== 'auto' && !swiper.params.autoHeight) { 11576 return; 11577 } 11578 swiper.update(); 11579 } 11580 11581 function onDocumentTouchStart() { 11582 const swiper = this; 11583 if (swiper.documentTouchHandlerProceeded) return; 11584 swiper.documentTouchHandlerProceeded = true; 11585 if (swiper.params.touchReleaseOnEdges) { 11586 swiper.el.style.touchAction = 'auto'; 11587 } 11588 } 11589 11590 const events = (swiper, method) => { 11591 const document = getDocument(); 11592 const { 11593 params, 11594 el, 11595 wrapperEl, 11596 device 11597 } = swiper; 11598 const capture = !!params.nested; 11599 const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener'; 11600 const swiperMethod = method; 11601 if (!el || typeof el === 'string') return; 11602 11603 // Touch Events 11604 document[domMethod]('touchstart', swiper.onDocumentTouchStart, { 11605 passive: false, 11606 capture 11607 }); 11608 el[domMethod]('touchstart', swiper.onTouchStart, { 11609 passive: false 11610 }); 11611 el[domMethod]('pointerdown', swiper.onTouchStart, { 11612 passive: false 11613 }); 11614 document[domMethod]('touchmove', swiper.onTouchMove, { 11615 passive: false, 11616 capture 11617 }); 11618 document[domMethod]('pointermove', swiper.onTouchMove, { 11619 passive: false, 11620 capture 11621 }); 11622 document[domMethod]('touchend', swiper.onTouchEnd, { 11623 passive: true 11624 }); 11625 document[domMethod]('pointerup', swiper.onTouchEnd, { 11626 passive: true 11627 }); 11628 document[domMethod]('pointercancel', swiper.onTouchEnd, { 11629 passive: true 11630 }); 11631 document[domMethod]('touchcancel', swiper.onTouchEnd, { 11632 passive: true 11633 }); 11634 document[domMethod]('pointerout', swiper.onTouchEnd, { 11635 passive: true 11636 }); 11637 document[domMethod]('pointerleave', swiper.onTouchEnd, { 11638 passive: true 11639 }); 11640 document[domMethod]('contextmenu', swiper.onTouchEnd, { 11641 passive: true 11642 }); 11643 11644 // Prevent Links Clicks 11645 if (params.preventClicks || params.preventClicksPropagation) { 11646 el[domMethod]('click', swiper.onClick, true); 11647 } 11648 if (params.cssMode) { 11649 wrapperEl[domMethod]('scroll', swiper.onScroll); 11650 } 11651 11652 // Resize handler 11653 if (params.updateOnWindowResize) { 11654 swiper[swiperMethod](device.ios || device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate', onResize, true); 11655 } else { 11656 swiper[swiperMethod]('observerUpdate', onResize, true); 11657 } 11658 11659 // Images loader 11660 el[domMethod]('load', swiper.onLoad, { 11661 capture: true 11662 }); 11663 }; 11664 function attachEvents() { 11665 const swiper = this; 11666 const { 11667 params 11668 } = swiper; 11669 swiper.onTouchStart = onTouchStart.bind(swiper); 11670 swiper.onTouchMove = onTouchMove.bind(swiper); 11671 swiper.onTouchEnd = onTouchEnd.bind(swiper); 11672 swiper.onDocumentTouchStart = onDocumentTouchStart.bind(swiper); 11673 if (params.cssMode) { 11674 swiper.onScroll = onScroll.bind(swiper); 11675 } 11676 swiper.onClick = onClick.bind(swiper); 11677 swiper.onLoad = onLoad.bind(swiper); 11678 events(swiper, 'on'); 11679 } 11680 function detachEvents() { 11681 const swiper = this; 11682 events(swiper, 'off'); 11683 } 11684 var events$1 = { 11685 attachEvents, 11686 detachEvents 11687 }; 11688 11689 const isGridEnabled = (swiper, params) => { 11690 return swiper.grid && params.grid && params.grid.rows > 1; 11691 }; 11692 function setBreakpoint() { 11693 const swiper = this; 11694 const { 11695 realIndex, 11696 initialized, 11697 params, 11698 el 11699 } = swiper; 11700 const breakpoints = params.breakpoints; 11701 if (!breakpoints || breakpoints && Object.keys(breakpoints).length === 0) return; 11702 const document = getDocument(); 11703 11704 // Get breakpoint for window/container width and update parameters 11705 const breakpointsBase = params.breakpointsBase === 'window' || !params.breakpointsBase ? params.breakpointsBase : 'container'; 11706 const breakpointContainer = ['window', 'container'].includes(params.breakpointsBase) || !params.breakpointsBase ? swiper.el : document.querySelector(params.breakpointsBase);
vendor: 26,382 bytes, lines 11707-12521
11707 const breakpoint = swiper.getBreakpoint(breakpoints, breakpointsBase, breakpointContainer); 11708 if (!breakpoint || swiper.currentBreakpoint === breakpoint) return; 11709 const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined; 11710 const breakpointParams = breakpointOnlyParams || swiper.originalParams; 11711 const wasMultiRow = isGridEnabled(swiper, params); 11712 const isMultiRow = isGridEnabled(swiper, breakpointParams); 11713 const wasGrabCursor = swiper.params.grabCursor; 11714 const isGrabCursor = breakpointParams.grabCursor; 11715 const wasEnabled = params.enabled; 11716 if (wasMultiRow && !isMultiRow) { 11717 el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`); 11718 swiper.emitContainerClasses(); 11719 } else if (!wasMultiRow && isMultiRow) { 11720 el.classList.add(`${params.containerModifierClass}grid`); 11721 if (breakpointParams.grid.fill && breakpointParams.grid.fill === 'column' || !breakpointParams.grid.fill && params.grid.fill === 'column') { 11722 el.classList.add(`${params.containerModifierClass}grid-column`); 11723 } 11724 swiper.emitContainerClasses(); 11725 } 11726 if (wasGrabCursor && !isGrabCursor) { 11727 swiper.unsetGrabCursor(); 11728 } else if (!wasGrabCursor && isGrabCursor) { 11729 swiper.setGrabCursor(); 11730 } 11731 11732 // Toggle navigation, pagination, scrollbar 11733 ['navigation', 'pagination', 'scrollbar'].forEach(prop => { 11734 if (typeof breakpointParams[prop] === 'undefined') return; 11735 const wasModuleEnabled = params[prop] && params[prop].enabled; 11736 const isModuleEnabled = breakpointParams[prop] && breakpointParams[prop].enabled; 11737 if (wasModuleEnabled && !isModuleEnabled) { 11738 swiper[prop].disable(); 11739 } 11740 if (!wasModuleEnabled && isModuleEnabled) { 11741 swiper[prop].enable(); 11742 } 11743 }); 11744 const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction; 11745 const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged); 11746 const wasLoop = params.loop; 11747 if (directionChanged && initialized) { 11748 swiper.changeDirection(); 11749 } 11750 extend(swiper.params, breakpointParams); 11751 const isEnabled = swiper.params.enabled; 11752 const hasLoop = swiper.params.loop; 11753 Object.assign(swiper, { 11754 allowTouchMove: swiper.params.allowTouchMove, 11755 allowSlideNext: swiper.params.allowSlideNext, 11756 allowSlidePrev: swiper.params.allowSlidePrev 11757 }); 11758 if (wasEnabled && !isEnabled) { 11759 swiper.disable(); 11760 } else if (!wasEnabled && isEnabled) { 11761 swiper.enable(); 11762 } 11763 swiper.currentBreakpoint = breakpoint; 11764 swiper.emit('_beforeBreakpoint', breakpointParams); 11765 if (initialized) { 11766 if (needsReLoop) { 11767 swiper.loopDestroy(); 11768 swiper.loopCreate(realIndex); 11769 swiper.updateSlides(); 11770 } else if (!wasLoop && hasLoop) { 11771 swiper.loopCreate(realIndex); 11772 swiper.updateSlides(); 11773 } else if (wasLoop && !hasLoop) { 11774 swiper.loopDestroy(); 11775 } 11776 } 11777 swiper.emit('breakpoint', breakpointParams); 11778 } 11779 11780 function getBreakpoint(breakpoints, base = 'window', containerEl) { 11781 if (!breakpoints || base === 'container' && !containerEl) return undefined; 11782 let breakpoint = false; 11783 const window = getWindow(); 11784 const currentHeight = base === 'window' ? window.innerHeight : containerEl.clientHeight; 11785 const points = Object.keys(breakpoints).map(point => { 11786 if (typeof point === 'string' && point.indexOf('@') === 0) { 11787 const minRatio = parseFloat(point.substr(1)); 11788 const value = currentHeight * minRatio; 11789 return { 11790 value, 11791 point 11792 }; 11793 } 11794 return { 11795 value: point, 11796 point 11797 }; 11798 }); 11799 points.sort((a, b) => parseInt(a.value, 10) - parseInt(b.value, 10)); 11800 for (let i = 0; i < points.length; i += 1) { 11801 const { 11802 point, 11803 value 11804 } = points[i]; 11805 if (base === 'window') { 11806 if (window.matchMedia(`(min-width: ${value}px)`).matches) { 11807 breakpoint = point; 11808 } 11809 } else if (value <= containerEl.clientWidth) { 11810 breakpoint = point; 11811 } 11812 } 11813 return breakpoint || 'max'; 11814 } 11815 11816 var breakpoints = { 11817 setBreakpoint, 11818 getBreakpoint 11819 }; 11820 11821 function prepareClasses(entries, prefix) { 11822 const resultClasses = []; 11823 entries.forEach(item => { 11824 if (typeof item === 'object') { 11825 Object.keys(item).forEach(classNames => { 11826 if (item[classNames]) { 11827 resultClasses.push(prefix + classNames); 11828 } 11829 }); 11830 } else if (typeof item === 'string') { 11831 resultClasses.push(prefix + item); 11832 } 11833 }); 11834 return resultClasses; 11835 } 11836 function addClasses() { 11837 const swiper = this; 11838 const { 11839 classNames, 11840 params, 11841 rtl, 11842 el, 11843 device 11844 } = swiper; 11845 // prettier-ignore 11846 const suffixes = prepareClasses(['initialized', params.direction, { 11847 'free-mode': swiper.params.freeMode && params.freeMode.enabled 11848 }, { 11849 'autoheight': params.autoHeight 11850 }, { 11851 'rtl': rtl 11852 }, { 11853 'grid': params.grid && params.grid.rows > 1 11854 }, { 11855 'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column' 11856 }, { 11857 'android': device.android 11858 }, { 11859 'ios': device.ios 11860 }, { 11861 'css-mode': params.cssMode 11862 }, { 11863 'centered': params.cssMode && params.centeredSlides 11864 }, { 11865 'watch-progress': params.watchSlidesProgress 11866 }], params.containerModifierClass); 11867 classNames.push(...suffixes); 11868 el.classList.add(...classNames); 11869 swiper.emitContainerClasses(); 11870 } 11871 11872 function removeClasses() { 11873 const swiper = this; 11874 const { 11875 el, 11876 classNames 11877 } = swiper; 11878 if (!el || typeof el === 'string') return; 11879 el.classList.remove(...classNames); 11880 swiper.emitContainerClasses(); 11881 } 11882 11883 var classes = { 11884 addClasses, 11885 removeClasses 11886 }; 11887 11888 function checkOverflow() { 11889 const swiper = this; 11890 const { 11891 isLocked: wasLocked, 11892 params 11893 } = swiper; 11894 const { 11895 slidesOffsetBefore 11896 } = params; 11897 if (slidesOffsetBefore) { 11898 const lastSlideIndex = swiper.slides.length - 1; 11899 const lastSlideRightEdge = swiper.slidesGrid[lastSlideIndex] + swiper.slidesSizesGrid[lastSlideIndex] + slidesOffsetBefore * 2; 11900 swiper.isLocked = swiper.size > lastSlideRightEdge; 11901 } else { 11902 swiper.isLocked = swiper.snapGrid.length === 1; 11903 } 11904 if (params.allowSlideNext === true) { 11905 swiper.allowSlideNext = !swiper.isLocked; 11906 } 11907 if (params.allowSlidePrev === true) { 11908 swiper.allowSlidePrev = !swiper.isLocked; 11909 } 11910 if (wasLocked && wasLocked !== swiper.isLocked) { 11911 swiper.isEnd = false; 11912 } 11913 if (wasLocked !== swiper.isLocked) { 11914 swiper.emit(swiper.isLocked ? 'lock' : 'unlock'); 11915 } 11916 } 11917 var checkOverflow$1 = { 11918 checkOverflow 11919 }; 11920 11921 var defaults = { 11922 init: true, 11923 direction: 'horizontal', 11924 oneWayMovement: false, 11925 swiperElementNodeName: 'SWIPER-CONTAINER', 11926 touchEventsTarget: 'wrapper', 11927 initialSlide: 0, 11928 speed: 300, 11929 cssMode: false, 11930 updateOnWindowResize: true, 11931 resizeObserver: true, 11932 nested: false, 11933 createElements: false, 11934 eventsPrefix: 'swiper', 11935 enabled: true, 11936 focusableElements: 'input, select, option, textarea, button, video, label', 11937 // Overrides 11938 width: null, 11939 height: null, 11940 // 11941 preventInteractionOnTransition: false, 11942 // ssr 11943 userAgent: null, 11944 url: null, 11945 // To support iOS's swipe-to-go-back gesture (when being used in-app). 11946 edgeSwipeDetection: false, 11947 edgeSwipeThreshold: 20, 11948 // Autoheight 11949 autoHeight: false, 11950 // Set wrapper width 11951 setWrapperSize: false, 11952 // Virtual Translate 11953 virtualTranslate: false, 11954 // Effects 11955 effect: 'slide', 11956 // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip' 11957 11958 // Breakpoints 11959 breakpoints: undefined, 11960 breakpointsBase: 'window', 11961 // Slides grid 11962 spaceBetween: 0, 11963 slidesPerView: 1, 11964 slidesPerGroup: 1, 11965 slidesPerGroupSkip: 0, 11966 slidesPerGroupAuto: false, 11967 centeredSlides: false, 11968 centeredSlidesBounds: false, 11969 slidesOffsetBefore: 0, 11970 // in px 11971 slidesOffsetAfter: 0, 11972 // in px 11973 normalizeSlideIndex: true, 11974 centerInsufficientSlides: false, 11975 // Disable swiper and hide navigation when container not overflow 11976 watchOverflow: true, 11977 // Round length 11978 roundLengths: false, 11979 // Touches 11980 touchRatio: 1, 11981 touchAngle: 45, 11982 simulateTouch: true, 11983 shortSwipes: true, 11984 longSwipes: true, 11985 longSwipesRatio: 0.5, 11986 longSwipesMs: 300, 11987 followFinger: true, 11988 allowTouchMove: true, 11989 threshold: 5, 11990 touchMoveStopPropagation: false, 11991 touchStartPreventDefault: true, 11992 touchStartForcePreventDefault: false, 11993 touchReleaseOnEdges: false, 11994 // Unique Navigation Elements 11995 uniqueNavElements: true, 11996 // Resistance 11997 resistance: true, 11998 resistanceRatio: 0.85, 11999 // Progress 12000 watchSlidesProgress: false, 12001 // Cursor 12002 grabCursor: false, 12003 // Clicks 12004 preventClicks: true, 12005 preventClicksPropagation: true, 12006 slideToClickedSlide: false, 12007 // loop 12008 loop: false, 12009 loopAddBlankSlides: true, 12010 loopAdditionalSlides: 0, 12011 loopPreventsSliding: true, 12012 // rewind 12013 rewind: false, 12014 // Swiping/no swiping 12015 allowSlidePrev: true, 12016 allowSlideNext: true, 12017 swipeHandler: null, 12018 // '.swipe-handler', 12019 noSwiping: true, 12020 noSwipingClass: 'swiper-no-swiping', 12021 noSwipingSelector: null, 12022 // Passive Listeners 12023 passiveListeners: true, 12024 maxBackfaceHiddenSlides: 10, 12025 // NS 12026 containerModifierClass: 'swiper-', 12027 // NEW 12028 slideClass: 'swiper-slide', 12029 slideBlankClass: 'swiper-slide-blank', 12030 slideActiveClass: 'swiper-slide-active', 12031 slideVisibleClass: 'swiper-slide-visible', 12032 slideFullyVisibleClass: 'swiper-slide-fully-visible', 12033 slideNextClass: 'swiper-slide-next', 12034 slidePrevClass: 'swiper-slide-prev', 12035 wrapperClass: 'swiper-wrapper', 12036 lazyPreloaderClass: 'swiper-lazy-preloader', 12037 lazyPreloadPrevNext: 0, 12038 // Callbacks 12039 runCallbacksOnInit: true, 12040 // Internals 12041 _emitClasses: false 12042 }; 12043 12044 function moduleExtendParams(params, allModulesParams) { 12045 return function extendParams(obj = {}) { 12046 const moduleParamName = Object.keys(obj)[0]; 12047 const moduleParams = obj[moduleParamName]; 12048 if (typeof moduleParams !== 'object' || moduleParams === null) { 12049 extend(allModulesParams, obj); 12050 return; 12051 } 12052 if (params[moduleParamName] === true) { 12053 params[moduleParamName] = { 12054 enabled: true 12055 }; 12056 } 12057 if (moduleParamName === 'navigation' && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].prevEl && !params[moduleParamName].nextEl) { 12058 params[moduleParamName].auto = true; 12059 } 12060 if (['pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].el) { 12061 params[moduleParamName].auto = true; 12062 } 12063 if (!(moduleParamName in params && 'enabled' in moduleParams)) { 12064 extend(allModulesParams, obj); 12065 return; 12066 } 12067 if (typeof params[moduleParamName] === 'object' && !('enabled' in params[moduleParamName])) { 12068 params[moduleParamName].enabled = true; 12069 } 12070 if (!params[moduleParamName]) params[moduleParamName] = { 12071 enabled: false 12072 }; 12073 extend(allModulesParams, obj); 12074 }; 12075 } 12076 12077 /* eslint no-param-reassign: "off" */ 12078 const prototypes = { 12079 eventsEmitter, 12080 update, 12081 translate, 12082 transition, 12083 slide, 12084 loop, 12085 grabCursor, 12086 events: events$1, 12087 breakpoints, 12088 checkOverflow: checkOverflow$1, 12089 classes 12090 }; 12091 const extendedDefaults = {}; 12092 class Swiper { 12093 constructor(...args) { 12094 let el; 12095 let params; 12096 if (args.length === 1 && args[0].constructor && Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object') { 12097 params = args[0]; 12098 } else { 12099 [el, params] = args; 12100 } 12101 if (!params) params = {}; 12102 params = extend({}, params); 12103 if (el && !params.el) params.el = el; 12104 const document = getDocument(); 12105 if (params.el && typeof params.el === 'string' && document.querySelectorAll(params.el).length > 1) { 12106 const swipers = []; 12107 document.querySelectorAll(params.el).forEach(containerEl => { 12108 const newParams = extend({}, params, { 12109 el: containerEl 12110 }); 12111 swipers.push(new Swiper(newParams)); 12112 }); 12113 // eslint-disable-next-line no-constructor-return 12114 return swipers; 12115 } 12116 12117 // Swiper Instance 12118 const swiper = this; 12119 swiper.__swiper__ = true; 12120 swiper.support = getSupport(); 12121 swiper.device = getDevice({ 12122 userAgent: params.userAgent 12123 }); 12124 swiper.browser = getBrowser(); 12125 swiper.eventsListeners = {}; 12126 swiper.eventsAnyListeners = []; 12127 swiper.modules = [...swiper.__modules__]; 12128 if (params.modules && Array.isArray(params.modules)) { 12129 swiper.modules.push(...params.modules); 12130 } 12131 const allModulesParams = {}; 12132 swiper.modules.forEach(mod => { 12133 mod({ 12134 params, 12135 swiper, 12136 extendParams: moduleExtendParams(params, allModulesParams), 12137 on: swiper.on.bind(swiper), 12138 once: swiper.once.bind(swiper), 12139 off: swiper.off.bind(swiper), 12140 emit: swiper.emit.bind(swiper) 12141 }); 12142 }); 12143 12144 // Extend defaults with modules params 12145 const swiperParams = extend({}, defaults, allModulesParams); 12146 12147 // Extend defaults with passed params 12148 swiper.params = extend({}, swiperParams, extendedDefaults, params); 12149 swiper.originalParams = extend({}, swiper.params); 12150 swiper.passedParams = extend({}, params); 12151 12152 // add event listeners 12153 if (swiper.params && swiper.params.on) { 12154 Object.keys(swiper.params.on).forEach(eventName => { 12155 swiper.on(eventName, swiper.params.on[eventName]); 12156 }); 12157 } 12158 if (swiper.params && swiper.params.onAny) { 12159 swiper.onAny(swiper.params.onAny); 12160 } 12161 12162 // Extend Swiper 12163 Object.assign(swiper, { 12164 enabled: swiper.params.enabled, 12165 el, 12166 // Classes 12167 classNames: [], 12168 // Slides 12169 slides: [], 12170 slidesGrid: [], 12171 snapGrid: [], 12172 slidesSizesGrid: [], 12173 // isDirection 12174 isHorizontal() { 12175 return swiper.params.direction === 'horizontal'; 12176 }, 12177 isVertical() { 12178 return swiper.params.direction === 'vertical'; 12179 }, 12180 // Indexes 12181 activeIndex: 0, 12182 realIndex: 0, 12183 // 12184 isBeginning: true, 12185 isEnd: false, 12186 // Props 12187 translate: 0, 12188 previousTranslate: 0, 12189 progress: 0, 12190 velocity: 0, 12191 animating: false, 12192 cssOverflowAdjustment() { 12193 // Returns 0 unless `translate` is > 2**23 12194 // Should be subtracted from css values to prevent overflow 12195 return Math.trunc(this.translate / 2 ** 23) * 2 ** 23; 12196 }, 12197 // Locks 12198 allowSlideNext: swiper.params.allowSlideNext, 12199 allowSlidePrev: swiper.params.allowSlidePrev, 12200 // Touch Events 12201 touchEventsData: { 12202 isTouched: undefined, 12203 isMoved: undefined, 12204 allowTouchCallbacks: undefined, 12205 touchStartTime: undefined, 12206 isScrolling: undefined, 12207 currentTranslate: undefined, 12208 startTranslate: undefined, 12209 allowThresholdMove: undefined, 12210 // Form elements to match 12211 focusableElements: swiper.params.focusableElements, 12212 // Last click time 12213 lastClickTime: 0, 12214 clickTimeout: undefined, 12215 // Velocities 12216 velocities: [], 12217 allowMomentumBounce: undefined, 12218 startMoving: undefined, 12219 pointerId: null, 12220 touchId: null 12221 }, 12222 // Clicks 12223 allowClick: true, 12224 // Touches 12225 allowTouchMove: swiper.params.allowTouchMove, 12226 touches: { 12227 startX: 0, 12228 startY: 0, 12229 currentX: 0, 12230 currentY: 0, 12231 diff: 0 12232 }, 12233 // Images 12234 imagesToLoad: [], 12235 imagesLoaded: 0 12236 }); 12237 swiper.emit('_swiper'); 12238 12239 // Init 12240 if (swiper.params.init) { 12241 swiper.init(); 12242 } 12243 12244 // Return app instance 12245 // eslint-disable-next-line no-constructor-return 12246 return swiper; 12247 } 12248 getDirectionLabel(property) { 12249 if (this.isHorizontal()) { 12250 return property; 12251 } 12252 // prettier-ignore 12253 return { 12254 'width': 'height', 12255 'margin-top': 'margin-left', 12256 'margin-bottom ': 'margin-right', 12257 'margin-left': 'margin-top', 12258 'margin-right': 'margin-bottom', 12259 'padding-left': 'padding-top', 12260 'padding-right': 'padding-bottom', 12261 'marginRight': 'marginBottom' 12262 }[property]; 12263 } 12264 getSlideIndex(slideEl) { 12265 const { 12266 slidesEl, 12267 params 12268 } = this; 12269 const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`); 12270 const firstSlideIndex = elementIndex(slides[0]); 12271 return elementIndex(slideEl) - firstSlideIndex; 12272 } 12273 getSlideIndexByData(index) { 12274 return this.getSlideIndex(this.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === index)); 12275 } 12276 getSlideIndexWhenGrid(index) { 12277 if (this.grid && this.params.grid && this.params.grid.rows > 1) { 12278 if (this.params.grid.fill === 'column') { 12279 index = Math.floor(index / this.params.grid.rows); 12280 } else if (this.params.grid.fill === 'row') { 12281 index = index % Math.ceil(this.slides.length / this.params.grid.rows); 12282 } 12283 } 12284 return index; 12285 } 12286 recalcSlides() { 12287 const swiper = this; 12288 const { 12289 slidesEl, 12290 params 12291 } = swiper; 12292 swiper.slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`); 12293 } 12294 enable() { 12295 const swiper = this; 12296 if (swiper.enabled) return; 12297 swiper.enabled = true; 12298 if (swiper.params.grabCursor) { 12299 swiper.setGrabCursor(); 12300 } 12301 swiper.emit('enable'); 12302 } 12303 disable() { 12304 const swiper = this; 12305 if (!swiper.enabled) return; 12306 swiper.enabled = false; 12307 if (swiper.params.grabCursor) { 12308 swiper.unsetGrabCursor(); 12309 } 12310 swiper.emit('disable'); 12311 } 12312 setProgress(progress, speed) { 12313 const swiper = this; 12314 progress = Math.min(Math.max(progress, 0), 1); 12315 const min = swiper.minTranslate(); 12316 const max = swiper.maxTranslate(); 12317 const current = (max - min) * progress + min; 12318 swiper.translateTo(current, typeof speed === 'undefined' ? 0 : speed); 12319 swiper.updateActiveIndex(); 12320 swiper.updateSlidesClasses(); 12321 } 12322 emitContainerClasses() { 12323 const swiper = this; 12324 if (!swiper.params._emitClasses || !swiper.el) return; 12325 const cls = swiper.el.className.split(' ').filter(className => { 12326 return className.indexOf('swiper') === 0 || className.indexOf(swiper.params.containerModifierClass) === 0; 12327 }); 12328 swiper.emit('_containerClasses', cls.join(' ')); 12329 } 12330 getSlideClasses(slideEl) { 12331 const swiper = this; 12332 if (swiper.destroyed) return ''; 12333 return slideEl.className.split(' ').filter(className => { 12334 return className.indexOf('swiper-slide') === 0 || className.indexOf(swiper.params.slideClass) === 0; 12335 }).join(' '); 12336 } 12337 emitSlidesClasses() { 12338 const swiper = this; 12339 if (!swiper.params._emitClasses || !swiper.el) return; 12340 const updates = []; 12341 swiper.slides.forEach(slideEl => { 12342 const classNames = swiper.getSlideClasses(slideEl); 12343 updates.push({ 12344 slideEl, 12345 classNames 12346 }); 12347 swiper.emit('_slideClass', slideEl, classNames); 12348 }); 12349 swiper.emit('_slideClasses', updates); 12350 } 12351 slidesPerViewDynamic(view = 'current', exact = false) { 12352 const swiper = this; 12353 const { 12354 params, 12355 slides, 12356 slidesGrid, 12357 slidesSizesGrid, 12358 size: swiperSize, 12359 activeIndex 12360 } = swiper; 12361 let spv = 1; 12362 if (typeof params.slidesPerView === 'number') return params.slidesPerView; 12363 if (params.centeredSlides) { 12364 let slideSize = slides[activeIndex] ? Math.ceil(slides[activeIndex].swiperSlideSize) : 0; 12365 let breakLoop; 12366 for (let i = activeIndex + 1; i < slides.length; i += 1) { 12367 if (slides[i] && !breakLoop) { 12368 slideSize += Math.ceil(slides[i].swiperSlideSize); 12369 spv += 1; 12370 if (slideSize > swiperSize) breakLoop = true; 12371 } 12372 } 12373 for (let i = activeIndex - 1; i >= 0; i -= 1) { 12374 if (slides[i] && !breakLoop) { 12375 slideSize += slides[i].swiperSlideSize; 12376 spv += 1; 12377 if (slideSize > swiperSize) breakLoop = true; 12378 } 12379 } 12380 } else { 12381 // eslint-disable-next-line 12382 if (view === 'current') { 12383 for (let i = activeIndex + 1; i < slides.length; i += 1) { 12384 const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize; 12385 if (slideInView) { 12386 spv += 1; 12387 } 12388 } 12389 } else { 12390 // previous 12391 for (let i = activeIndex - 1; i >= 0; i -= 1) { 12392 const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize; 12393 if (slideInView) { 12394 spv += 1; 12395 } 12396 } 12397 } 12398 } 12399 return spv; 12400 } 12401 update() { 12402 const swiper = this; 12403 if (!swiper || swiper.destroyed) return; 12404 const { 12405 snapGrid, 12406 params 12407 } = swiper; 12408 // Breakpoints 12409 if (params.breakpoints) { 12410 swiper.setBreakpoint(); 12411 } 12412 [...swiper.el.querySelectorAll('[loading="lazy"]')].forEach(imageEl => { 12413 if (imageEl.complete) { 12414 processLazyPreloader(swiper, imageEl); 12415 } 12416 }); 12417 swiper.updateSize(); 12418 swiper.updateSlides(); 12419 swiper.updateProgress(); 12420 swiper.updateSlidesClasses(); 12421 function setTranslate() { 12422 const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate; 12423 const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate()); 12424 swiper.setTranslate(newTranslate); 12425 swiper.updateActiveIndex(); 12426 swiper.updateSlidesClasses(); 12427 } 12428 let translated; 12429 if (params.freeMode && params.freeMode.enabled && !params.cssMode) { 12430 setTranslate(); 12431 if (params.autoHeight) { 12432 swiper.updateAutoHeight(); 12433 } 12434 } else { 12435 if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !params.centeredSlides) { 12436 const slides = swiper.virtual && params.virtual.enabled ? swiper.virtual.slides : swiper.slides; 12437 translated = swiper.slideTo(slides.length - 1, 0, false, true); 12438 } else { 12439 translated = swiper.slideTo(swiper.activeIndex, 0, false, true); 12440 } 12441 if (!translated) { 12442 setTranslate(); 12443 } 12444 } 12445 if (params.watchOverflow && snapGrid !== swiper.snapGrid) { 12446 swiper.checkOverflow(); 12447 } 12448 swiper.emit('update'); 12449 } 12450 changeDirection(newDirection, needUpdate = true) { 12451 const swiper = this; 12452 const currentDirection = swiper.params.direction; 12453 if (!newDirection) { 12454 // eslint-disable-next-line 12455 newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal'; 12456 } 12457 if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') { 12458 return swiper; 12459 } 12460 swiper.el.classList.remove(`${swiper.params.containerModifierClass}${currentDirection}`); 12461 swiper.el.classList.add(`${swiper.params.containerModifierClass}${newDirection}`); 12462 swiper.emitContainerClasses(); 12463 swiper.params.direction = newDirection; 12464 swiper.slides.forEach(slideEl => { 12465 if (newDirection === 'vertical') { 12466 slideEl.style.width = ''; 12467 } else { 12468 slideEl.style.height = ''; 12469 } 12470 }); 12471 swiper.emit('changeDirection'); 12472 if (needUpdate) swiper.update(); 12473 return swiper; 12474 } 12475 changeLanguageDirection(direction) { 12476 const swiper = this; 12477 if (swiper.rtl && direction === 'rtl' || !swiper.rtl && direction === 'ltr') return; 12478 swiper.rtl = direction === 'rtl'; 12479 swiper.rtlTranslate = swiper.params.direction === 'horizontal' && swiper.rtl; 12480 if (swiper.rtl) { 12481 swiper.el.classList.add(`${swiper.params.containerModifierClass}rtl`); 12482 swiper.el.dir = 'rtl'; 12483 } else { 12484 swiper.el.classList.remove(`${swiper.params.containerModifierClass}rtl`); 12485 swiper.el.dir = 'ltr'; 12486 } 12487 swiper.update(); 12488 } 12489 mount(element) { 12490 const swiper = this; 12491 if (swiper.mounted) return true; 12492 12493 // Find el 12494 let el = element || swiper.params.el; 12495 if (typeof el === 'string') { 12496 el = document.querySelector(el); 12497 } 12498 if (!el) { 12499 return false; 12500 } 12501 el.swiper = swiper; 12502 if (el.parentNode && el.parentNode.host && el.parentNode.host.nodeName === swiper.params.swiperElementNodeName.toUpperCase()) { 12503 swiper.isElement = true; 12504 } 12505 const getWrapperSelector = () => { 12506 return `.${(swiper.params.wrapperClass || '').trim().split(' ').join('.')}`; 12507 }; 12508 const getWrapper = () => { 12509 if (el && el.shadowRoot && el.shadowRoot.querySelector) { 12510 const res = el.shadowRoot.querySelector(getWrapperSelector()); 12511 // Children needs to return slot items 12512 return res; 12513 } 12514 return elementChildren(el, getWrapperSelector())[0]; 12515 }; 12516 // Find Wrapper 12517 let wrapperEl = getWrapper(); 12518 if (!wrapperEl && swiper.params.createElements) { 12519 wrapperEl = createElement('div', swiper.params.wrapperClass); 12520 el.append(wrapperEl); 12521 elementChildren(el, `.${swiper.params.slideClass}
12521`).forEach(slideEl => { 12522 wrapperEl.append(slideEl); 12523 }); 12524 } 12525 Object.assign(swiper, { 12526 el, 12527 wrapperEl, 12528 slidesEl: swiper.isElement && !el.parentNode.host.slideSlots ? el.parentNode.host : wrapperEl, 12529 hostEl: swiper.isElement ? el.parentNode.host : el, 12530 mounted: true, 12531 // RTL 12532 rtl: el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl', 12533 rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl'), 12534 wrongRTL: elementStyle(wrapperEl, 'display') === '-webkit-box' 12535 }); 12536 return true; 12537 } 12538 init(el) { 12539 const swiper = this; 12540 if (swiper.initialized) return swiper; 12541 const mounted = swiper.mount(el); 12542 if (mounted === false) return swiper; 12543 swiper.emit('beforeInit'); 12544 12545 // Set breakpoint 12546 if (swiper.params.breakpoints) { 12547 swiper.setBreakpoint(); 12548 } 12549 12550 // Add Classes 12551 swiper.addClasses(); 12552 12553 // Update size 12554 swiper.updateSize(); 12555 12556 // Update slides 12557 swiper.updateSlides(); 12558 if (swiper.params.watchOverflow) { 12559 swiper.checkOverflow(); 12560 } 12561 12562 // Set Grab Cursor 12563 if (swiper.params.grabCursor && swiper.enabled) { 12564 swiper.setGrabCursor(); 12565 } 12566 12567 // Slide To Initial Slide 12568 if (swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) { 12569 swiper.slideTo(swiper.params.initialSlide + swiper.virtual.slidesBefore, 0, swiper.params.runCallbacksOnInit, false, true); 12570 } else { 12571 swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true); 12572 } 12573 12574 // Create loop 12575 if (swiper.params.loop) { 12576 swiper.loopCreate(undefined, true); 12577 } 12578 12579 // Attach events 12580 swiper.attachEvents(); 12581 const lazyElements = [...swiper.el.querySelectorAll('[loading="lazy"]')]; 12582 if (swiper.isElement) { 12583 lazyElements.push(...swiper.hostEl.querySelectorAll('[loading="lazy"]')); 12584 } 12585 lazyElements.forEach(imageEl => { 12586 if (imageEl.complete) { 12587 processLazyPreloader(swiper, imageEl); 12588 } else { 12589 imageEl.addEventListener('load', e => { 12590 processLazyPreloader(swiper, e.target); 12591 }); 12592 } 12593 }); 12594 preload(swiper); 12595 12596 // Init Flag 12597 swiper.initialized = true; 12598 preload(swiper); 12599 12600 // Emit 12601 swiper.emit('init'); 12602 swiper.emit('afterInit'); 12603 return swiper; 12604 } 12605 destroy(deleteInstance = true, cleanStyles = true) { 12606 const swiper = this; 12607 const { 12608 params, 12609 el, 12610 wrapperEl, 12611 slides 12612 } = swiper; 12613 if (typeof swiper.params === 'undefined' || swiper.destroyed) { 12614 return null; 12615 } 12616 swiper.emit('beforeDestroy'); 12617 12618 // Init Flag 12619 swiper.initialized = false; 12620 12621 // Detach events 12622 swiper.detachEvents(); 12623 12624 // Destroy loop 12625 if (params.loop) { 12626 swiper.loopDestroy(); 12627 } 12628 12629 // Cleanup styles 12630 if (cleanStyles) { 12631 swiper.removeClasses(); 12632 if (el && typeof el !== 'string') { 12633 el.removeAttribute('style'); 12634 } 12635 if (wrapperEl) { 12636 wrapperEl.removeAttribute('style'); 12637 } 12638 if (slides && slides.length) {
vendor: 6,255 bytes, lines 12639-12831
12639 slides.forEach(slideEl => { 12640 slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass); 12641 slideEl.removeAttribute('style'); 12642 slideEl.removeAttribute('data-swiper-slide-index'); 12643 }); 12644 } 12645 } 12646 swiper.emit('destroy'); 12647 12648 // Detach emitter events 12649 Object.keys(swiper.eventsListeners).forEach(eventName => { 12650 swiper.off(eventName); 12651 }); 12652 if (deleteInstance !== false) { 12653 if (swiper.el && typeof swiper.el !== 'string') { 12654 swiper.el.swiper = null; 12655 } 12656 deleteProps(swiper); 12657 } 12658 swiper.destroyed = true; 12659 return null; 12660 } 12661 static extendDefaults(newDefaults) { 12662 extend(extendedDefaults, newDefaults); 12663 } 12664 static get extendedDefaults() { 12665 return extendedDefaults; 12666 } 12667 static get defaults() { 12668 return defaults; 12669 } 12670 static installModule(mod) { 12671 if (!Swiper.prototype.__modules__) Swiper.prototype.__modules__ = []; 12672 const modules = Swiper.prototype.__modules__; 12673 if (typeof mod === 'function' && modules.indexOf(mod) < 0) { 12674 modules.push(mod); 12675 } 12676 } 12677 static use(module) { 12678 if (Array.isArray(module)) { 12679 module.forEach(m => Swiper.installModule(m)); 12680 return Swiper; 12681 } 12682 Swiper.installModule(module); 12683 return Swiper; 12684 } 12685 } 12686 Object.keys(prototypes).forEach(prototypeGroup => { 12687 Object.keys(prototypes[prototypeGroup]).forEach(protoMethod => { 12688 Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod]; 12689 }); 12690 }); 12691 Swiper.use([Resize, Observer]); 12692 12693 function Virtual({ 12694 swiper, 12695 extendParams, 12696 on, 12697 emit 12698 }) { 12699 extendParams({ 12700 virtual: { 12701 enabled: false, 12702 slides: [], 12703 cache: true, 12704 slidesPerViewAutoSlideSize: 320, 12705 renderSlide: null, 12706 renderExternal: null, 12707 renderExternalUpdate: true, 12708 addSlidesBefore: 0, 12709 addSlidesAfter: 0 12710 } 12711 }); 12712 let cssModeTimeout; 12713 const document = getDocument(); 12714 swiper.virtual = { 12715 cache: {}, 12716 from: undefined, 12717 to: undefined, 12718 slides: [], 12719 offset: 0, 12720 slidesGrid: [] 12721 }; 12722 const tempDOM = document.createElement('div'); 12723 function renderSlide(slide, index) { 12724 const params = swiper.params.virtual; 12725 if (params.cache && swiper.virtual.cache[index]) { 12726 return swiper.virtual.cache[index]; 12727 } 12728 // eslint-disable-next-line 12729 let slideEl; 12730 if (params.renderSlide) { 12731 slideEl = params.renderSlide.call(swiper, slide, index); 12732 if (typeof slideEl === 'string') { 12733 setInnerHTML(tempDOM, slideEl); 12734 slideEl = tempDOM.children[0]; 12735 } 12736 } else if (swiper.isElement) { 12737 slideEl = createElement('swiper-slide'); 12738 } else { 12739 slideEl = createElement('div', swiper.params.slideClass); 12740 } 12741 slideEl.setAttribute('data-swiper-slide-index', index); 12742 if (!params.renderSlide) { 12743 setInnerHTML(slideEl, slide); 12744 } 12745 if (params.cache) { 12746 swiper.virtual.cache[index] = slideEl; 12747 } 12748 return slideEl; 12749 } 12750 function update(force, beforeInit, forceActiveIndex) { 12751 const { 12752 slidesPerGroup, 12753 centeredSlides, 12754 slidesPerView, 12755 loop: isLoop, 12756 initialSlide 12757 } = swiper.params; 12758 if (beforeInit && !isLoop && initialSlide > 0) { 12759 return; 12760 } 12761 const { 12762 addSlidesBefore, 12763 addSlidesAfter, 12764 slidesPerViewAutoSlideSize 12765 } = swiper.params.virtual; 12766 const { 12767 from: previousFrom, 12768 to: previousTo, 12769 slides, 12770 slidesGrid: previousSlidesGrid, 12771 offset: previousOffset 12772 } = swiper.virtual; 12773 if (!swiper.params.cssMode) { 12774 swiper.updateActiveIndex(); 12775 } 12776 const activeIndex = typeof forceActiveIndex === 'undefined' ? swiper.activeIndex || 0 : forceActiveIndex; 12777 let offsetProp; 12778 if (swiper.rtlTranslate) offsetProp = 'right';else offsetProp = swiper.isHorizontal() ? 'left' : 'top'; 12779 let slidesPerViewNumeric; 12780 if (slidesPerView === 'auto') { 12781 if (slidesPerViewAutoSlideSize) { 12782 let swiperSize = swiper.size; 12783 if (!swiperSize) { 12784 swiperSize = swiper.isHorizontal() ? swiper.el.getBoundingClientRect().width : swiper.el.getBoundingClientRect().height; 12785 } 12786 slidesPerViewNumeric = Math.max(1, Math.ceil(swiperSize / slidesPerViewAutoSlideSize)); 12787 } else { 12788 slidesPerViewNumeric = 1; 12789 } 12790 } else { 12791 slidesPerViewNumeric = slidesPerView; 12792 } 12793 let slidesAfter; 12794 let slidesBefore; 12795 if (centeredSlides) { 12796 slidesAfter = Math.floor(slidesPerViewNumeric / 2) + slidesPerGroup + addSlidesAfter; 12797 slidesBefore = Math.floor(slidesPerViewNumeric / 2) + slidesPerGroup + addSlidesBefore; 12798 } else { 12799 slidesAfter = slidesPerViewNumeric + (slidesPerGroup - 1) + addSlidesAfter; 12800 slidesBefore = (isLoop ? slidesPerViewNumeric : slidesPerGroup) + addSlidesBefore; 12801 } 12802 let from = activeIndex - slidesBefore; 12803 let to = activeIndex + slidesAfter; 12804 if (!isLoop) { 12805 from = Math.max(from, 0); 12806 to = Math.min(to, slides.length - 1); 12807 } 12808 let offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0); 12809 if (isLoop && activeIndex >= slidesBefore) { 12810 from -= slidesBefore; 12811 if (!centeredSlides) offset += swiper.slidesGrid[0]; 12812 } else if (isLoop && activeIndex < slidesBefore) { 12813 from = -slidesBefore; 12814 if (centeredSlides) offset += swiper.slidesGrid[0]; 12815 } 12816 Object.assign(swiper.virtual, { 12817 from, 12818 to, 12819 offset, 12820 slidesGrid: swiper.slidesGrid, 12821 slidesBefore, 12822 slidesAfter 12823 }); 12824 function onRendered() { 12825 swiper.updateSlides(); 12826 swiper.updateProgress(); 12827 swiper.updateSlidesClasses(); 12828 emit('virtualUpdate'); 12829 } 12830 if (previousFrom === from && previousTo === to && !force) { 12831 if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
vendor: 1,316 bytes, lines 12832-12873
12832 swiper.slides.forEach(slideEl => { 12833 slideEl.style[offsetProp] = `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`; 12834 }); 12835 } 12836 swiper.updateProgress(); 12837 emit('virtualUpdate'); 12838 return; 12839 } 12840 if (swiper.params.virtual.renderExternal) { 12841 swiper.params.virtual.renderExternal.call(swiper, { 12842 offset, 12843 from, 12844 to, 12845 slides: function getSlides() { 12846 const slidesToRender = []; 12847 for (let i = from; i <= to; i += 1) { 12848 slidesToRender.push(slides[i]); 12849 } 12850 return slidesToRender; 12851 }() 12852 }); 12853 if (swiper.params.virtual.renderExternalUpdate) { 12854 onRendered(); 12855 } else { 12856 emit('virtualUpdate'); 12857 } 12858 return; 12859 } 12860 const prependIndexes = []; 12861 const appendIndexes = []; 12862 const getSlideIndex = index => { 12863 let slideIndex = index; 12864 if (index < 0) { 12865 slideIndex = slides.length + index; 12866 } else if (slideIndex >= slides.length) { 12867 // eslint-disable-next-line 12868 slideIndex = slideIndex - slides.length; 12869 } 12870 return slideIndex; 12871 }; 12872 if (force) { 12873 swiper.slides.filter(el => el.matches(`.${swiper.params.slideClass}
12873, swiper-slide`)).forEach(slideEl => { 12874 slideEl.remove(); 12875 }); 12876 } else { 12877 for (let i = previousFrom; i <= previousTo; i += 1) { 12878 if (i < from || i > to) { 12879 const slideIndex = getSlideIndex(i); 12880 swiper.slides.filter(el => el.matches(`.${swiper.params.slideClass}[data-swiper-slide-index="${slideIndex}"], swiper-slide[data-swiper-slide-index="${slideIndex}"]`)).forEach(slideEl => { 12881 slideEl.remove(); 12882 }); 12883 } 12884 } 12885 } 12886 const loopFrom = isLoop ? -slides.length : 0; 12887 const loopTo = isLoop ? slides.length * 2 : slides.length; 12888 for (let i = loopFrom; i < loopTo; i += 1) { 12889 if (i >= from && i <= to) { 12890 const slideIndex = getSlideIndex(i); 12891 if (typeof previousTo === 'undefined' || force) { 12892 appendIndexes.push(slideIndex); 12893 } else { 12894 if (i > previousTo) appendIndexes.push(slideIndex); 12895 if (i < previousFrom) prependIndexes.push(slideIndex); 12896 } 12897 } 12898 } 12899 appendIndexes.forEach(index => { 12900 swiper.slidesEl.append(renderSlide(slides[index], index)); 12901 }); 12902 if (isLoop) { 12903 for (let i = prependIndexes.length - 1; i >= 0; i -= 1) { 12904 const index = prependIndexes[i]; 12905 swiper.slidesEl.prepend(renderSlide(slides[index], index)); 12906 } 12907 } else { 12908 prependIndexes.sort((a, b) => b - a); 12909 prependIndexes.forEach(index => { 12910 swiper.slidesEl.prepend(renderSlide(slides[index], index)); 12911 }); 12912 } 12913 elementChildren(swiper.slidesEl, '.swiper-slide, swiper-slide').forEach(sli
vendor: 28,679 bytes, lines 12913-13653
12913deEl => { 12914 slideEl.style[offsetProp] = `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`; 12915 }); 12916 onRendered(); 12917 } 12918 function appendSlide(slides) { 12919 if (typeof slides === 'object' && 'length' in slides) { 12920 for (let i = 0; i < slides.length; i += 1) { 12921 if (slides[i]) swiper.virtual.slides.push(slides[i]); 12922 } 12923 } else { 12924 swiper.virtual.slides.push(slides); 12925 } 12926 update(true); 12927 } 12928 function prependSlide(slides) { 12929 const activeIndex = swiper.activeIndex; 12930 let newActiveIndex = activeIndex + 1; 12931 let numberOfNewSlides = 1; 12932 if (Array.isArray(slides)) { 12933 for (let i = 0; i < slides.length; i += 1) { 12934 if (slides[i]) swiper.virtual.slides.unshift(slides[i]); 12935 } 12936 newActiveIndex = activeIndex + slides.length; 12937 numberOfNewSlides = slides.length; 12938 } else { 12939 swiper.virtual.slides.unshift(slides); 12940 } 12941 if (swiper.params.virtual.cache) { 12942 const cache = swiper.virtual.cache; 12943 const newCache = {}; 12944 Object.keys(cache).forEach(cachedIndex => { 12945 const cachedEl = cache[cachedIndex]; 12946 const cachedElIndex = cachedEl.getAttribute('data-swiper-slide-index'); 12947 if (cachedElIndex) { 12948 cachedEl.setAttribute('data-swiper-slide-index', parseInt(cachedElIndex, 10) + numberOfNewSlides); 12949 } 12950 newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = cachedEl; 12951 }); 12952 swiper.virtual.cache = newCache; 12953 } 12954 update(true); 12955 swiper.slideTo(newActiveIndex, 0); 12956 } 12957 function removeSlide(slidesIndexes) { 12958 if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) return; 12959 let activeIndex = swiper.activeIndex; 12960 if (Array.isArray(slidesIndexes)) { 12961 for (let i = slidesIndexes.length - 1; i >= 0; i -= 1) { 12962 if (swiper.params.virtual.cache) { 12963 delete swiper.virtual.cache[slidesIndexes[i]]; 12964 // shift cache indexes 12965 Object.keys(swiper.virtual.cache).forEach(key => { 12966 if (key > slidesIndexes) { 12967 swiper.virtual.cache[key - 1] = swiper.virtual.cache[key]; 12968 swiper.virtual.cache[key - 1].setAttribute('data-swiper-slide-index', key - 1); 12969 delete swiper.virtual.cache[key]; 12970 } 12971 }); 12972 } 12973 swiper.virtual.slides.splice(slidesIndexes[i], 1); 12974 if (slidesIndexes[i] < activeIndex) activeIndex -= 1; 12975 activeIndex = Math.max(activeIndex, 0); 12976 } 12977 } else { 12978 if (swiper.params.virtual.cache) { 12979 delete swiper.virtual.cache[slidesIndexes]; 12980 // shift cache indexes 12981 Object.keys(swiper.virtual.cache).forEach(key => { 12982 if (key > slidesIndexes) { 12983 swiper.virtual.cache[key - 1] = swiper.virtual.cache[key]; 12984 swiper.virtual.cache[key - 1].setAttribute('data-swiper-slide-index', key - 1); 12985 delete swiper.virtual.cache[key]; 12986 } 12987 }); 12988 } 12989 swiper.virtual.slides.splice(slidesIndexes, 1); 12990 if (slidesIndexes < activeIndex) activeIndex -= 1; 12991 activeIndex = Math.max(activeIndex, 0); 12992 } 12993 update(true); 12994 swiper.slideTo(activeIndex, 0); 12995 } 12996 function removeAllSlides() { 12997 swiper.virtual.slides = []; 12998 if (swiper.params.virtual.cache) { 12999 swiper.virtual.cache = {}; 13000 } 13001 update(true); 13002 swiper.slideTo(0, 0); 13003 } 13004 on('beforeInit', () => { 13005 if (!swiper.params.virtual.enabled) return; 13006 let domSlidesAssigned; 13007 if (typeof swiper.passedParams.virtual.slides === 'undefined') { 13008 const slides = [...swiper.slidesEl.children].filter(el => el.matches(`.${swiper.params.slideClass}, swiper-slide`)); 13009 if (slides && slides.length) { 13010 swiper.virtual.slides = [...slides]; 13011 domSlidesAssigned = true; 13012 slides.forEach((slideEl, slideIndex) => { 13013 slideEl.setAttribute('data-swiper-slide-index', slideIndex); 13014 swiper.virtual.cache[slideIndex] = slideEl; 13015 slideEl.remove(); 13016 }); 13017 } 13018 } 13019 if (!domSlidesAssigned) { 13020 swiper.virtual.slides = swiper.params.virtual.slides; 13021 } 13022 swiper.classNames.push(`${swiper.params.containerModifierClass}virtual`); 13023 swiper.params.watchSlidesProgress = true; 13024 swiper.originalParams.watchSlidesProgress = true; 13025 update(false, true); 13026 }); 13027 on('setTranslate', () => { 13028 if (!swiper.params.virtual.enabled) return; 13029 if (swiper.params.cssMode && !swiper._immediateVirtual) { 13030 clearTimeout(cssModeTimeout); 13031 cssModeTimeout = setTimeout(() => { 13032 update(); 13033 }, 100); 13034 } else { 13035 update(); 13036 } 13037 }); 13038 on('init update resize', () => { 13039 if (!swiper.params.virtual.enabled) return; 13040 if (swiper.params.cssMode) { 13041 setCSSProperty(swiper.wrapperEl, '--swiper-virtual-size', `${swiper.virtualSize}px`); 13042 } 13043 }); 13044 Object.assign(swiper.virtual, { 13045 appendSlide, 13046 prependSlide, 13047 removeSlide, 13048 removeAllSlides, 13049 update 13050 }); 13051 } 13052 13053 /* eslint-disable consistent-return */ 13054 function Keyboard({ 13055 swiper, 13056 extendParams, 13057 on, 13058 emit 13059 }) { 13060 const document = getDocument(); 13061 const window = getWindow(); 13062 swiper.keyboard = { 13063 enabled: false 13064 }; 13065 extendParams({ 13066 keyboard: { 13067 enabled: false, 13068 onlyInViewport: true, 13069 pageUpDown: true 13070 } 13071 }); 13072 function handle(event) { 13073 if (!swiper.enabled) return; 13074 const { 13075 rtlTranslate: rtl 13076 } = swiper; 13077 let e = event; 13078 if (e.originalEvent) e = e.originalEvent; // jquery fix 13079 const kc = e.keyCode || e.charCode; 13080 const pageUpDown = swiper.params.keyboard.pageUpDown; 13081 const isPageUp = pageUpDown && kc === 33; 13082 const isPageDown = pageUpDown && kc === 34; 13083 const isArrowLeft = kc === 37; 13084 const isArrowRight = kc === 39; 13085 const isArrowUp = kc === 38; 13086 const isArrowDown = kc === 40; 13087 // Directions locks 13088 if (!swiper.allowSlideNext && (swiper.isHorizontal() && isArrowRight || swiper.isVertical() && isArrowDown || isPageDown)) { 13089 return false; 13090 } 13091 if (!swiper.allowSlidePrev && (swiper.isHorizontal() && isArrowLeft || swiper.isVertical() && isArrowUp || isPageUp)) { 13092 return false; 13093 } 13094 if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { 13095 return undefined; 13096 } 13097 if (document.activeElement && (document.activeElement.isContentEditable || document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea'))) { 13098 return undefined; 13099 } 13100 if (swiper.params.keyboard.onlyInViewport && (isPageUp || isPageDown || isArrowLeft || isArrowRight || isArrowUp || isArrowDown)) { 13101 let inView = false; 13102 // Check that swiper should be inside of visible area of window 13103 if (elementParents(swiper.el, `.${swiper.params.slideClass}, swiper-slide`).length > 0 && elementParents(swiper.el, `.${swiper.params.slideActiveClass}`).length === 0) { 13104 return undefined; 13105 } 13106 const el = swiper.el; 13107 const swiperWidth = el.clientWidth; 13108 const swiperHeight = el.clientHeight; 13109 const windowWidth = window.innerWidth; 13110 const windowHeight = window.innerHeight; 13111 const swiperOffset = elementOffset(el); 13112 if (rtl) swiperOffset.left -= el.scrollLeft; 13113 const swiperCoord = [[swiperOffset.left, swiperOffset.top], [swiperOffset.left + swiperWidth, swiperOffset.top], [swiperOffset.left, swiperOffset.top + swiperHeight], [swiperOffset.left + swiperWidth, swiperOffset.top + swiperHeight]]; 13114 for (let i = 0; i < swiperCoord.length; i += 1) { 13115 const point = swiperCoord[i]; 13116 if (point[0] >= 0 && point[0] <= windowWidth && point[1] >= 0 && point[1] <= windowHeight) { 13117 if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line 13118 inView = true; 13119 } 13120 } 13121 if (!inView) return undefined; 13122 } 13123 if (swiper.isHorizontal()) { 13124 if (isPageUp || isPageDown || isArrowLeft || isArrowRight) { 13125 if (e.preventDefault) e.preventDefault();else e.returnValue = false; 13126 } 13127 if ((isPageDown || isArrowRight) && !rtl || (isPageUp || isArrowLeft) && rtl) swiper.slideNext(); 13128 if ((isPageUp || isArrowLeft) && !rtl || (isPageDown || isArrowRight) && rtl) swiper.slidePrev(); 13129 } else { 13130 if (isPageUp || isPageDown || isArrowUp || isArrowDown) { 13131 if (e.preventDefault) e.preventDefault();else e.returnValue = false; 13132 } 13133 if (isPageDown || isArrowDown) swiper.slideNext(); 13134 if (isPageUp || isArrowUp) swiper.slidePrev(); 13135 } 13136 emit('keyPress', kc); 13137 return undefined; 13138 } 13139 function enable() { 13140 if (swiper.keyboard.enabled) return; 13141 document.addEventListener('keydown', handle); 13142 swiper.keyboard.enabled = true; 13143 } 13144 function disable() { 13145 if (!swiper.keyboard.enabled) return; 13146 document.removeEventListener('keydown', handle); 13147 swiper.keyboard.enabled = false; 13148 } 13149 on('init', () => { 13150 if (swiper.params.keyboard.enabled) { 13151 enable(); 13152 } 13153 }); 13154 on('destroy', () => { 13155 if (swiper.keyboard.enabled) { 13156 disable(); 13157 } 13158 }); 13159 Object.assign(swiper.keyboard, { 13160 enable, 13161 disable 13162 }); 13163 } 13164 13165 /* eslint-disable consistent-return */ 13166 function Mousewheel({ 13167 swiper, 13168 extendParams, 13169 on, 13170 emit 13171 }) { 13172 const window = getWindow(); 13173 extendParams({ 13174 mousewheel: { 13175 enabled: false, 13176 releaseOnEdges: false, 13177 invert: false, 13178 forceToAxis: false, 13179 sensitivity: 1, 13180 eventsTarget: 'container', 13181 thresholdDelta: null, 13182 thresholdTime: null, 13183 noMousewheelClass: 'swiper-no-mousewheel' 13184 } 13185 }); 13186 swiper.mousewheel = { 13187 enabled: false 13188 }; 13189 let timeout; 13190 let lastScrollTime = now(); 13191 let lastEventBeforeSnap; 13192 const recentWheelEvents = []; 13193 function normalize(e) { 13194 // Reasonable defaults 13195 const PIXEL_STEP = 10; 13196 const LINE_HEIGHT = 40; 13197 const PAGE_HEIGHT = 800; 13198 let sX = 0; 13199 let sY = 0; // spinX, spinY 13200 let pX = 0; 13201 let pY = 0; // pixelX, pixelY 13202 13203 // Legacy 13204 if ('detail' in e) { 13205 sY = e.detail; 13206 } 13207 if ('wheelDelta' in e) { 13208 sY = -e.wheelDelta / 120; 13209 } 13210 if ('wheelDeltaY' in e) { 13211 sY = -e.wheelDeltaY / 120; 13212 } 13213 if ('wheelDeltaX' in e) { 13214 sX = -e.wheelDeltaX / 120; 13215 } 13216 13217 // side scrolling on FF with DOMMouseScroll 13218 if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) { 13219 sX = sY; 13220 sY = 0; 13221 } 13222 pX = sX * PIXEL_STEP; 13223 pY = sY * PIXEL_STEP; 13224 if ('deltaY' in e) { 13225 pY = e.deltaY; 13226 } 13227 if ('deltaX' in e) { 13228 pX = e.deltaX; 13229 } 13230 if (e.shiftKey && !pX) { 13231 // if user scrolls with shift he wants horizontal scroll 13232 pX = pY; 13233 pY = 0; 13234 } 13235 if ((pX || pY) && e.deltaMode) { 13236 if (e.deltaMode === 1) { 13237 // delta in LINE units 13238 pX *= LINE_HEIGHT; 13239 pY *= LINE_HEIGHT; 13240 } else { 13241 // delta in PAGE units 13242 pX *= PAGE_HEIGHT; 13243 pY *= PAGE_HEIGHT; 13244 } 13245 } 13246 13247 // Fall-back if spin cannot be determined 13248 if (pX && !sX) { 13249 sX = pX < 1 ? -1 : 1; 13250 } 13251 if (pY && !sY) { 13252 sY = pY < 1 ? -1 : 1; 13253 } 13254 return { 13255 spinX: sX, 13256 spinY: sY, 13257 pixelX: pX, 13258 pixelY: pY 13259 }; 13260 } 13261 function handleMouseEnter() { 13262 if (!swiper.enabled) return; 13263 swiper.mouseEntered = true; 13264 } 13265 function handleMouseLeave() { 13266 if (!swiper.enabled) return; 13267 swiper.mouseEntered = false; 13268 } 13269 function animateSlider(newEvent) { 13270 if (swiper.params.mousewheel.thresholdDelta && newEvent.delta < swiper.params.mousewheel.thresholdDelta) { 13271 // Prevent if delta of wheel scroll delta is below configured threshold 13272 return false; 13273 } 13274 if (swiper.params.mousewheel.thresholdTime && now() - lastScrollTime < swiper.params.mousewheel.thresholdTime) { 13275 // Prevent if time between scrolls is below configured threshold 13276 return false; 13277 } 13278 13279 // If the movement is NOT big enough and 13280 // if the last time the user scrolled was too close to the current one (avoid continuously triggering the slider): 13281 // Don't go any further (avoid insignificant scroll movement). 13282 if (newEvent.delta >= 6 && now() - lastScrollTime < 60) { 13283 // Return false as a default 13284 return true; 13285 } 13286 // If user is scrolling towards the end: 13287 // If the slider hasn't hit the latest slide or 13288 // if the slider is a loop and 13289 // if the slider isn't moving right now: 13290 // Go to next slide and 13291 // emit a scroll event. 13292 // Else (the user is scrolling towards the beginning) and 13293 // if the slider hasn't hit the first slide or 13294 // if the slider is a loop and 13295 // if the slider isn't moving right now: 13296 // Go to prev slide and 13297 // emit a scroll event. 13298 if (newEvent.direction < 0) { 13299 if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) { 13300 swiper.slideNext(); 13301 emit('scroll', newEvent.raw); 13302 } 13303 } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) { 13304 swiper.slidePrev(); 13305 emit('scroll', newEvent.raw); 13306 } 13307 // If you got here is because an animation has been triggered so store the current time 13308 lastScrollTime = new window.Date().getTime(); 13309 // Return false as a default 13310 return false; 13311 } 13312 function releaseScroll(newEvent) { 13313 const params = swiper.params.mousewheel; 13314 if (newEvent.direction < 0) { 13315 if (swiper.isEnd && !swiper.params.loop && params.releaseOnEdges) { 13316 // Return true to animate scroll on edges 13317 return true; 13318 } 13319 } else if (swiper.isBeginning && !swiper.params.loop && params.releaseOnEdges) { 13320 // Return true to animate scroll on edges 13321 return true; 13322 } 13323 return false; 13324 } 13325 function handle(event) { 13326 let e = event; 13327 let disableParentSwiper = true; 13328 if (!swiper.enabled) return; 13329 13330 // Ignore event if the target or its parents have the swiper-no-mousewheel class 13331 if (event.target.closest(`.${swiper.params.mousewheel.noMousewheelClass}`)) return; 13332 const params = swiper.params.mousewheel; 13333 if (swiper.params.cssMode) { 13334 e.preventDefault(); 13335 } 13336 let targetEl = swiper.el; 13337 if (swiper.params.mousewheel.eventsTarget !== 'container') { 13338 targetEl = document.querySelector(swiper.params.mousewheel.eventsTarget); 13339 } 13340 const targetElContainsTarget = targetEl && targetEl.contains(e.target); 13341 if (!swiper.mouseEntered && !targetElContainsTarget && !params.releaseOnEdges) return true; 13342 if (e.originalEvent) e = e.originalEvent; // jquery fix 13343 let delta = 0; 13344 const rtlFactor = swiper.rtlTranslate ? -1 : 1; 13345 const data = normalize(e); 13346 if (params.forceToAxis) { 13347 if (swiper.isHorizontal()) { 13348 if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = -data.pixelX * rtlFactor;else return true; 13349 } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = -data.pixelY;else return true; 13350 } else { 13351 delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY; 13352 } 13353 if (delta === 0) return true; 13354 if (params.invert) delta = -delta; 13355 13356 // Get the scroll positions 13357 let positions = swiper.getTranslate() + delta * params.sensitivity; 13358 if (positions >= swiper.minTranslate()) positions = swiper.minTranslate(); 13359 if (positions <= swiper.maxTranslate()) positions = swiper.maxTranslate(); 13360 13361 // When loop is true: 13362 // the disableParentSwiper will be true. 13363 // When loop is false: 13364 // if the scroll positions is not on edge, 13365 // then the disableParentSwiper will be true. 13366 // if the scroll on edge positions, 13367 // then the disableParentSwiper will be false. 13368 disableParentSwiper = swiper.params.loop ? true : !(positions === swiper.minTranslate() || positions === swiper.maxTranslate()); 13369 if (disableParentSwiper && swiper.params.nested) e.stopPropagation(); 13370 if (!swiper.params.freeMode || !swiper.params.freeMode.enabled) { 13371 // Register the new event in a variable which stores the relevant data 13372 const newEvent = { 13373 time: now(), 13374 delta: Math.abs(delta), 13375 direction: Math.sign(delta), 13376 raw: event 13377 }; 13378 13379 // Keep the most recent events 13380 if (recentWheelEvents.length >= 2) { 13381 recentWheelEvents.shift(); // only store the last N events 13382 } 13383 13384 const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined; 13385 recentWheelEvents.push(newEvent); 13386 13387 // If there is at least one previous recorded event: 13388 // If direction has changed or 13389 // if the scroll is quicker than the previous one: 13390 // Animate the slider. 13391 // Else (this is the first time the wheel is moved): 13392 // Animate the slider. 13393 if (prevEvent) { 13394 if (newEvent.direction !== prevEvent.direction || newEvent.delta > prevEvent.delta || newEvent.time > prevEvent.time + 150) { 13395 animateSlider(newEvent); 13396 } 13397 } else { 13398 animateSlider(newEvent); 13399 } 13400 13401 // If it's time to release the scroll: 13402 // Return now so you don't hit the preventDefault. 13403 if (releaseScroll(newEvent)) { 13404 return true; 13405 } 13406 } else { 13407 // Freemode or scrollContainer: 13408 13409 // If we recently snapped after a momentum scroll, then ignore wheel events 13410 // to give time for the deceleration to finish. Stop ignoring after 500 msecs 13411 // or if it's a new scroll (larger delta or inverse sign as last event before 13412 // an end-of-momentum snap). 13413 const newEvent = { 13414 time: now(), 13415 delta: Math.abs(delta), 13416 direction: Math.sign(delta) 13417 }; 13418 const ignoreWheelEvents = lastEventBeforeSnap && newEvent.time < lastEventBeforeSnap.time + 500 && newEvent.delta <= lastEventBeforeSnap.delta && newEvent.direction === lastEventBeforeSnap.direction; 13419 if (!ignoreWheelEvents) { 13420 lastEventBeforeSnap = undefined; 13421 let position = swiper.getTranslate() + delta * params.sensitivity; 13422 const wasBeginning = swiper.isBeginning; 13423 const wasEnd = swiper.isEnd; 13424 if (position >= swiper.minTranslate()) position = swiper.minTranslate(); 13425 if (position <= swiper.maxTranslate()) position = swiper.maxTranslate(); 13426 swiper.setTransition(0); 13427 swiper.setTranslate(position); 13428 swiper.updateProgress(); 13429 swiper.updateActiveIndex(); 13430 swiper.updateSlidesClasses(); 13431 if (!wasBeginning && swiper.isBeginning || !wasEnd && swiper.isEnd) { 13432 swiper.updateSlidesClasses(); 13433 } 13434 if (swiper.params.loop) { 13435 swiper.loopFix({ 13436 direction: newEvent.direction < 0 ? 'next' : 'prev', 13437 byMousewheel: true 13438 }); 13439 } 13440 if (swiper.params.freeMode.sticky) { 13441 // When wheel scrolling starts with sticky (aka snap) enabled, then detect 13442 // the end of a momentum scroll by storing recent (N=15?) wheel events. 13443 // 1. do all N events have decreasing or same (absolute value) delta? 13444 // 2. did all N events arrive in the last M (M=500?) msecs? 13445 // 3. does the earliest event have an (absolute value) delta that's 13446 // at least P (P=1?) larger than the most recent event's delta? 13447 // 4. does the latest event have a delta that's smaller than Q (Q=6?) pixels? 13448 // If 1-4 are "yes" then we're near the end of a momentum scroll deceleration. 13449 // Snap immediately and ignore remaining wheel events in this scroll. 13450 // See comment above for "remaining wheel events in this scroll" determination. 13451 // If 1-4 aren't satisfied, then wait to snap until 500ms after the last event. 13452 clearTimeout(timeout); 13453 timeout = undefined; 13454 if (recentWheelEvents.length >= 15) { 13455 recentWheelEvents.shift(); // only store the last N events 13456 } 13457 13458 const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined; 13459 const firstEvent = recentWheelEvents[0]; 13460 recentWheelEvents.push(newEvent); 13461 if (prevEvent && (newEvent.delta > prevEvent.delta || newEvent.direction !== prevEvent.direction)) { 13462 // Increasing or reverse-sign delta means the user started scrolling again. Clear the wheel event log. 13463 recentWheelEvents.splice(0); 13464 } else if (recentWheelEvents.length >= 15 && newEvent.time - firstEvent.time < 500 && firstEvent.delta - newEvent.delta >= 1 && newEvent.delta <= 6) { 13465 // We're at the end of the deceleration of a momentum scroll, so there's no need 13466 // to wait for more events. Snap ASAP on the next tick. 13467 // Also, because there's some remaining momentum we'll bias the snap in the 13468 // direction of the ongoing scroll because it's better UX for the scroll to snap 13469 // in the same direction as the scroll instead of reversing to snap. Therefore, 13470 // if it's already scrolled more than 20% in the current direction, keep going. 13471 const snapToThreshold = delta > 0 ? 0.8 : 0.2; 13472 lastEventBeforeSnap = newEvent; 13473 recentWheelEvents.splice(0); 13474 timeout = nextTick(() => { 13475 if (swiper.destroyed || !swiper.params) return; 13476 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold); 13477 }, 0); // no delay; move on next tick 13478 } 13479 13480 if (!timeout) { 13481 // if we get here, then we haven't detected the end of a momentum scroll, so 13482 // we'll consider a scroll "complete" when there haven't been any wheel events 13483 // for 500ms. 13484 timeout = nextTick(() => { 13485 if (swiper.destroyed || !swiper.params) return; 13486 const snapToThreshold = 0.5; 13487 lastEventBeforeSnap = newEvent; 13488 recentWheelEvents.splice(0); 13489 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold); 13490 }, 500); 13491 } 13492 } 13493 13494 // Emit event 13495 if (!ignoreWheelEvents) emit('scroll', e); 13496 13497 // Stop autoplay 13498 if (swiper.params.autoplay && swiper.params.autoplay.disableOnInteraction) swiper.autoplay.stop(); 13499 // Return page scroll on edge positions 13500 if (params.releaseOnEdges && (position === swiper.minTranslate() || position === swiper.maxTranslate())) { 13501 return true; 13502 } 13503 } 13504 } 13505 if (e.preventDefault) e.preventDefault();else e.returnValue = false; 13506 return false; 13507 } 13508 function events(method) { 13509 let targetEl = swiper.el; 13510 if (swiper.params.mousewheel.eventsTarget !== 'container') { 13511 targetEl = document.querySelector(swiper.params.mousewheel.eventsTarget); 13512 } 13513 targetEl[method]('mouseenter', handleMouseEnter); 13514 targetEl[method]('mouseleave', handleMouseLeave); 13515 targetEl[method]('wheel', handle); 13516 } 13517 function enable() { 13518 if (swiper.params.cssMode) { 13519 swiper.wrapperEl.removeEventListener('wheel', handle); 13520 return true; 13521 } 13522 if (swiper.mousewheel.enabled) return false; 13523 events('addEventListener'); 13524 swiper.mousewheel.enabled = true; 13525 return true; 13526 } 13527 function disable() { 13528 if (swiper.params.cssMode) { 13529 swiper.wrapperEl.addEventListener(event, handle); 13530 return true; 13531 } 13532 if (!swiper.mousewheel.enabled) return false; 13533 events('removeEventListener'); 13534 swiper.mousewheel.enabled = false; 13535 return true; 13536 } 13537 on('init', () => { 13538 if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) { 13539 disable(); 13540 } 13541 if (swiper.params.mousewheel.enabled) enable(); 13542 }); 13543 on('destroy', () => { 13544 if (swiper.params.cssMode) { 13545 enable(); 13546 } 13547 if (swiper.mousewheel.enabled) disable(); 13548 }); 13549 Object.assign(swiper.mousewheel, { 13550 enable, 13551 disable 13552 }); 13553 } 13554 13555 function createElementIfNotDefined(swiper, originalParams, params, checkProps) { 13556 if (swiper.params.createElements) { 13557 Object.keys(checkProps).forEach(key => { 13558 if (!params[key] && params.auto === true) { 13559 let element = elementChildren(swiper.el, `.${checkProps[key]}`)[0]; 13560 if (!element) { 13561 element = createElement('div', checkProps[key]); 13562 element.className = checkProps[key]; 13563 swiper.el.append(element); 13564 } 13565 params[key] = element; 13566 originalParams[key] = element; 13567 } 13568 }); 13569 } 13570 return params; 13571 } 13572 13573 const arrowSvg = `<svg class="swiper-navigation-icon" width="11" height="20" viewBox="0 0 11 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.38296 20.0762C0.111788 19.805 0.111788 19.3654 0.38296 19.0942L9.19758 10.2796L0.38296 1.46497C0.111788 1.19379 0.111788 0.754138 0.38296 0.482966C0.654131 0.211794 1.09379 0.211794 1.36496 0.482966L10.4341 9.55214C10.8359 9.9539 10.8359 10.6053 10.4341 11.007L1.36496 20.0762C1.09379 20.3474 0.654131 20.3474 0.38296 20.0762Z" fill="currentColor"/></svg>`; 13574 function Navigation({ 13575 swiper, 13576 extendParams, 13577 on, 13578 emit 13579 }) { 13580 extendParams({ 13581 navigation: { 13582 nextEl: null, 13583 prevEl: null, 13584 addIcons: true, 13585 hideOnClick: false, 13586 disabledClass: 'swiper-button-disabled', 13587 hiddenClass: 'swiper-button-hidden', 13588 lockClass: 'swiper-button-lock', 13589 navigationDisabledClass: 'swiper-navigation-disabled' 13590 } 13591 }); 13592 swiper.navigation = { 13593 nextEl: null, 13594 prevEl: null, 13595 arrowSvg 13596 }; 13597 function getEl(el) { 13598 let res; 13599 if (el && typeof el === 'string' && swiper.isElement) { 13600 res = swiper.el.querySelector(el) || swiper.hostEl.querySelector(el); 13601 if (res) return res; 13602 } 13603 if (el) { 13604 if (typeof el === 'string') res = [...document.querySelectorAll(el)]; 13605 if (swiper.params.uniqueNavElements && typeof el === 'string' && res && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) { 13606 res = swiper.el.querySelector(el); 13607 } else if (res && res.length === 1) { 13608 res = res[0]; 13609 } 13610 } 13611 if (el && !res) return el; 13612 // if (Array.isArray(res) && res.length === 1) res = res[0]; 13613 return res; 13614 } 13615 function toggleEl(el, disabled) { 13616 const params = swiper.params.navigation; 13617 el = makeElementsArray(el); 13618 el.forEach(subEl => { 13619 if (subEl) { 13620 subEl.classList[disabled ? 'add' : 'remove'](...params.disabledClass.split(' ')); 13621 if (subEl.tagName === 'BUTTON') subEl.disabled = disabled; 13622 if (swiper.params.watchOverflow && swiper.enabled) { 13623 subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass); 13624 } 13625 } 13626 }); 13627 } 13628 function update() { 13629 // Update Navigation Buttons 13630 const { 13631 nextEl, 13632 prevEl 13633 } = swiper.navigation; 13634 if (swiper.params.loop) { 13635 toggleEl(prevEl, false); 13636 toggleEl(nextEl, false); 13637 return; 13638 } 13639 toggleEl(prevEl, swiper.isBeginning && !swiper.params.rewind); 13640 toggleEl(nextEl, swiper.isEnd && !swiper.params.rewind); 13641 } 13642 function onPrevClick(e) { 13643 e.preventDefault(); 13644 if (swiper.isBeginning && !swiper.params.loop && !swiper.params.rewind) return; 13645 swiper.slidePrev(); 13646 emit('navigationPrev'); 13647 } 13648 function onNextClick(e) { 13649 e.preventDefault(); 13650 if (swiper.isEnd && !swiper.params.loop && !swiper.params.rewind) return; 13651 swiper.slideNext(); 13652 emit('navigationNext'); 13653 }
vendor: 4,164 bytes, lines 13654-13767
13654 function init() { 13655 const params = swiper.params.navigation; 13656 swiper.params.navigation = createElementIfNotDefined(swiper, swiper.originalParams.navigation, swiper.params.navigation, { 13657 nextEl: 'swiper-button-next', 13658 prevEl: 'swiper-button-prev' 13659 }); 13660 if (!(params.nextEl || params.prevEl)) return; 13661 let nextEl = getEl(params.nextEl); 13662 let prevEl = getEl(params.prevEl); 13663 Object.assign(swiper.navigation, { 13664 nextEl, 13665 prevEl 13666 }); 13667 nextEl = makeElementsArray(nextEl); 13668 prevEl = makeElementsArray(prevEl); 13669 const initButton = (el, dir) => { 13670 if (el) { 13671 if (params.addIcons && el.matches('.swiper-button-next,.swiper-button-prev') && !el.querySelector('svg')) { 13672 const tempEl = document.createElement('div'); 13673 setInnerHTML(tempEl, arrowSvg); 13674 el.appendChild(tempEl.querySelector('svg')); 13675 tempEl.remove(); 13676 } 13677 el.addEventListener('click', dir === 'next' ? onNextClick : onPrevClick); 13678 } 13679 if (!swiper.enabled && el) { 13680 el.classList.add(...params.lockClass.split(' ')); 13681 } 13682 }; 13683 nextEl.forEach(el => initButton(el, 'next')); 13684 prevEl.forEach(el => initButton(el, 'prev')); 13685 } 13686 function destroy() { 13687 let { 13688 nextEl, 13689 prevEl 13690 } = swiper.navigation; 13691 nextEl = makeElementsArray(nextEl); 13692 prevEl = makeElementsArray(prevEl); 13693 const destroyButton = (el, dir) => { 13694 el.removeEventListener('click', dir === 'next' ? onNextClick : onPrevClick); 13695 el.classList.remove(...swiper.params.navigation.disabledClass.split(' ')); 13696 }; 13697 nextEl.forEach(el => destroyButton(el, 'next')); 13698 prevEl.forEach(el => destroyButton(el, 'prev')); 13699 } 13700 on('init', () => { 13701 if (swiper.params.navigation.enabled === false) { 13702 // eslint-disable-next-line 13703 disable(); 13704 } else { 13705 init(); 13706 update(); 13707 } 13708 }); 13709 on('toEdge fromEdge lock unlock', () => { 13710 update(); 13711 }); 13712 on('destroy', () => { 13713 destroy(); 13714 }); 13715 on('enable disable', () => { 13716 let { 13717 nextEl, 13718 prevEl 13719 } = swiper.navigation; 13720 nextEl = makeElementsArray(nextEl); 13721 prevEl = makeElementsArray(prevEl); 13722 if (swiper.enabled) { 13723 update(); 13724 return; 13725 } 13726 [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.add(swiper.params.navigation.lockClass)); 13727 }); 13728 on('click', (_s, e) => { 13729 let { 13730 nextEl, 13731 prevEl 13732 } = swiper.navigation; 13733 nextEl = makeElementsArray(nextEl); 13734 prevEl = makeElementsArray(prevEl); 13735 const targetEl = e.target; 13736 let targetIsButton = prevEl.includes(targetEl) || nextEl.includes(targetEl); 13737 if (swiper.isElement && !targetIsButton) { 13738 const path = e.path || e.composedPath && e.composedPath(); 13739 if (path) { 13740 targetIsButton = path.find(pathEl => nextEl.includes(pathEl) || prevEl.includes(pathEl)); 13741 } 13742 } 13743 if (swiper.params.navigation.hideOnClick && !targetIsButton) { 13744 if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return; 13745 let isHidden; 13746 if (nextEl.length) { 13747 isHidden = nextEl[0].classList.contains(swiper.params.navigation.hiddenClass); 13748 } else if (prevEl.length) { 13749 isHidden = prevEl[0].classList.contains(swiper.params.navigation.hiddenClass); 13750 } 13751 if (isHidden === true) { 13752 emit('navigationShow'); 13753 } else { 13754 emit('navigationHide'); 13755 } 13756 [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.toggle(swiper.params.navigation.hiddenClass)); 13757 } 13758 }); 13759 const enable = () => { 13760 swiper.el.classList.remove(...swiper.params.navigation.navigationDisabledClass.split(' ')); 13761 init(); 13762 update(); 13763 }; 13764 const disable = () => { 13765 swiper.el.classList.add(...swiper.params.navigation.navigationDisabledClass.split(' ')); 13766 destroy(); 13767 };
vendor: 5,665 bytes, lines 13768-13919
13768 Object.assign(swiper.navigation, { 13769 enable, 13770 disable, 13771 update, 13772 init, 13773 destroy 13774 }); 13775 } 13776 13777 function classesToSelector(classes = '') { 13778 return `.${classes.trim().replace(/([\.:!+\/()[\]])/g, '\\$1') // eslint-disable-line 13779 .replace(/ /g, '.')}`; 13780 } 13781 13782 function Pagination({ 13783 swiper, 13784 extendParams, 13785 on, 13786 emit 13787 }) { 13788 const pfx = 'swiper-pagination'; 13789 extendParams({ 13790 pagination: { 13791 el: null, 13792 bulletElement: 'span', 13793 clickable: false, 13794 hideOnClick: false, 13795 renderBullet: null, 13796 renderProgressbar: null, 13797 renderFraction: null, 13798 renderCustom: null, 13799 progressbarOpposite: false, 13800 type: 'bullets', 13801 // 'bullets' or 'progressbar' or 'fraction' or 'custom' 13802 dynamicBullets: false, 13803 dynamicMainBullets: 1, 13804 formatFractionCurrent: number => number, 13805 formatFractionTotal: number => number, 13806 bulletClass: `${pfx}-bullet`, 13807 bulletActiveClass: `${pfx}-bullet-active`, 13808 modifierClass: `${pfx}-`, 13809 currentClass: `${pfx}-current`, 13810 totalClass: `${pfx}-total`, 13811 hiddenClass: `${pfx}-hidden`, 13812 progressbarFillClass: `${pfx}-progressbar-fill`, 13813 progressbarOppositeClass: `${pfx}-progressbar-opposite`, 13814 clickableClass: `${pfx}-clickable`, 13815 lockClass: `${pfx}-lock`, 13816 horizontalClass: `${pfx}-horizontal`, 13817 verticalClass: `${pfx}-vertical`, 13818 paginationDisabledClass: `${pfx}-disabled` 13819 } 13820 }); 13821 swiper.pagination = { 13822 el: null, 13823 bullets: [] 13824 }; 13825 let bulletSize; 13826 let dynamicBulletIndex = 0; 13827 function isPaginationDisabled() { 13828 return !swiper.params.pagination.el || !swiper.pagination.el || Array.isArray(swiper.pagination.el) && swiper.pagination.el.length === 0; 13829 } 13830 function setSideBullets(bulletEl, position) { 13831 const { 13832 bulletActiveClass 13833 } = swiper.params.pagination; 13834 if (!bulletEl) return; 13835 bulletEl = bulletEl[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`]; 13836 if (bulletEl) { 13837 bulletEl.classList.add(`${bulletActiveClass}-${position}`); 13838 bulletEl = bulletEl[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`]; 13839 if (bulletEl) { 13840 bulletEl.classList.add(`${bulletActiveClass}-${position}-${position}`); 13841 } 13842 } 13843 } 13844 function getMoveDirection(prevIndex, nextIndex, length) { 13845 prevIndex = prevIndex % length; 13846 nextIndex = nextIndex % length; 13847 if (nextIndex === prevIndex + 1) { 13848 return 'next'; 13849 } else if (nextIndex === prevIndex - 1) { 13850 return 'previous'; 13851 } 13852 return; 13853 } 13854 function onBulletClick(e) { 13855 const bulletEl = e.target.closest(classesToSelector(swiper.params.pagination.bulletClass)); 13856 if (!bulletEl) { 13857 return; 13858 } 13859 e.preventDefault(); 13860 const index = elementIndex(bulletEl) * swiper.params.slidesPerGroup; 13861 if (swiper.params.loop) { 13862 if (swiper.realIndex === index) return; 13863 const moveDirection = getMoveDirection(swiper.realIndex, index, swiper.slides.length); 13864 if (moveDirection === 'next') { 13865 swiper.slideNext(); 13866 } else if (moveDirection === 'previous') { 13867 swiper.slidePrev(); 13868 } else { 13869 swiper.slideToLoop(index); 13870 } 13871 } else { 13872 swiper.slideTo(index); 13873 } 13874 } 13875 function update() { 13876 // Render || Update Pagination bullets/items 13877 const rtl = swiper.rtl; 13878 const params = swiper.params.pagination; 13879 if (isPaginationDisabled()) return; 13880 let el = swiper.pagination.el; 13881 el = makeElementsArray(el); 13882 // Current/Total 13883 let current; 13884 let previousIndex; 13885 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length; 13886 const total = swiper.params.loop ? Math.ceil(slidesLength / swiper.params.slidesPerGroup) : swiper.snapGrid.length; 13887 if (swiper.params.loop) { 13888 previousIndex = swiper.previousRealIndex || 0; 13889 current = swiper.params.slidesPerGroup > 1 ? Math.floor(swiper.realIndex / swiper.params.slidesPerGroup) : swiper.realIndex; 13890 } else if (typeof swiper.snapIndex !== 'undefined') { 13891 current = swiper.snapIndex; 13892 previousIndex = swiper.previousSnapIndex; 13893 } else { 13894 previousIndex = swiper.previousIndex || 0; 13895 current = swiper.activeIndex || 0; 13896 } 13897 // Types 13898 if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) { 13899 const bullets = swiper.pagination.bullets; 13900 let firstIndex; 13901 let lastIndex; 13902 let midIndex; 13903 if (params.dynamicBullets) { 13904 bulletSize = elementOuterSize(bullets[0], swiper.isHorizontal() ? 'width' : 'height', true); 13905 el.forEach(subEl => { 13906 subEl.style[swiper.isHorizontal() ? 'width' : 'height'] = `${bulletSize * (params.dynamicMainBullets + 4)}px`; 13907 }); 13908 if (params.dynamicMainBullets > 1 && previousIndex !== undefined) { 13909 dynamicBulletIndex += current - (previousIndex || 0); 13910 if (dynamicBulletIndex > params.dynamicMainBullets - 1) { 13911 dynamicBulletIndex = params.dynamicMainBullets - 1; 13912 } else if (dynamicBulletIndex < 0) { 13913 dynamicBulletIndex = 0; 13914 } 13915 } 13916 firstIndex = Math.max(current - dynamicBulletIndex, 0); 13917 lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1); 13918 midIndex = (lastIndex + firstIndex) / 2; 13919 }
vendor: 9,584 bytes, lines 13920-14137
13920 bullets.forEach(bulletEl => { 13921 const classesToRemove = [...['', '-next', '-next-next', '-prev', '-prev-prev', '-main'].map(suffix => `${params.bulletActiveClass}${suffix}`)].map(s => typeof s === 'string' && s.includes(' ') ? s.split(' ') : s).flat(); 13922 bulletEl.classList.remove(...classesToRemove); 13923 }); 13924 if (el.length > 1) { 13925 bullets.forEach(bullet => { 13926 const bulletIndex = elementIndex(bullet); 13927 if (bulletIndex === current) { 13928 bullet.classList.add(...params.bulletActiveClass.split(' ')); 13929 } else if (swiper.isElement) { 13930 bullet.setAttribute('part', 'bullet'); 13931 } 13932 if (params.dynamicBullets) { 13933 if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) { 13934 bullet.classList.add(...`${params.bulletActiveClass}-main`.split(' ')); 13935 } 13936 if (bulletIndex === firstIndex) { 13937 setSideBullets(bullet, 'prev'); 13938 } 13939 if (bulletIndex === lastIndex) { 13940 setSideBullets(bullet, 'next'); 13941 } 13942 } 13943 }); 13944 } else { 13945 const bullet = bullets[current]; 13946 if (bullet) { 13947 bullet.classList.add(...params.bulletActiveClass.split(' ')); 13948 } 13949 if (swiper.isElement) { 13950 bullets.forEach((bulletEl, bulletIndex) => { 13951 bulletEl.setAttribute('part', bulletIndex === current ? 'bullet-active' : 'bullet'); 13952 }); 13953 } 13954 if (params.dynamicBullets) { 13955 const firstDisplayedBullet = bullets[firstIndex]; 13956 const lastDisplayedBullet = bullets[lastIndex]; 13957 for (let i = firstIndex; i <= lastIndex; i += 1) { 13958 if (bullets[i]) { 13959 bullets[i].classList.add(...`${params.bulletActiveClass}-main`.split(' ')); 13960 } 13961 } 13962 setSideBullets(firstDisplayedBullet, 'prev'); 13963 setSideBullets(lastDisplayedBullet, 'next'); 13964 } 13965 } 13966 if (params.dynamicBullets) { 13967 const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4); 13968 const bulletsOffset = (bulletSize * dynamicBulletsLength - bulletSize) / 2 - midIndex * bulletSize; 13969 const offsetProp = rtl ? 'right' : 'left'; 13970 bullets.forEach(bullet => { 13971 bullet.style[swiper.isHorizontal() ? offsetProp : 'top'] = `${bulletsOffset}px`; 13972 }); 13973 } 13974 } 13975 el.forEach((subEl, subElIndex) => { 13976 if (params.type === 'fraction') { 13977 subEl.querySelectorAll(classesToSelector(params.currentClass)).forEach(fractionEl => { 13978 fractionEl.textContent = params.formatFractionCurrent(current + 1); 13979 }); 13980 subEl.querySelectorAll(classesToSelector(params.totalClass)).forEach(totalEl => { 13981 totalEl.textContent = params.formatFractionTotal(total); 13982 }); 13983 } 13984 if (params.type === 'progressbar') { 13985 let progressbarDirection; 13986 if (params.progressbarOpposite) { 13987 progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal'; 13988 } else { 13989 progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical'; 13990 } 13991 const scale = (current + 1) / total; 13992 let scaleX = 1; 13993 let scaleY = 1; 13994 if (progressbarDirection === 'horizontal') { 13995 scaleX = scale; 13996 } else { 13997 scaleY = scale; 13998 } 13999 subEl.querySelectorAll(classesToSelector(params.progressbarFillClass)).forEach(progressEl => { 14000 progressEl.style.transform = `translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`; 14001 progressEl.style.transitionDuration = `${swiper.params.speed}ms`; 14002 }); 14003 } 14004 if (params.type === 'custom' && params.renderCustom) { 14005 setInnerHTML(subEl, params.renderCustom(swiper, current + 1, total)); 14006 if (subElIndex === 0) emit('paginationRender', subEl); 14007 } else { 14008 if (subElIndex === 0) emit('paginationRender', subEl); 14009 emit('paginationUpdate', subEl); 14010 } 14011 if (swiper.params.watchOverflow && swiper.enabled) { 14012 subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass); 14013 } 14014 }); 14015 } 14016 function render() { 14017 // Render Container 14018 const params = swiper.params.pagination; 14019 if (isPaginationDisabled()) return; 14020 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.grid && swiper.params.grid.rows > 1 ? swiper.slides.length / Math.ceil(swiper.params.grid.rows) : swiper.slides.length; 14021 let el = swiper.pagination.el; 14022 el = makeElementsArray(el); 14023 let paginationHTML = ''; 14024 if (params.type === 'bullets') { 14025 let numberOfBullets = swiper.params.loop ? Math.ceil(slidesLength / swiper.params.slidesPerGroup) : swiper.snapGrid.length; 14026 if (swiper.params.freeMode && swiper.params.freeMode.enabled && numberOfBullets > slidesLength) { 14027 numberOfBullets = slidesLength; 14028 } 14029 for (let i = 0; i < numberOfBullets; i += 1) { 14030 if (params.renderBullet) { 14031 paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass); 14032 } else { 14033 // prettier-ignore 14034 paginationHTML += `<${params.bulletElement} ${swiper.isElement ? 'part="bullet"' : ''} class="${params.bulletClass}"></${params.bulletElement}>`; 14035 } 14036 } 14037 } 14038 if (params.type === 'fraction') { 14039 if (params.renderFraction) { 14040 paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass); 14041 } else { 14042 paginationHTML = `<span class="${params.currentClass}"></span>` + ' / ' + `<span class="${params.totalClass}"></span>`; 14043 } 14044 } 14045 if (params.type === 'progressbar') { 14046 if (params.renderProgressbar) { 14047 paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass); 14048 } else { 14049 paginationHTML = `<span class="${params.progressbarFillClass}"></span>`; 14050 } 14051 } 14052 swiper.pagination.bullets = []; 14053 el.forEach(subEl => { 14054 if (params.type !== 'custom') { 14055 setInnerHTML(subEl, paginationHTML || ''); 14056 } 14057 if (params.type === 'bullets') { 14058 swiper.pagination.bullets.push(...subEl.querySelectorAll(classesToSelector(params.bulletClass))); 14059 } 14060 }); 14061 if (params.type !== 'custom') { 14062 emit('paginationRender', el[0]); 14063 } 14064 } 14065 function init() { 14066 swiper.params.pagination = createElementIfNotDefined(swiper, swiper.originalParams.pagination, swiper.params.pagination, { 14067 el: 'swiper-pagination' 14068 }); 14069 const params = swiper.params.pagination; 14070 if (!params.el) return; 14071 let el; 14072 if (typeof params.el === 'string' && swiper.isElement) { 14073 el = swiper.el.querySelector(params.el); 14074 } 14075 if (!el && typeof params.el === 'string') { 14076 el = [...document.querySelectorAll(params.el)]; 14077 } 14078 if (!el) { 14079 el = params.el; 14080 } 14081 if (!el || el.length === 0) return; 14082 if (swiper.params.uniqueNavElements && typeof params.el === 'string' && Array.isArray(el) && el.length > 1) { 14083 el = [...swiper.el.querySelectorAll(params.el)]; 14084 // check if it belongs to another nested Swiper 14085 if (el.length > 1) { 14086 el = el.find(subEl => { 14087 if (elementParents(subEl, '.swiper')[0] !== swiper.el) return false; 14088 return true; 14089 }); 14090 } 14091 } 14092 if (Array.isArray(el) && el.length === 1) el = el[0]; 14093 Object.assign(swiper.pagination, { 14094 el 14095 }); 14096 el = makeElementsArray(el); 14097 el.forEach(subEl => { 14098 if (params.type === 'bullets' && params.clickable) { 14099 subEl.classList.add(...(params.clickableClass || '').split(' ')); 14100 } 14101 subEl.classList.add(params.modifierClass + params.type); 14102 subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 14103 if (params.type === 'bullets' && params.dynamicBullets) { 14104 subEl.classList.add(`${params.modifierClass}${params.type}-dynamic`); 14105 dynamicBulletIndex = 0; 14106 if (params.dynamicMainBullets < 1) { 14107 params.dynamicMainBullets = 1; 14108 } 14109 } 14110 if (params.type === 'progressbar' && params.progressbarOpposite) { 14111 subEl.classList.add(params.progressbarOppositeClass); 14112 } 14113 if (params.clickable) { 14114 subEl.addEventListener('click', onBulletClick); 14115 } 14116 if (!swiper.enabled) { 14117 subEl.classList.add(params.lockClass); 14118 } 14119 }); 14120 } 14121 function destroy() { 14122 const params = swiper.params.pagination; 14123 if (isPaginationDisabled()) return; 14124 let el = swiper.pagination.el; 14125 if (el) { 14126 el = makeElementsArray(el); 14127 el.forEach(subEl => { 14128 subEl.classList.remove(params.hiddenClass); 14129 subEl.classList.remove(params.modifierClass + params.type); 14130 subEl.classList.remove(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 14131 if (params.clickable) { 14132 subEl.classList.remove(...(params.clickableClass || '').split(' ')); 14133 subEl.removeEventListener('click', onBulletClick); 14134 } 14135 }); 14136 } 14137 if (swiper.pagination.bullets) swiper.pagination.bullets.forEac
vendor: 8,195 bytes, lines 14137-14396
14137h(subEl => subEl.classList.remove(...params.bulletActiveClass.split(' '))); 14138 } 14139 on('changeDirection', () => { 14140 if (!swiper.pagination || !swiper.pagination.el) return; 14141 const params = swiper.params.pagination; 14142 let { 14143 el 14144 } = swiper.pagination; 14145 el = makeElementsArray(el); 14146 el.forEach(subEl => { 14147 subEl.classList.remove(params.horizontalClass, params.verticalClass); 14148 subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 14149 }); 14150 }); 14151 on('init', () => { 14152 if (swiper.params.pagination.enabled === false) { 14153 // eslint-disable-next-line 14154 disable(); 14155 } else { 14156 init(); 14157 render(); 14158 update(); 14159 } 14160 }); 14161 on('activeIndexChange', () => { 14162 if (typeof swiper.snapIndex === 'undefined') { 14163 update(); 14164 } 14165 }); 14166 on('snapIndexChange', () => { 14167 update(); 14168 }); 14169 on('snapGridLengthChange', () => { 14170 render(); 14171 update(); 14172 }); 14173 on('destroy', () => { 14174 destroy(); 14175 }); 14176 on('enable disable', () => { 14177 let { 14178 el 14179 } = swiper.pagination; 14180 if (el) { 14181 el = makeElementsArray(el); 14182 el.forEach(subEl => subEl.classList[swiper.enabled ? 'remove' : 'add'](swiper.params.pagination.lockClass)); 14183 } 14184 }); 14185 on('lock unlock', () => { 14186 update(); 14187 }); 14188 on('click', (_s, e) => { 14189 const targetEl = e.target; 14190 const el = makeElementsArray(swiper.pagination.el); 14191 if (swiper.params.pagination.el && swiper.params.pagination.hideOnClick && el && el.length > 0 && !targetEl.classList.contains(swiper.params.pagination.bulletClass)) { 14192 if (swiper.navigation && (swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl || swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl)) return; 14193 const isHidden = el[0].classList.contains(swiper.params.pagination.hiddenClass); 14194 if (isHidden === true) { 14195 emit('paginationShow'); 14196 } else { 14197 emit('paginationHide'); 14198 } 14199 el.forEach(subEl => subEl.classList.toggle(swiper.params.pagination.hiddenClass)); 14200 } 14201 }); 14202 const enable = () => { 14203 swiper.el.classList.remove(swiper.params.pagination.paginationDisabledClass); 14204 let { 14205 el 14206 } = swiper.pagination; 14207 if (el) { 14208 el = makeElementsArray(el); 14209 el.forEach(subEl => subEl.classList.remove(swiper.params.pagination.paginationDisabledClass)); 14210 } 14211 init(); 14212 render(); 14213 update(); 14214 }; 14215 const disable = () => { 14216 swiper.el.classList.add(swiper.params.pagination.paginationDisabledClass); 14217 let { 14218 el 14219 } = swiper.pagination; 14220 if (el) { 14221 el = makeElementsArray(el); 14222 el.forEach(subEl => subEl.classList.add(swiper.params.pagination.paginationDisabledClass)); 14223 } 14224 destroy(); 14225 }; 14226 Object.assign(swiper.pagination, { 14227 enable, 14228 disable, 14229 render, 14230 update, 14231 init, 14232 destroy 14233 }); 14234 } 14235 14236 function Scrollbar({ 14237 swiper, 14238 extendParams, 14239 on, 14240 emit 14241 }) { 14242 const document = getDocument(); 14243 let isTouched = false; 14244 let timeout = null; 14245 let dragTimeout = null; 14246 let dragStartPos; 14247 let dragSize; 14248 let trackSize; 14249 let divider; 14250 extendParams({ 14251 scrollbar: { 14252 el: null, 14253 dragSize: 'auto', 14254 hide: false, 14255 draggable: false, 14256 snapOnRelease: true, 14257 lockClass: 'swiper-scrollbar-lock', 14258 dragClass: 'swiper-scrollbar-drag', 14259 scrollbarDisabledClass: 'swiper-scrollbar-disabled', 14260 horizontalClass: `swiper-scrollbar-horizontal`, 14261 verticalClass: `swiper-scrollbar-vertical` 14262 } 14263 }); 14264 swiper.scrollbar = { 14265 el: null, 14266 dragEl: null 14267 }; 14268 function setTranslate() { 14269 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return; 14270 const { 14271 scrollbar, 14272 rtlTranslate: rtl 14273 } = swiper; 14274 const { 14275 dragEl, 14276 el 14277 } = scrollbar; 14278 const params = swiper.params.scrollbar; 14279 const progress = swiper.params.loop ? swiper.progressLoop : swiper.progress; 14280 let newSize = dragSize; 14281 let newPos = (trackSize - dragSize) * progress; 14282 if (rtl) { 14283 newPos = -newPos; 14284 if (newPos > 0) { 14285 newSize = dragSize - newPos; 14286 newPos = 0; 14287 } else if (-newPos + dragSize > trackSize) { 14288 newSize = trackSize + newPos; 14289 } 14290 } else if (newPos < 0) { 14291 newSize = dragSize + newPos; 14292 newPos = 0; 14293 } else if (newPos + dragSize > trackSize) { 14294 newSize = trackSize - newPos; 14295 } 14296 if (swiper.isHorizontal()) { 14297 dragEl.style.transform = `translate3d(${newPos}px, 0, 0)`; 14298 dragEl.style.width = `${newSize}px`; 14299 } else { 14300 dragEl.style.transform = `translate3d(0px, ${newPos}px, 0)`; 14301 dragEl.style.height = `${newSize}px`; 14302 } 14303 if (params.hide) { 14304 clearTimeout(timeout); 14305 el.style.opacity = 1; 14306 timeout = setTimeout(() => { 14307 el.style.opacity = 0; 14308 el.style.transitionDuration = '400ms'; 14309 }, 1000); 14310 } 14311 } 14312 function setTransition(duration) { 14313 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return; 14314 swiper.scrollbar.dragEl.style.transitionDuration = `${duration}ms`; 14315 } 14316 function updateSize() { 14317 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return; 14318 const { 14319 scrollbar 14320 } = swiper; 14321 const { 14322 dragEl, 14323 el 14324 } = scrollbar; 14325 dragEl.style.width = ''; 14326 dragEl.style.height = ''; 14327 trackSize = swiper.isHorizontal() ? el.offsetWidth : el.offsetHeight; 14328 divider = swiper.size / (swiper.virtualSize + swiper.params.slidesOffsetBefore - (swiper.params.centeredSlides ? swiper.snapGrid[0] : 0)); 14329 if (swiper.params.scrollbar.dragSize === 'auto') { 14330 dragSize = trackSize * divider; 14331 } else { 14332 dragSize = parseInt(swiper.params.scrollbar.dragSize, 10); 14333 } 14334 if (swiper.isHorizontal()) { 14335 dragEl.style.width = `${dragSize}px`; 14336 } else { 14337 dragEl.style.height = `${dragSize}px`; 14338 } 14339 if (divider >= 1) { 14340 el.style.display = 'none'; 14341 } else { 14342 el.style.display = ''; 14343 } 14344 if (swiper.params.scrollbar.hide) { 14345 el.style.opacity = 0; 14346 } 14347 if (swiper.params.watchOverflow && swiper.enabled) { 14348 scrollbar.el.classList[swiper.isLocked ? 'add' : 'remove'](swiper.params.scrollbar.lockClass); 14349 } 14350 } 14351 function getPointerPosition(e) { 14352 return swiper.isHorizontal() ? e.clientX : e.clientY; 14353 } 14354 function setDragPosition(e) { 14355 const { 14356 scrollbar, 14357 rtlTranslate: rtl 14358 } = swiper; 14359 const { 14360 el 14361 } = scrollbar; 14362 let positionRatio; 14363 positionRatio = (getPointerPosition(e) - elementOffset(el)[swiper.isHorizontal() ? 'left' : 'top'] - (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize); 14364 positionRatio = Math.max(Math.min(positionRatio, 1), 0); 14365 if (rtl) { 14366 positionRatio = 1 - positionRatio; 14367 } 14368 const position = swiper.minTranslate() + (swiper.maxTranslate() - swiper.minTranslate()) * positionRatio; 14369 swiper.updateProgress(position); 14370 swiper.setTranslate(position); 14371 swiper.updateActiveIndex(); 14372 swiper.updateSlidesClasses(); 14373 } 14374 function onDragStart(e) { 14375 const params = swiper.params.scrollbar; 14376 const { 14377 scrollbar, 14378 wrapperEl 14379 } = swiper; 14380 const { 14381 el, 14382 dragEl 14383 } = scrollbar; 14384 isTouched = true; 14385 dragStartPos = e.target === dragEl ? getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null; 14386 e.preventDefault(); 14387 e.stopPropagation(); 14388 wrapperEl.style.transitionDuration = '100ms'; 14389 dragEl.style.transitionDuration = '100ms'; 14390 setDragPosition(e); 14391 clearTimeout(dragTimeout); 14392 el.style.transitionDuration = '0ms'; 14393 if (params.hide) { 14394 el.style.opacity = 1; 14395 } 14396 if (swiper.params.cssMode) {
vendor: 6,010 bytes, lines 14397-14584
14397 swiper.wrapperEl.style['scroll-snap-type'] = 'none'; 14398 } 14399 emit('scrollbarDragStart', e); 14400 } 14401 function onDragMove(e) { 14402 const { 14403 scrollbar, 14404 wrapperEl 14405 } = swiper; 14406 const { 14407 el, 14408 dragEl 14409 } = scrollbar; 14410 if (!isTouched) return; 14411 if (e.preventDefault && e.cancelable) e.preventDefault();else e.returnValue = false; 14412 setDragPosition(e); 14413 wrapperEl.style.transitionDuration = '0ms'; 14414 el.style.transitionDuration = '0ms'; 14415 dragEl.style.transitionDuration = '0ms'; 14416 emit('scrollbarDragMove', e); 14417 } 14418 function onDragEnd(e) { 14419 const params = swiper.params.scrollbar; 14420 const { 14421 scrollbar, 14422 wrapperEl 14423 } = swiper; 14424 const { 14425 el 14426 } = scrollbar; 14427 if (!isTouched) return; 14428 isTouched = false; 14429 if (swiper.params.cssMode) { 14430 swiper.wrapperEl.style['scroll-snap-type'] = ''; 14431 wrapperEl.style.transitionDuration = ''; 14432 } 14433 if (params.hide) { 14434 clearTimeout(dragTimeout); 14435 dragTimeout = nextTick(() => { 14436 el.style.opacity = 0; 14437 el.style.transitionDuration = '400ms'; 14438 }, 1000); 14439 } 14440 emit('scrollbarDragEnd', e); 14441 if (params.snapOnRelease) { 14442 swiper.slideToClosest(); 14443 } 14444 } 14445 function events(method) { 14446 const { 14447 scrollbar, 14448 params 14449 } = swiper; 14450 const el = scrollbar.el; 14451 if (!el) return; 14452 const target = el; 14453 const activeListener = params.passiveListeners ? { 14454 passive: false, 14455 capture: false 14456 } : false; 14457 const passiveListener = params.passiveListeners ? { 14458 passive: true, 14459 capture: false 14460 } : false; 14461 if (!target) return; 14462 const eventMethod = method === 'on' ? 'addEventListener' : 'removeEventListener'; 14463 target[eventMethod]('pointerdown', onDragStart, activeListener); 14464 document[eventMethod]('pointermove', onDragMove, activeListener); 14465 document[eventMethod]('pointerup', onDragEnd, passiveListener); 14466 } 14467 function enableDraggable() { 14468 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return; 14469 events('on'); 14470 } 14471 function disableDraggable() { 14472 if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return; 14473 events('off'); 14474 } 14475 function init() { 14476 const { 14477 scrollbar, 14478 el: swiperEl 14479 } = swiper; 14480 swiper.params.scrollbar = createElementIfNotDefined(swiper, swiper.originalParams.scrollbar, swiper.params.scrollbar, { 14481 el: 'swiper-scrollbar' 14482 }); 14483 const params = swiper.params.scrollbar; 14484 if (!params.el) return; 14485 let el; 14486 if (typeof params.el === 'string' && swiper.isElement) { 14487 el = swiper.el.querySelector(params.el); 14488 } 14489 if (!el && typeof params.el === 'string') { 14490 el = document.querySelectorAll(params.el); 14491 if (!el.length) return; 14492 } else if (!el) { 14493 el = params.el; 14494 } 14495 if (swiper.params.uniqueNavElements && typeof params.el === 'string' && el.length > 1 && swiperEl.querySelectorAll(params.el).length === 1) { 14496 el = swiperEl.querySelector(params.el); 14497 } 14498 if (el.length > 0) el = el[0]; 14499 el.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 14500 let dragEl; 14501 if (el) { 14502 dragEl = el.querySelector(classesToSelector(swiper.params.scrollbar.dragClass)); 14503 if (!dragEl) { 14504 dragEl = createElement('div', swiper.params.scrollbar.dragClass); 14505 el.append(dragEl); 14506 } 14507 } 14508 Object.assign(scrollbar, { 14509 el, 14510 dragEl 14511 }); 14512 if (params.draggable) { 14513 enableDraggable(); 14514 } 14515 if (el) { 14516 el.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(swiper.params.scrollbar.lockClass)); 14517 } 14518 } 14519 function destroy() { 14520 const params = swiper.params.scrollbar; 14521 const el = swiper.scrollbar.el; 14522 if (el) { 14523 el.classList.remove(...classesToTokens(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass)); 14524 } 14525 disableDraggable(); 14526 } 14527 on('changeDirection', () => { 14528 if (!swiper.scrollbar || !swiper.scrollbar.el) return; 14529 const params = swiper.params.scrollbar; 14530 let { 14531 el 14532 } = swiper.scrollbar; 14533 el = makeElementsArray(el); 14534 el.forEach(subEl => { 14535 subEl.classList.remove(params.horizontalClass, params.verticalClass); 14536 subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 14537 }); 14538 }); 14539 on('init', () => { 14540 if (swiper.params.scrollbar.enabled === false) { 14541 // eslint-disable-next-line 14542 disable(); 14543 } else { 14544 init(); 14545 updateSize(); 14546 setTranslate(); 14547 } 14548 }); 14549 on('update resize observerUpdate lock unlock changeDirection', () => { 14550 updateSize(); 14551 }); 14552 on('setTranslate', () => { 14553 setTranslate(); 14554 }); 14555 on('setTransition', (_s, duration) => { 14556 setTransition(duration); 14557 }); 14558 on('enable disable', () => { 14559 const { 14560 el 14561 } = swiper.scrollbar; 14562 if (el) { 14563 el.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(swiper.params.scrollbar.lockClass)); 14564 } 14565 }); 14566 on('destroy', () => { 14567 destroy(); 14568 }); 14569 const enable = () => { 14570 swiper.el.classList.remove(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass)); 14571 if (swiper.scrollbar.el) { 14572 swiper.scrollbar.el.classList.remove(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass)); 14573 } 14574 init(); 14575 updateSize(); 14576 setTranslate(); 14577 }; 14578 const disable = () => { 14579 swiper.el.classList.add(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass)); 14580 if (swiper.scrollbar.el) { 14581 swiper.scrollbar.el.classList.add(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass)); 14582 } 14583 destroy(); 14584 };
vendor: 14,492 bytes, lines 14585-14992
14585 Object.assign(swiper.scrollbar, { 14586 enable, 14587 disable, 14588 updateSize, 14589 setTranslate, 14590 init, 14591 destroy 14592 }); 14593 } 14594 14595 function Parallax({ 14596 swiper, 14597 extendParams, 14598 on 14599 }) { 14600 extendParams({ 14601 parallax: { 14602 enabled: false 14603 } 14604 }); 14605 const elementsSelector = '[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]'; 14606 const setTransform = (el, progress) => { 14607 const { 14608 rtl 14609 } = swiper; 14610 const rtlFactor = rtl ? -1 : 1; 14611 const p = el.getAttribute('data-swiper-parallax') || '0'; 14612 let x = el.getAttribute('data-swiper-parallax-x'); 14613 let y = el.getAttribute('data-swiper-parallax-y'); 14614 const scale = el.getAttribute('data-swiper-parallax-scale'); 14615 const opacity = el.getAttribute('data-swiper-parallax-opacity'); 14616 const rotate = el.getAttribute('data-swiper-parallax-rotate'); 14617 if (x || y) { 14618 x = x || '0'; 14619 y = y || '0'; 14620 } else if (swiper.isHorizontal()) { 14621 x = p; 14622 y = '0'; 14623 } else { 14624 y = p; 14625 x = '0'; 14626 } 14627 if (x.indexOf('%') >= 0) { 14628 x = `${parseInt(x, 10) * progress * rtlFactor}%`; 14629 } else { 14630 x = `${x * progress * rtlFactor}px`; 14631 } 14632 if (y.indexOf('%') >= 0) { 14633 y = `${parseInt(y, 10) * progress}%`; 14634 } else { 14635 y = `${y * progress}px`; 14636 } 14637 if (typeof opacity !== 'undefined' && opacity !== null) { 14638 const currentOpacity = opacity - (opacity - 1) * (1 - Math.abs(progress)); 14639 el.style.opacity = currentOpacity; 14640 } 14641 let transform = `translate3d(${x}, ${y}, 0px)`; 14642 if (typeof scale !== 'undefined' && scale !== null) { 14643 const currentScale = scale - (scale - 1) * (1 - Math.abs(progress)); 14644 transform += ` scale(${currentScale})`; 14645 } 14646 if (rotate && typeof rotate !== 'undefined' && rotate !== null) { 14647 const currentRotate = rotate * progress * -1; 14648 transform += ` rotate(${currentRotate}deg)`; 14649 } 14650 el.style.transform = transform; 14651 }; 14652 const setTranslate = () => { 14653 const { 14654 el, 14655 slides, 14656 progress, 14657 snapGrid, 14658 isElement 14659 } = swiper; 14660 const elements = elementChildren(el, elementsSelector); 14661 if (swiper.isElement) { 14662 elements.push(...elementChildren(swiper.hostEl, elementsSelector)); 14663 } 14664 elements.forEach(subEl => { 14665 setTransform(subEl, progress); 14666 }); 14667 slides.forEach((slideEl, slideIndex) => { 14668 let slideProgress = slideEl.progress; 14669 if (swiper.params.slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') { 14670 slideProgress += Math.ceil(slideIndex / 2) - progress * (snapGrid.length - 1); 14671 } 14672 slideProgress = Math.min(Math.max(slideProgress, -1), 1); 14673 slideEl.querySelectorAll(`${elementsSelector}, [data-swiper-parallax-rotate]`).forEach(subEl => { 14674 setTransform(subEl, slideProgress); 14675 }); 14676 }); 14677 }; 14678 const setTransition = (duration = swiper.params.speed) => { 14679 const { 14680 el, 14681 hostEl 14682 } = swiper; 14683 const elements = [...el.querySelectorAll(elementsSelector)]; 14684 if (swiper.isElement) { 14685 elements.push(...hostEl.querySelectorAll(elementsSelector)); 14686 } 14687 elements.forEach(parallaxEl => { 14688 let parallaxDuration = parseInt(parallaxEl.getAttribute('data-swiper-parallax-duration'), 10) || duration; 14689 if (duration === 0) parallaxDuration = 0; 14690 parallaxEl.style.transitionDuration = `${parallaxDuration}ms`; 14691 }); 14692 }; 14693 on('beforeInit', () => { 14694 if (!swiper.params.parallax.enabled) return; 14695 swiper.params.watchSlidesProgress = true; 14696 swiper.originalParams.watchSlidesProgress = true; 14697 }); 14698 on('init', () => { 14699 if (!swiper.params.parallax.enabled) return; 14700 setTranslate(); 14701 }); 14702 on('setTranslate', () => { 14703 if (!swiper.params.parallax.enabled) return; 14704 setTranslate(); 14705 }); 14706 on('setTransition', (_swiper, duration) => { 14707 if (!swiper.params.parallax.enabled) return; 14708 setTransition(duration); 14709 }); 14710 } 14711 14712 function Zoom({ 14713 swiper, 14714 extendParams, 14715 on, 14716 emit 14717 }) { 14718 const window = getWindow(); 14719 extendParams({ 14720 zoom: { 14721 enabled: false, 14722 limitToOriginalSize: false, 14723 maxRatio: 3, 14724 minRatio: 1, 14725 panOnMouseMove: false, 14726 toggle: true, 14727 containerClass: 'swiper-zoom-container', 14728 zoomedSlideClass: 'swiper-slide-zoomed' 14729 } 14730 }); 14731 swiper.zoom = { 14732 enabled: false 14733 }; 14734 let currentScale = 1; 14735 let isScaling = false; 14736 let isPanningWithMouse = false; 14737 let mousePanStart = { 14738 x: 0, 14739 y: 0 14740 }; 14741 const mousePanSensitivity = -3; // Negative to invert pan direction 14742 let fakeGestureTouched; 14743 let fakeGestureMoved; 14744 const evCache = []; 14745 const gesture = { 14746 originX: 0, 14747 originY: 0, 14748 slideEl: undefined, 14749 slideWidth: undefined, 14750 slideHeight: undefined, 14751 imageEl: undefined, 14752 imageWrapEl: undefined, 14753 maxRatio: 3 14754 }; 14755 const image = { 14756 isTouched: undefined, 14757 isMoved: undefined, 14758 currentX: undefined, 14759 currentY: undefined, 14760 minX: undefined, 14761 minY: undefined, 14762 maxX: undefined, 14763 maxY: undefined, 14764 width: undefined, 14765 height: undefined, 14766 startX: undefined, 14767 startY: undefined, 14768 touchesStart: {}, 14769 touchesCurrent: {} 14770 }; 14771 const velocity = { 14772 x: undefined, 14773 y: undefined, 14774 prevPositionX: undefined, 14775 prevPositionY: undefined, 14776 prevTime: undefined 14777 }; 14778 let scale = 1; 14779 Object.defineProperty(swiper.zoom, 'scale', { 14780 get() { 14781 return scale; 14782 }, 14783 set(value) { 14784 if (scale !== value) { 14785 const imageEl = gesture.imageEl; 14786 const slideEl = gesture.slideEl; 14787 emit('zoomChange', value, imageEl, slideEl); 14788 } 14789 scale = value; 14790 } 14791 }); 14792 function getDistanceBetweenTouches() { 14793 if (evCache.length < 2) return 1; 14794 const x1 = evCache[0].pageX; 14795 const y1 = evCache[0].pageY; 14796 const x2 = evCache[1].pageX; 14797 const y2 = evCache[1].pageY; 14798 const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); 14799 return distance; 14800 } 14801 function getMaxRatio() { 14802 const params = swiper.params.zoom; 14803 const maxRatio = gesture.imageWrapEl.getAttribute('data-swiper-zoom') || params.maxRatio; 14804 if (params.limitToOriginalSize && gesture.imageEl && gesture.imageEl.naturalWidth) { 14805 const imageMaxRatio = gesture.imageEl.naturalWidth / gesture.imageEl.offsetWidth; 14806 return Math.min(imageMaxRatio, maxRatio); 14807 } 14808 return maxRatio; 14809 } 14810 function getScaleOrigin() { 14811 if (evCache.length < 2) return { 14812 x: null, 14813 y: null 14814 }; 14815 const box = gesture.imageEl.getBoundingClientRect(); 14816 return [(evCache[0].pageX + (evCache[1].pageX - evCache[0].pageX) / 2 - box.x - window.scrollX) / currentScale, (evCache[0].pageY + (evCache[1].pageY - evCache[0].pageY) / 2 - box.y - window.scrollY) / currentScale]; 14817 } 14818 function getSlideSelector() { 14819 return swiper.isElement ? `swiper-slide` : `.${swiper.params.slideClass}`; 14820 } 14821 function eventWithinSlide(e) { 14822 const slideSelector = getSlideSelector(); 14823 if (e.target.matches(slideSelector)) return true; 14824 if (swiper.slides.filter(slideEl => slideEl.contains(e.target)).length > 0) return true; 14825 return false; 14826 } 14827 function eventWithinZoomContainer(e) { 14828 const selector = `.${swiper.params.zoom.containerClass}`; 14829 if (e.target.matches(selector)) return true; 14830 if ([...swiper.hostEl.querySelectorAll(selector)].filter(containerEl => containerEl.contains(e.target)).length > 0) return true; 14831 return false; 14832 } 14833 14834 // Events 14835 function onGestureStart(e) { 14836 if (e.pointerType === 'mouse') { 14837 evCache.splice(0, evCache.length); 14838 } 14839 if (!eventWithinSlide(e)) return; 14840 const params = swiper.params.zoom; 14841 fakeGestureTouched = false; 14842 fakeGestureMoved = false; 14843 evCache.push(e); 14844 if (evCache.length < 2) { 14845 return; 14846 } 14847 fakeGestureTouched = true; 14848 gesture.scaleStart = getDistanceBetweenTouches(); 14849 if (!gesture.slideEl) { 14850 gesture.slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`); 14851 if (!gesture.slideEl) gesture.slideEl = swiper.slides[swiper.activeIndex]; 14852 let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`); 14853 if (imageEl) { 14854 imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0]; 14855 } 14856 gesture.imageEl = imageEl; 14857 if (imageEl) { 14858 gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0]; 14859 } else { 14860 gesture.imageWrapEl = undefined; 14861 } 14862 if (!gesture.imageWrapEl) { 14863 gesture.imageEl = undefined; 14864 return; 14865 } 14866 gesture.maxRatio = getMaxRatio(); 14867 } 14868 if (gesture.imageEl) { 14869 const [originX, originY] = getScaleOrigin(); 14870 gesture.originX = originX; 14871 gesture.originY = originY; 14872 gesture.imageEl.style.transitionDuration = '0ms'; 14873 } 14874 isScaling = true; 14875 } 14876 function onGestureChange(e) { 14877 if (!eventWithinSlide(e)) return; 14878 const params = swiper.params.zoom; 14879 const zoom = swiper.zoom; 14880 const pointerIndex = evCache.findIndex(cachedEv => cachedEv.pointerId === e.pointerId); 14881 if (pointerIndex >= 0) evCache[pointerIndex] = e; 14882 if (evCache.length < 2) { 14883 return; 14884 } 14885 fakeGestureMoved = true; 14886 gesture.scaleMove = getDistanceBetweenTouches(); 14887 if (!gesture.imageEl) { 14888 return; 14889 } 14890 zoom.scale = gesture.scaleMove / gesture.scaleStart * currentScale; 14891 if (zoom.scale > gesture.maxRatio) { 14892 zoom.scale = gesture.maxRatio - 1 + (zoom.scale - gesture.maxRatio + 1) ** 0.5; 14893 } 14894 if (zoom.scale < params.minRatio) { 14895 zoom.scale = params.minRatio + 1 - (params.minRatio - zoom.scale + 1) ** 0.5; 14896 } 14897 gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`; 14898 } 14899 function onGestureEnd(e) { 14900 if (!eventWithinSlide(e)) return; 14901 if (e.pointerType === 'mouse' && e.type === 'pointerout') return; 14902 const params = swiper.params.zoom; 14903 const zoom = swiper.zoom; 14904 const pointerIndex = evCache.findIndex(cachedEv => cachedEv.pointerId === e.pointerId); 14905 if (pointerIndex >= 0) evCache.splice(pointerIndex, 1); 14906 if (!fakeGestureTouched || !fakeGestureMoved) { 14907 return; 14908 } 14909 fakeGestureTouched = false; 14910 fakeGestureMoved = false; 14911 if (!gesture.imageEl) return; 14912 zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio); 14913 gesture.imageEl.style.transitionDuration = `${swiper.params.speed}ms`; 14914 gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`; 14915 currentScale = zoom.scale; 14916 isScaling = false; 14917 if (zoom.scale > 1 && gesture.slideEl) { 14918 gesture.slideEl.classList.add(`${params.zoomedSlideClass}`); 14919 } else if (zoom.scale <= 1 && gesture.slideEl) { 14920 gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`); 14921 } 14922 if (zoom.scale === 1) { 14923 gesture.originX = 0; 14924 gesture.originY = 0; 14925 gesture.slideEl = undefined; 14926 } 14927 } 14928 let allowTouchMoveTimeout; 14929 function allowTouchMove() { 14930 swiper.touchEventsData.preventTouchMoveFromPointerMove = false; 14931 } 14932 function preventTouchMove() { 14933 clearTimeout(allowTouchMoveTimeout); 14934 swiper.touchEventsData.preventTouchMoveFromPointerMove = true; 14935 allowTouchMoveTimeout = setTimeout(() => { 14936 if (swiper.destroyed) return; 14937 allowTouchMove(); 14938 }); 14939 } 14940 function onTouchStart(e) { 14941 const device = swiper.device; 14942 if (!gesture.imageEl) return; 14943 if (image.isTouched) return; 14944 if (device.android && e.cancelable) e.preventDefault(); 14945 image.isTouched = true; 14946 const event = evCache.length > 0 ? evCache[0] : e; 14947 image.touchesStart.x = event.pageX; 14948 image.touchesStart.y = event.pageY; 14949 } 14950 function onTouchMove(e) { 14951 const isMouseEvent = e.pointerType === 'mouse'; 14952 const isMousePan = isMouseEvent && swiper.params.zoom.panOnMouseMove; 14953 if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) { 14954 return; 14955 } 14956 const zoom = swiper.zoom; 14957 if (!gesture.imageEl) { 14958 return; 14959 } 14960 if (!image.isTouched || !gesture.slideEl) { 14961 if (isMousePan) onMouseMove(e); 14962 return; 14963 } 14964 if (isMousePan) { 14965 onMouseMove(e); 14966 return; 14967 } 14968 if (!image.isMoved) { 14969 image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth; 14970 image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight; 14971 image.startX = getTranslate(gesture.imageWrapEl, 'x') || 0; 14972 image.startY = getTranslate(gesture.imageWrapEl, 'y') || 0; 14973 gesture.slideWidth = gesture.slideEl.offsetWidth; 14974 gesture.slideHeight = gesture.slideEl.offsetHeight; 14975 gesture.imageWrapEl.style.transitionDuration = '0ms'; 14976 } 14977 // Define if we need image drag 14978 const scaledWidth = image.width * zoom.scale; 14979 const scaledHeight = image.height * zoom.scale; 14980 image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0); 14981 image.maxX = -image.minX; 14982 image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0); 14983 image.maxY = -image.minY; 14984 image.touchesCurrent.x = evCache.length > 0 ? evCache[0].pageX : e.pageX; 14985 image.touchesCurrent.y = evCache.length > 0 ? evCache[0].pageY : e.pageY; 14986 const touchesDiff = Math.max(Math.abs(image.touchesCurrent.x - image.touchesStart.x), Math.abs(image.touchesCurrent.y - image.touchesStart.y)); 14987 if (touchesDiff > 5) { 14988 swiper.allowClick = false; 14989 } 14990 if (!image.isMoved && !isScaling) { 14991 if (swiper.isHorizontal() && (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x || Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)) { 14992 image.isTouched = false;
vendor: 4,335 bytes, lines 14993-15080
14993 allowTouchMove(); 14994 return; 14995 } 14996 if (!swiper.isHorizontal() && (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y || Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)) { 14997 image.isTouched = false; 14998 allowTouchMove(); 14999 return; 15000 } 15001 } 15002 if (e.cancelable) { 15003 e.preventDefault(); 15004 } 15005 e.stopPropagation(); 15006 preventTouchMove(); 15007 image.isMoved = true; 15008 const scaleRatio = (zoom.scale - currentScale) / (gesture.maxRatio - swiper.params.zoom.minRatio); 15009 const { 15010 originX, 15011 originY 15012 } = gesture; 15013 image.currentX = image.touchesCurrent.x - image.touchesStart.x + image.startX + scaleRatio * (image.width - originX * 2); 15014 image.currentY = image.touchesCurrent.y - image.touchesStart.y + image.startY + scaleRatio * (image.height - originY * 2); 15015 if (image.currentX < image.minX) { 15016 image.currentX = image.minX + 1 - (image.minX - image.currentX + 1) ** 0.8; 15017 } 15018 if (image.currentX > image.maxX) { 15019 image.currentX = image.maxX - 1 + (image.currentX - image.maxX + 1) ** 0.8; 15020 } 15021 if (image.currentY < image.minY) { 15022 image.currentY = image.minY + 1 - (image.minY - image.currentY + 1) ** 0.8; 15023 } 15024 if (image.currentY > image.maxY) { 15025 image.currentY = image.maxY - 1 + (image.currentY - image.maxY + 1) ** 0.8; 15026 } 15027 15028 // Velocity 15029 if (!velocity.prevPositionX) velocity.prevPositionX = image.touchesCurrent.x; 15030 if (!velocity.prevPositionY) velocity.prevPositionY = image.touchesCurrent.y; 15031 if (!velocity.prevTime) velocity.prevTime = Date.now(); 15032 velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2; 15033 velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2; 15034 if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) velocity.x = 0; 15035 if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) velocity.y = 0; 15036 velocity.prevPositionX = image.touchesCurrent.x; 15037 velocity.prevPositionY = image.touchesCurrent.y; 15038 velocity.prevTime = Date.now(); 15039 gesture.imageWrapEl.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`; 15040 } 15041 function onTouchEnd() { 15042 const zoom = swiper.zoom; 15043 evCache.length = 0; 15044 if (!gesture.imageEl) return; 15045 if (!image.isTouched || !image.isMoved) { 15046 image.isTouched = false; 15047 image.isMoved = false; 15048 return; 15049 } 15050 image.isTouched = false; 15051 image.isMoved = false; 15052 let momentumDurationX = 300; 15053 let momentumDurationY = 300; 15054 const momentumDistanceX = velocity.x * momentumDurationX; 15055 const newPositionX = image.currentX + momentumDistanceX; 15056 const momentumDistanceY = velocity.y * momentumDurationY; 15057 const newPositionY = image.currentY + momentumDistanceY; 15058 15059 // Fix duration 15060 if (velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x); 15061 if (velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y); 15062 const momentumDuration = Math.max(momentumDurationX, momentumDurationY); 15063 image.currentX = newPositionX; 15064 image.currentY = newPositionY; 15065 // Define if we need image drag 15066 const scaledWidth = image.width * zoom.scale; 15067 const scaledHeight = image.height * zoom.scale; 15068 image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0); 15069 image.maxX = -image.minX; 15070 image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0); 15071 image.maxY = -image.minY; 15072 image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX); 15073 image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY); 15074 gesture.imageWrapEl.style.transitionDuration = `${momentumDuration}ms`; 15075 gesture.imageWrapEl.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`; 15076 } 15077 function onTransitionEnd() { 15078 const zoom = swiper.zoom; 15079 if (gesture.slideEl && swiper.activeIndex !== swiper.slides.indexOf(gesture.slideEl)) { 15080 if (gesture.imageEl) {
vendor: 65,834 bytes, lines 15081-16926
15081 gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)'; 15082 } 15083 if (gesture.imageWrapEl) { 15084 gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)'; 15085 } 15086 gesture.slideEl.classList.remove(`${swiper.params.zoom.zoomedSlideClass}`); 15087 zoom.scale = 1; 15088 currentScale = 1; 15089 gesture.slideEl = undefined; 15090 gesture.imageEl = undefined; 15091 gesture.imageWrapEl = undefined; 15092 gesture.originX = 0; 15093 gesture.originY = 0; 15094 } 15095 } 15096 function onMouseMove(e) { 15097 // Only pan if zoomed in and mouse panning is enabled 15098 if (currentScale <= 1 || !gesture.imageWrapEl) return; 15099 if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) return; 15100 const currentTransform = window.getComputedStyle(gesture.imageWrapEl).transform; 15101 const matrix = new window.DOMMatrix(currentTransform); 15102 if (!isPanningWithMouse) { 15103 isPanningWithMouse = true; 15104 mousePanStart.x = e.clientX; 15105 mousePanStart.y = e.clientY; 15106 image.startX = matrix.e; 15107 image.startY = matrix.f; 15108 image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth; 15109 image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight; 15110 gesture.slideWidth = gesture.slideEl.offsetWidth; 15111 gesture.slideHeight = gesture.slideEl.offsetHeight; 15112 return; 15113 } 15114 const deltaX = (e.clientX - mousePanStart.x) * mousePanSensitivity; 15115 const deltaY = (e.clientY - mousePanStart.y) * mousePanSensitivity; 15116 const scaledWidth = image.width * currentScale; 15117 const scaledHeight = image.height * currentScale; 15118 const slideWidth = gesture.slideWidth; 15119 const slideHeight = gesture.slideHeight; 15120 const minX = Math.min(slideWidth / 2 - scaledWidth / 2, 0); 15121 const maxX = -minX; 15122 const minY = Math.min(slideHeight / 2 - scaledHeight / 2, 0); 15123 const maxY = -minY; 15124 const newX = Math.max(Math.min(image.startX + deltaX, maxX), minX); 15125 const newY = Math.max(Math.min(image.startY + deltaY, maxY), minY); 15126 gesture.imageWrapEl.style.transitionDuration = '0ms'; 15127 gesture.imageWrapEl.style.transform = `translate3d(${newX}px, ${newY}px, 0)`; 15128 mousePanStart.x = e.clientX; 15129 mousePanStart.y = e.clientY; 15130 image.startX = newX; 15131 image.startY = newY; 15132 image.currentX = newX; 15133 image.currentY = newY; 15134 } 15135 function zoomIn(e) { 15136 const zoom = swiper.zoom; 15137 const params = swiper.params.zoom; 15138 if (!gesture.slideEl) { 15139 if (e && e.target) { 15140 gesture.slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`); 15141 } 15142 if (!gesture.slideEl) { 15143 if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) { 15144 gesture.slideEl = elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0]; 15145 } else { 15146 gesture.slideEl = swiper.slides[swiper.activeIndex]; 15147 } 15148 } 15149 let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`); 15150 if (imageEl) { 15151 imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0]; 15152 } 15153 gesture.imageEl = imageEl; 15154 if (imageEl) { 15155 gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0]; 15156 } else { 15157 gesture.imageWrapEl = undefined; 15158 } 15159 } 15160 if (!gesture.imageEl || !gesture.imageWrapEl) return; 15161 if (swiper.params.cssMode) { 15162 swiper.wrapperEl.style.overflow = 'hidden'; 15163 swiper.wrapperEl.style.touchAction = 'none'; 15164 } 15165 gesture.slideEl.classList.add(`${params.zoomedSlideClass}`); 15166 let touchX; 15167 let touchY; 15168 let offsetX; 15169 let offsetY; 15170 let diffX; 15171 let diffY; 15172 let translateX; 15173 let translateY; 15174 let imageWidth; 15175 let imageHeight; 15176 let scaledWidth; 15177 let scaledHeight; 15178 let translateMinX; 15179 let translateMinY; 15180 let translateMaxX; 15181 let translateMaxY; 15182 let slideWidth; 15183 let slideHeight; 15184 if (typeof image.touchesStart.x === 'undefined' && e) { 15185 touchX = e.pageX; 15186 touchY = e.pageY; 15187 } else { 15188 touchX = image.touchesStart.x; 15189 touchY = image.touchesStart.y; 15190 } 15191 const prevScale = currentScale; 15192 const forceZoomRatio = typeof e === 'number' ? e : null; 15193 if (currentScale === 1 && forceZoomRatio) { 15194 touchX = undefined; 15195 touchY = undefined; 15196 image.touchesStart.x = undefined; 15197 image.touchesStart.y = undefined; 15198 } 15199 const maxRatio = getMaxRatio(); 15200 zoom.scale = forceZoomRatio || maxRatio; 15201 currentScale = forceZoomRatio || maxRatio; 15202 if (e && !(currentScale === 1 && forceZoomRatio)) { 15203 slideWidth = gesture.slideEl.offsetWidth; 15204 slideHeight = gesture.slideEl.offsetHeight; 15205 offsetX = elementOffset(gesture.slideEl).left + window.scrollX; 15206 offsetY = elementOffset(gesture.slideEl).top + window.scrollY; 15207 diffX = offsetX + slideWidth / 2 - touchX; 15208 diffY = offsetY + slideHeight / 2 - touchY; 15209 imageWidth = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth; 15210 imageHeight = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight; 15211 scaledWidth = imageWidth * zoom.scale; 15212 scaledHeight = imageHeight * zoom.scale; 15213 translateMinX = Math.min(slideWidth / 2 - scaledWidth / 2, 0); 15214 translateMinY = Math.min(slideHeight / 2 - scaledHeight / 2, 0); 15215 translateMaxX = -translateMinX; 15216 translateMaxY = -translateMinY; 15217 if (prevScale > 0 && forceZoomRatio && typeof image.currentX === 'number' && typeof image.currentY === 'number') { 15218 translateX = image.currentX * zoom.scale / prevScale; 15219 translateY = image.currentY * zoom.scale / prevScale; 15220 } else { 15221 translateX = diffX * zoom.scale; 15222 translateY = diffY * zoom.scale; 15223 } 15224 if (translateX < translateMinX) { 15225 translateX = translateMinX; 15226 } 15227 if (translateX > translateMaxX) { 15228 translateX = translateMaxX; 15229 } 15230 if (translateY < translateMinY) { 15231 translateY = translateMinY; 15232 } 15233 if (translateY > translateMaxY) { 15234 translateY = translateMaxY; 15235 } 15236 } else { 15237 translateX = 0; 15238 translateY = 0; 15239 } 15240 if (forceZoomRatio && zoom.scale === 1) { 15241 gesture.originX = 0; 15242 gesture.originY = 0; 15243 } 15244 image.currentX = translateX; 15245 image.currentY = translateY; 15246 gesture.imageWrapEl.style.transitionDuration = '300ms'; 15247 gesture.imageWrapEl.style.transform = `translate3d(${translateX}px, ${translateY}px,0)`; 15248 gesture.imageEl.style.transitionDuration = '300ms'; 15249 gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`; 15250 } 15251 function zoomOut() { 15252 const zoom = swiper.zoom; 15253 const params = swiper.params.zoom; 15254 if (!gesture.slideEl) { 15255 if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) { 15256 gesture.slideEl = elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0]; 15257 } else { 15258 gesture.slideEl = swiper.slides[swiper.activeIndex]; 15259 } 15260 let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`); 15261 if (imageEl) { 15262 imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0]; 15263 } 15264 gesture.imageEl = imageEl; 15265 if (imageEl) { 15266 gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0]; 15267 } else { 15268 gesture.imageWrapEl = undefined; 15269 } 15270 } 15271 if (!gesture.imageEl || !gesture.imageWrapEl) return; 15272 if (swiper.params.cssMode) { 15273 swiper.wrapperEl.style.overflow = ''; 15274 swiper.wrapperEl.style.touchAction = ''; 15275 } 15276 zoom.scale = 1; 15277 currentScale = 1; 15278 image.currentX = undefined; 15279 image.currentY = undefined; 15280 image.touchesStart.x = undefined; 15281 image.touchesStart.y = undefined; 15282 gesture.imageWrapEl.style.transitionDuration = '300ms'; 15283 gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)'; 15284 gesture.imageEl.style.transitionDuration = '300ms'; 15285 gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)'; 15286 gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`); 15287 gesture.slideEl = undefined; 15288 gesture.originX = 0; 15289 gesture.originY = 0; 15290 if (swiper.params.zoom.panOnMouseMove) { 15291 mousePanStart = { 15292 x: 0, 15293 y: 0 15294 }; 15295 if (isPanningWithMouse) { 15296 isPanningWithMouse = false; 15297 image.startX = 0; 15298 image.startY = 0; 15299 } 15300 } 15301 } 15302 15303 // Toggle Zoom 15304 function zoomToggle(e) { 15305 const zoom = swiper.zoom; 15306 if (zoom.scale && zoom.scale !== 1) { 15307 // Zoom Out 15308 zoomOut(); 15309 } else { 15310 // Zoom In 15311 zoomIn(e); 15312 } 15313 } 15314 function getListeners() { 15315 const passiveListener = swiper.params.passiveListeners ? { 15316 passive: true, 15317 capture: false 15318 } : false; 15319 const activeListenerWithCapture = swiper.params.passiveListeners ? { 15320 passive: false, 15321 capture: true 15322 } : true; 15323 return { 15324 passiveListener, 15325 activeListenerWithCapture 15326 }; 15327 } 15328 15329 // Attach/Detach Events 15330 function enable() { 15331 const zoom = swiper.zoom; 15332 if (zoom.enabled) return; 15333 zoom.enabled = true; 15334 const { 15335 passiveListener, 15336 activeListenerWithCapture 15337 } = getListeners(); 15338 15339 // Scale image 15340 swiper.wrapperEl.addEventListener('pointerdown', onGestureStart, passiveListener); 15341 swiper.wrapperEl.addEventListener('pointermove', onGestureChange, activeListenerWithCapture); 15342 ['pointerup', 'pointercancel', 'pointerout'].forEach(eventName => { 15343 swiper.wrapperEl.addEventListener(eventName, onGestureEnd, passiveListener); 15344 }); 15345 15346 // Move image 15347 swiper.wrapperEl.addEventListener('pointermove', onTouchMove, activeListenerWithCapture); 15348 } 15349 function disable() { 15350 const zoom = swiper.zoom; 15351 if (!zoom.enabled) return; 15352 zoom.enabled = false; 15353 const { 15354 passiveListener, 15355 activeListenerWithCapture 15356 } = getListeners(); 15357 15358 // Scale image 15359 swiper.wrapperEl.removeEventListener('pointerdown', onGestureStart, passiveListener); 15360 swiper.wrapperEl.removeEventListener('pointermove', onGestureChange, activeListenerWithCapture); 15361 ['pointerup', 'pointercancel', 'pointerout'].forEach(eventName => { 15362 swiper.wrapperEl.removeEventListener(eventName, onGestureEnd, passiveListener); 15363 }); 15364 15365 // Move image 15366 swiper.wrapperEl.removeEventListener('pointermove', onTouchMove, activeListenerWithCapture); 15367 } 15368 on('init', () => { 15369 if (swiper.params.zoom.enabled) { 15370 enable(); 15371 } 15372 }); 15373 on('destroy', () => { 15374 disable(); 15375 }); 15376 on('touchStart', (_s, e) => { 15377 if (!swiper.zoom.enabled) return; 15378 onTouchStart(e); 15379 }); 15380 on('touchEnd', (_s, e) => { 15381 if (!swiper.zoom.enabled) return; 15382 onTouchEnd(); 15383 }); 15384 on('doubleTap', (_s, e) => { 15385 if (!swiper.animating && swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) { 15386 zoomToggle(e); 15387 } 15388 }); 15389 on('transitionEnd', () => { 15390 if (swiper.zoom.enabled && swiper.params.zoom.enabled) { 15391 onTransitionEnd(); 15392 } 15393 }); 15394 on('slideChange', () => { 15395 if (swiper.zoom.enabled && swiper.params.zoom.enabled && swiper.params.cssMode) { 15396 onTransitionEnd(); 15397 } 15398 }); 15399 Object.assign(swiper.zoom, { 15400 enable, 15401 disable, 15402 in: zoomIn, 15403 out: zoomOut, 15404 toggle: zoomToggle 15405 }); 15406 } 15407 15408 /* eslint no-bitwise: ["error", { "allow": [">>"] }] */ 15409 function Controller({ 15410 swiper, 15411 extendParams, 15412 on 15413 }) { 15414 extendParams({ 15415 controller: { 15416 control: undefined, 15417 inverse: false, 15418 by: 'slide' // or 'container' 15419 } 15420 }); 15421 15422 swiper.controller = { 15423 control: undefined 15424 }; 15425 function LinearSpline(x, y) { 15426 const binarySearch = function search() { 15427 let maxIndex; 15428 let minIndex; 15429 let guess; 15430 return (array, val) => { 15431 minIndex = -1; 15432 maxIndex = array.length; 15433 while (maxIndex - minIndex > 1) { 15434 guess = maxIndex + minIndex >> 1; 15435 if (array[guess] <= val) { 15436 minIndex = guess; 15437 } else { 15438 maxIndex = guess; 15439 } 15440 } 15441 return maxIndex; 15442 }; 15443 }(); 15444 this.x = x; 15445 this.y = y; 15446 this.lastIndex = x.length - 1; 15447 // Given an x value (x2), return the expected y2 value: 15448 // (x1,y1) is the known point before given value, 15449 // (x3,y3) is the known point after given value. 15450 let i1; 15451 let i3; 15452 this.interpolate = function interpolate(x2) { 15453 if (!x2) return 0; 15454 15455 // Get the indexes of x1 and x3 (the array indexes before and after given x2): 15456 i3 = binarySearch(this.x, x2); 15457 i1 = i3 - 1; 15458 15459 // We have our indexes i1 & i3, so we can calculate already: 15460 // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1 15461 return (x2 - this.x[i1]) * (this.y[i3] - this.y[i1]) / (this.x[i3] - this.x[i1]) + this.y[i1]; 15462 }; 15463 return this; 15464 } 15465 function getInterpolateFunction(c) { 15466 swiper.controller.spline = swiper.params.loop ? new LinearSpline(swiper.slidesGrid, c.slidesGrid) : new LinearSpline(swiper.snapGrid, c.snapGrid); 15467 } 15468 function setTranslate(_t, byController) { 15469 const controlled = swiper.controller.control; 15470 let multiplier; 15471 let controlledTranslate; 15472 const Swiper = swiper.constructor; 15473 function setControlledTranslate(c) { 15474 if (c.destroyed) return; 15475 15476 // this will create an Interpolate function based on the snapGrids 15477 // x is the Grid of the scrolled scroller and y will be the controlled scroller 15478 // it makes sense to create this only once and recall it for the interpolation 15479 // the function does a lot of value caching for performance 15480 const translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate; 15481 if (swiper.params.controller.by === 'slide') { 15482 getInterpolateFunction(c); 15483 // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid 15484 // but it did not work out 15485 controlledTranslate = -swiper.controller.spline.interpolate(-translate); 15486 } 15487 if (!controlledTranslate || swiper.params.controller.by === 'container') { 15488 multiplier = (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate()); 15489 if (Number.isNaN(multiplier) || !Number.isFinite(multiplier)) { 15490 multiplier = 1; 15491 } 15492 controlledTranslate = (translate - swiper.minTranslate()) * multiplier + c.minTranslate(); 15493 } 15494 if (swiper.params.controller.inverse) { 15495 controlledTranslate = c.maxTranslate() - controlledTranslate; 15496 } 15497 c.updateProgress(controlledTranslate); 15498 c.setTranslate(controlledTranslate, swiper); 15499 c.updateActiveIndex(); 15500 c.updateSlidesClasses(); 15501 } 15502 if (Array.isArray(controlled)) { 15503 for (let i = 0; i < controlled.length; i += 1) { 15504 if (controlled[i] !== byController && controlled[i] instanceof Swiper) { 15505 setControlledTranslate(controlled[i]); 15506 } 15507 } 15508 } else if (controlled instanceof Swiper && byController !== controlled) { 15509 setControlledTranslate(controlled); 15510 } 15511 } 15512 function setTransition(duration, byController) { 15513 const Swiper = swiper.constructor; 15514 const controlled = swiper.controller.control; 15515 let i; 15516 function setControlledTransition(c) { 15517 if (c.destroyed) return; 15518 c.setTransition(duration, swiper); 15519 if (duration !== 0) { 15520 c.transitionStart(); 15521 if (c.params.autoHeight) { 15522 nextTick(() => { 15523 c.updateAutoHeight(); 15524 }); 15525 } 15526 elementTransitionEnd(c.wrapperEl, () => { 15527 if (!controlled) return; 15528 c.transitionEnd(); 15529 }); 15530 } 15531 } 15532 if (Array.isArray(controlled)) { 15533 for (i = 0; i < controlled.length; i += 1) { 15534 if (controlled[i] !== byController && controlled[i] instanceof Swiper) { 15535 setControlledTransition(controlled[i]); 15536 } 15537 } 15538 } else if (controlled instanceof Swiper && byController !== controlled) { 15539 setControlledTransition(controlled); 15540 } 15541 } 15542 function removeSpline() { 15543 if (!swiper.controller.control) return; 15544 if (swiper.controller.spline) { 15545 swiper.controller.spline = undefined; 15546 delete swiper.controller.spline; 15547 } 15548 } 15549 on('beforeInit', () => { 15550 if (typeof window !== 'undefined' && ( 15551 // eslint-disable-line 15552 typeof swiper.params.controller.control === 'string' || swiper.params.controller.control instanceof HTMLElement)) { 15553 const controlElements = typeof swiper.params.controller.control === 'string' ? [...document.querySelectorAll(swiper.params.controller.control)] : [swiper.params.controller.control]; 15554 controlElements.forEach(controlElement => { 15555 if (!swiper.controller.control) swiper.controller.control = []; 15556 if (controlElement && controlElement.swiper) { 15557 swiper.controller.control.push(controlElement.swiper); 15558 } else if (controlElement) { 15559 const eventName = `${swiper.params.eventsPrefix}init`; 15560 const onControllerSwiper = e => { 15561 swiper.controller.control.push(e.detail[0]); 15562 swiper.update(); 15563 controlElement.removeEventListener(eventName, onControllerSwiper); 15564 }; 15565 controlElement.addEventListener(eventName, onControllerSwiper); 15566 } 15567 }); 15568 return; 15569 } 15570 swiper.controller.control = swiper.params.controller.control; 15571 }); 15572 on('update', () => { 15573 removeSpline(); 15574 }); 15575 on('resize', () => { 15576 removeSpline(); 15577 }); 15578 on('observerUpdate', () => { 15579 removeSpline(); 15580 }); 15581 on('setTranslate', (_s, translate, byController) => { 15582 if (!swiper.controller.control || swiper.controller.control.destroyed) return; 15583 swiper.controller.setTranslate(translate, byController); 15584 }); 15585 on('setTransition', (_s, duration, byController) => { 15586 if (!swiper.controller.control || swiper.controller.control.destroyed) return; 15587 swiper.controller.setTransition(duration, byController); 15588 }); 15589 Object.assign(swiper.controller, { 15590 setTranslate, 15591 setTransition 15592 }); 15593 } 15594 15595 function A11y({ 15596 swiper, 15597 extendParams, 15598 on 15599 }) { 15600 extendParams({ 15601 a11y: { 15602 enabled: true, 15603 notificationClass: 'swiper-notification', 15604 prevSlideMessage: 'Previous slide', 15605 nextSlideMessage: 'Next slide', 15606 firstSlideMessage: 'This is the first slide', 15607 lastSlideMessage: 'This is the last slide', 15608 paginationBulletMessage: 'Go to slide {{index}}', 15609 slideLabelMessage: '{{index}} / {{slidesLength}}', 15610 containerMessage: null, 15611 containerRoleDescriptionMessage: null, 15612 containerRole: null, 15613 itemRoleDescriptionMessage: null, 15614 slideRole: 'group', 15615 id: null, 15616 scrollOnFocus: true, 15617 wrapperLiveRegion: true 15618 } 15619 }); 15620 swiper.a11y = { 15621 clicked: false 15622 }; 15623 let liveRegion = null; 15624 let preventFocusHandler; 15625 let focusTargetSlideEl; 15626 let visibilityChangedTimestamp = new Date().getTime(); 15627 function notify(message) { 15628 const notification = liveRegion; 15629 if (notification.length === 0) return; 15630 setInnerHTML(notification, message); 15631 } 15632 function getRandomNumber(size = 16) { 15633 const randomChar = () => Math.round(16 * Math.random()).toString(16); 15634 return 'x'.repeat(size).replace(/x/g, randomChar); 15635 } 15636 function makeElFocusable(el) { 15637 el = makeElementsArray(el); 15638 el.forEach(subEl => { 15639 subEl.setAttribute('tabIndex', '0'); 15640 }); 15641 } 15642 function makeElNotFocusable(el) { 15643 el = makeElementsArray(el); 15644 el.forEach(subEl => { 15645 subEl.setAttribute('tabIndex', '-1'); 15646 }); 15647 } 15648 function addElRole(el, role) { 15649 el = makeElementsArray(el); 15650 el.forEach(subEl => { 15651 subEl.setAttribute('role', role); 15652 }); 15653 } 15654 function addElRoleDescription(el, description) { 15655 el = makeElementsArray(el); 15656 el.forEach(subEl => { 15657 subEl.setAttribute('aria-roledescription', description); 15658 }); 15659 } 15660 function addElControls(el, controls) { 15661 el = makeElementsArray(el); 15662 el.forEach(subEl => { 15663 subEl.setAttribute('aria-controls', controls); 15664 }); 15665 } 15666 function addElLabel(el, label) { 15667 el = makeElementsArray(el); 15668 el.forEach(subEl => { 15669 subEl.setAttribute('aria-label', label); 15670 }); 15671 } 15672 function addElId(el, id) { 15673 el = makeElementsArray(el); 15674 el.forEach(subEl => { 15675 subEl.setAttribute('id', id); 15676 }); 15677 } 15678 function addElLive(el, live) { 15679 el = makeElementsArray(el); 15680 el.forEach(subEl => { 15681 subEl.setAttribute('aria-live', live); 15682 }); 15683 } 15684 function disableEl(el) { 15685 el = makeElementsArray(el); 15686 el.forEach(subEl => { 15687 subEl.setAttribute('aria-disabled', true); 15688 }); 15689 } 15690 function enableEl(el) { 15691 el = makeElementsArray(el); 15692 el.forEach(subEl => { 15693 subEl.setAttribute('aria-disabled', false); 15694 }); 15695 } 15696 function onEnterOrSpaceKey(e) { 15697 if (e.keyCode !== 13 && e.keyCode !== 32) return; 15698 const params = swiper.params.a11y; 15699 const targetEl = e.target; 15700 if (swiper.pagination && swiper.pagination.el && (targetEl === swiper.pagination.el || swiper.pagination.el.contains(e.target))) { 15701 if (!e.target.matches(classesToSelector(swiper.params.pagination.bulletClass))) return; 15702 } 15703 if (swiper.navigation && swiper.navigation.prevEl && swiper.navigation.nextEl) { 15704 const prevEls = makeElementsArray(swiper.navigation.prevEl); 15705 const nextEls = makeElementsArray(swiper.navigation.nextEl); 15706 if (nextEls.includes(targetEl)) { 15707 if (!(swiper.isEnd && !swiper.params.loop)) { 15708 swiper.slideNext(); 15709 } 15710 if (swiper.isEnd) { 15711 notify(params.lastSlideMessage); 15712 } else { 15713 notify(params.nextSlideMessage); 15714 } 15715 } 15716 if (prevEls.includes(targetEl)) { 15717 if (!(swiper.isBeginning && !swiper.params.loop)) { 15718 swiper.slidePrev(); 15719 } 15720 if (swiper.isBeginning) { 15721 notify(params.firstSlideMessage); 15722 } else { 15723 notify(params.prevSlideMessage); 15724 } 15725 } 15726 } 15727 if (swiper.pagination && targetEl.matches(classesToSelector(swiper.params.pagination.bulletClass))) { 15728 targetEl.click(); 15729 } 15730 } 15731 function updateNavigation() { 15732 if (swiper.params.loop || swiper.params.rewind || !swiper.navigation) return; 15733 const { 15734 nextEl, 15735 prevEl 15736 } = swiper.navigation; 15737 if (prevEl) { 15738 if (swiper.isBeginning) { 15739 disableEl(prevEl); 15740 makeElNotFocusable(prevEl); 15741 } else { 15742 enableEl(prevEl); 15743 makeElFocusable(prevEl); 15744 } 15745 } 15746 if (nextEl) { 15747 if (swiper.isEnd) { 15748 disableEl(nextEl); 15749 makeElNotFocusable(nextEl); 15750 } else { 15751 enableEl(nextEl); 15752 makeElFocusable(nextEl); 15753 } 15754 } 15755 } 15756 function hasPagination() { 15757 return swiper.pagination && swiper.pagination.bullets && swiper.pagination.bullets.length; 15758 } 15759 function hasClickablePagination() { 15760 return hasPagination() && swiper.params.pagination.clickable; 15761 } 15762 function updatePagination() { 15763 const params = swiper.params.a11y; 15764 if (!hasPagination()) return; 15765 swiper.pagination.bullets.forEach(bulletEl => { 15766 if (swiper.params.pagination.clickable) { 15767 makeElFocusable(bulletEl); 15768 if (!swiper.params.pagination.renderBullet) { 15769 addElRole(bulletEl, 'button'); 15770 addElLabel(bulletEl, params.paginationBulletMessage.replace(/\{\{index\}\}/, elementIndex(bulletEl) + 1)); 15771 } 15772 } 15773 if (bulletEl.matches(classesToSelector(swiper.params.pagination.bulletActiveClass))) { 15774 bulletEl.setAttribute('aria-current', 'true'); 15775 } else { 15776 bulletEl.removeAttribute('aria-current'); 15777 } 15778 }); 15779 } 15780 const initNavEl = (el, wrapperId, message) => { 15781 makeElFocusable(el); 15782 if (el.tagName !== 'BUTTON') { 15783 addElRole(el, 'button'); 15784 el.addEventListener('keydown', onEnterOrSpaceKey); 15785 } 15786 addElLabel(el, message); 15787 addElControls(el, wrapperId); 15788 }; 15789 const handlePointerDown = e => { 15790 if (focusTargetSlideEl && focusTargetSlideEl !== e.target && !focusTargetSlideEl.contains(e.target)) { 15791 preventFocusHandler = true; 15792 } 15793 swiper.a11y.clicked = true; 15794 }; 15795 const handlePointerUp = () => { 15796 preventFocusHandler = false; 15797 requestAnimationFrame(() => { 15798 requestAnimationFrame(() => { 15799 if (!swiper.destroyed) { 15800 swiper.a11y.clicked = false; 15801 } 15802 }); 15803 }); 15804 }; 15805 const onVisibilityChange = e => { 15806 visibilityChangedTimestamp = new Date().getTime(); 15807 }; 15808 const handleFocus = e => { 15809 if (swiper.a11y.clicked || !swiper.params.a11y.scrollOnFocus) return; 15810 if (new Date().getTime() - visibilityChangedTimestamp < 100) return; 15811 const slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`); 15812 if (!slideEl || !swiper.slides.includes(slideEl)) return; 15813 focusTargetSlideEl = slideEl; 15814 const isActive = swiper.slides.indexOf(slideEl) === swiper.activeIndex; 15815 const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl); 15816 if (isActive || isVisible) return; 15817 if (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents) return; 15818 if (swiper.isHorizontal()) { 15819 swiper.el.scrollLeft = 0; 15820 } else { 15821 swiper.el.scrollTop = 0; 15822 } 15823 requestAnimationFrame(() => { 15824 if (preventFocusHandler) return; 15825 if (swiper.params.loop) { 15826 swiper.slideToLoop(swiper.getSlideIndexWhenGrid(parseInt(slideEl.getAttribute('data-swiper-slide-index'))), 0); 15827 } else { 15828 swiper.slideTo(swiper.getSlideIndexWhenGrid(swiper.slides.indexOf(slideEl)), 0); 15829 } 15830 preventFocusHandler = false; 15831 }); 15832 }; 15833 const initSlides = () => { 15834 const params = swiper.params.a11y; 15835 if (params.itemRoleDescriptionMessage) { 15836 addElRoleDescription(swiper.slides, params.itemRoleDescriptionMessage); 15837 } 15838 if (params.slideRole) { 15839 addElRole(swiper.slides, params.slideRole); 15840 } 15841 const slidesLength = swiper.slides.length; 15842 if (params.slideLabelMessage) { 15843 swiper.slides.forEach((slideEl, index) => { 15844 const slideIndex = swiper.params.loop ? parseInt(slideEl.getAttribute('data-swiper-slide-index'), 10) : index; 15845 const ariaLabelMessage = params.slideLabelMessage.replace(/\{\{index\}\}/, slideIndex + 1).replace(/\{\{slidesLength\}\}/, slidesLength); 15846 addElLabel(slideEl, ariaLabelMessage); 15847 }); 15848 } 15849 }; 15850 const init = () => { 15851 const params = swiper.params.a11y; 15852 swiper.el.append(liveRegion); 15853 15854 // Container 15855 const containerEl = swiper.el; 15856 if (params.containerRoleDescriptionMessage) { 15857 addElRoleDescription(containerEl, params.containerRoleDescriptionMessage); 15858 } 15859 if (params.containerMessage) { 15860 addElLabel(containerEl, params.containerMessage); 15861 } 15862 if (params.containerRole) { 15863 addElRole(containerEl, params.containerRole); 15864 } 15865 15866 // Wrapper 15867 const wrapperEl = swiper.wrapperEl; 15868 const wrapperId = params.id || wrapperEl.getAttribute('id') || `swiper-wrapper-${getRandomNumber(16)}`; 15869 addElId(wrapperEl, wrapperId); 15870 if (params.wrapperLiveRegion) { 15871 const live = swiper.params.autoplay && swiper.params.autoplay.enabled ? 'off' : 'polite'; 15872 addElLive(wrapperEl, live); 15873 } 15874 15875 // Slide 15876 initSlides(); 15877 15878 // Navigation 15879 let { 15880 nextEl, 15881 prevEl 15882 } = swiper.navigation ? swiper.navigation : {}; 15883 nextEl = makeElementsArray(nextEl); 15884 prevEl = makeElementsArray(prevEl); 15885 if (nextEl) { 15886 nextEl.forEach(el => initNavEl(el, wrapperId, params.nextSlideMessage)); 15887 } 15888 if (prevEl) { 15889 prevEl.forEach(el => initNavEl(el, wrapperId, params.prevSlideMessage)); 15890 } 15891 15892 // Pagination 15893 if (hasClickablePagination()) { 15894 const paginationEl = makeElementsArray(swiper.pagination.el); 15895 paginationEl.forEach(el => { 15896 el.addEventListener('keydown', onEnterOrSpaceKey); 15897 }); 15898 } 15899 15900 // Tab focus 15901 const document = getDocument(); 15902 document.addEventListener('visibilitychange', onVisibilityChange); 15903 swiper.el.addEventListener('focus', handleFocus, true); 15904 swiper.el.addEventListener('focus', handleFocus, true); 15905 swiper.el.addEventListener('pointerdown', handlePointerDown, true); 15906 swiper.el.addEventListener('pointerup', handlePointerUp, true); 15907 }; 15908 function destroy() { 15909 if (liveRegion) liveRegion.remove(); 15910 let { 15911 nextEl, 15912 prevEl 15913 } = swiper.navigation ? swiper.navigation : {}; 15914 nextEl = makeElementsArray(nextEl); 15915 prevEl = makeElementsArray(prevEl); 15916 if (nextEl) { 15917 nextEl.forEach(el => el.removeEventListener('keydown', onEnterOrSpaceKey)); 15918 } 15919 if (prevEl) { 15920 prevEl.forEach(el => el.removeEventListener('keydown', onEnterOrSpaceKey)); 15921 } 15922 15923 // Pagination 15924 if (hasClickablePagination()) { 15925 const paginationEl = makeElementsArray(swiper.pagination.el); 15926 paginationEl.forEach(el => { 15927 el.removeEventListener('keydown', onEnterOrSpaceKey); 15928 }); 15929 } 15930 const document = getDocument(); 15931 document.removeEventListener('visibilitychange', onVisibilityChange); 15932 // Tab focus 15933 if (swiper.el && typeof swiper.el !== 'string') { 15934 swiper.el.removeEventListener('focus', handleFocus, true); 15935 swiper.el.removeEventListener('pointerdown', handlePointerDown, true); 15936 swiper.el.removeEventListener('pointerup', handlePointerUp, true); 15937 } 15938 } 15939 on('beforeInit', () => { 15940 liveRegion = createElement('span', swiper.params.a11y.notificationClass); 15941 liveRegion.setAttribute('aria-live', 'assertive'); 15942 liveRegion.setAttribute('aria-atomic', 'true'); 15943 }); 15944 on('afterInit', () => { 15945 if (!swiper.params.a11y.enabled) return; 15946 init(); 15947 }); 15948 on('slidesLengthChange snapGridLengthChange slidesGridLengthChange', () => { 15949 if (!swiper.params.a11y.enabled) return; 15950 initSlides(); 15951 }); 15952 on('fromEdge toEdge afterInit lock unlock', () => { 15953 if (!swiper.params.a11y.enabled) return; 15954 updateNavigation(); 15955 }); 15956 on('paginationUpdate', () => { 15957 if (!swiper.params.a11y.enabled) return; 15958 updatePagination(); 15959 }); 15960 on('destroy', () => { 15961 if (!swiper.params.a11y.enabled) return; 15962 destroy(); 15963 }); 15964 } 15965 15966 function History({ 15967 swiper, 15968 extendParams, 15969 on 15970 }) { 15971 extendParams({ 15972 history: { 15973 enabled: false, 15974 root: '', 15975 replaceState: false, 15976 key: 'slides', 15977 keepQuery: false 15978 } 15979 }); 15980 let initialized = false; 15981 let paths = {}; 15982 const slugify = text => { 15983 return text.toString().replace(/\s+/g, '-').replace(/[^\w-]+/g, '').replace(/--+/g, '-').replace(/^-+/, '').replace(/-+$/, ''); 15984 }; 15985 const getPathValues = urlOverride => { 15986 const window = getWindow(); 15987 let location; 15988 if (urlOverride) { 15989 location = new URL(urlOverride); 15990 } else { 15991 location = window.location; 15992 } 15993 const pathArray = location.pathname.slice(1).split('/').filter(part => part !== ''); 15994 const total = pathArray.length; 15995 const key = pathArray[total - 2]; 15996 const value = pathArray[total - 1]; 15997 return { 15998 key, 15999 value 16000 }; 16001 }; 16002 const setHistory = (key, index) => { 16003 const window = getWindow(); 16004 if (!initialized || !swiper.params.history.enabled) return; 16005 let location; 16006 if (swiper.params.url) { 16007 location = new URL(swiper.params.url); 16008 } else { 16009 location = window.location; 16010 } 16011 const slide = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${index}"]`) : swiper.slides[index]; 16012 let value = slugify(slide.getAttribute('data-history')); 16013 if (swiper.params.history.root.length > 0) { 16014 let root = swiper.params.history.root; 16015 if (root[root.length - 1] === '/') root = root.slice(0, root.length - 1); 16016 value = `${root}/${key ? `${key}/` : ''}${value}`; 16017 } else if (!location.pathname.includes(key)) { 16018 value = `${key ? `${key}/` : ''}${value}`; 16019 } 16020 if (swiper.params.history.keepQuery) { 16021 value += location.search; 16022 } 16023 const currentState = window.history.state; 16024 if (currentState && currentState.value === value) { 16025 return; 16026 } 16027 if (swiper.params.history.replaceState) { 16028 window.history.replaceState({ 16029 value 16030 }, null, value); 16031 } else { 16032 window.history.pushState({ 16033 value 16034 }, null, value); 16035 } 16036 }; 16037 const scrollToSlide = (speed, value, runCallbacks) => { 16038 if (value) { 16039 for (let i = 0, length = swiper.slides.length; i < length; i += 1) { 16040 const slide = swiper.slides[i]; 16041 const slideHistory = slugify(slide.getAttribute('data-history')); 16042 if (slideHistory === value) { 16043 const index = swiper.getSlideIndex(slide); 16044 swiper.slideTo(index, speed, runCallbacks); 16045 } 16046 } 16047 } else { 16048 swiper.slideTo(0, speed, runCallbacks); 16049 } 16050 }; 16051 const setHistoryPopState = () => { 16052 paths = getPathValues(swiper.params.url); 16053 scrollToSlide(swiper.params.speed, paths.value, false); 16054 }; 16055 const init = () => { 16056 const window = getWindow(); 16057 if (!swiper.params.history) return; 16058 if (!window.history || !window.history.pushState) { 16059 swiper.params.history.enabled = false; 16060 swiper.params.hashNavigation.enabled = true; 16061 return; 16062 } 16063 initialized = true; 16064 paths = getPathValues(swiper.params.url); 16065 if (!paths.key && !paths.value) { 16066 if (!swiper.params.history.replaceState) { 16067 window.addEventListener('popstate', setHistoryPopState); 16068 } 16069 return; 16070 } 16071 scrollToSlide(0, paths.value, swiper.params.runCallbacksOnInit); 16072 if (!swiper.params.history.replaceState) { 16073 window.addEventListener('popstate', setHistoryPopState); 16074 } 16075 }; 16076 const destroy = () => { 16077 const window = getWindow(); 16078 if (!swiper.params.history.replaceState) { 16079 window.removeEventListener('popstate', setHistoryPopState); 16080 } 16081 }; 16082 on('init', () => { 16083 if (swiper.params.history.enabled) { 16084 init(); 16085 } 16086 }); 16087 on('destroy', () => { 16088 if (swiper.params.history.enabled) { 16089 destroy(); 16090 } 16091 }); 16092 on('transitionEnd _freeModeNoMomentumRelease', () => { 16093 if (initialized) { 16094 setHistory(swiper.params.history.key, swiper.activeIndex); 16095 } 16096 }); 16097 on('slideChange', () => { 16098 if (initialized && swiper.params.cssMode) { 16099 setHistory(swiper.params.history.key, swiper.activeIndex); 16100 } 16101 }); 16102 } 16103 16104 function HashNavigation({ 16105 swiper, 16106 extendParams, 16107 emit, 16108 on 16109 }) { 16110 let initialized = false; 16111 const document = getDocument(); 16112 const window = getWindow(); 16113 extendParams({ 16114 hashNavigation: { 16115 enabled: false, 16116 replaceState: false, 16117 watchState: false, 16118 getSlideIndex(_s, hash) { 16119 if (swiper.virtual && swiper.params.virtual.enabled) { 16120 const slideWithHash = swiper.slides.find(slideEl => slideEl.getAttribute('data-hash') === hash); 16121 if (!slideWithHash) return 0; 16122 const index = parseInt(slideWithHash.getAttribute('data-swiper-slide-index'), 10); 16123 return index; 16124 } 16125 return swiper.getSlideIndex(elementChildren(swiper.slidesEl, `.${swiper.params.slideClass}[data-hash="${hash}"], swiper-slide[data-hash="${hash}"]`)[0]); 16126 } 16127 } 16128 }); 16129 const onHashChange = () => { 16130 emit('hashChange'); 16131 const newHash = document.location.hash.replace('#', ''); 16132 const activeSlideEl = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) : swiper.slides[swiper.activeIndex]; 16133 const activeSlideHash = activeSlideEl ? activeSlideEl.getAttribute('data-hash') : ''; 16134 if (newHash !== activeSlideHash) { 16135 const newIndex = swiper.params.hashNavigation.getSlideIndex(swiper, newHash); 16136 if (typeof newIndex === 'undefined' || Number.isNaN(newIndex)) return; 16137 swiper.slideTo(newIndex); 16138 } 16139 }; 16140 const setHash = () => { 16141 if (!initialized || !swiper.params.hashNavigation.enabled) return; 16142 const activeSlideEl = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) : swiper.slides[swiper.activeIndex]; 16143 const activeSlideHash = activeSlideEl ? activeSlideEl.getAttribute('data-hash') || activeSlideEl.getAttribute('data-history') : ''; 16144 if (swiper.params.hashNavigation.replaceState && window.history && window.history.replaceState) { 16145 window.history.replaceState(null, null, `#${activeSlideHash}` || ''); 16146 emit('hashSet'); 16147 } else { 16148 document.location.hash = activeSlideHash || ''; 16149 emit('hashSet'); 16150 } 16151 }; 16152 const init = () => { 16153 if (!swiper.params.hashNavigation.enabled || swiper.params.history && swiper.params.history.enabled) return; 16154 initialized = true; 16155 const hash = document.location.hash.replace('#', ''); 16156 if (hash) { 16157 const speed = 0; 16158 const index = swiper.params.hashNavigation.getSlideIndex(swiper, hash); 16159 swiper.slideTo(index || 0, speed, swiper.params.runCallbacksOnInit, true); 16160 } 16161 if (swiper.params.hashNavigation.watchState) { 16162 window.addEventListener('hashchange', onHashChange); 16163 } 16164 }; 16165 const destroy = () => { 16166 if (swiper.params.hashNavigation.watchState) { 16167 window.removeEventListener('hashchange', onHashChange); 16168 } 16169 }; 16170 on('init', () => { 16171 if (swiper.params.hashNavigation.enabled) { 16172 init(); 16173 } 16174 }); 16175 on('destroy', () => { 16176 if (swiper.params.hashNavigation.enabled) { 16177 destroy(); 16178 } 16179 }); 16180 on('transitionEnd _freeModeNoMomentumRelease', () => { 16181 if (initialized) { 16182 setHash(); 16183 } 16184 }); 16185 on('slideChange', () => { 16186 if (initialized && swiper.params.cssMode) { 16187 setHash(); 16188 } 16189 }); 16190 } 16191 16192 /* eslint no-underscore-dangle: "off" */ 16193 /* eslint no-use-before-define: "off" */ 16194 function Autoplay({ 16195 swiper, 16196 extendParams, 16197 on, 16198 emit, 16199 params 16200 }) { 16201 swiper.autoplay = { 16202 running: false, 16203 paused: false, 16204 timeLeft: 0 16205 }; 16206 extendParams({ 16207 autoplay: { 16208 enabled: false, 16209 delay: 3000, 16210 waitForTransition: true, 16211 disableOnInteraction: false, 16212 stopOnLastSlide: false, 16213 reverseDirection: false, 16214 pauseOnMouseEnter: false 16215 } 16216 }); 16217 let timeout; 16218 let raf; 16219 let autoplayDelayTotal = params && params.autoplay ? params.autoplay.delay : 3000; 16220 let autoplayDelayCurrent = params && params.autoplay ? params.autoplay.delay : 3000; 16221 let autoplayTimeLeft; 16222 let autoplayStartTime = new Date().getTime(); 16223 let wasPaused; 16224 let isTouched; 16225 let pausedByTouch; 16226 let touchStartTimeout; 16227 let slideChanged; 16228 let pausedByInteraction; 16229 let pausedByPointerEnter; 16230 function onTransitionEnd(e) { 16231 if (!swiper || swiper.destroyed || !swiper.wrapperEl) return; 16232 if (e.target !== swiper.wrapperEl) return; 16233 swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd); 16234 if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) { 16235 return; 16236 } 16237 resume(); 16238 } 16239 const calcTimeLeft = () => { 16240 if (swiper.destroyed || !swiper.autoplay.running) return; 16241 if (swiper.autoplay.paused) { 16242 wasPaused = true; 16243 } else if (wasPaused) { 16244 autoplayDelayCurrent = autoplayTimeLeft; 16245 wasPaused = false; 16246 } 16247 const timeLeft = swiper.autoplay.paused ? autoplayTimeLeft : autoplayStartTime + autoplayDelayCurrent - new Date().getTime(); 16248 swiper.autoplay.timeLeft = timeLeft; 16249 emit('autoplayTimeLeft', timeLeft, timeLeft / autoplayDelayTotal); 16250 raf = requestAnimationFrame(() => { 16251 calcTimeLeft(); 16252 }); 16253 }; 16254 const getSlideDelay = () => { 16255 let activeSlideEl; 16256 if (swiper.virtual && swiper.params.virtual.enabled) { 16257 activeSlideEl = swiper.slides.find(slideEl => slideEl.classList.contains('swiper-slide-active')); 16258 } else { 16259 activeSlideEl = swiper.slides[swiper.activeIndex]; 16260 } 16261 if (!activeSlideEl) return undefined; 16262 const currentSlideDelay = parseInt(activeSlideEl.getAttribute('data-swiper-autoplay'), 10); 16263 return currentSlideDelay; 16264 }; 16265 const run = delayForce => { 16266 if (swiper.destroyed || !swiper.autoplay.running) return; 16267 cancelAnimationFrame(raf); 16268 calcTimeLeft(); 16269 let delay = typeof delayForce === 'undefined' ? swiper.params.autoplay.delay : delayForce; 16270 autoplayDelayTotal = swiper.params.autoplay.delay; 16271 autoplayDelayCurrent = swiper.params.autoplay.delay; 16272 const currentSlideDelay = getSlideDelay(); 16273 if (!Number.isNaN(currentSlideDelay) && currentSlideDelay > 0 && typeof delayForce === 'undefined') { 16274 delay = currentSlideDelay; 16275 autoplayDelayTotal = currentSlideDelay; 16276 autoplayDelayCurrent = currentSlideDelay; 16277 } 16278 autoplayTimeLeft = delay; 16279 const speed = swiper.params.speed; 16280 const proceed = () => { 16281 if (!swiper || swiper.destroyed) return; 16282 if (swiper.params.autoplay.reverseDirection) { 16283 if (!swiper.isBeginning || swiper.params.loop || swiper.params.rewind) { 16284 swiper.slidePrev(speed, true, true); 16285 emit('autoplay'); 16286 } else if (!swiper.params.autoplay.stopOnLastSlide) { 16287 swiper.slideTo(swiper.slides.length - 1, speed, true, true); 16288 emit('autoplay'); 16289 } 16290 } else { 16291 if (!swiper.isEnd || swiper.params.loop || swiper.params.rewind) { 16292 swiper.slideNext(speed, true, true); 16293 emit('autoplay'); 16294 } else if (!swiper.params.autoplay.stopOnLastSlide) { 16295 swiper.slideTo(0, speed, true, true); 16296 emit('autoplay'); 16297 } 16298 } 16299 if (swiper.params.cssMode) { 16300 autoplayStartTime = new Date().getTime(); 16301 requestAnimationFrame(() => { 16302 run(); 16303 }); 16304 } 16305 }; 16306 if (delay > 0) { 16307 clearTimeout(timeout); 16308 timeout = setTimeout(() => { 16309 proceed(); 16310 }, delay); 16311 } else { 16312 requestAnimationFrame(() => { 16313 proceed(); 16314 }); 16315 } 16316 16317 // eslint-disable-next-line 16318 return delay; 16319 }; 16320 const start = () => { 16321 autoplayStartTime = new Date().getTime(); 16322 swiper.autoplay.running = true; 16323 run(); 16324 emit('autoplayStart'); 16325 }; 16326 const stop = () => { 16327 swiper.autoplay.running = false; 16328 clearTimeout(timeout); 16329 cancelAnimationFrame(raf); 16330 emit('autoplayStop'); 16331 }; 16332 const pause = (internal, reset) => { 16333 if (swiper.destroyed || !swiper.autoplay.running) return; 16334 clearTimeout(timeout); 16335 if (!internal) { 16336 pausedByInteraction = true; 16337 } 16338 const proceed = () => { 16339 emit('autoplayPause'); 16340 if (swiper.params.autoplay.waitForTransition) { 16341 swiper.wrapperEl.addEventListener('transitionend', onTransitionEnd); 16342 } else { 16343 resume(); 16344 } 16345 }; 16346 swiper.autoplay.paused = true; 16347 if (reset) { 16348 if (slideChanged) { 16349 autoplayTimeLeft = swiper.params.autoplay.delay; 16350 } 16351 slideChanged = false; 16352 proceed(); 16353 return; 16354 } 16355 const delay = autoplayTimeLeft || swiper.params.autoplay.delay; 16356 autoplayTimeLeft = delay - (new Date().getTime() - autoplayStartTime); 16357 if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) return; 16358 if (autoplayTimeLeft < 0) autoplayTimeLeft = 0; 16359 proceed(); 16360 }; 16361 const resume = () => { 16362 if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop || swiper.destroyed || !swiper.autoplay.running) return; 16363 autoplayStartTime = new Date().getTime(); 16364 if (pausedByInteraction) { 16365 pausedByInteraction = false; 16366 run(autoplayTimeLeft); 16367 } else { 16368 run(); 16369 } 16370 swiper.autoplay.paused = false; 16371 emit('autoplayResume'); 16372 }; 16373 const onVisibilityChange = () => { 16374 if (swiper.destroyed || !swiper.autoplay.running) return; 16375 const document = getDocument(); 16376 if (document.visibilityState === 'hidden') { 16377 pausedByInteraction = true; 16378 pause(true); 16379 } 16380 if (document.visibilityState === 'visible') { 16381 resume(); 16382 } 16383 }; 16384 const onPointerEnter = e => { 16385 if (e.pointerType !== 'mouse') return; 16386 pausedByInteraction = true; 16387 pausedByPointerEnter = true; 16388 if (swiper.animating || swiper.autoplay.paused) return; 16389 pause(true); 16390 }; 16391 const onPointerLeave = e => { 16392 if (e.pointerType !== 'mouse') return; 16393 pausedByPointerEnter = false; 16394 if (swiper.autoplay.paused) { 16395 resume(); 16396 } 16397 }; 16398 const attachMouseEvents = () => { 16399 if (swiper.params.autoplay.pauseOnMouseEnter) { 16400 swiper.el.addEventListener('pointerenter', onPointerEnter); 16401 swiper.el.addEventListener('pointerleave', onPointerLeave); 16402 } 16403 }; 16404 const detachMouseEvents = () => { 16405 if (swiper.el && typeof swiper.el !== 'string') { 16406 swiper.el.removeEventListener('pointerenter', onPointerEnter); 16407 swiper.el.removeEventListener('pointerleave', onPointerLeave); 16408 } 16409 }; 16410 const attachDocumentEvents = () => { 16411 const document = getDocument(); 16412 document.addEventListener('visibilitychange', onVisibilityChange); 16413 }; 16414 const detachDocumentEvents = () => { 16415 const document = getDocument(); 16416 document.removeEventListener('visibilitychange', onVisibilityChange); 16417 }; 16418 on('init', () => { 16419 if (swiper.params.autoplay.enabled) { 16420 attachMouseEvents(); 16421 attachDocumentEvents(); 16422 start(); 16423 } 16424 }); 16425 on('destroy', () => { 16426 detachMouseEvents(); 16427 detachDocumentEvents(); 16428 if (swiper.autoplay.running) { 16429 stop(); 16430 } 16431 }); 16432 on('_freeModeStaticRelease', () => { 16433 if (pausedByTouch || pausedByInteraction) { 16434 resume(); 16435 } 16436 }); 16437 on('_freeModeNoMomentumRelease', () => { 16438 if (!swiper.params.autoplay.disableOnInteraction) { 16439 pause(true, true); 16440 } else { 16441 stop(); 16442 } 16443 }); 16444 on('beforeTransitionStart', (_s, speed, internal) => { 16445 if (swiper.destroyed || !swiper.autoplay.running) return; 16446 if (internal || !swiper.params.autoplay.disableOnInteraction) { 16447 pause(true, true); 16448 } else { 16449 stop(); 16450 } 16451 }); 16452 on('sliderFirstMove', () => { 16453 if (swiper.destroyed || !swiper.autoplay.running) return; 16454 if (swiper.params.autoplay.disableOnInteraction) { 16455 stop(); 16456 return; 16457 } 16458 isTouched = true; 16459 pausedByTouch = false; 16460 pausedByInteraction = false; 16461 touchStartTimeout = setTimeout(() => { 16462 pausedByInteraction = true; 16463 pausedByTouch = true; 16464 pause(true); 16465 }, 200); 16466 }); 16467 on('touchEnd', () => { 16468 if (swiper.destroyed || !swiper.autoplay.running || !isTouched) return; 16469 clearTimeout(touchStartTimeout); 16470 clearTimeout(timeout); 16471 if (swiper.params.autoplay.disableOnInteraction) { 16472 pausedByTouch = false; 16473 isTouched = false; 16474 return; 16475 } 16476 if (pausedByTouch && swiper.params.cssMode) resume(); 16477 pausedByTouch = false; 16478 isTouched = false; 16479 }); 16480 on('slideChange', () => { 16481 if (swiper.destroyed || !swiper.autoplay.running) return; 16482 slideChanged = true; 16483 }); 16484 Object.assign(swiper.autoplay, { 16485 start, 16486 stop, 16487 pause, 16488 resume 16489 }); 16490 } 16491 16492 function Thumb({ 16493 swiper, 16494 extendParams, 16495 on 16496 }) { 16497 extendParams({ 16498 thumbs: { 16499 swiper: null, 16500 multipleActiveThumbs: true, 16501 autoScrollOffset: 0, 16502 slideThumbActiveClass: 'swiper-slide-thumb-active', 16503 thumbsContainerClass: 'swiper-thumbs' 16504 } 16505 }); 16506 let initialized = false; 16507 let swiperCreated = false; 16508 swiper.thumbs = { 16509 swiper: null 16510 }; 16511 function onThumbClick() { 16512 const thumbsSwiper = swiper.thumbs.swiper; 16513 if (!thumbsSwiper || thumbsSwiper.destroyed) return; 16514 const clickedIndex = thumbsSwiper.clickedIndex; 16515 const clickedSlide = thumbsSwiper.clickedSlide; 16516 if (clickedSlide && clickedSlide.classList.contains(swiper.params.thumbs.slideThumbActiveClass)) return; 16517 if (typeof clickedIndex === 'undefined' || clickedIndex === null) return; 16518 let slideToIndex; 16519 if (thumbsSwiper.params.loop) { 16520 slideToIndex = parseInt(thumbsSwiper.clickedSlide.getAttribute('data-swiper-slide-index'), 10); 16521 } else { 16522 slideToIndex = clickedIndex; 16523 } 16524 if (swiper.params.loop) { 16525 swiper.slideToLoop(slideToIndex); 16526 } else { 16527 swiper.slideTo(slideToIndex); 16528 } 16529 } 16530 function init() { 16531 const { 16532 thumbs: thumbsParams 16533 } = swiper.params; 16534 if (initialized) return false; 16535 initialized = true; 16536 const SwiperClass = swiper.constructor; 16537 if (thumbsParams.swiper instanceof SwiperClass) { 16538 if (thumbsParams.swiper.destroyed) { 16539 initialized = false; 16540 return false; 16541 } 16542 swiper.thumbs.swiper = thumbsParams.swiper; 16543 Object.assign(swiper.thumbs.swiper.originalParams, { 16544 watchSlidesProgress: true, 16545 slideToClickedSlide: false 16546 }); 16547 Object.assign(swiper.thumbs.swiper.params, { 16548 watchSlidesProgress: true, 16549 slideToClickedSlide: false 16550 }); 16551 swiper.thumbs.swiper.update(); 16552 } else if (isObject(thumbsParams.swiper)) { 16553 const thumbsSwiperParams = Object.assign({}, thumbsParams.swiper); 16554 Object.assign(thumbsSwiperParams, { 16555 watchSlidesProgress: true, 16556 slideToClickedSlide: false 16557 }); 16558 swiper.thumbs.swiper = new SwiperClass(thumbsSwiperParams); 16559 swiperCreated = true; 16560 } 16561 swiper.thumbs.swiper.el.classList.add(swiper.params.thumbs.thumbsContainerClass); 16562 swiper.thumbs.swiper.on('tap', onThumbClick); 16563 return true; 16564 } 16565 function update(initial) { 16566 const thumbsSwiper = swiper.thumbs.swiper; 16567 if (!thumbsSwiper || thumbsSwiper.destroyed) return; 16568 const slidesPerView = thumbsSwiper.params.slidesPerView === 'auto' ? thumbsSwiper.slidesPerViewDynamic() : thumbsSwiper.params.slidesPerView; 16569 16570 // Activate thumbs 16571 let thumbsToActivate = 1; 16572 const thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass; 16573 if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) { 16574 thumbsToActivate = swiper.params.slidesPerView; 16575 } 16576 if (!swiper.params.thumbs.multipleActiveThumbs) { 16577 thumbsToActivate = 1; 16578 } 16579 thumbsToActivate = Math.floor(thumbsToActivate); 16580 thumbsSwiper.slides.forEach(slideEl => slideEl.classList.remove(thumbActiveClass)); 16581 if (thumbsSwiper.params.loop || thumbsSwiper.params.virtual && thumbsSwiper.params.virtual.enabled) { 16582 for (let i = 0; i < thumbsToActivate; i += 1) { 16583 elementChildren(thumbsSwiper.slidesEl, `[data-swiper-slide-index="${swiper.realIndex + i}"]`).forEach(slideEl => { 16584 slideEl.classList.add(thumbActiveClass); 16585 }); 16586 } 16587 } else { 16588 for (let i = 0; i < thumbsToActivate; i += 1) { 16589 if (thumbsSwiper.slides[swiper.realIndex + i]) { 16590 thumbsSwiper.slides[swiper.realIndex + i].classList.add(thumbActiveClass); 16591 } 16592 } 16593 } 16594 const autoScrollOffset = swiper.params.thumbs.autoScrollOffset; 16595 const useOffset = autoScrollOffset && !thumbsSwiper.params.loop; 16596 if (swiper.realIndex !== thumbsSwiper.realIndex || useOffset) { 16597 const currentThumbsIndex = thumbsSwiper.activeIndex; 16598 let newThumbsIndex; 16599 let direction; 16600 if (thumbsSwiper.params.loop) { 16601 const newThumbsSlide = thumbsSwiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') === `${swiper.realIndex}`); 16602 newThumbsIndex = thumbsSwiper.slides.indexOf(newThumbsSlide); 16603 direction = swiper.activeIndex > swiper.previousIndex ? 'next' : 'prev'; 16604 } else { 16605 newThumbsIndex = swiper.realIndex; 16606 direction = newThumbsIndex > swiper.previousIndex ? 'next' : 'prev'; 16607 } 16608 if (useOffset) { 16609 newThumbsIndex += direction === 'next' ? autoScrollOffset : -1 * autoScrollOffset; 16610 } 16611 if (thumbsSwiper.visibleSlidesIndexes && thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) { 16612 if (thumbsSwiper.params.centeredSlides) { 16613 if (newThumbsIndex > currentThumbsIndex) { 16614 newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1; 16615 } else { 16616 newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1; 16617 } 16618 } else if (newThumbsIndex > currentThumbsIndex && thumbsSwiper.params.slidesPerGroup === 1) ; 16619 thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined); 16620 } 16621 } 16622 } 16623 on('beforeInit', () => { 16624 const { 16625 thumbs 16626 } = swiper.params; 16627 if (!thumbs || !thumbs.swiper) return; 16628 if (typeof thumbs.swiper === 'string' || thumbs.swiper instanceof HTMLElement) { 16629 const document = getDocument(); 16630 const getThumbsElementAndInit = () => { 16631 const thumbsElement = typeof thumbs.swiper === 'string' ? document.querySelector(thumbs.swiper) : thumbs.swiper; 16632 if (thumbsElement && thumbsElement.swiper) { 16633 thumbs.swiper = thumbsElement.swiper; 16634 init(); 16635 update(true); 16636 } else if (thumbsElement) { 16637 const eventName = `${swiper.params.eventsPrefix}init`; 16638 const onThumbsSwiper = e => { 16639 thumbs.swiper = e.detail[0]; 16640 thumbsElement.removeEventListener(eventName, onThumbsSwiper); 16641 init(); 16642 update(true); 16643 thumbs.swiper.update(); 16644 swiper.update(); 16645 }; 16646 thumbsElement.addEventListener(eventName, onThumbsSwiper); 16647 } 16648 return thumbsElement; 16649 }; 16650 const watchForThumbsToAppear = () => { 16651 if (swiper.destroyed) return; 16652 const thumbsElement = getThumbsElementAndInit(); 16653 if (!thumbsElement) { 16654 requestAnimationFrame(watchForThumbsToAppear); 16655 } 16656 }; 16657 requestAnimationFrame(watchForThumbsToAppear); 16658 } else { 16659 init(); 16660 update(true); 16661 } 16662 }); 16663 on('slideChange update resize observerUpdate', () => { 16664 update(); 16665 }); 16666 on('setTransition', (_s, duration) => { 16667 const thumbsSwiper = swiper.thumbs.swiper; 16668 if (!thumbsSwiper || thumbsSwiper.destroyed) return; 16669 thumbsSwiper.setTransition(duration); 16670 }); 16671 on('beforeDestroy', () => { 16672 const thumbsSwiper = swiper.thumbs.swiper; 16673 if (!thumbsSwiper || thumbsSwiper.destroyed) return; 16674 if (swiperCreated) { 16675 thumbsSwiper.destroy(); 16676 } 16677 }); 16678 Object.assign(swiper.thumbs, { 16679 init, 16680 update 16681 }); 16682 } 16683 16684 function freeMode({ 16685 swiper, 16686 extendParams, 16687 emit, 16688 once 16689 }) { 16690 extendParams({ 16691 freeMode: { 16692 enabled: false, 16693 momentum: true, 16694 momentumRatio: 1, 16695 momentumBounce: true, 16696 momentumBounceRatio: 1, 16697 momentumVelocityRatio: 1, 16698 sticky: false, 16699 minimumVelocity: 0.02 16700 } 16701 }); 16702 function onTouchStart() { 16703 if (swiper.params.cssMode) return; 16704 const translate = swiper.getTranslate(); 16705 swiper.setTranslate(translate); 16706 swiper.setTransition(0); 16707 swiper.touchEventsData.velocities.length = 0; 16708 swiper.freeMode.onTouchEnd({ 16709 currentPos: swiper.rtl ? swiper.translate : -swiper.translate 16710 }); 16711 } 16712 function onTouchMove() { 16713 if (swiper.params.cssMode) return; 16714 const { 16715 touchEventsData: data, 16716 touches 16717 } = swiper; 16718 // Velocity 16719 if (data.velocities.length === 0) { 16720 data.velocities.push({ 16721 position: touches[swiper.isHorizontal() ? 'startX' : 'startY'], 16722 time: data.touchStartTime 16723 }); 16724 } 16725 data.velocities.push({ 16726 position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'], 16727 time: now() 16728 }); 16729 } 16730 function onTouchEnd({ 16731 currentPos 16732 }) { 16733 if (swiper.params.cssMode) return; 16734 const { 16735 params, 16736 wrapperEl, 16737 rtlTranslate: rtl, 16738 snapGrid, 16739 touchEventsData: data 16740 } = swiper; 16741 // Time diff 16742 const touchEndTime = now(); 16743 const timeDiff = touchEndTime - data.touchStartTime; 16744 if (currentPos < -swiper.minTranslate()) { 16745 swiper.slideTo(swiper.activeIndex); 16746 return; 16747 } 16748 if (currentPos > -swiper.maxTranslate()) { 16749 if (swiper.slides.length < snapGrid.length) { 16750 swiper.slideTo(snapGrid.length - 1); 16751 } else { 16752 swiper.slideTo(swiper.slides.length - 1); 16753 } 16754 return; 16755 } 16756 if (params.freeMode.momentum) { 16757 if (data.velocities.length > 1) { 16758 const lastMoveEvent = data.velocities.pop(); 16759 const velocityEvent = data.velocities.pop(); 16760 const distance = lastMoveEvent.position - velocityEvent.position; 16761 const time = lastMoveEvent.time - velocityEvent.time; 16762 swiper.velocity = distance / time; 16763 swiper.velocity /= 2; 16764 if (Math.abs(swiper.velocity) < params.freeMode.minimumVelocity) { 16765 swiper.velocity = 0; 16766 } 16767 // this implies that the user stopped moving a finger then released. 16768 // There would be no events with distance zero, so the last event is stale. 16769 if (time > 150 || now() - lastMoveEvent.time > 300) { 16770 swiper.velocity = 0; 16771 } 16772 } else { 16773 swiper.velocity = 0; 16774 } 16775 swiper.velocity *= params.freeMode.momentumVelocityRatio; 16776 data.velocities.length = 0; 16777 let momentumDuration = 1000 * params.freeMode.momentumRatio; 16778 const momentumDistance = swiper.velocity * momentumDuration; 16779 let newPosition = swiper.translate + momentumDistance; 16780 if (rtl) newPosition = -newPosition; 16781 let doBounce = false; 16782 let afterBouncePosition; 16783 const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeMode.momentumBounceRatio; 16784 let needsLoopFix; 16785 if (newPosition < swiper.maxTranslate()) { 16786 if (params.freeMode.momentumBounce) { 16787 if (newPosition + swiper.maxTranslate() < -bounceAmount) { 16788 newPosition = swiper.maxTranslate() - bounceAmount; 16789 } 16790 afterBouncePosition = swiper.maxTranslate(); 16791 doBounce = true; 16792 data.allowMomentumBounce = true; 16793 } else { 16794 newPosition = swiper.maxTranslate(); 16795 } 16796 if (params.loop && params.centeredSlides) needsLoopFix = true; 16797 } else if (newPosition > swiper.minTranslate()) { 16798 if (params.freeMode.momentumBounce) { 16799 if (newPosition - swiper.minTranslate() > bounceAmount) { 16800 newPosition = swiper.minTranslate() + bounceAmount; 16801 } 16802 afterBouncePosition = swiper.minTranslate(); 16803 doBounce = true; 16804 data.allowMomentumBounce = true; 16805 } else { 16806 newPosition = swiper.minTranslate(); 16807 } 16808 if (params.loop && params.centeredSlides) needsLoopFix = true; 16809 } else if (params.freeMode.sticky) { 16810 let nextSlide; 16811 for (let j = 0; j < snapGrid.length; j += 1) { 16812 if (snapGrid[j] > -newPosition) { 16813 nextSlide = j; 16814 break; 16815 } 16816 } 16817 if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') { 16818 newPosition = snapGrid[nextSlide]; 16819 } else { 16820 newPosition = snapGrid[nextSlide - 1]; 16821 } 16822 newPosition = -newPosition; 16823 } 16824 if (needsLoopFix) { 16825 once('transitionEnd', () => { 16826 swiper.loopFix(); 16827 }); 16828 } 16829 // Fix duration 16830 if (swiper.velocity !== 0) { 16831 if (rtl) { 16832 momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity); 16833 } else { 16834 momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity); 16835 } 16836 if (params.freeMode.sticky) { 16837 // If freeMode.sticky is active and the user ends a swipe with a slow-velocity 16838 // event, then durations can be 20+ seconds to slide one (or zero!) slides. 16839 // It's easy to see this when simulating touch with mouse events. To fix this, 16840 // limit single-slide swipes to the default slide duration. This also has the 16841 // nice side effect of matching slide speed if the user stopped moving before 16842 // lifting finger or mouse vs. moving slowly before lifting the finger/mouse. 16843 // For faster swipes, also apply limits (albeit higher ones). 16844 const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate); 16845 const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex]; 16846 if (moveDistance < currentSlideSize) { 16847 momentumDuration = params.speed; 16848 } else if (moveDistance < 2 * currentSlideSize) { 16849 momentumDuration = params.speed * 1.5; 16850 } else { 16851 momentumDuration = params.speed * 2.5; 16852 } 16853 } 16854 } else if (params.freeMode.sticky) { 16855 swiper.slideToClosest(); 16856 return; 16857 } 16858 if (params.freeMode.momentumBounce && doBounce) { 16859 swiper.updateProgress(afterBouncePosition); 16860 swiper.setTransition(momentumDuration); 16861 swiper.setTranslate(newPosition); 16862 swiper.transitionStart(true, swiper.swipeDirection); 16863 swiper.animating = true; 16864 elementTransitionEnd(wrapperEl, () => { 16865 if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return; 16866 emit('momentumBounce'); 16867 swiper.setTransition(params.speed); 16868 setTimeout(() => { 16869 swiper.setTranslate(afterBouncePosition); 16870 elementTransitionEnd(wrapperEl, () => { 16871 if (!swiper || swiper.destroyed) return; 16872 swiper.transitionEnd(); 16873 }); 16874 }, 0); 16875 }); 16876 } else if (swiper.velocity) { 16877 emit('_freeModeNoMomentumRelease'); 16878 swiper.updateProgress(newPosition); 16879 swiper.setTransition(momentumDuration); 16880 swiper.setTranslate(newPosition); 16881 swiper.transitionStart(true, swiper.swipeDirection); 16882 if (!swiper.animating) { 16883 swiper.animating = true; 16884 elementTransitionEnd(wrapperEl, () => { 16885 if (!swiper || swiper.destroyed) return; 16886 swiper.transitionEnd(); 16887 }); 16888 } 16889 } else { 16890 swiper.updateProgress(newPosition); 16891 } 16892 swiper.updateActiveIndex(); 16893 swiper.updateSlidesClasses(); 16894 } else if (params.freeMode.sticky) { 16895 swiper.slideToClosest(); 16896 return; 16897 } else if (params.freeMode) { 16898 emit('_freeModeNoMomentumRelease'); 16899 } 16900 if (!params.freeMode.momentum || timeDiff >= params.longSwipesMs) { 16901 emit('_freeModeStaticRelease'); 16902 swiper.updateProgress(); 16903 swiper.updateActiveIndex(); 16904 swiper.updateSlidesClasses(); 16905 } 16906 } 16907 Object.assign(swiper, { 16908 freeMode: { 16909 onTouchStart, 16910 onTouchMove, 16911 onTouchEnd 16912 } 16913 }); 16914 } 16915 16916 function Grid({ 16917 swiper, 16918 extendParams, 16919 on 16920 }) { 16921 extendParams({ 16922 grid: { 16923 rows: 1, 16924 fill: 'column' 16925 } 16926 });
vendor: 1,326 bytes, lines 16927-16961
16927 let slidesNumberEvenToRows; 16928 let slidesPerRow; 16929 let numFullColumns; 16930 let wasMultiRow; 16931 const getSpaceBetween = () => { 16932 let spaceBetween = swiper.params.spaceBetween; 16933 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { 16934 spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiper.size; 16935 } else if (typeof spaceBetween === 'string') { 16936 spaceBetween = parseFloat(spaceBetween); 16937 } 16938 return spaceBetween; 16939 }; 16940 const initSlides = slides => { 16941 const { 16942 slidesPerView 16943 } = swiper.params; 16944 const { 16945 rows, 16946 fill 16947 } = swiper.params.grid; 16948 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : slides.length; 16949 numFullColumns = Math.floor(slidesLength / rows); 16950 if (Math.floor(slidesLength / rows) === slidesLength / rows) { 16951 slidesNumberEvenToRows = slidesLength; 16952 } else { 16953 slidesNumberEvenToRows = Math.ceil(slidesLength / rows) * rows; 16954 } 16955 if (slidesPerView !== 'auto' && fill === 'row') { 16956 slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, slidesPerView * rows); 16957 } 16958 slidesPerRow = slidesNumberEvenToRows / rows; 16959 }; 16960 const unsetSlides = () => { 16961 if (swiper.slides) {
vendor: 38,075 bytes, lines 16962-18028
16962 swiper.slides.forEach(slide => { 16963 if (slide.swiperSlideGridSet) { 16964 slide.style.height = ''; 16965 slide.style[swiper.getDirectionLabel('margin-top')] = ''; 16966 } 16967 }); 16968 } 16969 }; 16970 const updateSlide = (i, slide, slides) => { 16971 const { 16972 slidesPerGroup 16973 } = swiper.params; 16974 const spaceBetween = getSpaceBetween(); 16975 const { 16976 rows, 16977 fill 16978 } = swiper.params.grid; 16979 const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : slides.length; 16980 // Set slides order 16981 let newSlideOrderIndex; 16982 let column; 16983 let row; 16984 if (fill === 'row' && slidesPerGroup > 1) { 16985 const groupIndex = Math.floor(i / (slidesPerGroup * rows)); 16986 const slideIndexInGroup = i - rows * slidesPerGroup * groupIndex; 16987 const columnsInGroup = groupIndex === 0 ? slidesPerGroup : Math.min(Math.ceil((slidesLength - groupIndex * rows * slidesPerGroup) / rows), slidesPerGroup); 16988 row = Math.floor(slideIndexInGroup / columnsInGroup); 16989 column = slideIndexInGroup - row * columnsInGroup + groupIndex * slidesPerGroup; 16990 newSlideOrderIndex = column + row * slidesNumberEvenToRows / rows; 16991 slide.style.order = newSlideOrderIndex; 16992 } else if (fill === 'column') { 16993 column = Math.floor(i / rows); 16994 row = i - column * rows; 16995 if (column > numFullColumns || column === numFullColumns && row === rows - 1) { 16996 row += 1; 16997 if (row >= rows) { 16998 row = 0; 16999 column += 1; 17000 } 17001 } 17002 } else { 17003 row = Math.floor(i / slidesPerRow); 17004 column = i - row * slidesPerRow; 17005 } 17006 slide.row = row; 17007 slide.column = column; 17008 slide.style.height = `calc((100% - ${(rows - 1) * spaceBetween}px) / ${rows})`; 17009 slide.style[swiper.getDirectionLabel('margin-top')] = row !== 0 ? spaceBetween && `${spaceBetween}px` : ''; 17010 slide.swiperSlideGridSet = true; 17011 }; 17012 const updateWrapperSize = (slideSize, snapGrid) => { 17013 const { 17014 centeredSlides, 17015 roundLengths 17016 } = swiper.params; 17017 const spaceBetween = getSpaceBetween(); 17018 const { 17019 rows 17020 } = swiper.params.grid; 17021 swiper.virtualSize = (slideSize + spaceBetween) * slidesNumberEvenToRows; 17022 swiper.virtualSize = Math.ceil(swiper.virtualSize / rows) - spaceBetween; 17023 if (!swiper.params.cssMode) { 17024 swiper.wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`; 17025 } 17026 if (centeredSlides) { 17027 const newSlidesGrid = []; 17028 for (let i = 0; i < snapGrid.length; i += 1) { 17029 let slidesGridItem = snapGrid[i]; 17030 if (roundLengths) slidesGridItem = Math.floor(slidesGridItem); 17031 if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem); 17032 } 17033 snapGrid.splice(0, snapGrid.length); 17034 snapGrid.push(...newSlidesGrid); 17035 } 17036 }; 17037 const onInit = () => { 17038 wasMultiRow = swiper.params.grid && swiper.params.grid.rows > 1; 17039 }; 17040 const onUpdate = () => { 17041 const { 17042 params, 17043 el 17044 } = swiper; 17045 const isMultiRow = params.grid && params.grid.rows > 1; 17046 if (wasMultiRow && !isMultiRow) { 17047 el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`); 17048 numFullColumns = 1; 17049 swiper.emitContainerClasses(); 17050 } else if (!wasMultiRow && isMultiRow) { 17051 el.classList.add(`${params.containerModifierClass}grid`); 17052 if (params.grid.fill === 'column') { 17053 el.classList.add(`${params.containerModifierClass}grid-column`); 17054 } 17055 swiper.emitContainerClasses(); 17056 } 17057 wasMultiRow = isMultiRow; 17058 }; 17059 on('init', onInit); 17060 on('update', onUpdate); 17061 swiper.grid = { 17062 initSlides, 17063 unsetSlides, 17064 updateSlide, 17065 updateWrapperSize 17066 }; 17067 } 17068 17069 function appendSlide(slides) { 17070 const swiper = this; 17071 const { 17072 params, 17073 slidesEl 17074 } = swiper; 17075 if (params.loop) { 17076 swiper.loopDestroy(); 17077 } 17078 const appendElement = slideEl => { 17079 if (typeof slideEl === 'string') { 17080 const tempDOM = document.createElement('div'); 17081 setInnerHTML(tempDOM, slideEl); 17082 slidesEl.append(tempDOM.children[0]); 17083 setInnerHTML(tempDOM, ''); 17084 } else { 17085 slidesEl.append(slideEl); 17086 } 17087 }; 17088 if (typeof slides === 'object' && 'length' in slides) { 17089 for (let i = 0; i < slides.length; i += 1) { 17090 if (slides[i]) appendElement(slides[i]); 17091 } 17092 } else { 17093 appendElement(slides); 17094 } 17095 swiper.recalcSlides(); 17096 if (params.loop) { 17097 swiper.loopCreate(); 17098 } 17099 if (!params.observer || swiper.isElement) { 17100 swiper.update(); 17101 } 17102 } 17103 17104 function prependSlide(slides) { 17105 const swiper = this; 17106 const { 17107 params, 17108 activeIndex, 17109 slidesEl 17110 } = swiper; 17111 if (params.loop) { 17112 swiper.loopDestroy(); 17113 } 17114 let newActiveIndex = activeIndex + 1; 17115 const prependElement = slideEl => { 17116 if (typeof slideEl === 'string') { 17117 const tempDOM = document.createElement('div'); 17118 setInnerHTML(tempDOM, slideEl); 17119 slidesEl.prepend(tempDOM.children[0]); 17120 setInnerHTML(tempDOM, ''); 17121 } else { 17122 slidesEl.prepend(slideEl); 17123 } 17124 }; 17125 if (typeof slides === 'object' && 'length' in slides) { 17126 for (let i = 0; i < slides.length; i += 1) { 17127 if (slides[i]) prependElement(slides[i]); 17128 } 17129 newActiveIndex = activeIndex + slides.length; 17130 } else { 17131 prependElement(slides); 17132 } 17133 swiper.recalcSlides(); 17134 if (params.loop) { 17135 swiper.loopCreate(); 17136 } 17137 if (!params.observer || swiper.isElement) { 17138 swiper.update(); 17139 } 17140 swiper.slideTo(newActiveIndex, 0, false); 17141 } 17142 17143 function addSlide(index, slides) { 17144 const swiper = this; 17145 const { 17146 params, 17147 activeIndex, 17148 slidesEl 17149 } = swiper; 17150 let activeIndexBuffer = activeIndex; 17151 if (params.loop) { 17152 activeIndexBuffer -= swiper.loopedSlides; 17153 swiper.loopDestroy(); 17154 swiper.recalcSlides(); 17155 } 17156 const baseLength = swiper.slides.length; 17157 if (index <= 0) { 17158 swiper.prependSlide(slides); 17159 return; 17160 } 17161 if (index >= baseLength) { 17162 swiper.appendSlide(slides); 17163 return; 17164 } 17165 let newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer; 17166 const slidesBuffer = []; 17167 for (let i = baseLength - 1; i >= index; i -= 1) { 17168 const currentSlide = swiper.slides[i]; 17169 currentSlide.remove(); 17170 slidesBuffer.unshift(currentSlide); 17171 } 17172 if (typeof slides === 'object' && 'length' in slides) { 17173 for (let i = 0; i < slides.length; i += 1) { 17174 if (slides[i]) slidesEl.append(slides[i]); 17175 } 17176 newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer; 17177 } else { 17178 slidesEl.append(slides); 17179 } 17180 for (let i = 0; i < slidesBuffer.length; i += 1) { 17181 slidesEl.append(slidesBuffer[i]); 17182 } 17183 swiper.recalcSlides(); 17184 if (params.loop) { 17185 swiper.loopCreate(); 17186 } 17187 if (!params.observer || swiper.isElement) { 17188 swiper.update(); 17189 } 17190 if (params.loop) { 17191 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false); 17192 } else { 17193 swiper.slideTo(newActiveIndex, 0, false); 17194 } 17195 } 17196 17197 function removeSlide(slidesIndexes) { 17198 const swiper = this; 17199 const { 17200 params, 17201 activeIndex 17202 } = swiper; 17203 let activeIndexBuffer = activeIndex; 17204 if (params.loop) { 17205 activeIndexBuffer -= swiper.loopedSlides; 17206 swiper.loopDestroy(); 17207 } 17208 let newActiveIndex = activeIndexBuffer; 17209 let indexToRemove; 17210 if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) { 17211 for (let i = 0; i < slidesIndexes.length; i += 1) { 17212 indexToRemove = slidesIndexes[i]; 17213 if (swiper.slides[indexToRemove]) swiper.slides[indexToRemove].remove(); 17214 if (indexToRemove < newActiveIndex) newActiveIndex -= 1; 17215 } 17216 newActiveIndex = Math.max(newActiveIndex, 0); 17217 } else { 17218 indexToRemove = slidesIndexes; 17219 if (swiper.slides[indexToRemove]) swiper.slides[indexToRemove].remove(); 17220 if (indexToRemove < newActiveIndex) newActiveIndex -= 1; 17221 newActiveIndex = Math.max(newActiveIndex, 0); 17222 } 17223 swiper.recalcSlides(); 17224 if (params.loop) { 17225 swiper.loopCreate(); 17226 } 17227 if (!params.observer || swiper.isElement) { 17228 swiper.update(); 17229 } 17230 if (params.loop) { 17231 swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false); 17232 } else { 17233 swiper.slideTo(newActiveIndex, 0, false); 17234 } 17235 } 17236 17237 function removeAllSlides() { 17238 const swiper = this; 17239 const slidesIndexes = []; 17240 for (let i = 0; i < swiper.slides.length; i += 1) { 17241 slidesIndexes.push(i); 17242 } 17243 swiper.removeSlide(slidesIndexes); 17244 } 17245 17246 function Manipulation({ 17247 swiper 17248 }) { 17249 Object.assign(swiper, { 17250 appendSlide: appendSlide.bind(swiper), 17251 prependSlide: prependSlide.bind(swiper), 17252 addSlide: addSlide.bind(swiper), 17253 removeSlide: removeSlide.bind(swiper), 17254 removeAllSlides: removeAllSlides.bind(swiper) 17255 }); 17256 } 17257 17258 function effectInit(params) { 17259 const { 17260 effect, 17261 swiper, 17262 on, 17263 setTranslate, 17264 setTransition, 17265 overwriteParams, 17266 perspective, 17267 recreateShadows, 17268 getEffectParams 17269 } = params; 17270 on('beforeInit', () => { 17271 if (swiper.params.effect !== effect) return; 17272 swiper.classNames.push(`${swiper.params.containerModifierClass}${effect}`); 17273 if (perspective && perspective()) { 17274 swiper.classNames.push(`${swiper.params.containerModifierClass}3d`); 17275 } 17276 const overwriteParamsResult = overwriteParams ? overwriteParams() : {}; 17277 Object.assign(swiper.params, overwriteParamsResult); 17278 Object.assign(swiper.originalParams, overwriteParamsResult); 17279 }); 17280 on('setTranslate _virtualUpdated', () => { 17281 if (swiper.params.effect !== effect) return; 17282 setTranslate(); 17283 }); 17284 on('setTransition', (_s, duration) => { 17285 if (swiper.params.effect !== effect) return; 17286 setTransition(duration); 17287 }); 17288 on('transitionEnd', () => { 17289 if (swiper.params.effect !== effect) return; 17290 if (recreateShadows) { 17291 if (!getEffectParams || !getEffectParams().slideShadows) return; 17292 // remove shadows 17293 swiper.slides.forEach(slideEl => { 17294 slideEl.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(shadowEl => shadowEl.remove()); 17295 }); 17296 // create new one 17297 recreateShadows(); 17298 } 17299 }); 17300 let requireUpdateOnVirtual; 17301 on('virtualUpdate', () => { 17302 if (swiper.params.effect !== effect) return; 17303 if (!swiper.slides.length) { 17304 requireUpdateOnVirtual = true; 17305 } 17306 requestAnimationFrame(() => { 17307 if (requireUpdateOnVirtual && swiper.slides && swiper.slides.length) { 17308 setTranslate(); 17309 requireUpdateOnVirtual = false; 17310 } 17311 }); 17312 }); 17313 } 17314 17315 function effectTarget(effectParams, slideEl) { 17316 const transformEl = getSlideTransformEl(slideEl); 17317 if (transformEl !== slideEl) { 17318 transformEl.style.backfaceVisibility = 'hidden'; 17319 transformEl.style['-webkit-backface-visibility'] = 'hidden'; 17320 } 17321 return transformEl; 17322 } 17323 17324 function effectVirtualTransitionEnd({ 17325 swiper, 17326 duration, 17327 transformElements, 17328 allSlides 17329 }) { 17330 const { 17331 activeIndex 17332 } = swiper; 17333 const getSlide = el => { 17334 if (!el.parentElement) { 17335 // assume shadow root 17336 const slide = swiper.slides.find(slideEl => slideEl.shadowRoot && slideEl.shadowRoot === el.parentNode); 17337 return slide; 17338 } 17339 return el.parentElement; 17340 }; 17341 if (swiper.params.virtualTranslate && duration !== 0) { 17342 let eventTriggered = false; 17343 let transitionEndTarget; 17344 if (allSlides) { 17345 transitionEndTarget = transformElements; 17346 } else { 17347 transitionEndTarget = transformElements.filter(transformEl => { 17348 const el = transformEl.classList.contains('swiper-slide-transform') ? getSlide(transformEl) : transformEl; 17349 return swiper.getSlideIndex(el) === activeIndex; 17350 }); 17351 } 17352 transitionEndTarget.forEach(el => { 17353 elementTransitionEnd(el, () => { 17354 if (eventTriggered) return; 17355 if (!swiper || swiper.destroyed) return; 17356 eventTriggered = true; 17357 swiper.animating = false; 17358 const evt = new window.CustomEvent('transitionend', { 17359 bubbles: true, 17360 cancelable: true 17361 }); 17362 swiper.wrapperEl.dispatchEvent(evt); 17363 }); 17364 }); 17365 } 17366 } 17367 17368 function EffectFade({ 17369 swiper, 17370 extendParams, 17371 on 17372 }) { 17373 extendParams({ 17374 fadeEffect: { 17375 crossFade: false 17376 } 17377 }); 17378 const setTranslate = () => { 17379 const { 17380 slides 17381 } = swiper; 17382 const params = swiper.params.fadeEffect; 17383 for (let i = 0; i < slides.length; i += 1) { 17384 const slideEl = swiper.slides[i]; 17385 const offset = slideEl.swiperSlideOffset; 17386 let tx = -offset; 17387 if (!swiper.params.virtualTranslate) tx -= swiper.translate; 17388 let ty = 0; 17389 if (!swiper.isHorizontal()) { 17390 ty = tx; 17391 tx = 0; 17392 } 17393 const slideOpacity = swiper.params.fadeEffect.crossFade ? Math.max(1 - Math.abs(slideEl.progress), 0) : 1 + Math.min(Math.max(slideEl.progress, -1), 0); 17394 const targetEl = effectTarget(params, slideEl); 17395 targetEl.style.opacity = slideOpacity; 17396 targetEl.style.transform = `translate3d(${tx}px, ${ty}px, 0px)`; 17397 } 17398 }; 17399 const setTransition = duration => { 17400 const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl)); 17401 transformElements.forEach(el => { 17402 el.style.transitionDuration = `${duration}ms`; 17403 }); 17404 effectVirtualTransitionEnd({ 17405 swiper, 17406 duration, 17407 transformElements, 17408 allSlides: true 17409 }); 17410 }; 17411 effectInit({ 17412 effect: 'fade', 17413 swiper, 17414 on, 17415 setTranslate, 17416 setTransition, 17417 overwriteParams: () => ({ 17418 slidesPerView: 1, 17419 slidesPerGroup: 1, 17420 watchSlidesProgress: true, 17421 spaceBetween: 0, 17422 virtualTranslate: !swiper.params.cssMode 17423 }) 17424 }); 17425 } 17426 17427 function EffectCube({ 17428 swiper, 17429 extendParams, 17430 on 17431 }) { 17432 extendParams({ 17433 cubeEffect: { 17434 slideShadows: true, 17435 shadow: true, 17436 shadowOffset: 20, 17437 shadowScale: 0.94 17438 } 17439 }); 17440 const createSlideShadows = (slideEl, progress, isHorizontal) => { 17441 let shadowBefore = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-left') : slideEl.querySelector('.swiper-slide-shadow-top'); 17442 let shadowAfter = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-right') : slideEl.querySelector('.swiper-slide-shadow-bottom'); 17443 if (!shadowBefore) { 17444 shadowBefore = createElement('div', `swiper-slide-shadow-cube swiper-slide-shadow-${isHorizontal ? 'left' : 'top'}`.split(' ')); 17445 slideEl.append(shadowBefore); 17446 } 17447 if (!shadowAfter) { 17448 shadowAfter = createElement('div', `swiper-slide-shadow-cube swiper-slide-shadow-${isHorizontal ? 'right' : 'bottom'}`.split(' ')); 17449 slideEl.append(shadowAfter); 17450 } 17451 if (shadowBefore) shadowBefore.style.opacity = Math.max(-progress, 0); 17452 if (shadowAfter) shadowAfter.style.opacity = Math.max(progress, 0); 17453 }; 17454 const recreateShadows = () => { 17455 // create new ones 17456 const isHorizontal = swiper.isHorizontal(); 17457 swiper.slides.forEach(slideEl => { 17458 const progress = Math.max(Math.min(slideEl.progress, 1), -1); 17459 createSlideShadows(slideEl, progress, isHorizontal); 17460 }); 17461 }; 17462 const setTranslate = () => { 17463 const { 17464 el, 17465 wrapperEl, 17466 slides, 17467 width: swiperWidth, 17468 height: swiperHeight, 17469 rtlTranslate: rtl, 17470 size: swiperSize, 17471 browser 17472 } = swiper; 17473 const r = getRotateFix(swiper); 17474 const params = swiper.params.cubeEffect; 17475 const isHorizontal = swiper.isHorizontal(); 17476 const isVirtual = swiper.virtual && swiper.params.virtual.enabled; 17477 let wrapperRotate = 0; 17478 let cubeShadowEl; 17479 if (params.shadow) { 17480 if (isHorizontal) { 17481 cubeShadowEl = swiper.wrapperEl.querySelector('.swiper-cube-shadow'); 17482 if (!cubeShadowEl) { 17483 cubeShadowEl = createElement('div', 'swiper-cube-shadow'); 17484 swiper.wrapperEl.append(cubeShadowEl); 17485 } 17486 cubeShadowEl.style.height = `${swiperWidth}px`; 17487 } else { 17488 cubeShadowEl = el.querySelector('.swiper-cube-shadow'); 17489 if (!cubeShadowEl) { 17490 cubeShadowEl = createElement('div', 'swiper-cube-shadow'); 17491 el.append(cubeShadowEl); 17492 } 17493 } 17494 } 17495 for (let i = 0; i < slides.length; i += 1) { 17496 const slideEl = slides[i]; 17497 let slideIndex = i; 17498 if (isVirtual) { 17499 slideIndex = parseInt(slideEl.getAttribute('data-swiper-slide-index'), 10); 17500 } 17501 let slideAngle = slideIndex * 90; 17502 let round = Math.floor(slideAngle / 360); 17503 if (rtl) { 17504 slideAngle = -slideAngle; 17505 round = Math.floor(-slideAngle / 360); 17506 } 17507 const progress = Math.max(Math.min(slideEl.progress, 1), -1); 17508 let tx = 0; 17509 let ty = 0; 17510 let tz = 0; 17511 if (slideIndex % 4 === 0) { 17512 tx = -round * 4 * swiperSize; 17513 tz = 0; 17514 } else if ((slideIndex - 1) % 4 === 0) { 17515 tx = 0; 17516 tz = -round * 4 * swiperSize; 17517 } else if ((slideIndex - 2) % 4 === 0) { 17518 tx = swiperSize + round * 4 * swiperSize; 17519 tz = swiperSize; 17520 } else if ((slideIndex - 3) % 4 === 0) { 17521 tx = -swiperSize; 17522 tz = 3 * swiperSize + swiperSize * 4 * round; 17523 } 17524 if (rtl) { 17525 tx = -tx; 17526 } 17527 if (!isHorizontal) { 17528 ty = tx; 17529 tx = 0; 17530 } 17531 const transform = `rotateX(${r(isHorizontal ? 0 : -slideAngle)}deg) rotateY(${r(isHorizontal ? slideAngle : 0)}deg) translate3d(${tx}px, ${ty}px, ${tz}px)`; 17532 if (progress <= 1 && progress > -1) { 17533 wrapperRotate = slideIndex * 90 + progress * 90; 17534 if (rtl) wrapperRotate = -slideIndex * 90 - progress * 90; 17535 } 17536 slideEl.style.transform = transform; 17537 if (params.slideShadows) { 17538 createSlideShadows(slideEl, progress, isHorizontal); 17539 } 17540 } 17541 wrapperEl.style.transformOrigin = `50% 50% -${swiperSize / 2}px`; 17542 wrapperEl.style['-webkit-transform-origin'] = `50% 50% -${swiperSize / 2}px`; 17543 if (params.shadow) { 17544 if (isHorizontal) { 17545 cubeShadowEl.style.transform = `translate3d(0px, ${swiperWidth / 2 + params.shadowOffset}px, ${-swiperWidth / 2}px) rotateX(89.99deg) rotateZ(0deg) scale(${params.shadowScale})`; 17546 } else { 17547 const shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90; 17548 const multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2); 17549 const scale1 = params.shadowScale; 17550 const scale2 = params.shadowScale / multiplier; 17551 const offset = params.shadowOffset; 17552 cubeShadowEl.style.transform = `scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${swiperHeight / 2 + offset}px, ${-swiperHeight / 2 / scale2}px) rotateX(-89.99deg)`; 17553 } 17554 } 17555 const zFactor = (browser.isSafari || browser.isWebView) && browser.needPerspectiveFix ? -swiperSize / 2 : 0; 17556 wrapperEl.style.transform = `translate3d(0px,0,${zFactor}px) rotateX(${r(swiper.isHorizontal() ? 0 : wrapperRotate)}deg) rotateY(${r(swiper.isHorizontal() ? -wrapperRotate : 0)}deg)`; 17557 wrapperEl.style.setProperty('--swiper-cube-translate-z', `${zFactor}px`); 17558 }; 17559 const setTransition = duration => { 17560 const { 17561 el, 17562 slides 17563 } = swiper; 17564 slides.forEach(slideEl => { 17565 slideEl.style.transitionDuration = `${duration}ms`; 17566 slideEl.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(subEl => { 17567 subEl.style.transitionDuration = `${duration}ms`; 17568 }); 17569 }); 17570 if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) { 17571 const shadowEl = el.querySelector('.swiper-cube-shadow'); 17572 if (shadowEl) shadowEl.style.transitionDuration = `${duration}ms`; 17573 } 17574 }; 17575 effectInit({ 17576 effect: 'cube', 17577 swiper, 17578 on, 17579 setTranslate, 17580 setTransition, 17581 recreateShadows, 17582 getEffectParams: () => swiper.params.cubeEffect, 17583 perspective: () => true, 17584 overwriteParams: () => ({ 17585 slidesPerView: 1, 17586 slidesPerGroup: 1, 17587 watchSlidesProgress: true, 17588 resistanceRatio: 0, 17589 spaceBetween: 0, 17590 centeredSlides: false, 17591 virtualTranslate: true 17592 }) 17593 }); 17594 } 17595 17596 function createShadow(suffix, slideEl, side) { 17597 const shadowClass = `swiper-slide-shadow${side ? `-${side}` : ''}${suffix ? ` swiper-slide-shadow-${suffix}` : ''}`; 17598 const shadowContainer = getSlideTransformEl(slideEl); 17599 let shadowEl = shadowContainer.querySelector(`.${shadowClass.split(' ').join('.')}`); 17600 if (!shadowEl) { 17601 shadowEl = createElement('div', shadowClass.split(' ')); 17602 shadowContainer.append(shadowEl); 17603 } 17604 return shadowEl; 17605 } 17606 17607 function EffectFlip({ 17608 swiper, 17609 extendParams, 17610 on 17611 }) { 17612 extendParams({ 17613 flipEffect: { 17614 slideShadows: true, 17615 limitRotation: true 17616 } 17617 }); 17618 const createSlideShadows = (slideEl, progress) => { 17619 let shadowBefore = swiper.isHorizontal() ? slideEl.querySelector('.swiper-slide-shadow-left') : slideEl.querySelector('.swiper-slide-shadow-top'); 17620 let shadowAfter = swiper.isHorizontal() ? slideEl.querySelector('.swiper-slide-shadow-right') : slideEl.querySelector('.swiper-slide-shadow-bottom'); 17621 if (!shadowBefore) { 17622 shadowBefore = createShadow('flip', slideEl, swiper.isHorizontal() ? 'left' : 'top'); 17623 } 17624 if (!shadowAfter) { 17625 shadowAfter = createShadow('flip', slideEl, swiper.isHorizontal() ? 'right' : 'bottom'); 17626 } 17627 if (shadowBefore) shadowBefore.style.opacity = Math.max(-progress, 0); 17628 if (shadowAfter) shadowAfter.style.opacity = Math.max(progress, 0); 17629 }; 17630 const recreateShadows = () => { 17631 // Set shadows 17632 swiper.params.flipEffect; 17633 swiper.slides.forEach(slideEl => { 17634 let progress = slideEl.progress; 17635 if (swiper.params.flipEffect.limitRotation) { 17636 progress = Math.max(Math.min(slideEl.progress, 1), -1); 17637 } 17638 createSlideShadows(slideEl, progress); 17639 }); 17640 }; 17641 const setTranslate = () => { 17642 const { 17643 slides, 17644 rtlTranslate: rtl 17645 } = swiper; 17646 const params = swiper.params.flipEffect; 17647 const rotateFix = getRotateFix(swiper); 17648 for (let i = 0; i < slides.length; i += 1) { 17649 const slideEl = slides[i]; 17650 let progress = slideEl.progress; 17651 if (swiper.params.flipEffect.limitRotation) { 17652 progress = Math.max(Math.min(slideEl.progress, 1), -1); 17653 } 17654 const offset = slideEl.swiperSlideOffset; 17655 const rotate = -180 * progress; 17656 let rotateY = rotate; 17657 let rotateX = 0; 17658 let tx = swiper.params.cssMode ? -offset - swiper.translate : -offset; 17659 let ty = 0; 17660 if (!swiper.isHorizontal()) { 17661 ty = tx; 17662 tx = 0; 17663 rotateX = -rotateY; 17664 rotateY = 0; 17665 } else if (rtl) { 17666 rotateY = -rotateY; 17667 } 17668 slideEl.style.zIndex = -Math.abs(Math.round(progress)) + slides.length; 17669 if (params.slideShadows) { 17670 createSlideShadows(slideEl, progress); 17671 } 17672 const transform = `translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateFix(rotateX)}deg) rotateY(${rotateFix(rotateY)}deg)`; 17673 const targetEl = effectTarget(params, slideEl); 17674 targetEl.style.transform = transform; 17675 } 17676 }; 17677 const setTransition = duration => { 17678 const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl)); 17679 transformElements.forEach(el => { 17680 el.style.transitionDuration = `${duration}ms`; 17681 el.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(shadowEl => { 17682 shadowEl.style.transitionDuration = `${duration}ms`; 17683 }); 17684 }); 17685 effectVirtualTransitionEnd({ 17686 swiper, 17687 duration, 17688 transformElements 17689 }); 17690 }; 17691 effectInit({ 17692 effect: 'flip', 17693 swiper, 17694 on, 17695 setTranslate, 17696 setTransition, 17697 recreateShadows, 17698 getEffectParams: () => swiper.params.flipEffect, 17699 perspective: () => true, 17700 overwriteParams: () => ({ 17701 slidesPerView: 1, 17702 slidesPerGroup: 1, 17703 watchSlidesProgress: true, 17704 spaceBetween: 0, 17705 virtualTranslate: !swiper.params.cssMode 17706 }) 17707 }); 17708 } 17709 17710 function EffectCoverflow({ 17711 swiper, 17712 extendParams, 17713 on 17714 }) { 17715 extendParams({ 17716 coverflowEffect: { 17717 rotate: 50, 17718 stretch: 0, 17719 depth: 100, 17720 scale: 1, 17721 modifier: 1, 17722 slideShadows: true 17723 } 17724 }); 17725 const setTranslate = () => { 17726 const { 17727 width: swiperWidth, 17728 height: swiperHeight, 17729 slides, 17730 slidesSizesGrid 17731 } = swiper; 17732 const params = swiper.params.coverflowEffect; 17733 const isHorizontal = swiper.isHorizontal(); 17734 const transform = swiper.translate; 17735 const center = isHorizontal ? -transform + swiperWidth / 2 : -transform + swiperHeight / 2; 17736 const rotate = isHorizontal ? params.rotate : -params.rotate; 17737 const translate = params.depth; 17738 const r = getRotateFix(swiper); 17739 // Each slide offset from center 17740 for (let i = 0, length = slides.length; i < length; i += 1) { 17741 const slideEl = slides[i]; 17742 const slideSize = slidesSizesGrid[i]; 17743 const slideOffset = slideEl.swiperSlideOffset; 17744 const centerOffset = (center - slideOffset - slideSize / 2) / slideSize; 17745 const offsetMultiplier = typeof params.modifier === 'function' ? params.modifier(centerOffset) : centerOffset * params.modifier; 17746 let rotateY = isHorizontal ? rotate * offsetMultiplier : 0; 17747 let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier; 17748 // var rotateZ = 0 17749 let translateZ = -translate * Math.abs(offsetMultiplier); 17750 let stretch = params.stretch; 17751 // Allow percentage to make a relative stretch for responsive sliders 17752 if (typeof stretch === 'string' && stretch.indexOf('%') !== -1) { 17753 stretch = parseFloat(params.stretch) / 100 * slideSize; 17754 } 17755 let translateY = isHorizontal ? 0 : stretch * offsetMultiplier; 17756 let translateX = isHorizontal ? stretch * offsetMultiplier : 0; 17757 let scale = 1 - (1 - params.scale) * Math.abs(offsetMultiplier); 17758 17759 // Fix for ultra small values 17760 if (Math.abs(translateX) < 0.001) translateX = 0; 17761 if (Math.abs(translateY) < 0.001) translateY = 0; 17762 if (Math.abs(translateZ) < 0.001) translateZ = 0; 17763 if (Math.abs(rotateY) < 0.001) rotateY = 0; 17764 if (Math.abs(rotateX) < 0.001) rotateX = 0; 17765 if (Math.abs(scale) < 0.001) scale = 0; 17766 const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px) rotateX(${r(rotateX)}deg) rotateY(${r(rotateY)}deg) scale(${scale})`; 17767 const targetEl = effectTarget(params, slideEl); 17768 targetEl.style.transform = slideTransform; 17769 slideEl.style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1; 17770 if (params.slideShadows) { 17771 // Set shadows 17772 let shadowBeforeEl = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-left') : slideEl.querySelector('.swiper-slide-shadow-top'); 17773 let shadowAfterEl = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-right') : slideEl.querySelector('.swiper-slide-shadow-bottom'); 17774 if (!shadowBeforeEl) { 17775 shadowBeforeEl = createShadow('coverflow', slideEl, isHorizontal ? 'left' : 'top'); 17776 } 17777 if (!shadowAfterEl) { 17778 shadowAfterEl = createShadow('coverflow', slideEl, isHorizontal ? 'right' : 'bottom'); 17779 } 17780 if (shadowBeforeEl) shadowBeforeEl.style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0; 17781 if (shadowAfterEl) shadowAfterEl.style.opacity = -offsetMultiplier > 0 ? -offsetMultiplier : 0; 17782 } 17783 } 17784 }; 17785 const setTransition = duration => { 17786 const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl)); 17787 transformElements.forEach(el => { 17788 el.style.transitionDuration = `${duration}ms`; 17789 el.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(shadowEl => { 17790 shadowEl.style.transitionDuration = `${duration}ms`; 17791 }); 17792 }); 17793 }; 17794 effectInit({ 17795 effect: 'coverflow', 17796 swiper, 17797 on, 17798 setTranslate, 17799 setTransition, 17800 perspective: () => true, 17801 overwriteParams: () => ({ 17802 watchSlidesProgress: true 17803 }) 17804 }); 17805 } 17806 17807 function EffectCreative({ 17808 swiper, 17809 extendParams, 17810 on 17811 }) { 17812 extendParams({ 17813 creativeEffect: { 17814 limitProgress: 1, 17815 shadowPerProgress: false, 17816 progressMultiplier: 1, 17817 perspective: true, 17818 prev: { 17819 translate: [0, 0, 0], 17820 rotate: [0, 0, 0], 17821 opacity: 1, 17822 scale: 1 17823 }, 17824 next: { 17825 translate: [0, 0, 0], 17826 rotate: [0, 0, 0], 17827 opacity: 1, 17828 scale: 1 17829 } 17830 } 17831 }); 17832 const getTranslateValue = value => { 17833 if (typeof value === 'string') return value; 17834 return `${value}px`; 17835 }; 17836 const setTranslate = () => { 17837 const { 17838 slides, 17839 wrapperEl, 17840 slidesSizesGrid 17841 } = swiper; 17842 const params = swiper.params.creativeEffect; 17843 const { 17844 progressMultiplier: multiplier 17845 } = params; 17846 const isCenteredSlides = swiper.params.centeredSlides; 17847 const rotateFix = getRotateFix(swiper); 17848 if (isCenteredSlides) { 17849 const margin = slidesSizesGrid[0] / 2 - swiper.params.slidesOffsetBefore || 0; 17850 wrapperEl.style.transform = `translateX(calc(50% - ${margin}px))`; 17851 } 17852 for (let i = 0; i < slides.length; i += 1) { 17853 const slideEl = slides[i]; 17854 const slideProgress = slideEl.progress; 17855 const progress = Math.min(Math.max(slideEl.progress, -params.limitProgress), params.limitProgress); 17856 let originalProgress = progress; 17857 if (!isCenteredSlides) { 17858 originalProgress = Math.min(Math.max(slideEl.originalProgress, -params.limitProgress), params.limitProgress); 17859 } 17860 const offset = slideEl.swiperSlideOffset; 17861 const t = [swiper.params.cssMode ? -offset - swiper.translate : -offset, 0, 0]; 17862 const r = [0, 0, 0]; 17863 let custom = false; 17864 if (!swiper.isHorizontal()) { 17865 t[1] = t[0]; 17866 t[0] = 0; 17867 } 17868 let data = { 17869 translate: [0, 0, 0], 17870 rotate: [0, 0, 0], 17871 scale: 1, 17872 opacity: 1 17873 }; 17874 if (progress < 0) { 17875 data = params.next; 17876 custom = true; 17877 } else if (progress > 0) { 17878 data = params.prev; 17879 custom = true; 17880 } 17881 // set translate 17882 t.forEach((value, index) => { 17883 t[index] = `calc(${value}px + (${getTranslateValue(data.translate[index])} * ${Math.abs(progress * multiplier)}))`; 17884 }); 17885 // set rotates 17886 r.forEach((value, index) => { 17887 let val = data.rotate[index] * Math.abs(progress * multiplier); 17888 r[index] = val; 17889 }); 17890 slideEl.style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length; 17891 const translateString = t.join(', '); 17892 const rotateString = `rotateX(${rotateFix(r[0])}deg) rotateY(${rotateFix(r[1])}deg) rotateZ(${rotateFix(r[2])}deg)`; 17893 const scaleString = originalProgress < 0 ? `scale(${1 + (1 - data.scale) * originalProgress * multiplier})` : `scale(${1 - (1 - data.scale) * originalProgress * multiplier})`; 17894 const opacityString = originalProgress < 0 ? 1 + (1 - data.opacity) * originalProgress * multiplier : 1 - (1 - data.opacity) * originalProgress * multiplier; 17895 const transform = `translate3d(${translateString}) ${rotateString} ${scaleString}`; 17896 17897 // Set shadows 17898 if (custom && data.shadow || !custom) { 17899 let shadowEl = slideEl.querySelector('.swiper-slide-shadow'); 17900 if (!shadowEl && data.shadow) { 17901 shadowEl = createShadow('creative', slideEl); 17902 } 17903 if (shadowEl) { 17904 const shadowOpacity = params.shadowPerProgress ? progress * (1 / params.limitProgress) : progress; 17905 shadowEl.style.opacity = Math.min(Math.max(Math.abs(shadowOpacity), 0), 1); 17906 } 17907 } 17908 const targetEl = effectTarget(params, slideEl); 17909 targetEl.style.transform = transform; 17910 targetEl.style.opacity = opacityString; 17911 if (data.origin) { 17912 targetEl.style.transformOrigin = data.origin; 17913 } 17914 } 17915 }; 17916 const setTransition = duration => { 17917 const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl)); 17918 transformElements.forEach(el => { 17919 el.style.transitionDuration = `${duration}ms`; 17920 el.querySelectorAll('.swiper-slide-shadow').forEach(shadowEl => { 17921 shadowEl.style.transitionDuration = `${duration}ms`; 17922 }); 17923 }); 17924 effectVirtualTransitionEnd({ 17925 swiper, 17926 duration, 17927 transformElements, 17928 allSlides: true 17929 }); 17930 }; 17931 effectInit({ 17932 effect: 'creative', 17933 swiper, 17934 on, 17935 setTranslate, 17936 setTransition, 17937 perspective: () => swiper.params.creativeEffect.perspective, 17938 overwriteParams: () => ({ 17939 watchSlidesProgress: true, 17940 virtualTranslate: !swiper.params.cssMode 17941 }) 17942 }); 17943 } 17944 17945 function EffectCards({ 17946 swiper, 17947 extendParams, 17948 on 17949 }) { 17950 extendParams({ 17951 cardsEffect: { 17952 slideShadows: true, 17953 rotate: true, 17954 perSlideRotate: 2, 17955 perSlideOffset: 8 17956 } 17957 }); 17958 const setTranslate = () => { 17959 const { 17960 slides, 17961 activeIndex, 17962 rtlTranslate: rtl 17963 } = swiper; 17964 const params = swiper.params.cardsEffect; 17965 const { 17966 startTranslate, 17967 isTouched 17968 } = swiper.touchEventsData; 17969 const currentTranslate = rtl ? -swiper.translate : swiper.translate; 17970 for (let i = 0; i < slides.length; i += 1) { 17971 const slideEl = slides[i]; 17972 const slideProgress = slideEl.progress; 17973 const progress = Math.min(Math.max(slideProgress, -4), 4); 17974 let offset = slideEl.swiperSlideOffset; 17975 if (swiper.params.centeredSlides && !swiper.params.cssMode) { 17976 swiper.wrapperEl.style.transform = `translateX(${swiper.minTranslate()}px)`; 17977 } 17978 if (swiper.params.centeredSlides && swiper.params.cssMode) { 17979 offset -= slides[0].swiperSlideOffset; 17980 } 17981 let tX = swiper.params.cssMode ? -offset - swiper.translate : -offset; 17982 let tY = 0; 17983 const tZ = -100 * Math.abs(progress); 17984 let scale = 1; 17985 let rotate = -params.perSlideRotate * progress; 17986 let tXAdd = params.perSlideOffset - Math.abs(progress) * 0.75; 17987 const slideIndex = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.from + i : i; 17988 const isSwipeToNext = (slideIndex === activeIndex || slideIndex === activeIndex - 1) && progress > 0 && progress < 1 && (isTouched || swiper.params.cssMode) && currentTranslate < startTranslate; 17989 const isSwipeToPrev = (slideIndex === activeIndex || slideIndex === activeIndex + 1) && progress < 0 && progress > -1 && (isTouched || swiper.params.cssMode) && currentTranslate > startTranslate; 17990 if (isSwipeToNext || isSwipeToPrev) { 17991 const subProgress = (1 - Math.abs((Math.abs(progress) - 0.5) / 0.5)) ** 0.5; 17992 rotate += -28 * progress * subProgress; 17993 scale += -0.5 * subProgress; 17994 tXAdd += 96 * subProgress; 17995 tY = `${(params.rotate || swiper.isHorizontal() ? -25 : 0) * subProgress * Math.abs(progress)}%`; 17996 } 17997 if (progress < 0) { 17998 // next 17999 tX = `calc(${tX}px ${rtl ? '-' : '+'} (${tXAdd * Math.abs(progress)}%))`; 18000 } else if (progress > 0) { 18001 // prev 18002 tX = `calc(${tX}px ${rtl ? '-' : '+'} (-${tXAdd * Math.abs(progress)}%))`; 18003 } else { 18004 tX = `${tX}px`; 18005 } 18006 if (!swiper.isHorizontal()) { 18007 const prevY = tY; 18008 tY = tX; 18009 tX = prevY; 18010 } 18011 const scaleString = progress < 0 ? `${1 + (1 - scale) * progress}` : `${1 - (1 - scale) * progress}`; 18012 18013 /* eslint-disable */ 18014 const transform = ` 18015 translate3d(${tX}, ${tY}, ${tZ}px) 18016 rotateZ(${params.rotate ? rtl ? -rotate : rotate : 0}deg) 18017 scale(${scaleString}) 18018 `; 18019 /* eslint-enable */ 18020 18021 if (params.slideShadows) { 18022 // Set shadows 18023 let shadowEl = slideEl.querySelector('.swiper-slide-shadow'); 18024 if (!shadowEl) { 18025 shadowEl = createShadow('cards', slideEl); 18026 } 18027 if (shadowEl) shadowEl.style.opacity = Math.min(Math.max((Math.abs(progress) - 0.5) / 0.5, 0), 1); 18028 }
18029 slideEl.style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length; 18030 const targetEl = effectTarget(params, slideEl); 18031 targetEl.style.transform = transform; 18032 } 18033 }; 18034 const setTransition = duration => { 18035 const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl)); 18036 transformElements.forEach(el => { 18037 el.style.transitionDuration = `${duration}ms`; 18038 el.querySelectorAll('.swiper-slide-shadow').forEach(shadowEl => { 18039 shadowEl.style.transitionDuration = `${duration}ms`; 18040 }); 18041 }); 18042 effectVirtualTransitionEnd({ 18043 swiper, 18044 duration, 18045 transformElements 18046 }); 18047 }; 18048 effectInit({ 18049 effect: 'cards', 18050 swiper, 18051 on, 18052 setTranslate, 18053 setTransition, 18054 perspective: () => true, 18055 overwriteParams: () => ({ 18056 _loopSwapReset: false, 18057 watchSlidesProgress: true, 18058 loopAdditionalSlides: swiper.params.cardsEffect.rotate ? 3 : 2, 18059 centeredSlides: true, 18060 virtualTranslate: !swiper.params.cssMode 18061 }) 18062 }); 18063 } 18064 18065 /** 18066 * Swiper 12.0.3 18067 * Most modern mobile touch slider and framework with hardware accelerated transitions 18068 * https://swiperjs.com 18069 * 18070 * Copyright 2014-2025 Vladimir Kharlampidi 18071 * 18072 * Released under the MIT License 18073 * 18074 * Released on: October 21, 2025 18075 */ 18076 18077 18078 // Swiper Class 18079 const modules = [Virtual, Keyboard, Mousewheel, Navigation, Pagination, Scrollbar, Parallax, Zoom, Controller, A11y, History, HashNavigation, Autoplay, Thumb, freeMode, Grid, Manipulation, EffectFade, EffectCube, EffectFlip, EffectCoverflow, EffectCreative, EffectCards]; 18080 Swiper.use(modules); 18081 18082 return Swiper; 18083 18084})(); 18085 18086(function () { 18087 18088 const hasGalleryBodyClass = !!(document.body && ( 18089 document.body.classList.contains('Gallery') || 18090 document.body.classList.contains('Body--Gallery') || 18091 document.body.classList.contains('BodyGallery') 18092 )); 18093 18094 const galleries = document.querySelectorAll('.MediaGallery, .MediaGalleryFullWidth'); 18095 if (!galleries.length) { 18096 return; 18097 } 18098 const adIds = []; 18099 const adSlots = new Map(); 18100 18101 /* 18102 * Konstanten-Dokumentation 18103 * 18104 * Layout/Rendering: 18105 * - AD_VERTICAL_OFFSET_PERCENT: Vertikaler Offset zur Positionierung des Ads im Ad-Slide. 18106 * - DEFAULT_INITIAL_SLIDE_HEIGHT_PX: Fallback-Start-Minimalhoehe fuer Slider/Slides. 18107 * - DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX: Standard-Minimalhoehe fuer normale Galerien. 18108 * - DEFAULT_FULLWIDTH_SLIDER_CONTAINER_MIN_HEIGHT_PX: Standard-Minimalhoehe fuer Fullwidth-Galerien. 18109 * - AUTO_HEIGHT_TOLERANCE_PX: Toleranz, ab der eine AutoHeight-Neuberechnung noetig ist. 18110 * 18111 * Debug/Beobachtbarkeit: 18112 * - DEBUG_EVENT_LIMIT: Maximale Anzahl gespeicherter Debug-Events im Ringpuffer. 18113 * - EXTERNAL_SLOT_HISTORY_LIMIT: Maximale Anzahl Historieneintraege je externem Slot. 18114 * 18115 * Refresh-Regeln (intern/extern): 18116 * - MIN_REFRESH_INTERVAL_MS: Untergrenze fuer konfigurierbares Refresh-Intervall (>= 30s). 18117 * - DEFAULT_REFRESH_INTERVAL_MS: Default-Refresh-Intervall fuer zeitgesteuerte Pruefungen. 18118 * - DEFAULT_MIN_VIEWABLE_MS: Mindestdauer, die ein Slot sichtbar sein muss. 18119 * - DEFAULT_USER_IDLE_TIMEOUT_MS: Inaktivitaetsgrenze; danach wird Refresh pausiert. 18120 * - DEFAULT_ELIGIBILITY_CACHE_TTL_MS: Cache-Lebensdauer fuer Eligibility-Abfragen. 18121 * - SLOT_VIEWPORT_THRESHOLD: Sichtbarkeits-Schwelle fuer internen Gallery-Slot (0..1). 18122 * - EXTERNAL_SLOT_VIEWPORT_THRESHOLD: Sichtbarkeits-Schwelle fuer externe Slots (0..1). 18123 * - EXTERNAL_REFRESH_COOLDOWN_MS: Mindestabstand zwischen externen Refreshes (ausser adPos-Trigger). 18124 * 18125 * Externe Slots: 18126 * - EXTERNAL_REFRESH_SLOT_IDS: IDs der externen Werbeflaechen, die mitrefreshen sollen. 18127 * 18128 * Display/Targeting-Orchestrierung: 18129 * - REQUIRED_PAGE_TARGETING_KEYS: Muss-Targeting-Keys vor display(), sonst Warteschleife/Fallback. 18130 * - MAX_DISPLAY_WAIT_ATTEMPTS: Maximale Anzahl Warteversuche auf Targeting. 18131 * - DISPLAY_WAIT_INTERVAL_MS: Intervall zwischen den Warteversuchen. 18132 *
18133 * Debug-Helfer (window.*): 18134 * - __galleryDebug: Aktiviert Konsolen-Logs der Galerie-Debugmeldungen. 18135 * - __galleryDebugVisualRefresh: Visuelle Marker an externen Slots (Request/Render). 18136 * - __galleryExternalRefreshForceNewCorrelator: Erzwingt externen Refresh mit changeCorrelator=true. 18137 * - __galleryExternalSlotViewportThreshold: Optionaler Viewport-Threshold (0..1) fuer externe Slots. 18138 * - __galleryDebugPing(): Kurzer Lebenszeichen-Check (Galleries/Slots/pubadsReady). 18139 * - __galleryDebugEvents(): Liefert den aktuellen Event-Puffer als Array. 18140 * - __galleryDebugDumpEvents(): Schreibt kompletten Event-Puffer als Snapshot ins Log. 18141 * - __galleryDebugDumpAdFlow(): Loggt gefilterten Ad-Flow ohne Thumb/Virtual-Tracking-Rauschen. 18142 * - __galleryDebugDump(): Snapshot zu adIds, Slot-States und registrierten GPT-Slots. 18143 * - __galleryDebugRefresh(): Trigger fuer manuellen Refresh der internen Gallery-Slots. 18144 * - __galleryDebugTargetingDump(): Dump der aktuellen Slot-Targeting-Informationen. 18145 * - __galleryDebugExternalStats(): Snapshot inkl. Historie fuer externe Slots. 18146 */ 18147 18148 const AD_VERTICAL_OFFSET_PERCENT = 0; 18149 const DEFAULT_INITIAL_SLIDE_HEIGHT_PX = 0; 18150 const DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX = 540; 18151 const DEFAULT_FULLWIDTH_SLIDER_CONTAINER_MIN_HEIGHT_PX = 940; 18152 const AUTO_HEIGHT_TOLERANCE_PX = 6; 18153 const slotTargetingState = new WeakMap(); 18154 const debugEventBuffer = []; 18155 const DEBUG_EVENT_LIMIT = 250; 18156 const REQUIRED_PAGE_TARGETING_KEYS = ['kw_page_url']; 18157 const MAX_DISPLAY_WAIT_ATTEMPTS = 20; 18158 const DISPLAY_WAIT_INTERVAL_MS = 120; 18159 const MIN_REFRESH_INTERVAL_MS = 30000; 18160 const DEFAULT_REFRESH_INTERVAL_MS = 30000; 18161 const DEFAULT_MIN_VIEWABLE_MS = 3000; 18162 const DEFAULT_USER_IDLE_TIMEOUT_MS = 20000; 18163 const DEFAULT_ELIGIBILITY_CACHE_TTL_MS = 120000; 18164 const SLOT_VIEWPORT_THRESHOLD = 0.5; 18165 const EXTERNAL_SLOT_VIEWPORT_THRESHOLD = 0.2; 18166 const EXTERNAL_REFRESH_SLOT_IDS = [ 18167 'renderSlot_Billboard', 18168 'renderSlot_Skyscraper-links', 18169 'renderSlot_Skyscraper-rechts', 18170 ]; 18171 const EXTERNAL_REFRESH_COOLDOWN_MS = 1000;
18172 const EXTERNAL_SLOT_HISTORY_LIMIT = 20; 18173 const ACTIVE_AD_FALLBACK_RETRY_MS = 450; 18174 const AD_SLIDE_REENTRY_GUARD_MS = 900; 18175 let lastExternalRefreshTs = Date.now(); 18176 let externalRefreshCount = 0; 18177 18178 function createExternalSlotStatsBucket() { 18179 return { 18180 refreshCallTriggered: 0, 18181 slotRequested: 0, 18182 slotResponseReceived: 0, 18183 slotRenderEnded: 0, 18184 lastRenderLineItemId: null, 18185 lastRenderCreativeId: null, 18186 lastRenderTs: null, 18187 history: [], 18188 }; 18189 } 18190 18191 const externalSlotDebugStats = { 18192 totals: { 18193 refreshCallTriggered: 0, 18194 slotRequested: 0, 18195 slotResponseReceived: 0, 18196 slotRenderEnded: 0, 18197 }, 18198 bySlot: EXTERNAL_REFRESH_SLOT_IDS.reduce(function (acc, slotId) { 18199 acc[slotId] = createExternalSlotStatsBucket(); 18200 return acc; 18201 }, {}), 18202 }; 18203 18204 function ensureExternalSlotStats(slotId) { 18205 if (!externalSlotDebugStats.bySlot[slotId]) { 18206 externalSlotDebugStats.bySlot[slotId] = createExternalSlotStatsBucket(); 18207 } 18208 return externalSlotDebugStats.bySlot[slotId]; 18209 } 18210 18211 function pushExternalSlotHistory(slotId, eventType, payload) { 18212 if (!slotId || !eventType) { 18213 return; 18214 } 18215 18216 const slotStats = ensureExternalSlotStats(slotId); 18217 slotStats.history.push(Object.assign({ 18218 ts: new Date().toISOString(), 18219 event: eventType, 18220 }, payload || {})); 18221 18222 if (slotStats.history.length > EXTERNAL_SLOT_HISTORY_LIMIT) { 18223 slotStats.history.shift(); 18224 } 18225 } 18226 18227 function flashExternalSlotDebugMarker(slotId, phase) { 18228 if (typeof window === 'undefined' || !window.__galleryDebugVisualRefresh) { 18229 return; 18230 } 18231 18232 const slotElement = document.getElementById(slotId); 18233 if (!slotElement) { 18234 return; 18235 } 18236 18237 const isRenderPhase = phase === 'render'; 18238 const borderColor = isRenderPhase ? '#2e7d32' : '#c62828'; 18239 const shadowColor = isRenderPhase ? 'rgba(46, 125, 50, 0.82)' : 'rgba(198, 40, 40, 0.72)'; 18240 const holdMs = isRenderPhase ? 700 : 260; 18241 const transitionMs = isRenderPhase ? 180 : 120; 18242 18243 slotElement.__galleryDebugMarkerToken = (slotElement.__galleryDebugMarkerToken || 0) + 1; 18244 const markerToken = slotElement.__galleryDebugMarkerToken; 18245 18246 slotElement.style.transition = 'box-shadow ' + transitionMs + 'ms ease-out, outline-color ' + transitionMs + 'ms ease-out'; 18247 slotElement.style.outline = '3px solid ' + borderColor; 18248 slotElement.style.boxShadow = '0 0 0 4px ' + shadowColor; 18249 18250 window.setTimeout(function () { 18251 if (!slotElement || !slotElement.style) { 18252 return; 18253 } 18254 if (slotElement.__galleryDebugMarkerToken !== markerToken) { 18255 return; 18256 } 18257 slotElement.style.outline = ''; 18258 slotElement.style.boxShadow = ''; 18259 }, holdMs); 18260 } 18261 18262 function incrementExternalSlotStat(slotId, key) { 18263 if (!slotId || !key) { 18264 return; 18265 } 18266 18267 if (externalSlotDebugStats.totals[key] === undefined) { 18268 externalSlotDebugStats.totals[key] = 0; 18269 } 18270 externalSlotDebugStats.totals[key] += 1; 18271 18272 const slotStats = ensureExternalSlotStats(slotId); 18273 18274 if (slotStats[key] === undefined) { 18275 slotStats[key] = 0; 18276 } 18277 slotStats[key] += 1; 18278 } 18279 18280 function parsePositiveInt(value, fallback) { 18281 const parsed = parseInt(value, 10); 18282 return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback; 18283 } 18284 18285 function getRefreshRuntimeConfig() { 18286 const cfg = (typeof window !== 'undefined' && window.__galleryAdRefreshConfig && typeof window.__galleryAdRefreshConfig === 'object') 18287 ? window.__galleryAdRefreshConfig 18288 : {}; 18289 18290 const refreshIntervalMs = Math.max( 18291 MIN_REFRESH_INTERVAL_MS, 18292 parsePositiveInt(cfg.refreshIntervalMs, DEFAULT_REFRESH_INTERVAL_MS) 18293 ); 18294 18295 return { 18296 refreshIntervalMs: refreshIntervalMs, 18297 minViewableMs: parsePositiveInt(cfg.minViewableMs, DEFAULT_MIN_VIEWABLE_MS), 18298 userIdleTimeoutMs: parsePositiveInt(cfg.userIdleTimeoutMs, DEFAULT_USER_IDLE_TIMEOUT_MS), 18299 eligibilityCacheTtlMs: parsePositiveInt(cfg.eligibilityCacheTtlMs, DEFAULT_ELIGIBILITY_CACHE_TTL_MS), 18300 refreshCheckIntervalMs: parsePositiveInt(cfg.refreshCheckIntervalMs, 1000),
18301 strictDifferentLineItem: cfg.strictDifferentLineItem !== false, 18302 }; 18303 } 18304 18305 const refreshRuntimeConfig = getRefreshRuntimeConfig(); 18306 let lastUserActivityTs = Date.now(); 18307 let hasExplicitUserInteraction = false; 18308 18309 function markUserActivity() { 18310 lastUserActivityTs = Date.now(); 18311 } 18312 18313 function isUserRecentlyActive() { 18314 return (Date.now() - lastUserActivityTs) <= refreshRuntimeConfig.userIdleTimeoutMs; 18315 } 18316 18317 function isDocumentVisible() { 18318 if (typeof document === 'undefined') { 18319 return true; 18320 } 18321 if (typeof document.visibilityState === 'string') { 18322 return document.visibilityState === 'visible'; 18323 } 18324 return true; 18325 } 18326 18327 if (typeof window !== 'undefined') { 18328 ['pointerdown', 'pointermove', 'keydown', 'scroll', 'touchstart', 'wheel', 'focus'].forEach(function (eventName) { 18329 window.addEventListener(eventName, markUserActivity, { passive: true }); 18330 }); 18331 ['pointerdown', 'keydown', 'touchstart', 'wheel', 'mousedown', 'click'].forEach(function (eventName) { 18332 window.addEventListener(eventName, function () { 18333 hasExplicitUserInteraction = true; 18334 }, { passive: true }); 18335 }); 18336 document.addEventListener('visibilitychange', function () { 18337 if (isDocumentVisible()) { 18338 markUserActivity(); 18339 } 18340 }); 18341 } 18342 18343 function debugAdLog(message, meta) { 18344 debugEventBuffer.push({ 18345 ts: new Date().toISOString(), 18346 message: message, 18347 meta: meta || {}, 18348 }); 18349 if (debugEventBuffer.length > DEBUG_EVENT_LIMIT) { 18350 debugEventBuffer.shift(); 18351 } 18352 18353 const isGalleryDebugEnabled = typeof window !== 'undefined' && !!window.__galleryDebug; 18354 if (!isGalleryDebugEnabled || !window.console) { 18355 return; 18356 } 18357 18358 if (typeof window.console.log === 'function') { 18359 window.console.log('[GalleryAds] ' + message, meta || ''); 18360 return; 18361 } 18362 18363 if (typeof window.console.info === 'function') { 18364 window.console.info('[GalleryAds] ' + message, meta || ''); 18365 } 18366 } 18367 18368 function applySlotConfigTargeting(slotObj, targeting) { 18369 if (!slotObj || !targeting || typeof targeting !== 'object') { 18370 return; 18371 } 18372 18373 const previousTargeting = slotTargetingState.get(slotObj) || {}; 18374 const mergedTargeting = Object.assign({}, previousTargeting, targeting); 18375 slotTargetingState.set(slotObj, mergedTargeting); 18376 18377 if (typeof slotObj.setConfig === 'function') { 18378 slotObj.setConfig({ targeting: mergedTargeting }); 18379 return; 18380 } 18381 18382 if (typeof slotObj.setTargeting !== 'function') { 18383 return; 18384 } 18385 18386 Object.keys(targeting).forEach(function (key) { 18387 slotObj.setTargeting(key, targeting[key]); 18388 }); 18389 } 18390 18391 function getStoredSlotTargetingSnapshot(slotObj) { 18392 const stored = slotTargetingState.get(slotObj) || {}; 18393 return Object.assign({}, stored); 18394 } 18395 18396 function normalizeTargetingSnapshot(rawTargeting) { 18397 if (!rawTargeting || typeof rawTargeting !== 'object') { 18398 return {}; 18399 } 18400 18401 function collectPrimitiveTargetingValues(inputValue, collector) { 18402 if (inputValue === null || typeof inputValue === 'undefined') { 18403 return; 18404 } 18405 18406 if (Array.isArray(inputValue)) { 18407 inputValue.forEach(function (entry) { 18408 collectPrimitiveTargetingValues(entry, collector); 18409 }); 18410 return; 18411 } 18412 18413 if (typeof inputValue === 'object') { 18414 // GPT kann je nach API-Variante Objektstrukturen liefern (z. B. mit `value`). 18415 if (Object.prototype.hasOwnProperty.call(inputValue, 'value')) { 18416 collectPrimitiveTargetingValues(inputValue.value, collector); 18417 return; 18418 } 18419 return; 18420 } 18421 18422 if (typeof inputValue === 'function') { 18423 return; 18424 } 18425 18426 const normalized = String(inputValue); 18427 if (normalized.length > 0) { 18428 collector[normalized] = true; 18429 } 18430 } 18431 18432 function setNormalizedValue(target, key, value) { 18433 if (!key || typeof key !== 'string') { 18434 return; 18435 } 18436 18437 const valuesCollector = {}; 18438 collectPrimitiveTargetingValues(value, valuesCollector); 18439 const normalizedValues = Object.keys(valuesCollector); 18440 if (normalizedValues.length === 0) { 18441 return; 18442 } 18443 18444 target[key] = normalizedValues; 18445 } 18446 18447 const normalized = {}; 18448 18449 // GPT `getConfig('targeting')` kann als `{ targeting: {...} }` zurückkommen. 18450 if ( 18451 Object.prototype.hasOwnProperty.call(rawTargeting, 'targeting') && 18452 rawTargeting.targeting && 18453 typeof rawTargeting.targeting === 'object' && 18454 !Array.isArray(rawTargeting.targeting) 18455 ) { 18456 Object.keys(rawTargeting.targeting).forEach(function (nestedKey) { 18457 setNormalizedValue(normalized, nestedKey, rawTargeting.targeting[nestedKey]); 18458 }); 18459 return normalized; 18460 } 18461
18462 Object.keys(rawTargeting).forEach(function (key) { 18463 setNormalizedValue(normalized, key, rawTargeting[key]); 18464 }); 18465 18466 return normalized; 18467 } 18468 18469 function getSlotTargetingSnapshot(slotObj) { 18470 if (!slotObj) { 18471 return {}; 18472 } 18473 18474 if (typeof slotObj.getConfig === 'function') { 18475 return normalizeTargetingSnapshot(slotObj.getConfig('targeting')); 18476 } 18477 18478 if (typeof slotObj.getTargetingKeys !== 'function' || typeof slotObj.getTargeting !== 'function') { 18479 return {}; 18480 } 18481 18482 const targeting = {}; 18483 slotObj.getTargetingKeys().forEach(function (key) { 18484 targeting[key] = slotObj.getTargeting(key); 18485 }); 18486 18487 return normalizeTargetingSnapshot(targeting); 18488 } 18489 18490 function getPageTargetingSnapshot() { 18491 if (typeof googletag === 'undefined') { 18492 return {}; 18493 } 18494 18495 if (typeof googletag.getConfig === 'function') { 18496 return normalizeTargetingSnapshot(googletag.getConfig('targeting')); 18497 } 18498 18499 if (!googletag.pubads || typeof googletag.pubads !== 'function') { 18500 return {}; 18501 } 18502 18503 const pubads = googletag.pubads(); 18504 if (!pubads || typeof pubads.getTargetingKeys !== 'function' || typeof pubads.getTargeting !== 'function') { 18505 return {}; 18506 } 18507 18508 const pageTargeting = {}; 18509 pubads.getTargetingKeys().forEach(function (key) { 18510 pageTargeting[key] = pubads.getTargeting(key); 18511 }); 18512 18513 return normalizeTargetingSnapshot(pageTargeting); 18514 } 18515 18516 function getGalleryAdDatasetSnapshot(gallery) { 18517 if (!gallery || !gallery.dataset) { 18518 return {}; 18519 } 18520 18521 const adGamIdRaw = typeof gallery.dataset.ad_gam_id === 'string' ? gallery.dataset.ad_gam_id : ''; 18522 return { 18523 galleryId: gallery.id || null, 18524 adPosRaw: typeof gallery.dataset.adpos === 'string' ? gallery.dataset.adpos : null, 18525 adTargetingRaw: typeof gallery.dataset.ad_targeting === 'string' ? gallery.dataset.ad_targeting : null, 18526 hasAdGamId: adGamIdRaw.length > 0, 18527 adGamIdPreview: adGamIdRaw.slice(0, 180), 18528 }; 18529 } 18530 18531 function mirrorPageTargetingToSlot(slotObj, keys) { 18532 if (!slotObj) { 18533 return; 18534 } 18535 18536 const pageTargeting = getPageTargetingSnapshot(); 18537 const targetKeys = Array.isArray(keys) && keys.length > 0 ? keys : Object.keys(pageTargeting); 18538 const mirrored = {}; 18539 18540 targetKeys.forEach(function (key) { 18541 const values = pageTargeting[key]; 18542 if (!Array.isArray(values) || values.length === 0) { 18543 return; 18544 } 18545 18546 const normalized = values.filter(function (v) { 18547 return v !== null && typeof v !== 'undefined' && String(v).length > 0; 18548 }).map(function (v) { 18549 return String(v); 18550 }); 18551 18552 if (normalized.length === 1) { 18553 mirrored[key] = normalized[0]; 18554 return; 18555 } 18556 18557 if (normalized.length > 1) { 18558 mirrored[key] = normalized; 18559 } 18560 }); 18561 18562 const mirroredKeys = Object.keys(mirrored); 18563 if (mirroredKeys.length === 0) { 18564 debugAdLog('Kein Page-Targeting zum Spiegeln vorhanden', { 18565 requestedKeys: targetKeys, 18566 availablePageKeys: Object.keys(pageTargeting), 18567 }); 18568 return; 18569 } 18570 18571 applySlotConfigTargeting(slotObj, mirrored); 18572 debugAdLog('Page-Targeting auf Slot gespiegelt', { 18573 keys: mirroredKeys, 18574 values: mirrored, 18575 }); 18576 } 18577 18578 function hasAllRequiredPageTargeting(keys) { 18579 if (!Array.isArray(keys) || keys.length === 0) { 18580 return true; 18581 } 18582 18583 const pageTargeting = getPageTargetingSnapshot(); 18584 return keys.every(function (key) { 18585 const values = pageTargeting[key]; 18586 return Array.isArray(values) && values.length > 0; 18587 }); 18588 } 18589 18590 if (typeof window !== 'undefined') { 18591 window.__galleryDebugPing = function () { 18592 debugAdLog('Debug-Ping', { 18593 galleries: galleries.length, 18594 adIds: adIds.length, 18595 slots: adSlots.size, 18596 pubadsReady: !!googletag.pubadsReady, 18597 }); 18598 }; 18599 18600 window.__galleryDebugEvents = function () { 18601 return debugEventBuffer.slice(); 18602 }; 18603 18604 window.__galleryDebugDumpEvents = function () { 18605 debugAdLog('Debug-Eventbuffer Snapshot', { 18606 count: debugEventBuffer.length, 18607 events: debugEventBuffer.slice(), 18608 }); 18609 }; 18610 18611 window.__galleryDebugDumpAdFlow = function () { 18612 const adFlowEvents = debugEventBuffer.filter(function (entry) { 18613 return entry.message.indexOf('ThumbTrace') === -1 && entry.message.indexOf('Virtual-Tracking') === -1; 18614 }); 18615 18616 debugAdLog('Debug-Ad-Flow Snapshot', { 18617 count: adFlowEvents.length, 18618 events: adFlowEvents, 18619 }); 18620 18621 return adFlowEvents; 18622 }; 18623 } 18624 18625 function normalizeTargetingValueForSlot(value) { 18626 if (value === null || typeof value === 'undefined') { 18627 return null; 18628 } 18629 18630 if (Array.isArray(value)) { 18631 const normalizedList = value.filter(function (v) { 18632 const valueType = typeof v; 18633 return v !== null && valueType !== 'undefined' && valueType !== 'object' && valueType !== 'function' && String(v).length > 0;
18634 }).map(function (v) { 18635 return String(v); 18636 }); 18637 18638 return normalizedList.length > 0 ? normalizedList : null; 18639 } 18640 18641 const valueType = typeof value; 18642 if (valueType === 'object' || valueType === 'function') { 18643 return null; 18644 } 18645 18646 const normalizedValue = String(value); 18647 return normalizedValue.length > 0 ? normalizedValue : null; 18648 } 18649 18650 function applySlotTargeting(slotObj, adData) { 18651 if (!slotObj || (typeof slotObj.setConfig !== 'function' && typeof slotObj.setTargeting !== 'function') || !adData) { 18652 return; 18653 } 18654 18655 const targetingSources = [ 18656 { name: 'targeting', data: adData.targeting }, 18657 { name: 'gam_config.targeting', data: adData.gam_config && adData.gam_config.targeting }, 18658 ]; 18659 18660 const mergedTargeting = {}; 18661 const sourceInfo = []; 18662 const droppedEntries = []; 18663 18664 targetingSources.forEach(function (source) { 18665 const targeting = source.data; 18666 if (!targeting || typeof targeting !== 'object') { 18667 sourceInfo.push({ source: source.name, present: false, keys: [] }); 18668 return; 18669 } 18670 18671 const sourceKeys = Object.keys(targeting); 18672 sourceInfo.push({ source: source.name, present: sourceKeys.length > 0, keys: sourceKeys }); 18673 18674 sourceKeys.forEach(function (key) { 18675 const value = targeting[key]; 18676 const normalizedValue = normalizeTargetingValueForSlot(value); 18677 if (normalizedValue === null) { 18678 droppedEntries.push({ 18679 key: key, 18680 source: source.name, 18681 type: Array.isArray(value) ? 'array' : typeof value, 18682 }); 18683 return; 18684 } 18685 18686 mergedTargeting[key] = normalizedValue; 18687 }); 18688 }); 18689 18690 const appliedKeys = Object.keys(mergedTargeting); 18691 if (appliedKeys.length > 0) { 18692 applySlotConfigTargeting(slotObj, mergedTargeting); 18693 } 18694 18695 debugAdLog('Slot-Targeting ausgewertet', { 18696 path: adData.path || null, 18697 sourceInfo: sourceInfo, 18698 appliedKeys: appliedKeys, 18699 droppedEntries: droppedEntries, 18700 }); 18701 } 18702 18703 function applyGalleryDatasetTargeting(slotObj, gallery) { 18704 if (!slotObj || (typeof slotObj.setConfig !== 'function' && typeof slotObj.setTargeting !== 'function') || !gallery || !gallery.dataset) { 18705 return; 18706 } 18707 18708 const adTargetingValue = typeof gallery.dataset.ad_targeting === 'string' 18709 ? gallery.dataset.ad_targeting.trim() 18710 : ''; 18711 18712 if (!adTargetingValue) { 18713 return; 18714 } 18715 18716 applySlotConfigTargeting(slotObj, { kw: adTargetingValue }); 18717 18718 debugAdLog('Gallery data-ad_targeting gesetzt', { 18719 galleryId: gallery.id || null, 18720 key: 'kw', 18721 value: adTargetingValue, 18722 }); 18723 } 18724 18725 googletag.cmd.push(function () { 18726 18727 function getReferenceSlideHeight(gallery, targetAdSlide) { 18728 if (!gallery) { 18729 return 0; 18730 } 18731 18732 if (gallery.__lastImageSlideHeight && gallery.__lastImageSlideHeight > 0) { 18733 return gallery.__lastImageSlideHeight; 18734 } 18735 18736 const sliderContainer = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer'); 18737 if (!sliderContainer) { 18738 return 0; 18739 } 18740 18741 const normalSlides = Array.from(sliderContainer.children).filter(function (slide) { 18742 return !slide.classList.contains('ad-slide'); 18743 }); 18744 18745 if (!normalSlides.length) { 18746 return targetAdSlide ? targetAdSlide.clientHeight : 0; 18747 } 18748 18749 const activeNormalSlide = normalSlides.find(function (slide) { 18750 return slide.classList.contains('swiper-slide-active'); 18751 }); 18752 18753 if (activeNormalSlide && activeNormalSlide.clientHeight > 0) { 18754 return activeNormalSlide.clientHeight; 18755 } 18756 18757 const maxHeight = normalSlides.reduce(function (acc, slide) { 18758 return Math.max(acc, slide.clientHeight || 0); 18759 }, 0); 18760 18761 return maxHeight; 18762 } 18763 18764 function rememberCurrentImageSlideHeight(gallery, swiperInstance) { 18765 if (!gallery || !swiperInstance || !swiperInstance.slides || typeof swiperInstance.activeIndex !== 'number') { 18766 return; 18767 } 18768 18769 const activeSlide = swiperInstance.slides[swiperInstance.activeIndex]; 18770 if (!activeSlide || activeSlide.classList.contains('ad-slide')) { 18771 return; 18772 } 18773 18774 const measuredHeight = Math.max( 18775 activeSlide.offsetHeight || 0, 18776 activeSlide.scrollHeight || 0, 18777 Math.ceil(activeSlide.getBoundingClientRect ? activeSlide.getBoundingClientRect().height : 0) 18778 ); 18779 18780 if (measuredHeight > 0) { 18781 gallery.__lastImageSlideHeight = measuredHeight; 18782 } 18783 } 18784 18785 function centerAdIframes(adContainer, targetAdSlide) { 18786 if (!adContainer) { 18787 return; 18788 } 18789 18790 let gallery = adContainer.closest('.MediaGallery, .MediaGalleryFullWidth'); 18791 if (targetAdSlide) { 18792 gallery = targetAdSlide.closest('.MediaGallery, .MediaGalleryFullWidth'); 18793 } 18794 18795 if (targetAdSlide) { 18796 // Kein Fremdwert von Bild-Slides erzwingen: Ad-Slide soll sich am Ad-Inhalt orientieren. 18797 targetAdSlide.style.minHeight = '0'; 18798 targetAdSlide.style.height = 'auto'; 18799 18800 targetAdSlide.style.display = 'flex'; 18801 targetAdSlide.style.justifyContent = 'center'; 18802 targetAdSlide.style.alignItems = 'center'; 18803 } 18804 18805 adContainer.style.width = '100%'; 18806 adContainer.style.height = '100%'; 18807 adContainer.style.display = 'flex'; 18808 adContainer.style.justifyContent = 'center'; 18809 adContainer.style.alignItems = 'center'; 18810 adContainer.style.textAlign = 'center'; 18811 adContainer.style.minHeight = '0'; 18812 adContainer.style.transform = 'translateY(' + AD_VERTICAL_OFFSET_PERCENT + '%)'; 18813 18814 adContainer.querySelectorAll('iframe').forEach(function (iframe) { 18815 iframe.style.display = 'block'; 18816 iframe.style.marginLeft = 'auto'; 18817 iframe.style.marginRight = 'auto'; 18818 }); 18819 18820 if (targetAdSlide) { 18821 const firstIframe = adContainer.querySelector('iframe'); 18822 const measuredHeight = firstIframe ? firstIframe.offsetHeight : adContainer.scrollHeight; 18823 const referenceHeight = getReferenceSlideHeight(gallery, targetAdSlide); 18824 const minHeight = Math.max(measuredHeight || 0, referenceHeight || 0
18824); 18825 if (minHeight > 0) { 18826 // Ensure vertical centering has enough available slide height. 18827 targetAdSlide.style.minHeight = minHeight + 'px'; 18828 } 18829 } 18830 18831 if (!adContainer.__galleryAdObserver) { 18832 const observer = new MutationObserver(function () { 18833 adContainer.querySelectorAll('iframe').forEach(function (iframe) { 18834 iframe.style.display = 'block'; 18835 iframe.style.marginLeft = 'auto'; 18836 iframe.style.marginRight = 'auto'; 18837 }); 18838 }); 18839 18840 observer.observe(adContainer, { childList: true, subtree: true }); 18841 adContainer.__galleryAdObserver = observer; 18842 } 18843 } 18844 18845 18846 function removeAllAdMarkup(gallery) { 18847 const adElements = gallery.querySelectorAll('.ad-thumb, .ad-slide'); 18848 adElements.forEach(function (el) { 18849 el.remove(); 18850 }); 18851 18852 debugAdLog('Ad-Markup entfernt', { 18853 galleryId: gallery.id || null, 18854 removedNodes: adElements.length, 18855 }); 18856 } 18857 18858 function injectAdMarkup(slotInfo) { 18859 let adsAdded = 0; 18860 let insertedSlides = 0; 18861 const originalSlides = Array.from(slotInfo.mainWrapper.children).filter(function (slide) { 18862 return !slide.classList.contains('ad-slide'); 18863 }); 18864 18865 originalSlides.forEach(function (slide, index) { 18866 if ((index + 1) % slotInfo.adPos === 0) { 18867 const adSlide = document.createElement('div'); 18868 adSlide.className = 'swiper-slide ad-slide MediaGallery_sliderImage'; 18869 adSlide.style.height = 'auto'; 18870 const insertAt = index + adsAdded + 1; 18871 slotInfo.mainWrapper.insertBefore(adSlide, slotInfo.mainWrapper.children[insertAt] || null); 18872 adsAdded++; 18873 insertedSlides++; 18874 } 18875 }); 18876 18877 debugAdLog('Ad-Markup eingefuegt', { 18878 adId: slotInfo.adId, 18879 galleryId: slotInfo.gallery.id || null, 18880 insertedSlides: insertedSlides, 18881 insertedThumbs: 0, 18882 }); 18883 } 18884 18885 function getImageIndexFromMainIndex(mainSlides, mainIndex) { 18886 let imageIndex = -1; 18887 for (let i = 0; i <= mainIndex; i++) { 18888 if (mainSlides[i] && !mainSlides[i].classList.contains('ad-slide')) { 18889 imageIndex++; 18890 } 18891 } 18892 return imageIndex; 18893 } 18894 18895 function getMainIndexFromImageIndex(mainSlides, imageIndex) { 18896 let currentImageIndex = -1; 18897 for (let i = 0; i < mainSlides.length; i++) { 18898 if (!mainSlides[i].classList.contains('ad-slide')) { 18899 currentImageIndex++; 18900 if (currentImageIndex === imageIndex) { 18901 return i; 18902 } 18903 } 18904 } 18905 return -1; 18906 } 18907 18908 function getThumbActiveClassIndex(gallery) { 18909 if (!gallery || !gallery.tSwiper || !gallery.tSwiper.slides) { 18910 return -1; 18911 } 18912 18913 for (let i = 0; i < gallery.tSwiper.slides.length; i++) { 18914 if (gallery.tSwiper.slides[i].classList.contains('swiper-slide-thumb-active')) { 18915 return i; 18916 } 18917 } 18918 18919 return -1; 18920 } 18921 18922 function traceThumbSync(gallery, stage, extra) { 18923 if (typeof window === 'undefined' || !window.__galleryDebug) { 18924 return; 18925 } 18926 18927 const mainSwiper = gallery && gallery.mSwiper; 18928 const mainActiveIndex = mainSwiper && typeof mainSwiper.activeIndex === 'number' ? mainSwiper.activeIndex : -1; 18929 const mainSlides = mainSwiper && mainSwiper.slides ? mainSwiper.slides : null; 18930 const imageIndex = mainSlides && mainActiveIndex >= 0 ? getImageIndexFromMainIndex(mainSlides, mainActiveIndex) : -1; 18931 const activeSlide = mainSlides && mainActiveIndex >= 0 ? mainSlides[mainActiveIndex] : null; 18932 18933 debugAdLog('ThumbTrace ' + stage, Object.assign({ 18934 galleryId: gallery && gallery.id ? gallery.id : null, 18935 mainActiveIndex: mainActiveIndex, 18936 imageIndex: imageIndex, 18937 mainIsAd: !!(activeSlide && activeSlide.classList.contains('ad-slide')), 18938 thumbSwiperActiveIndex: gallery && gallery.tSwiper && typeof gallery.tSwiper.activeIndex === 'number' ? gallery.tSwiper.activeIndex : -1, 18939 thumbActiveClassIndex: getThumbActiveClassIndex(gallery), 18940 thumbSyncToken: gallery && gallery.__thumbSyncToken ? gallery.__thumbSyncToken : 0, 18941 }, extra || {})); 18942 } 18943 18944 function updateActiveThumbState(gallery, imageIndex) { 18945 if (!gallery || !gallery.tSwiper || !gallery.tSwiper.slides) { 18946 return; 18947 } 18948
18949 Array.from(gallery.tSwiper.slides).forEach(function (slide, idx) { 18950 const isActive = idx === imageIndex; 18951 18952 // Beide Klassen konsistent pflegen, da Theme-Styling auf swiper-slide-active basiert. 18953 slide.classList.toggle('swiper-slide-thumb-active', isActive); 18954 slide.classList.toggle('swiper-slide-active', isActive); 18955 }); 18956 18957 traceThumbSync(gallery, 'updateActiveThumbState', { targetImageIndex: imageIndex }); 18958 } 18959 18960 function clearActiveThumbState(gallery) { 18961 if (!gallery || !gallery.tSwiper || !gallery.tSwiper.slides) { 18962 return; 18963 } 18964 18965 Array.from(gallery.tSwiper.slides).forEach(function (slide) { 18966 slide.classList.remove('swiper-slide-thumb-active'); 18967 slide.classList.remove('swiper-slide-active'); 18968 }); 18969 18970 traceThumbSync(gallery, 'clearActiveThumbState'); 18971 } 18972 18973 function syncThumbSwiperToImageIndex(gallery, imageIndex) { 18974 if (!gallery || !gallery.tSwiper || typeof gallery.tSwiper.slideTo !== 'function') { 18975 return; 18976 } 18977 18978 if (!Number.isInteger(imageIndex) || imageIndex < 0) { 18979 return; 18980 } 18981 18982 traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:start', { targetImageIndex: imageIndex }); 18983 18984 // Ohne Animation synchronisieren, damit nach Ad-Slides kein Versatz entsteht. 18985 gallery.tSwiper.slideTo(imageIndex, 0); 18986 updateActiveThumbState(gallery, imageIndex); 18987 18988 // Schutz gegen stale RAF-Updates: nur der neueste Sync darf nachlaufen. 18989 gallery.__thumbSyncToken = (gallery.__thumbSyncToken || 0) + 1; 18990 const syncToken = gallery.__thumbSyncToken; 18991 18992 // Zweiter Tick: manche Swiper-Zustaende laufen nach dem ersten slideTo noch nach. 18993 if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') { 18994 window.requestAnimationFrame(function () { 18995 if (gallery.__thumbSyncToken !== syncToken) { 18996 traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:raf-skip-stale', { targetImageIndex: imageIndex, syncToken: syncToken }); 18997 return; 18998 } 18999 19000 gallery.tSwiper.slideTo(imageIndex, 0); 19001 updateActiveThumbState(gallery, imageIndex); 19002 traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:raf-apply', { targetImageIndex: imageIndex, syncToken: syncToken }); 19003 }); 19004 } 19005 19006 traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:end', { targetImageIndex: imageIndex, syncToken: syncToken }); 19007 } 19008 19009 function syncThumbStateWithMainSwiper(gallery) { 19010 if (!gallery || !gallery.mSwiper || !gallery.tSwiper || !gallery.mSwiper.slides || typeof gallery.mSwiper.activeIndex !== 'number') { 19011 return; 19012 } 19013 19014 traceThumbSync(gallery, 'syncThumbStateWithMainSwiper:start'); 19015 19016 const activeSlide = gallery.mSwiper.slides[gallery.mSwiper.activeIndex]; 19017 if (!activeSlide) { 19018 return; 19019 } 19020 19021 if (activeSlide.classList.contains('ad-slide')) { 19022 clearActiveThumbState(gallery); 19023 traceThumbSync(gallery, 'syncThumbStateWithMainSwiper:active-ad'); 19024 return; 19025 } 19026 19027 const imageIndex = getImageIndexFromMainIndex(gallery.mSwiper.slides, gallery.mSwiper.activeIndex); 19028 if (imageIndex >= 0) { 19029 updateActiveThumbState(gallery, imageIndex); 19030 syncThumbSwiperToImageIndex(gallery, imageIndex); 19031 traceThumbSync(gallery, 'syncThumbStateWithMainSwiper:active-image', { targetImageIndex: imageIndex }); 19032 } 19033 } 19034 19035 function setGalleryAdNavigationState(gallery, activeSlide) { 19036 if (!gallery || !gallery.classList) { 19037 return; 19038 } 19039 19040 const isAdActive = !!(activeSlide && activeSlide.classList.contains('ad-slide')); 19041 gallery.classList.toggle('is-ad-active', isAdActive); 19042 19043 const overlays = gallery.querySelectorAll('.MediaGallery_slideLeft, .MediaGallery_slideRight, .MediaGalleryFullWidth_slideLeft, .MediaGalleryFullWidth_slideRight'); 19044 if (!overlays.length) { 19045 return; 19046 } 19047 19048 overlays.forEach(function (overlayEl) { 19049 if (isAdActive) { 19050 // Schmale Rand-Klickzonen nur fuer Ad-Slides: Mitte bleibt fuer Ad-Klicks frei. 19051 overlayEl.style.width = '8%'; 19052 overlayEl.style.pointerEvents = 'auto'; 19053 return; 19054 } 19055 19056 // Fuer normale Bild-Slides wieder das CSS-Layout verwenden. 19057 overlayEl.style.width = ''; 19058 overlayEl.style.pointerEvents = ''; 19059 }); 19060 } 19061 19062 function getActiveSlideHeight(swiperInstance) { 19063 if (!swiperInstance || !swiperInstance.slides || typeof swiperInstance.activeIndex !== 'number') { 19064 return 0; 19065 } 19066 19067 const activeSlide = swiperInstance.slides[swiperInstance.activeIndex]; 19068 if (!activeSlide) { 19069 return 0; 19070 } 19071 19072 return Math.max( 19073 activeSlide.offsetHeight || 0, 19074 activeSlide.scrollHeight || 0, 19075 Math.ceil(activeSlide.getBoundingClientRect ? activeSlide.getBoundingClientRect().height : 0) 19076 ); 19077 } 19078 19079 function shouldUpdateAutoHeight(gallery, swiperInstance, forceUpdate) { 19080 if (forceUpdate) { 19081 return true; 19082 } 19083 19084 const activeSlide = swiperInstance && swiperInstance.slides && typeof swiperInstance.activeIndex === 'number' 19085 ? swiperInstance.slides[swiperInstance.activeIndex] 19086 : null; 19087 19088 // Keep the previous image height while an ad slide is active to avoid small page jumps. 19089 if (activeSlide && activeSlide.classList.contains('ad-slide')) { 19090 return false; 19091 } 19092 19093 const activeSlideHeight = getActiveSlideHeight(swiperInstance); 19094 if (activeSlideHeight <= 0) { 19095 return false; 19096 } 19097 19098 // Solange die initiale Hoehe aktiv ist, nur updaten wenn sie sichtbar nicht passt. 19099 if (gallery && gallery.__initialSlideHeightActive) { 19100 const initialHeight = getInitialSlideHeightPx(gallery); 19101 if (initialHeight <= 0) { 19102 return true; 19103 } 19104 return Math.abs(activeSlideHeight - initialHeight) > AUTO_HEIGHT_TOLERANCE_PX; 19105 } 19106 19107 const wrapperHeight = swiperInstance && swiperInstance.wrapperEl ? swiperInstance.wrapperEl.offsetHeight : 0; 19108 if (wrapperHeight <= 0) { 19109 return true; 19110 } 19111 19112 return Math.abs(activeSlideHeight - wrapperHeight) > AUTO_HEIGHT_TOLERANCE_PX; 19113 } 19114
19115 function refreshSwiperAutoHeight(swiperInstance, gallery, forceUpdate) { 19116 if (!swiperInstance || typeof swiperInstance.updateAutoHeight !== 'function') { 19117 return; 19118 } 19119 19120 if (!shouldUpdateAutoHeight(gallery, swiperInstance, !!forceUpdate)) { 19121 return; 19122 } 19123 19124 swiperInstance.updateAutoHeight(); 19125 19126 // Zweiter Tick fuer sichere Hoehen-Neuberechnung nach Reflow/Render. 19127 if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') { 19128 window.requestAnimationFrame(function () { 19129 if (shouldUpdateAutoHeight(gallery, swiperInstance, !!forceUpdate)) { 19130 swiperInstance.updateAutoHeight(); 19131 } 19132 }); 19133 } 19134 } 19135 19136 // Optional data attributes: 19137 // - data-initial-slide-height 19138 // - data-slider-container-min-height 19139 // Numeric values are interpreted as px, missing/invalid/'auto' fall back to auto behavior. 19140 function getInitialSlideHeightPx(gallery) { 19141 if (!gallery || !gallery.dataset) { 19142 return DEFAULT_INITIAL_SLIDE_HEIGHT_PX; 19143 } 19144 19145 const fromData = parseInt(gallery.dataset.initialSlideHeight, 10); 19146 return Number.isFinite(fromData) && fromData > 0 ? fromData : DEFAULT_INITIAL_SLIDE_HEIGHT_PX; 19147 } 19148 19149 function isFullWidthGallery(gallery) { 19150 return !!(gallery && gallery.classList && gallery.classList.contains('MediaGalleryFullWidth')); 19151 } 19152 19153 function getSliderContainerMinHeightPx(gallery) { 19154 if (!gallery || !gallery.dataset) { 19155 return DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX; 19156 } 19157 19158 const fromData = parseInt(gallery.dataset.sliderContainerMinHeight, 10); 19159 if (Number.isFinite(fromData) && fromData > 0) { 19160 return fromData; 19161 } 19162 19163 if (isFullWidthGallery(gallery)) { 19164 return DEFAULT_FULLWIDTH_SLIDER_CONTAINER_MIN_HEIGHT_PX; 19165 } 19166 19167 const sliderEl = gallery.querySelector('.MediaGallery_slider'); 19168 const sliderWidth = sliderEl ? sliderEl.clientWidth : 0; 19169 19170 if (sliderWidth > 0) { 19171 // Adaptive Untergrenze fuer eingebettete, schmale Galerien (z. B. Artikelspalte). 19172 const adaptiveHeight = Math.round(sliderWidth * 0.62); 19173 return Math.max(220, Math.min(DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX, adaptiveHeight)); 19174 } 19175 19176 return DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX; 19177 } 19178 19179 function toMinHeightCssValue(heightPx) { 19180 return Number.isFinite(heightPx) && heightPx > 0 ? heightPx + 'px' : 'auto'; 19181 } 19182 19183 function applyInitialSlideHeight(gallery) { 19184 if (!gallery) { 19185 return; 19186 } 19187 19188 const slider = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider'); 19189 const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer'); 19190 const initialHeight = getInitialSlideHeightPx(gallery); 19191 19192 if (slider) { 19193 slider.style.minHeight = toMinHeightCssValue(initialHeight); 19194 } 19195 19196 if (wrapper) { 19197 wrapper.style.minHeight = toMinHeightCssValue(initialHeight); 19198 } 19199 19200 gallery.__initialSlideHeightActive = true; 19201 } 19202 19203 function clearInitialSlideHeightIfReady(gallery, swiperInstance) { 19204 if (!gallery || !gallery.__initialSlideHeightActive) { 19205 return; 19206 } 19207 19208 if (!swiperInstance || !swiperInstance.wrapperEl || swiperInstance.wrapperEl.offsetHeight <= 0) { 19209 return; 19210 } 19211 19212 const slider = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider'); 19213 const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer'); 19214 19215 if (slider) { 19216 slider.style.minHeight = '0'; 19217 } 19218 19219 if (wrapper) { 19220 wrapper.style.minHeight = toMinHeightCssValue(getSliderContainerMinHeightPx(gallery)); 19221 } 19222 19223 gallery.__initialSlideHeightActive = false; 19224 } 19225 19226 function normalizeGallerySlideHeights(gallery) { 19227 if (!gallery) { 19228 return; 19229 } 19230 19231 const slider = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider'); 19232 const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer'); 19233 19234 if (slider) { 19235 slider.style.height = 'auto'; 19236 if (!gallery.__initialSlideHeightActive) { 19237 slider.style.minHeight = '0'; 19238 } 19239 } 19240 19241 if (!wrapper) { 19242 return; 19243 } 19244 19245 wrapper.style.height = 'auto'; 19246 if (!gallery.__initialSlideHeightActive) { 19247 wrapper.style.minHeight = toMinHeightCssValue(getSliderContainerMinHeightPx(gallery)); 19248 } 19249
19250 Array.from(wrapper.children).forEach(function (slide) { 19251 slide.style.height = 'auto'; 19252 }); 19253 } 19254 19255 function bindImageLoadAutoHeight(gallery) { 19256 if (!gallery) { 19257 return; 19258 } 19259 19260 gallery.querySelectorAll('.MediaGallery_sliderImage img, .MediaGalleryFullWidth_sliderImage img').forEach(function (img) { 19261 if (img.complete) { 19262 return; 19263 } 19264 19265 img.addEventListener('load', function () { 19266 refreshSwiperAutoHeight(gallery.mSwiper, gallery); 19267 clearInitialSlideHeightIfReady(gallery, gallery.mSwiper); 19268 scheduleDescriptionThumbOverlapCheck(gallery); 19269 }, { once: true }); 19270 }); 19271 } 19272 19273 function refreshActiveAdSlot(gallery, activeSlide) { 19274 if (!gallery || !activeSlide || !activeSlide.classList.contains('ad-slide')) { 19275 return; 19276 } 19277 19278 traceThumbSync(gallery, 'refreshActiveAdSlot:start'); 19279 19280 const adDiv = gallery.querySelector('.ad-container'); 19281 if (!adDiv || !adDiv.children[0]) { 19282 debugAdLog('Interner Gallery-Slot nicht refreshbar (ad-container fehlt)', { 19283 galleryId: gallery.id || null, 19284 }); 19285 return; 19286 } 19287 19288 if (adDiv.parentNode !== activeSlide) { 19289 activeSlide.appendChild(adDiv); 19290 } 19291 19292 centerAdIframes(adDiv, activeSlide); 19293 19294 const slots = googletag.pubads().getSlots(); 19295 const slotElementId = adDiv.children[0].id; 19296 const currentSlot = slots.find(function (s) { 19297 return s.getSlotElementId() === slotElementId; 19298 }); 19299 19300 if (!currentSlot) { 19301 debugAdLog('Interner Gallery-Slot nicht refreshbar (Slotobjekt fehlt)', { 19302 galleryId: gallery.id || null, 19303 slotElementId: slotElementId, 19304 }); 19305 return; 19306 } 19307 19308 const activeSlotInfo = adSlots.get(slotElementId); 19309 if (activeSlotInfo) { 19310 activeSlotInfo.targetAdSlide = activeSlide; 19311 const refreshState = getOrCreateRefreshState(activeSlotInfo); 19312 const nowTs = Date.now(); 19313 if (refreshState.lastHandledAdSlideElement === activeSlide && (nowTs - refreshState.lastHandledAdSlideTs) < AD_SLIDE_REENTRY_GUARD_MS) { 19314 traceThumbSync(gallery, 'refreshActiveAdSlot:dedup-skip', { slotElementId: slotElementId }); 19315 return; 19316 } 19317 refreshState.lastHandledAdSlideElement = activeSlide; 19318 refreshState.lastHandledAdSlideTs = nowTs; 19319 refreshState.lastAdSlideActivationTs = nowTs; 19320 refreshState.fallbackRefreshDone = false; 19321 if (refreshState.activeSlideFallbackTimerId) { 19322 window.clearTimeout(refreshState.activeSlideFallbackTimerId); 19323 refreshState.activeSlideFallbackTimerId = null; 19324 } 19325 19326 maybeRefreshSlot(activeSlotInfo, 'slideChangeTransitionEnd').catch(function (err) { 19327 debugAdLog('Refresh bei aktivem Ad-Slide fehlgeschlagen', { 19328 adId: activeSlotInfo.adId, 19329 message: err && err.message ? err.message : String(err), 19330 }); 19331 }); 19332 19333 if (hasExplicitUserInteraction) { 19334 const activationTs = refreshState.lastAdSlideActivationTs; 19335 refreshState.activeSlideFallbackTimerId = window.setTimeout(function () { 19336 refreshState.activeSlideFallbackTimerId = null; 19337 19338 if (!hasExplicitUserInteraction || !activeSlide.isConnected || !activeSlide.classList.contains('swiper-slide-active')) { 19339 return; 19340 } 19341 if (activeSlotInfo.targetAdSlide !== activeSlide || refreshState.pending || refreshState.fallbackRefreshDone) { 19342 return; 19343 } 19344 19345 const iframe = adDiv.querySelector('iframe'); 19346 const hasNoVisibleIframe = !iframe || iframe.offsetWidth < 10 || iframe.offsetHeight < 10; 19347 const noRefreshSinceActivation = refreshState.lastRefreshTs < activationTs; 19348 if (!hasNoVisibleIframe && !noRefreshSinceActivation) { 19349 return; 19350 } 19351 19352 refreshState.fallbackRefreshDone = true; 19353 maybeRefreshSlot(activeSlotInfo, 'activeSlideFallback', { ignoreInterval: true }).catch(function (err) { 19354 debugAdLog('Fallback-Refresh bei aktivem Ad-Slide fehlgeschlagen', { 19355 adId: activeSlotInfo.adId,
19356 message: err && err.message ? err.message : String(err), 19357 }); 19358 }); 19359 }, ACTIVE_AD_FALLBACK_RETRY_MS); 19360 } 19361 } 19362 19363 traceThumbSync(gallery, 'refreshActiveAdSlot:evaluated', { slotElementId: slotElementId }); 19364 } 19365 19366 function maybeRefreshExternalSlotsByAdPos(gallery, mainSwiper) { 19367 if (!gallery || !mainSwiper || !mainSwiper.slides || typeof mainSwiper.activeIndex !== 'number') { 19368 return; 19369 } 19370 19371 const adPos = parseInt(gallery.dataset.adpos, 10); 19372 if (!adPos || adPos < 1) { 19373 return; 19374 } 19375 19376 const imageIndex = getImageIndexFromMainIndex(mainSwiper.slides, mainSwiper.activeIndex); 19377 if (imageIndex < 0) { 19378 return; 19379 } 19380 19381 const imageCount = imageIndex + 1; 19382 const stepCount = mainSwiper.activeIndex + 1; 19383 const triggerEvery = adPos + 1; 19384 19385 // Wenn der User zurueckblaettert, Trigger-Freigabe fuer bereits erreichte Positionen zuruecksetzen. 19386 const lastSeenStepCount = Number.isInteger(gallery.__lastExternalRefreshSeenStepCount) 19387 ? gallery.__lastExternalRefreshSeenStepCount 19388 : null; 19389 if (lastSeenStepCount !== null && stepCount < lastSeenStepCount) { 19390 gallery.__lastExternalRefreshTriggerStepCount = null; 19391 } 19392 gallery.__lastExternalRefreshSeenStepCount = stepCount; 19393 19394 if ((stepCount % triggerEvery) !== 0) { 19395 return; 19396 } 19397 19398 // Pro Slide-Position nur ein Trigger, bis wieder unter diese Position zurueckgeblaettert wurde. 19399 if (gallery.__lastExternalRefreshTriggerStepCount === stepCount) { 19400 return; 19401 } 19402 19403 const triggerMarker = stepCount + ':' + mainSwiper.activeIndex; 19404 19405 debugAdLog('Externer Refresh via adPos-Trigger', { 19406 galleryId: gallery.id || null, 19407 adPos: adPos, 19408 triggerEvery: triggerEvery, 19409 imageCount: imageCount, 19410 mainActiveIndex: mainSwiper.activeIndex, 19411 }); 19412 19413 const refreshExecuted = refreshExternalGalleryRelatedSlots('adPosTransition', { 19414 galleryId: gallery.id || null, 19415 imageCount: imageCount, 19416 stepCount: stepCount, 19417 mainActiveIndex: mainSwiper.activeIndex, 19418 triggerEvery: triggerEvery, 19419 triggerMarker: triggerMarker, 19420 }); 19421 if (refreshExecuted) { 19422 gallery.__lastExternalRefreshTriggerStepCount = stepCount; 19423 } 19424 } 19425 19426 function applySliderContainerMinHeight(gallery) { 19427 if (!gallery) { 19428 return; 19429 } 19430 19431 const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer'); 19432 if (!wrapper) { 19433 return; 19434 } 19435 19436 wrapper.style.minHeight = toMinHeightCssValue(getSliderContainerMinHeightPx(gallery)); 19437 } 19438 19439 function forceThumbnailContainerFullWidth(gallery) { 19440 if (!gallery) { 19441 return; 19442 } 19443 19444 const thumbWrapper = gallery.querySelector('.MediaGallery_thumbnailContainer'); 19445 if (!thumbWrapper) { 19446 return; 19447 } 19448 19449 // Override legacy theme offsets (left: ~45%) via inline styles. 19450 thumbWrapper.style.left = '0'; 19451 thumbWrapper.style.width = '100%'; 19452 thumbWrapper.style.maxWidth = '100%'; 19453 thumbWrapper.style.position = 'relative'; 19454 } 19455 19456 function getActiveDescriptionElement(gallery) { 19457 if (!gallery) { 19458 return null; 19459 } 19460 19461 return gallery.querySelector( 19462 '.MediaGallery_sliderImage.swiper-slide-active .MediaGallery_imageDescription, ' + 19463 '.MediaGalleryFullWidth_sliderImage.swiper-slide-active .MediaGallery_imageDescription, ' + 19464 '.MediaGallery_imageDescription' 19465 ); 19466 } 19467 19468 function preventDescriptionThumbOverlap(gallery) { 19469 if (!gallery) { 19470 return; 19471 } 19472 19473 const thumbsEl = gallery.querySelector('.MediaGallery_thumbnails'); 19474 if (!thumbsEl) { 19475 return; 19476 } 19477 19478 const descriptionEl = getActiveDescriptionElement(gallery); 19479 if (!descriptionEl) { 19480 thumbsEl.style.marginTop = ''; 19481 return; 19482 } 19483 19484 // Erst resetten, damit wiederholte Messungen keine Offsets aufaddieren. 19485 thumbsEl.style.marginTop = ''; 19486 19487 const descriptionRect = descriptionEl.getBoundingClientRect(); 19488 const thumbsRect = thumbsEl.getBoundingClientRect(); 19489 const overlapPx = Math.ceil(descriptionRect.bottom - thumbsRect.top); 19490 19491 if (overlapPx > 0) { 19492 // Kleiner Puffer, damit Border/Line-Height nicht am Thumb klebt. 19493 thumbsEl.style.marginTop = (overlapPx + 8) + 'px'; 19494 } 19495 } 19496 19497 function scheduleDescriptionThumbOverlapCheck(gallery) { 19498 if (!gallery) { 19499 return; 19500 } 19501 19502 if (gallery.__descThumbOverlapRaf && typeof window !== 'undefined' && typeof window.cancelAnimationFrame === 'function') { 19503 window.cancelAnimationFrame(gallery.__descThumbOverlapRaf); 19504 } 19505 19506 if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') { 19507 gallery.__descThumbOverlapRaf = window.requestAnimationFrame(function () { 19508 preventDescriptionThumbOverlap(gallery); 19509 gallery.__descThumbOverlapRaf = null; 19510 }); 19511 return; 19512 } 19513 19514 preventDescriptionThumbOverlap(gallery); 19515 } 19516 19517 function bindDescriptionThumbOverlapGuard(gallery) { 19518 if (!gallery || gallery.__descThumbOverlapResizeBound) { 19519 return; 19520 } 19521 19522 if (typeof window !== 'undefined') { 19523 window.addEventListener('resize', function () { 19524 scheduleDescriptionThumbOverlapCheck(gallery); 19525 }); 19526 } 19527 19528 gallery.__descThumbOverlapResizeBound = true; 19529 } 19530 19531 function buildTrackingUrl(gallery, activeSlide, activeIndex) { 19532 const baseUrl = (gallery && gallery.dataset && gallery.dataset.url) || (window.location.pathname + window.location.search); 19533 const hashFromSlide = activeSlide && activeSlide.getAttribute('data-hash'); 19534 const hash = hashFromSlide || ('slide-' + (activeIndex + 1)); 19535 return baseUrl.split('#')[0] + '#' + hash; 19536 } 19537 19538 function safeTrackerCall(label, fn) {
19539 try { 19540 fn(); 19541 } catch (err) { 19542 debugAdLog('Tracking-Fehler in ' + label, { 19543 message: err && err.message ? err.message : String(err), 19544 }); 19545 } 19546 } 19547 19548 function triggerVirtualPageTracking(gallery, activeSlide, activeIndex) { 19549 if (!gallery || !activeSlide) { 19550 return; 19551 } 19552 19553 // Ads nicht als virtuelle Seiten tracken, um externe Tracker-Fehler zu vermeiden. 19554 if (activeSlide.classList.contains('ad-slide')) { 19555 return; 19556 } 19557 19558 const url = buildTrackingUrl(gallery, activeSlide, activeIndex); 19559 const gtitle = (gallery && gallery.dataset && gallery.dataset.title) || document.title || ''; 19560 const galId = (gallery && gallery.id) || null; 19561 19562 if (typeof window.dfv_iom_rpl === 'function') { 19563 safeTrackerCall('window.dfv_iom_rpl', function () { 19564 window.dfv_iom_rpl(); 19565 }); 19566 } else if (typeof dfv_iom_rpl === 'function') { 19567 safeTrackerCall('dfv_iom_rpl', function () { 19568 dfv_iom_rpl(); 19569 }); 19570 } 19571 19572 if (typeof window.dfv_ga_vpageview === 'function') { 19573 safeTrackerCall('window.dfv_ga_vpageview', function () { 19574 window.dfv_ga_vpageview(url, gtitle); 19575 }); 19576 } 19577 19578 if (typeof window.sp_track_virtual_page_view === 'function') { 19579 safeTrackerCall('window.sp_track_virtual_page_view', function () { 19580 window.sp_track_virtual_page_view(galId, url, gtitle); 19581 }); 19582 } 19583 19584 debugAdLog('Virtual-Tracking ausgeloest', { 19585 galId: galId, 19586 url: url, 19587 title: gtitle, 19588 mainIndex: activeIndex, 19589 isAd: !!(activeSlide && activeSlide.classList.contains('ad-slide')), 19590 }); 19591 } 19592 19593 const refreshEligibilityCache = new Map(); 19594 19595 function getRegisteredSlotById(slotId) { 19596 const slots = googletag.pubads().getSlots(); 19597 return slots.find(function (slot) { 19598 return slot.getSlotElementId() === slotId; 19599 }) || null; 19600 } 19601 19602 function getVisibleRatio(element) { 19603 if (!element || typeof element.getBoundingClientRect !== 'function') { 19604 return 0; 19605 } 19606 const rect = element.getBoundingClientRect(); 19607 if (!rect.width || !rect.height) { 19608 return 0; 19609 } 19610 19611 const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0; 19612 const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0; 19613 if (!viewportWidth || !viewportHeight) { 19614 return 0; 19615 } 19616 19617 const intersectionWidth = Math.max(0, Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0)); 19618 const intersectionHeight = Math.max(0, Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0)); 19619 const intersectionArea = intersectionWidth * intersectionHeight; 19620 const area = rect.width * rect.height; 19621 return area > 0 ? (intersectionArea / area) : 0; 19622 } 19623 19624 function isSlotInViewport(slotInfo) { 19625 if (!slotInfo || !slotInfo.gallery) { 19626 return false; 19627 } 19628 const galleryRatio = getVisibleRatio(slotInfo.gallery); 19629 if (galleryRatio < SLOT_VIEWPORT_THRESHOLD) { 19630 return false; 19631 } 19632 19633 const adContainer = slotInfo.gallery.querySelector('.ad-container'); 19634 if (!adContainer) { 19635 return false; 19636 } 19637 19638 return getVisibleRatio(adContainer) >= SLOT_VIEWPORT_THRESHOLD; 19639 } 19640 19641 function getExternalSlotViewportThreshold() { 19642 if (typeof window === 'undefined') { 19643 return EXTERNAL_SLOT_VIEWPORT_THRESHOLD; 19644 } 19645 19646 const raw = Number(window.__galleryExternalSlotViewportThreshold); 19647 if (!Number.isFinite(raw)) { 19648 return EXTERNAL_SLOT_VIEWPORT_THRESHOLD; 19649 } 19650 19651 return Math.max(0, Math.min(1, raw)); 19652 } 19653 19654 function isExternalSlotInViewport(slotId) { 19655 if (!slotId) { 19656 return false; 19657 } 19658 19659 const slotElement = document.getElementById(slotId); 19660 if (!slotElement) { 19661 return false; 19662 } 19663 19664 const visibleRatio = getVisibleRatio(slotElement); 19665 const threshold = getExternalSlotViewportThreshold(); 19666 return visibleRatio >= threshold; 19667 } 19668
19669 function isExternalSlotRefreshEligible(slotId) { 19670 if (!slotId || typeof window === 'undefined') { 19671 return false; 19672 } 19673 19674 const eligibilityMap = window.__galleryAdRefreshEligibilityByAdUnitId; 19675 if (!eligibilityMap || typeof eligibilityMap !== 'object') { 19676 return false; 19677 } 19678 19679 const slotName = slotId.replace(/^renderSlot_/, ''); 19680 const candidates = [slotName, slotId]; 19681 for (let i = 0; i < candidates.length; i++) { 19682 const key = candidates[i]; 19683 if (Object.prototype.hasOwnProperty.call(eligibilityMap, key)) { 19684 return eligibilityMap[key] === true; 19685 } 19686 } 19687 19688 return false; 19689 } 19690 19691 function getOrCreateRefreshState(slotInfo) { 19692 if (!slotInfo.refreshState) { 19693 slotInfo.refreshState = { 19694 renderedLineItemId: null, 19695 previousRenderedLineItemId: null, 19696 viewableSinceTs: 0, 19697 lastRefreshTs: Date.now(), 19698 pending: false, 19699 lastRefreshReason: null, 19700 refreshCount: 0, 19701 lastAdSlideActivationTs: 0, 19702 fallbackRefreshDone: false, 19703 activeSlideFallbackTimerId: null, 19704 lastHandledAdSlideElement: null, 19705 lastHandledAdSlideTs: 0, 19706 }; 19707 } 19708 return slotInfo.refreshState; 19709 } 19710 19711 function resolveEligibilityFromAdData(slotInfo) { 19712 if (!slotInfo || !slotInfo.adData) { 19713 return null; 19714 } 19715 19716 if (typeof slotInfo.adData.refreshEligible === 'boolean') { 19717 return slotInfo.adData.refreshEligible; 19718 } 19719 19720 if (typeof slotInfo.adData.lineItemCount === 'number') { 19721 return slotInfo.adData.lineItemCount > 1; 19722 } 19723 19724 return null; 19725 } 19726 19727 function resolveEligibilityFromWindow(path, adUnitId) { 19728 if (typeof window === 'undefined') { 19729 return null; 19730 } 19731 19732 if (adUnitId && window.__galleryAdRefreshEligibilityByAdUnitId && typeof window.__galleryAdRefreshEligibilityByAdUnitId === 'object') { 19733 const mappedByAdUnit = window.__galleryAdRefreshEligibilityByAdUnitId[String(adUnitId)]; 19734 if (typeof mappedByAdUnit === 'boolean') { 19735 return mappedByAdUnit; 19736 } 19737 } 19738 19739 if (!path) { 19740 return null; 19741 } 19742 19743 const rawMap = window.__galleryAdRefreshEligibilityByPath; 19744 if (!rawMap || typeof rawMap !== 'object') { 19745 return null; 19746 } 19747 19748 const value = rawMap[path]; 19749 if (typeof value === 'boolean') { 19750 return value; 19751 } 19752 if (value && typeof value === 'object' && typeof value.refreshEligible === 'boolean') { 19753 return value.refreshEligible; 19754 } 19755 19756 return null; 19757 } 19758 19759 async function resolveSlotRefreshEligibility(slotInfo, slotObj) {
19760 const slotPath = slotObj && typeof slotObj.getAdUnitPath === 'function' ? slotObj.getAdUnitPath() : null; 19761 if (!slotPath) { 19762 return false; 19763 } 19764 19765 const nowTs = Date.now(); 19766 const cached = refreshEligibilityCache.get(slotPath); 19767 if (cached && (nowTs - cached.ts) <= refreshRuntimeConfig.eligibilityCacheTtlMs) { 19768 return cached.value; 19769 } 19770 19771 let eligible = resolveEligibilityFromAdData(slotInfo); 19772 const slotAdUnitId = slotInfo && slotInfo.adData ? String(slotInfo.adData.adUnitId || '') : ''; 19773 if (eligible === null) { 19774 eligible = resolveEligibilityFromWindow(slotPath, slotAdUnitId); 19775 } 19776 19777 if (eligible === null && typeof window !== 'undefined' && typeof window.__galleryAdRefreshEligibilityProvider === 'function') { 19778 try { 19779 const providerResult = await window.__galleryAdRefreshEligibilityProvider(slotPath); 19780 if (typeof providerResult === 'boolean') { 19781 eligible = providerResult; 19782 } else if (providerResult && typeof providerResult === 'object' && typeof providerResult.refreshEligible === 'boolean') { 19783 eligible = providerResult.refreshEligible; 19784 } 19785 } catch (err) { 19786 debugAdLog('Eligibility-Provider Fehler', { 19787 slotPath: slotPath, 19788 message: err && err.message ? err.message : String(err), 19789 }); 19790 } 19791 } 19792 19793 if (eligible === null) { 19794 // Falls keine Datenquelle vorhanden ist, defensiv keinen Refresh ausfuehren. 19795 eligible = false; 19796 } 19797 19798 refreshEligibilityCache.set(slotPath, { value: !!eligible, ts: nowTs }); 19799 return !!eligible; 19800 } 19801 19802 async function maybeRefreshSlot(slotInfo, reason, options) { 19803 if (!slotInfo || !slotInfo.injected) { 19804 return; 19805 } 19806 19807 // Legacy-Verhalten: Gallery-Slot nur beim Wechsel auf einen Ad-Slide refreshen. 19808 if (reason !== 'slideChangeTransitionEnd' && reason !== 'activeSlideFallback') { 19809 return; 19810 } 19811 19812 const refreshOptions = options || {}; 19813 const refreshState = getOrCreateRefreshState(slotInfo); 19814 if (refreshState.pending) { 19815 return; 19816 } 19817 19818 const nowTs = Date.now(); 19819 const ignoreInterval = !!refreshOptions.ignoreInterval; 19820 const intervalNotReached = (nowTs - refreshState.lastRefreshTs) < refreshRuntimeConfig.refreshIntervalMs; 19821 const canBypassInitialDelay = refreshState.refreshCount === 0 && hasExplicitUserInteraction; 19822 if (!ignoreInterval && intervalNotReached && !canBypassInitialDelay) { 19823 return; 19824 } 19825 19826 const slotObj = getRegisteredSlotById(slotInfo.adId); 19827 if (!slotObj) { 19828 return; 19829 } 19830 19831 refreshState.pending = true; 19832 refreshState.lastRefreshReason = reason; 19833 refreshState.lastRefreshTs = nowTs; 19834 refreshState.refreshCount += 1; 19835 19836 googletag.pubads().refresh([slotObj]); 19837 debugAdLog('Slot-Refresh ausgeloest', { 19838 adId: slotInfo.adId, 19839 reason: refreshState.lastRefreshReason, 19840 slotPath: typeof slotObj.getAdUnitPath === 'function' ? slotObj.getAdUnitPath() : null, 19841 }); 19842 } 19843 19844 function evaluateAllSlotRefreshes(reason) { 19845 adSlots.forEach(function (slotInfo) { 19846 maybeRefreshSlot(slotInfo, reason).catch(function (err) { 19847 debugAdLog('Refresh-Pruefung fehlgeschlagen', { 19848 adId: slotInfo && slotInfo.adId ? slotInfo.adId : null, 19849 reason: reason, 19850 message: err && err.message ? err.message : String(err), 19851 }); 19852 }); 19853 }); 19854 } 19855 19856 function refreshExternalGalleryRelatedSlots(reason, meta) { 19857 // Billboard/Skyscraper-Refreshes nur auf Gallerydetail-Seiten 19858 if (!hasGalleryBodyClass) { 19859 return false; 19860 } 19861 19862 const nowTs = Date.now(); 19863 const elapsedSinceLastRefreshMs = nowTs - lastExternalRefreshTs; 19864 const isAdPosTransition = reason === 'adPosTransition'; 19865 const canBypassInitialDelay = externalRefreshCount === 0 && hasExplicitUserInteraction; 19866 if (!isAdPosTransition && !canBypassInitialDelay && elapsedSinceLastRefreshMs < refreshRuntimeConfig.refreshIntervalMs) { 19867 debugAdLog('Externer Slot-Refresh wegen Initial-Intervall gesperrt', { 19868 reason: reason || null, 19869 elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs, 19870 minIntervalMs: refreshRuntimeConfig.refreshIntervalMs, 19871 externalRefreshCount: externalRefreshCount, 19872 hasExplicitUserInteraction: hasExplicitUserInteraction, 19873 }); 19874 return false; 19875 } 19876 19877 const shouldApplyCooldown = reason !== 'adPosTransition'; 19878 const forceNewCorrelator = typeof window !== 'undefined' && !!window.__galleryExternalRefreshForceNewCorrelator;
19879 if (shouldApplyCooldown && (nowTs - lastExternalRefreshTs) < EXTERNAL_REFRESH_COOLDOWN_MS) { 19880 debugAdLog('Externer Slot-Refresh wegen Cooldown uebersprungen', { 19881 reason: reason || null, 19882 cooldownMs: EXTERNAL_REFRESH_COOLDOWN_MS, 19883 }); 19884 return false; 19885 } 19886 19887 if (typeof window === 'undefined' || typeof window.refreshAdSlot !== 'function') { 19888 debugAdLog('Externer Slot-Refresh nicht verfuegbar', { 19889 reason: reason || null, 19890 hasWindow: typeof window !== 'undefined', 19891 hasRefreshFn: typeof window !== 'undefined' && typeof window.refreshAdSlot === 'function', 19892 }); 19893 return false; 19894 } 19895 19896 const attempted = []; 19897 let refreshedCount = 0; 19898 EXTERNAL_REFRESH_SLOT_IDS.forEach(function (slotId) { 19899 const slotObj = window.gamSlots && window.gamSlots[slotId] ? window.gamSlots[slotId] : null; 19900 const eligibilityAllowed = isExternalSlotRefreshEligible(slotId); 19901 const canRefresh = !!(slotObj && slotObj.allowRefresh && eligibilityAllowed); 19902 const inViewport = canRefresh ? isExternalSlotInViewport(slotId) : false; 19903 const visibleRatio = canRefresh ? getVisibleRatio(document.getElementById(slotId)) : 0; 19904 19905 attempted.push({ 19906 slotId: slotId, 19907 hasSlot: !!slotObj, 19908 refreshEligible: eligibilityAllowed, 19909 allowRefresh: canRefresh, 19910 inViewport: inViewport, 19911 visibleRatio: Number(visibleRatio.toFixed(3)), 19912 }); 19913 19914 if (!canRefresh || !inViewport) { 19915 if (!eligibilityAllowed) { 19916 pushExternalSlotHistory(slotId, 'refreshSkippedEligibilityFalse', { 19917 reason: reason || null, 19918 meta: meta || null, 19919 }); 19920 } else if (canRefresh && !inViewport) { 19921 pushExternalSlotHistory(slotId, 'refreshSkippedNotInViewport', { 19922 reason: reason || null, 19923 visibleRatio: Number(visibleRatio.toFixed(3)), 19924 threshold: getExternalSlotViewportThreshold(), 19925 meta: meta || null, 19926 }); 19927 } 19928 return; 19929 } 19930 19931 if (forceNewCorrelator && typeof googletag !== 'undefined' && googletag.pubads && typeof googletag.pubads === 'function') { 19932 googletag.pubads().refresh([slotObj], { changeCorrelator: true }); 19933 } else { 19934 window.refreshAdSlot(slotId); 19935 } 19936 incrementExternalSlotStat(slotId, 'refreshCallTriggered'); 19937 flashExternalSlotDebugMarker(slotId, 'request'); 19938 pushExternalSlotHistory(slotId, 'refreshCallTriggered', { 19939 reason: reason || null, 19940 forceNewCorrelator: forceNewCorrelator, 19941 meta: meta || null, 19942 }); 19943 refreshedCount += 1; 19944 }); 19945 19946 if (refreshedCount < 1) { 19947 debugAdLog('Externer Slot-Refresh ohne refreshbare Slots uebersprungen', { 19948 reason: reason || null, 19949 attempted: attempted, 19950 }); 19951 return false; 19952 } 19953 19954 lastExternalRefreshTs = nowTs; 19955 externalRefreshCount += 1; 19956 debugAdLog('Externer Slot-Refresh ausgefuehrt', { 19957 reason: reason || null, 19958 forceNewCorrelator: forceNewCorrelator, 19959 refreshedCount: refreshedCount, 19960 attempted: attempted, 19961 }); 19962 return true; 19963 } 19964 19965 function maybeRefreshExternalSlotsByInterval() { 19966 const nowTs = Date.now(); 19967 const elapsedSinceLastRefreshMs = nowTs - lastExternalRefreshTs; 19968 19969 if (elapsedSinceLastRefreshMs < refreshRuntimeConfig.refreshIntervalMs) { 19970 return; 19971 } 19972 19973 if (!isDocumentVisible()) { 19974 debugAdLog('Externer Intervall-Refresh ausgesetzt (Dokument nicht sichtbar)', { 19975 elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs, 19976 minIntervalMs: refreshRuntimeConfig.refreshIntervalMs, 19977 }); 19978 return; 19979 } 19980 19981 if (!isUserRecentlyActive()) { 19982 debugAdLog('Externer Intervall-Refresh ausgesetzt (Nutzer inaktiv)', { 19983 elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs, 19984 minIntervalMs: refreshRuntimeConfig.refreshIntervalMs, 19985 userIdleTimeoutMs: refreshRuntimeConfig.userIdleTimeoutMs, 19986 inactiveForMs: nowTs - lastUserActivityTs, 19987 }); 19988 return; 19989 } 19990 19991 refreshExternalGalleryRelatedSlots('autoInterval', { 19992 elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs, 19993 minIntervalMs: refreshRuntimeConfig.refreshIntervalMs, 19994 }); 19995 } 19996 19997 function isExternalGalleryRelatedSlotId(slotId) { 19998 return EXTERNAL_REFRESH_SLOT_IDS.indexOf(slotId) !== -1; 19999 } 20000
20001 function logExternalSlotEvent(eventName, event) { 20002 if (!event || !event.slot || typeof event.slot.getSlotElementId !== 'function') { 20003 return; 20004 } 20005 20006 const slotId = event.slot.getSlotElementId(); 20007 if (!isExternalGalleryRelatedSlotId(slotId)) { 20008 return; 20009 } 20010 20011 debugAdLog(eventName + ' (External)', { 20012 slotId: slotId, 20013 path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null, 20014 isEmpty: typeof event.isEmpty === 'boolean' ? event.isEmpty : null, 20015 size: event.size || null, 20016 lineItemId: typeof event.lineItemId === 'number' ? event.lineItemId : null, 20017 creativeId: typeof event.creativeId === 'number' ? event.creativeId : null, 20018 }); 20019 20020 if (eventName === 'slotRequested') { 20021 incrementExternalSlotStat(slotId, 'slotRequested'); 20022 pushExternalSlotHistory(slotId, 'slotRequested', { 20023 path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null, 20024 }); 20025 } else if (eventName === 'slotResponseReceived') { 20026 incrementExternalSlotStat(slotId, 'slotResponseReceived'); 20027 pushExternalSlotHistory(slotId, 'slotResponseReceived', { 20028 path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null, 20029 }); 20030 } else if (eventName === 'slotRenderEnded') { 20031 incrementExternalSlotStat(slotId, 'slotRenderEnded'); 20032 flashExternalSlotDebugMarker(slotId, 'render'); 20033 const slotStats = ensureExternalSlotStats(slotId); 20034 slotStats.lastRenderLineItemId = typeof event.lineItemId === 'number' ? event.lineItemId : null; 20035 slotStats.lastRenderCreativeId = typeof event.creativeId === 'number' ? event.creativeId : null; 20036 slotStats.lastRenderTs = new Date().toISOString(); 20037 pushExternalSlotHistory(slotId, 'slotRenderEnded', { 20038 isEmpty: typeof event.isEmpty === 'boolean' ? event.isEmpty : null, 20039 size: event.size || null, 20040 lineItemId: typeof event.lineItemId === 'number' ? event.lineItemId : null, 20041 creativeId: typeof event.creativeId === 'number' ? event.creativeId : null, 20042 }); 20043 } 20044 } 20045 20046 googletag.pubads().addEventListener('slotRenderEnded', function(event) { 20047 const slotId = event.slot.getSlotElementId(); 20048 const slotInfo = adSlots.get(slotId); 20049 if (!slotInfo) { 20050 logExternalSlotEvent('slotRenderEnded', event); 20051 return; 20052 } 20053 20054 debugAdLog('slotRenderEnded empfangen', { 20055 slotId: slotId, 20056 isEmpty: !!event.isEmpty, 20057 size: event.size || null, 20058 lineItemId: typeof event.lineItemId === 'number' ? event.lineItemId : null, 20059 creativeId: typeof event.creativeId === 'number' ? event.creativeId : null, 20060 }); 20061 20062 const gallery = slotInfo.gallery; 20063 const refreshState = getOrCreateRefreshState(slotInfo); 20064 refreshState.pending = false; 20065 if (refreshState.activeSlideFallbackTimerId) { 20066 window.clearTimeout(refreshState.activeSlideFallbackTimerId); 20067 refreshState.activeSlideFallbackTimerId = null; 20068 } 20069 refreshState.previousRenderedLineItemId = refreshState.renderedLineItemId; 20070 refreshState.renderedLineItemId = typeof event.lineItemId === 'number' ? String(event.lineItemId) : null; 20071 if (!gallery) { 20072 return; 20073 } 20074 20075 if (event.isEmpty) { 20076 if (!slotInfo.injected) { 20077 debugAdLog('Leerer Initial-Slot, Ad-Markup wird nicht eingefuegt', { 20078 adId: slotInfo.adId, 20079 galleryId: gallery.id || null, 20080 }); 20081 } else { 20082 debugAdLog('Leerer Refresh-Slot, Ad-Markup bleibt erhalten', { 20083 adId: slotInfo.adId, 20084 galleryId: gallery.id || null, 20085 }); 20086 } 20087 if (gallery.mSwiper && typeof gallery.mSwiper.update === 'function') { 20088 gallery.mSwiper.update(); 20089 } 20090 if (gallery.tSwiper && typeof gallery.tSwiper.update === 'function') {
20091 gallery.tSwiper.update(); 20092 } 20093 scheduleDescriptionThumbOverlapCheck(gallery); 20094 return; 20095 } 20096 20097 let hasInjectedAdMarkup = false; 20098 if (!slotInfo.injected) { 20099 injectAdMarkup(slotInfo); 20100 slotInfo.injected = true; 20101 hasInjectedAdMarkup = true; 20102 } 20103 20104 normalizeGallerySlideHeights(gallery); 20105 20106 const adContainer = gallery.querySelector('#renderSlot-' + slotId); 20107 const targetAdSlide = slotInfo.targetAdSlide && slotInfo.targetAdSlide.isConnected 20108 ? slotInfo.targetAdSlide 20109 : slotInfo.mainWrapper.querySelector('.ad-slide'); 20110 20111 if (adContainer && targetAdSlide && adContainer.parentNode !== targetAdSlide) { 20112 targetAdSlide.appendChild(adContainer); 20113 debugAdLog('Ad-Container in aktiven Ad-Slide verschoben', { 20114 adId: slotInfo.adId, 20115 galleryId: gallery.id || null, 20116 }); 20117 } 20118 20119 centerAdIframes(adContainer, targetAdSlide); 20120 20121 if (isSlotInViewport(slotInfo) && !refreshState.viewableSinceTs) { 20122 refreshState.viewableSinceTs = Date.now(); 20123 } 20124 20125 refreshSwiperAutoHeight(gallery.mSwiper, gallery); 20126 20127 if (hasInjectedAdMarkup && gallery.mSwiper && typeof gallery.mSwiper.update === 'function') { 20128 gallery.mSwiper.update(); 20129 } 20130 if (hasInjectedAdMarkup && gallery.tSwiper && typeof gallery.tSwiper.update === 'function') { 20131 gallery.tSwiper.update(); 20132 } 20133 20134 syncThumbStateWithMainSwiper(gallery); 20135 traceThumbSync(gallery, 'slotRenderEnded:after-sync', { slotId: slotId, isEmpty: !!event.isEmpty }); 20136 scheduleDescriptionThumbOverlapCheck(gallery); 20137 evaluateAllSlotRefreshes('slotRenderEnded'); 20138 }); 20139 20140 googletag.pubads().addEventListener('slotRequested', function (event) { 20141 const slotId = event.slot.getSlotElementId(); 20142 if (!adSlots.has(slotId)) { 20143 logExternalSlotEvent('slotRequested', event); 20144 return; 20145 } 20146 20147 debugAdLog('slotRequested (Gallery)', { 20148 slotId: slotId, 20149 path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null, 20150 slotTargetingFromCode: getStoredSlotTargetingSnapshot(event.slot), 20151 slotTargetingFromGpt: getSlotTargetingSnapshot(event.slot), 20152 pageTargeting: getPageTargetingSnapshot(), 20153 }); 20154 }); 20155 20156 googletag.pubads().addEventListener('slotResponseReceived', function (event) { 20157 const slotId = event.slot.getSlotElementId(); 20158 if (!adSlots.has(slotId)) { 20159 logExternalSlotEvent('slotResponseReceived', event); 20160 return; 20161 } 20162 20163 debugAdLog('slotResponseReceived (Gallery)', { 20164 slotId: slotId, 20165 path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null, 20166 }); 20167 }); 20168 20169 googletag.pubads().addEventListener('impressionViewable', function (event) { 20170 const slotId = event.slot.getSlotElementId(); 20171 const slotInfo = adSlots.get(slotId); 20172 if (!slotInfo) { 20173 return; 20174 } 20175 20176 const refreshState = getOrCreateRefreshState(slotInfo); 20177 if (!refreshState.viewableSinceTs) { 20178 refreshState.viewableSinceTs = Date.now(); 20179 } 20180 20181 debugAdLog('impressionViewable empfangen', { 20182 slotId: slotId, 20183 }); 20184 20185 evaluateAllSlotRefreshes('impressionViewable'); 20186 }); 20187 20188 galleries.forEach((gallery, wIndex) => { 20189 debugAdLog('Gallery-Ad-Konfiguration erkannt', getGalleryAdDatasetSnapshot(gallery)); 20190 20191 const adPos = parseInt(gallery.dataset.adpos, 10); 20192 let adData = {}; 20193 20194 if (!adPos || adPos < 1) { 20195 debugAdLog('Gallery ohne gueltige adPos uebersprungen', { 20196 galleryId: gallery.id || null, 20197 adPos: gallery.dataset.adpos, 20198 }); 20199 return; 20200 } 20201 20202 try { 20203 adData = JSON.parse(gallery.dataset.ad_gam_id); 20204 } catch (e) { 20205 debugAdLog('Gallery mit ungueltiger ad_gam_id uebersprungen', { 20206 galleryId: gallery.id || null, 20207 }); 20208 return; 20209 } 20210 if(!adData.path || !adData.sizes || adData.path.length < 1){ 20211 debugAdLog('Gallery ohne vollstaendige Ad-Daten uebersprungen', { 20212 galleryId: gallery.id || null, 20213 }); 20214 return; 20215 } 20216 20217 20218 const adId = `ad-id-${wIndex}`; 20219 20220 const mainWrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer'); 20221 if (!mainWrapper) { 20222 debugAdLog('Gallery ohne Slider-Container uebersprungen', { 20223 galleryId: gallery.id || null, 20224 }); 20225 return; 20226 } 20227 20228 if (Math.floor(mainWrapper.children.length / adPos) < 1) { 20229 debugAdLog('Gallery hat zu wenige Slides fuer Ad-Position', { 20230 galleryId: gallery.id || null, 20231 slideCount: mainWrapper.children.length, 20232 adPos: adPos, 20233 }); 20234 return; 20235 } 20236 20237 adIds.push(adId); 20238 const definedSlot = googletag.defineSlot(adData.path, adData.sizes, adId); 20239 if (!definedSlot) { 20240 debugAdLog('defineSlot lieferte kein Slot-Objekt, Gallery-Ad wird uebersprungen', { 20241 adId: adId, 20242 galleryId: gallery.id || null, 20243 path: adData.path || null, 20244 sizes: adData.sizes || null, 20245 }); 20246 adIds.pop(); 20247 return; 20248 } 20249 20250 const slotObj = definedSlot.addService(googletag.pubads()); 20251 applySlotTargeting(slotObj, adData); 20252 mirrorPageTargetingToSlot(slotObj); 20253 applyGalleryDatasetTargeting(slotObj, gallery); 20254 20255 const mainThumbWrapper = gallery.querySelector('.MediaGallery_thumbnailContainer'); 20256 20257 const staging = document.createElement('div'); 20258 // GPT/Creatives koennen in display:none sporadisch nicht sauber initialisieren. 20259 // Deshalb offscreen parken statt komplett aus dem Render-Tree zu nehmen. 20260 staging.style.position = 'absolute'; 20261 staging.style.left = '-10000px'; 20262 staging.style.top = '0'; 20263 staging.style.width = '1px'; 20264 staging.style.height = '1px'; 20265 staging.style.overflow = 'hidden'; 20266 staging.style.pointerEvents = 'none'; 20267 staging.innerHTML = `<div class="ad-container Ad" id="renderSlot-${adId}"><div id="${adId}"></div></div>`; 20268 gallery.appendChild(staging); 20269 20270 adSlots.set(adId, { 20271 adId: adId, 20272 gallery: gallery, 20273 adData: adData, 20274 mainWrapper: mainWrapper, 20275 mainThumbWrapper: mainThumbWrapper, 20276 adPos: adPos, 20277 staging: staging, 20278 injected: false, 20279 targetAdSlide: null, 20280 refreshState: { 20281 renderedLineItemId: null, 20282 previousRenderedLineItemId: null, 20283 viewableSinceTs: 0, 20284 lastRefreshTs: Date.now(), 20285 pending: false, 20286 lastRefreshReason: null, 20287 refreshCount: 0, 20288 lastAdSlideActivationTs: 0, 20289 fallbackRefreshDone: false, 20290 activeSlideFallbackTimerId: null, 20291 lastHandledAdSlideElement: null, 20292 lastHandledAdSlideTs: 0, 20293 }, 20294 }); 20295 20296 debugAdLog('Ad-Slot fuer Gallery registriert', { 20297 adId: adId, 20298 galleryId: gallery.id || null, 20299 adPos: adPos, 20300 slotTargetingFromCode: getStoredSlotTargetingSnapshot(slotObj), 20301 pageTargetingAtRegister: getPageTargetingSnapshot(), 20302 }); 20303 }); 20304 20305 function displayGallerySlots(waitAttempt) { 20306 const attempt = typeof waitAttempt === 'number' ? waitAttempt : 0; 20307 if (displayGallerySlots.executed) { 20308 return; 20309 } 20310 20311 if (!hasAllRequiredPageTargeting(REQUIRED_PAGE_TARGETING_KEYS) && attempt < MAX_DISPLAY_WAIT_ATTEMPTS) { 20312 debugAdLog('Display wartet auf required page-targeting', { 20313 attempt: attempt, 20314 maxAttempts: MAX_DISPLAY_WAIT_ATTEMPTS, 20315 requiredKeys: REQUIRED_PAGE_TARGETING_KEYS, 20316 pageTargetingNow: getPageTargetingSnapshot(), 20317 }); 20318 window.setTimeout(function () { 20319 displayGallerySlots(attempt + 1); 20320 }
20320, DISPLAY_WAIT_INTERVAL_MS); 20321 return; 20322 } 20323 20324 if (!hasAllRequiredPageTargeting(REQUIRED_PAGE_TARGETING_KEYS) && attempt >= MAX_DISPLAY_WAIT_ATTEMPTS) { 20325 debugAdLog('Display-Fallback ohne vollstaendiges page-targeting', { 20326 attempts: attempt, 20327 requiredKeys: REQUIRED_PAGE_TARGETING_KEYS, 20328 pageTargetingNow: getPageTargetingSnapshot(), 20329 }); 20330 } 20331 20332 displayGallerySlots.executed = true; 20333 adIds.forEach(function (id) { 20334 const slots = googletag.pubads().getSlots(); 20335 const slot = slots.find(function (s) { 20336 return s.getSlotElementId() === id; 20337 }); 20338 20339 if (slot) { 20340 mirrorPageTargetingToSlot(slot); 20341 } 20342 20343 debugAdLog('display() wird aufgerufen', { 20344 adId: id, 20345 hasSlotObject: !!slot, 20346 path: slot && typeof slot.getAdUnitPath === 'function' ? slot.getAdUnitPath() : null, 20347 slotTargetingFromCode: slot ? getStoredSlotTargetingSnapshot(slot) : {}, 20348 pageTargetingBeforeDisplay: getPageTargetingSnapshot(), 20349 }); 20350 20351 googletag.display(id); 20352 20353 debugAdLog('display() aufgerufen', { 20354 adId: id, 20355 }); 20356 }); 20357 debugAdLog('Gallery-Slots wurden ausgeloest', { count: adIds.length }); 20358 } 20359 20360 if (typeof window !== 'undefined') { 20361 window.__galleryDebugDump = function () { 20362 const slotStates = []; 20363 adSlots.forEach(function (slotInfo, adId) { 20364 slotStates.push({ 20365 adId: adId, 20366 injected: !!slotInfo.injected, 20367 hasTargetSlide: !!slotInfo.targetAdSlide, 20368 hasStaging: !!slotInfo.staging, 20369 adPos: slotInfo.adPos, 20370 }); 20371 }); 20372 20373 debugAdLog('Debug-Dump', { 20374 adIds: adIds.slice(), 20375 slotStates: slotStates, 20376 pubadsReady: !!googletag.pubadsReady, 20377 registeredSlots: googletag.pubads().getSlots().map(function (s) { 20378 return s.getSlotElementId(); 20379 }), 20380 }); 20381 }; 20382 20383 window.__galleryDebugRefresh = function () { 20384 const refreshed = []; 20385 const slots = googletag.pubads().getSlots(); 20386 20387 adIds.forEach(function (adId) { 20388 const slot = slots.find(function (s) { 20389 return s.getSlotElementId() === adId; 20390 }); 20391 if (slot) { 20392 googletag.pubads().refresh([slot]); 20393 refreshed.push(adId); 20394 } 20395 }); 20396 20397 debugAdLog('Debug-Refresh ausgefuehrt', { 20398 refreshedSlots: refreshed, 20399 requestedSlots: adIds.slice(), 20400 }); 20401 }; 20402 20403 window.__galleryDebugTargetingDump = function () { 20404 const slots = googletag.pubads().getSlots(); 20405 20406 adIds.forEach(function (adId) { 20407 const slot = slots.find(function (s) { 20408 return s.getSlotElementId() === adId; 20409 }); 20410 20411 if (!slot) { 20412 debugAdLog('Targeting-Dump: Slot nicht gefunden', { adId: adId }); 20413 return; 20414 } 20415 20416 const targeting = getSlotTargetingSnapshot(slot); 20417 const keys = Object.keys(targeting); 20418 20419 debugAdLog('Targeting-Dump', { 20420 adId: adId, 20421 keys: keys, 20422 targeting: targeting, 20423 }); 20424 }); 20425 }; 20426 20427 window.__galleryDebugExternalStats = function () { 20428 const snapshot = JSON.parse(JSON.stringify(externalSlotDebugStats)); 20429 debugAdLog('External-Slot-Debug-Stats', snapshot); 20430 return snapshot; 20431 }; 20432 } 20433 20434 if (googletag.pubadsReady) { 20435 debugAdLog('pubads bereits aktiv, display direkt', {}); 20436 displayGallerySlots(0); 20437 } else if (document.readyState === 'loading') { 20438 document.addEventListener('DOMContentLoaded', function () { 20439 googletag.cmd.push(function () { 20440 debugAdLog('display nach DOMContentLoaded ausgefuehrt', {}); 20441 displayGallerySlots(0); 20442 }); 20443 }, { once: true });
20444 } else { 20445 googletag.cmd.push(function () { 20446 debugAdLog('display nach spaeterem GPT-Init ausgefuehrt', {}); 20447 displayGallerySlots(0); 20448 }); 20449 } 20450 20451 if (typeof window !== 'undefined' && adSlots.size > 0) { 20452 window.setInterval(function () { 20453 evaluateAllSlotRefreshes('interval'); 20454 maybeRefreshExternalSlotsByInterval(); 20455 }, refreshRuntimeConfig.refreshCheckIntervalMs); 20456 } 20457 20458 20459 galleries.forEach(function (gallery) { 20460 const thumbnailsEl = gallery.querySelector('.MediaGallery_thumbnails'); 20461 const sliderEl = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider'); 20462 const paginationEl = gallery.querySelector('.swiper-pagination'); 20463 20464 forceThumbnailContainerFullWidth(gallery); 20465 bindDescriptionThumbOverlapGuard(gallery); 20466 20467 if (paginationEl) { 20468 paginationEl.style.display = 'none'; 20469 } 20470 20471 if (!sliderEl) { 20472 return; 20473 } 20474 20475 if (thumbnailsEl) { 20476 gallery.tSwiper = new Swiper(thumbnailsEl, { 20477 slidesPerView: 'auto', 20478 centeredSlides: false, 20479 centeredSlidesBounds: false, 20480 centerInsufficientSlides: false, 20481 slideToClickedSlide: true, 20482 watchSlidesProgress: true, 20483 observer: true, 20484 observeParents: true, 20485 spaceBetween: 10 20486 }); 20487 20488 gallery.tSwiper.on('tap', function () { 20489 if (!gallery.mSwiper || typeof this.clickedIndex !== 'number') { 20490 return; 20491 } 20492 20493 const clickedImageIndex = this.clickedIndex; 20494 const targetMainIndex = getMainIndexFromImageIndex(gallery.mSwiper.slides, clickedImageIndex); 20495 if (targetMainIndex >= 0) { 20496 const currentMainIndex = gallery.mSwiper.activeIndex; 20497 const currentImageIndex = getImageIndexFromMainIndex(gallery.mSwiper.slides, currentMainIndex); 20498 const adBeforeTargetMainIndex = targetMainIndex > 0 && gallery.mSwiper.slides[targetMainIndex - 1] && gallery.mSwiper.slides[targetMainIndex - 1].classList.contains('ad-slide') 20499 ? targetMainIndex - 1 20500 : -1; 20501 const adAfterTargetMainIndex = gallery.mSwiper.slides[targetMainIndex + 1] && gallery.mSwiper.slides[targetMainIndex + 1].classList.contains('ad-slide') 20502 ? targetMainIndex + 1 20503 : -1; 20504 const isForwardNavigation = clickedImageIndex > currentImageIndex; 20505 const isBackwardNavigation = clickedImageIndex < currentImageIndex; 20506 20507 if (isForwardNavigation && adBeforeTargetMainIndex >= 0 && currentMainIndex < adBeforeTargetMainIndex) { 20508 gallery.mSwiper.slideTo(adBeforeTargetMainIndex); 20509 return; 20510 } 20511 20512 if (isBackwardNavigation && adAfterTargetMainIndex >= 0 && currentMainIndex > adAfterTargetMainIndex) { 20513 gallery.mSwiper.slideTo(adAfterTargetMainIndex); 20514 return; 20515 } 20516 20517 gallery.mSwiper.slideTo(targetMainIndex); 20518 traceThumbSync(gallery, 'thumbTap:slideTo', { clickedImageIndex: clickedImageIndex, targetMainIndex: targetMainIndex }); 20519 } 20520 }); 20521 } else { 20522 gallery.tSwiper = null; 20523 } 20524 20525 const mainSwiperConfig = { 20526 loop: false, 20527 slidesPerView: 1, 20528 autoHeight: true, 20529 pagination: { 20530 el: '.swiper-pagination', 20531 clickable: true, 20532 centered: true, 20533 }, 20534 navigation: { 20535 nextEl: '.swiper-button-next', 20536 prevEl: '.swiper-button-prev', 20537 addIcons: false 20538 }, 20539 keyboard: { 20540 enabled: true, 20541 onlyInViewport: true, 20542 }, 20543 centeredSlides: true, 20544 centeredSlidesBounds: true, 20545 observer: true, 20546 observeParents: true, 20547 observeSlideChildren: true, 20548 on: { 20549 init: function () { 20550 normalizeGallerySlideHeights(gallery);
20551 refreshSwiperAutoHeight(this, gallery); 20552 clearInitialSlideHeightIfReady(gallery, this); 20553 rememberCurrentImageSlideHeight(gallery, this); 20554 setGalleryAdNavigationState(gallery, this.slides && typeof this.activeIndex === 'number' ? this.slides[this.activeIndex] : null); 20555 scheduleDescriptionThumbOverlapCheck(gallery); 20556 }, 20557 slideChange: function() { 20558 const activeIndex = this.activeIndex; 20559 const activeSlide = this.slides[this.activeIndex]; 20560 if (!activeSlide) { 20561 return; 20562 } 20563 20564 setGalleryAdNavigationState(gallery, activeSlide); 20565 20566 traceThumbSync(gallery, 'slideChange:start'); 20567 20568 refreshSwiperAutoHeight(this, gallery); 20569 clearInitialSlideHeightIfReady(gallery, this); 20570 20571 triggerVirtualPageTracking(gallery, activeSlide, activeIndex); 20572 20573 if (gallery.tSwiper && activeSlide && !activeSlide.classList.contains('ad-slide')) { 20574 rememberCurrentImageSlideHeight(gallery, this); 20575 const imageIndex = getImageIndexFromMainIndex(this.slides, this.activeIndex); 20576 if (imageIndex >= 0) { 20577 updateActiveThumbState(gallery, imageIndex); 20578 syncThumbSwiperToImageIndex(gallery, imageIndex); 20579 traceThumbSync(gallery, 'slideChangeTransitionEnd:image-slide', { targetImageIndex: imageIndex }); 20580 } 20581 } 20582 20583 maybeRefreshExternalSlotsByAdPos(gallery, this); 20584 refreshActiveAdSlot(gallery, activeSlide); 20585 traceThumbSync(gallery, 'slideChangeTransitionEnd:end'); 20586 scheduleDescriptionThumbOverlapCheck(gallery); 20587 } 20588 } 20589 }; 20590 20591 applyInitialSlideHeight(gallery); 20592 applySliderContainerMinHeight(gallery); 20593 20594 gallery.mSwiper = new Swiper(sliderEl, mainSwiperConfig); 20595 20596 setGalleryAdNavigationState( 20597 gallery, 20598 gallery.mSwiper && gallery.mSwiper.slides && typeof gallery.mSwiper.activeIndex === 'number' 20599 ? gallery.mSwiper.slides[gallery.mSwiper.activeIndex] 20600 : null 20601 ); 20602 20603 normalizeGallerySlideHeights(gallery); 20604 bindImageLoadAutoHeight(gallery); 20605 20606 refreshSwiperAutoHeight(gallery.mSwiper, gallery); 20607 clearInitialSlideHeightIfReady(gallery, gallery.mSwiper); 20608 scheduleDescriptionThumbOverlapCheck(gallery); 20609 20610 if (gallery.tSwiper && gallery.mSwiper && gallery.mSwiper.slides && typeof gallery.mSwiper.activeIndex === 'number') { 20611 rememberCurrentImageSlideHeight(gallery, gallery.mSwiper); 20612 const initialImageIndex = getImageIndexFromMainIndex(gallery.mSwiper.slides, gallery.mSwiper.activeIndex); 20613 if (initialImageIndex >= 0) { 20614 updateActiveThumbState(gallery, initialImageIndex); 20615 } 20616 } 20617 }); 20618 20619 }); 20620})(); 20621 20622 20623 20624 20625/* ----- DOCUMENT READY FUNCTION ------ */ 20626 20627$(function() { 20628 20629 if (!$("Body.BodyGallery").length ) { 20630 // Sticky Header nicht in Galerie-Detailseiten 20631 20632 $(window).on('scroll resize touchmove',function(){ 20633 stickybegins = $(".SiteHeader").offset().top + $(".SiteHeader").height(); 20634 20635 if($(this).scrollTop()>stickybegins && window.innerWidth>768){ 20636 $('.SiteHeaderSticky').fadeIn(); 20637 }else{ 20638 $('.SiteHeaderSticky').fadeOut(); 20639 } 20640 }); 20641 20642 20643 } 20644 20645 20646} ); 20647 20648
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.