vendor: 5,019 bytes, lines 1-4
1/*! Magnific Popup - v1.1.0 - 2016-02-20 2* http://dimsemenov.com/plugins/magnific-popup/ 3* Copyright (c) 2016 Dmitry Semenov; */ 4!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h="Close",i="BeforeClose",j="AfterClose",k="BeforeAppend",l="MarkupParse",m="Open",n="Change",o="mfp",p="."+o,q="mfp-ready",r="mfp-removing",s="mfp-prevent-close",t=function(){},u=!!window.jQuery,v=a(window),w=function(a,c){b.ev.on(o+a+p,c)},x=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},y=function(c,d){b.ev.triggerHandler(o+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},z=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},A=function(){a.magnificPopup.instance||(b=new t,b.init(),a.magnificPopup.instance=b)},B=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in a)return!0;return!1};t.prototype={constructor:t,init:function(){var c=navigator.appVersion;b.isLowIE=b.isIE8=document.all&&!document.addEventListener,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=B(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(c.isObj===!1){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f="",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=x("bg").on("click"+p,function(){b.close()}),b.wrap=x("wrap").attr("tabindex",-1).on("click"+p,function(a){b._checkIfClose(a.target)&&b.close()}),b.container=x("container",b.wrap)),b.contentContainer=x("content"),b.st.preloader&&(b.preloader=x("preloader",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var j=i[e];j=j.charAt(0).toUpperCase()+j.slice(1),b["init"+j].call(b)}y("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(w(l,function(a,b,c,d){c.close_replaceWith=z(d.type)}),f+=" mfp-close-btn-in"):b.wrap.append(z())),b.st.alignTop&&(f+=" mfp-align-top"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.st.overflowY}):b.wrap.css({top:v.scrollTop(),position:"absolute"}),(b.st.fixedBgPos===!1||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup"+p,function(a){27===a.keyCode&&b.close()}),v.on("resize"+p,function(){b.updateSize()}),b.st.closeOnContentClick||(f+=" mfp-auto-cursor"),f&&b.wrap.addClass(f);var k=b.wH=v.height(),n={};if(b.fixedContentPos&&b._hasScrollBar(k)){var o=b._getScrollbarSize();o&&(n.marginRight=o)}b.fixedContentPos&&(b.isIE7?a("body, html").css("overflow","hidden"):n.overflow="hidden");var r=b.st.mainClass;return b.isIE7&&(r+=" mfp-ie7"),r&&b._addClassToMFP(r),b.updateItemHTML(),y("BuildControls"),a("html").css(n),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP(q),b._setFocus()):b.bgOverlay.addClass(q),d.on("focusin"+p,b._onFocusIn)},16),b.isOpen=!0,b.updateSize(k),y(m),c},close:function(){b.isOpen&&(y(i),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP(r),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){y(h);var c=r+" "+q+" ";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+" "),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:""};b.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup"+p+" focusin"+p),b.ev.off(p),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&b.currTemplate[b.currItem.type]!==!0||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b.st.autoFocusLast&&b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,y(j)}
4,updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else b.wH=a||v.height();b.fixedContentPos||b.wrap.css("height",b.wH),y("Resize")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(y("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var f=b.st[d]?b.st[d].markup:!1;y("FirstMarkupParse",f),f?b.currTemplate[d]=a(f):b.currTemplate[d]=!0}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,y(n,c),e=c.type,b.container.prepend(b.contentContainer),y("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&b.currTemplate[c]===!0?b.content.find(".mfp-close").length||b.content.append(z()):b.content=a:b.content="",y(k),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,y("ElementParse",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){var f=void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick;if(f||!(2===c.which||c.ctrlKey||c.metaKey||c.altKey||c.shiftKey)){var g=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(g)if(a.isFunction(g)){if(!g.call(b))return!0}else if(v.width()<g)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var e={status:a,text:d};y("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass(s)){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||v.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){return c.target===b.wrap[0]||a.contains(b.wrap[0],c.target)?void 0:(b._setFocus(),!1)},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),y(l,[b,c,d]),a.each(c,function(c,d){if(void 0===d||d===!1)return!0;if(e=c.split("_"),e.length>1){var f=b.find(p+"-"+e[0]);if(f.length>0){var g=e[1];"replaceWith"===g?f[0]!==d[0]&&f.replaceWith(d):"img"===g?f.is("img")?f.attr("src",d):f.replaceWith(a("<img>").attr("src",d).attr("class",f.attr("class"))):f.attr(e[1],d)}}else b.find(p+"-"+c).html(d)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement("div");a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:t.prototype,modules:[],open:function(b,c){return A(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading...",autoFocusLast:!0}},a.fn.magnificPopup=function(c){A();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=u?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1
4));else c=a.extend(!0,{},c),u?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var C,D,E,F="inline",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push(F),w(h+"."+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C="mfp-"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("<div>");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var H,I="ajax",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+"."+I,K),w("BeforeChange."+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};y("ParseAjax",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus("ready"),y("AjaxContentAdded")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var L,M=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;
4var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),w(m+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off("resize"+p)}),w("Resize"+d,b.resizeImage),b.isLowIE&&w("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return d.naturalWidth>0?void b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,y("ImageLoadComplete")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var N,O=function(){return void 0===N&&(N=void 0!==document.createElement("p").style.MozTransform),N};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,j=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css("visibility","visible")};w("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),a=b._getItemToZoom(),!a)return void k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y("ZoomAnimationEnded")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return O()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});
4var P="iframe",Q="//about:blank",R=function(a){if(b.currTemplate[P]){var c=b.currTemplate[P].find("iframe");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule(P,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push(P),w("BeforeChange",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+"."+P,function(){R()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return e.indexOf(this.index)>-1?(this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1):void 0});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var S=function(a){var c=b.items.length;return a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery";return b.direction=!0,c&&c.enabled?(f+=" mfp-gallery",w(m+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){return b.items.length>1?(b.next(),!1):void 0}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w("UpdateStatus"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):""}),w("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass(s);e.click(function(){b.prev()}),f.click(function(){b.next()}),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void w(h+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),y("LazyLoad",d),"image"===d.type&&(d.img=a('<img class="mfp-img" />').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,y("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});var U="retina";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w("ImageHasSize."+U,function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),w("ElementParse."+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),A()}); 5/* 6 _ _ _ _ 7 ___| (_) ___| | __ (_)___ 8/ __| | |/ __| |/ / | / __| 9\__ \ | | (__| < _ | \__ \ 10|___/_|_|\___|_|\_(_)/ |___/ 11 |__/ 12 13 Version: 1.5.9 14 Author: Ken Wheeler 15 Website: http://kenwheeler.github.io 16 Docs: http://kenwheeler.github.io/slick 17 Repo: http://github.com/kenwheeler/slick 18 Issues: http://github.com/kenwheeler/slick/issues 19 20 */ 21!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'<button type="button" data-role="none" role="button" aria-required="false" tabindex="0">'+(b+1)+"</button>"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!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:!1
vendor: 38,833 bytes, lines 21-22
21,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},e.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,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.hidden="hidden",e.paused=!1,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,f,d),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.registerBreakpoints(),e.init(!0),e.checkResponsive(!0)}var b=0;return c}(),b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),e.options.vertical===!1?d[e.animType]="translate3d("+b+"px, 0px, 0px)":d[e.animType]="translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.asNavFor=function(b){var c=this,d=c.options.asNavFor;d&&null!==d&&(d=a(d).not(c.$slider)),null!==d&&"object"==typeof d&&d.each(function(){var c=a(this).slick("getSlick");c.unslicked||c.slideHandler(b,!0)})},b.prototype.applyTransition=function(a){var b=this,c={};b.options.fade===!1?c[b.transitionType]=b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:c[b.transitionType]="opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer),a.slideCount>a.options.slidesToShow&&a.paused!==!0&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this;a.options.infinite===!1?1===a.direction?(a.currentSlide+1===a.slideCount-1&&(a.direction=0),a.slideHandler(a.currentSlide+a.options.slidesToScroll)):(a.currentSlide-1===0&&(a.direction=1),a.slideHandler(a.currentSlide-a.options.slidesToScroll)):a.slideHandler(a.currentSlide+a.options.slidesToScroll)},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&(b.$prevArrow=a(b.options.prevArrow).addClass("slick-arrow"),b.$nextArrow=a(b.options.nextArrow).addClass("slick-arrow"),b.slideCount>b.options.slidesToShow?(b.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.prependTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):b.$prevArrow.add(b.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(d='<ul class="'+b.options.dotsClass+'">',c=0;c<=b.getDotCount();c+=1)d+="<li>"+b.options.customPaging.call(this,b,c)+"</li>";d+="</ul>",b.$dots=a(d).appendTo(b.options.appendDots),b.$dots.find("li").first().addClass("slick-active").attr("aria-hidden","false")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slides.each(function(b,c){a(c).attr("data-slick-index",b).data("originalStyling",a(c).attr("style")||"")}),b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('<div class="slick-track"/>').appendTo(b.$slider):b.$slides.wrapAll('<div class="slick-track"/>').parent(),b.$list=b.$slideTrack.wrap('<div aria-live="polite" class="slick-list"/>').parent(),b.$slideTrack.css("opacity",0),(b.options.centerMode===!0||b.options.swipeToSlide===!0)&&(b.options.slidesToScroll=1),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.buildRows=function(){var b,c,d,e,f,g,h,a=this;if(e=document.createDocumentFragment(),g=a.$slider.children(),a.options.rows>1){for(h=a.options.slidesPerRow*a.options.rows,f=Math.ceil(g.length/h),b=0;f>b;b++){var i=document.createElement("div");for(c=0;c<a.options.rows;c++){var j=document.createElement("div");for(d=0;d<a.options.slidesPerRow;d++){var k=b*h+(c*a.options.slidesPerRow+d);g.get(k)&&j.appendChild(g.get(k))}i.appendChild(j)}e.appendChild(i)}a.$slider.html(e),a.$slider.children().children().children().css({width:100/a.options.slidesPerRow+"%",display:"inline-block"})}},b.prototype.checkResponsive=function(b,c){var e,f,g,d=this,h=!1,i=d.$slider.width(),j=window.innerWidth||a(window).width();if("window"===d.respondTo?g=j:"slider"===d.respondTo?g=i:"min"===d.respondTo&&(g=Math.min(j,i)),d.options.responsive&&d.options.responsive.length&&null!==d.options.responsive){f=null;for(e in d.breakpoints)d.breakpoints.hasOwnProperty(e)&&(d.originalSettings.mobileFirst===!1?g<d.breakpoints[e]&&(f=d.breakpoints[e]):g>d.breakpoints[e]&&(f=d.breakpoints[e]));null!==f?null!==d.activeBreakpoint?(f!==d.activeBreakpoint||c)&&(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):null!==d.activeBreakpoint&&(d.activeBreakpoint=null,d.options=d.originalSettings,b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b),h=f),b||h===!1||d.$slider.trigger("breakpoint",[d,h])}},b.prototype.changeSlide=function(b,c){var f,g,h,d=this,e=a(b.target);switch(e.is("a")&&b.preventDefault(),e.is("li")||(e=e.closest("li")),h=d.slideCount%d.options.slidesToScroll!==0,f=h?0:(d.slideCount-d.currentSlide)%d.options.slidesToScroll,b.data.message){case"previous":g=0===f?d.options.slidesToScroll:d.options.slidesToShow-f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide-g,!1,c);break;case"next":g=0===f?d.options.slidesToScroll:f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide+g,!1,c);break;case"index":var i=0===b.data.index?0:b.data.index||e.index()*d.options.slidesToScroll;d.slideHandler(d.checkNavigable(i),!1,c),e.children().trigger("focus");break;default:return}},b.prototype.checkNavigable=function(a){var c,d,b=this;if(c=b.getNavigableIndexes(),d=0,a>c[c.length-1])a=c[c.length-1];else for(var e in c){if(a<c[e]){a=d;break}d=c[e]}return a},b.prototype.cleanUpEvents=function(){var b=this;b.options.dots&&null!==b.$dots&&(a("li",b.$dots).off("click.slick",b.changeSlide),b.options.pauseOnDotsHover===!0&&b.options.autoplay===!0&&a("li",b.$dots).off("mouseenter.slick",a.proxy(b.setPaused,b,!0)).off("mouseleave.slick",a.proxy(b.setPaused,b,!1))),b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow&&b.$prevArrow.off("click.slick",b.changeSlide),b.$nextArrow&&b.$nextArrow.off("click.slick",b.changeSlide)),b.$list.off("touchstart.slick mousedown.slick",b.swipeHandler),b.$list.off("touchmove.slick mousemove.slick",b.swipeHandler),b.$list.off("touchend.slick mouseup.slick",b.swipeHandler),b.$list.off("touchcancel.slick mouseleave.slick",b.swipeHandler),b.$list.off("click.slick",b.clickHandler),a(document).off(b.visibilityChange,b.visibility),b.$list.off("mouseenter.slick",a.proxy(b.setPaused,b,!0)),b.$list.off("mouseleave.slick",a.proxy(b.setPaused,b,!1)),b.options.accessibility===!0&&b.$list.off("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().off("click.slick",b.selectHandler),a(window).off("orientationchange.slick.slick-"+b.instanceUid,b.orientationChange),a(window).off("resize.slick.slick-"+b.instanceUid,b.resize),a("[draggable!=true]",b.$slideTrack).off("dragstart",b.preventDefault),a(window).off("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).off("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.cleanUpRows=function(){var b,a=this;a.options.rows>1&&(b=a.$slides.children().children(),b.removeAttr("style"),a.$slider.html(b))},b.prototype.clickHandler=function(a){var b=this;b.shouldClick===!1&&(a.stopImmediatePropagation(),a.stopPropagation(),a.preventDefault())},b.prototype.destroy=function(b){var c=this;c.autoPlayClear(),c.touchObject={},c.cleanUpEvents(),a(".slick-cloned",c.$slider).detach(),c.$dots&&c.$dots.remove(),c.$prevArrow&&c.$prevArrow.length&&(c.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.prevArrow)&&c.$prevArrow.remove()),c.$nextArrow&&c.$nextArrow.length&&(c.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.nextArrow)&&c.$nextArrow.remove()),c.$slides&&(c.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){a(this).attr("style",a(this).data("originalStyling"))}),c.$slideTrack.children(this.options.slide).detach(),c.$slideTrack.detach(),c.$list.detach(),c.$slider.append(c.$slides)),c.cleanUpRows(),c.$slider.removeClass("slick-slider"),c.$slider.removeClass("slick-initialized"),c.unslicked=!0,b||c.$slider.trigger("destroy",[c])},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b){var c=this;c.cssTransitions===!1?(c.$slides.eq(a).css({zIndex:c.options.zIndex}),c.$slides.eq(a).animate({opacity:1},c.options.speed,c.options.easing,b)):(c.applyTransition(a),c.$slides.eq(a).css({opacity:1,zIndex:c.options.zIndex}),b&&setTimeout(function(){c.disableTransition(a),b.call()},c.options.speed))},b.prototype.fadeSlideOut=function(a){var b=this;b.cssTransitions===!1?b.$slides.eq(a).animate({opacity:0,zIndex:b.options.zIndex-2},b.options.speed,b.options.easing):(b.applyTransition(a),b.$slides.eq(a).css({opacity:0,zIndex:b.options.zIndex-2}))},b.prototype.filterSlides=b.prototype.slickFilter=function(a){var b=this;null!==a&&(b.$slidesCache=b.$slides,b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.getCurrent=b.prototype.slickCurrentSlide=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var a=this,b=0,c=0,d=0;if(a.options.infinite===!0)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else if(a.options.centerMode===!0)d=a.slideCount;else for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d-1},b.prototype.getLeft=function(a){var c,d,f,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(!0),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=b.slideWidth*b.options.slidesToShow*-1,e=d*b.options.slidesToShow*-1),b.slideCount%b.options.slidesToScroll!==0&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(a>b.slideCount?(b.slideOffset=(b.options.slidesToShow-(a-b.slideCount))*b.slideWidth*-1,e=(b.options.slidesToShow-(a-b.slideCount))*d*-1):(b.slideOffset=b.slideCount%b.options.slidesToScroll*b.slideWidth*-1,e=b.slideCount%b.options.slidesToScroll*d*-1))):a+b.options.slidesToShow>b.slideCount&&(b.slideOffset=(a+b.options.slidesToShow-b.slideCount)*b.slideWidth,e=(a+b.options.slidesToShow-b.slideCount)*d),b.slideCount<=b.options.slidesToShow&&(b.slideOffset=0,e=0),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset=0,b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?a*b.slideWidth*-1+b.slideOffset:a*d*-1+e,b.options.variableWidth===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,b.options.centerMode===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow+1),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,c+=(b.$list.width()-f.outerWidth())/2)),c},b.prototype.getOption=b.prototype.slickGetOption=function(a){var b=this;return b.options[a]},b.prototype.getNavigableIndexes=function(){var e,a=this,b=0,c=0,d=[];for(a.options.infinite===!1?e=a.slideCount:(b=-1*a.options.slidesToScroll,c=-1*a.options.slidesToScroll,e=2*a.slideCount);e>b;)d.push(b),b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d},b.prototype.getSlick=function(){return this},b.prototype.getSlideCount=function(){var c,d,e,b=this;return e=b.options.centerMode===!0?b.slideWidth*Math.floor(b.options.slidesToShow/2):0,b.options.swipeToSlide===!0?(b.$slideTrack.find(".slick-slide").each(function(c,f){return f.offsetLeft-e+a(f).outerWidth()/2>-1*b.swipeLeft?(d=f,!1):void 0}),c=Math.abs(a(d).attr("data-slick-index")-b.currentSlide)||1):b.options.slidesToScroll},b.prototype.goTo=b.prototype.slickGoTo=function(a,b){var c=this;c.changeSlide({data:{message:"index",index:parseInt(a)}},b)},b.prototype.init=function(b){var c=this;a(c.$slider).hasClass("slick-initialized")||(a(c.$slider).addClass("slick-initialized"),c.buildRows(),c.buildOut(),c.setProps(),c.startLoad(),c.loadSlider(),c.initializeEvents(),c.updateArrows(),c.updateDots()),b&&c.$slider.trigger("init",[c]),c.options.accessibility===!0&&c.initADA()},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&b.options.autoplay===!0&&a("li",b.$dots).on("mouseenter.slick",a.proxy(b.setPaused,b,!0)).on("mouseleave.slick",a.proxy(b.setPaused,b,!1))},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.$list.on("click.slick",b.clickHandler),a(document).on(b.visibilityChange,a.proxy(b.visibility,b)),b.$list.on("mouseenter.slick",a.proxy(b.setPaused,b,!0)),b.$list.on("mouseleave.slick",a.proxy(b.setPaused,b,!1)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,a.proxy(b.orientationChange,b)),a(window).on("resize.slick.slick-"+b.instanceUid,a.proxy(b.resize,b)),a("[draggable!=true]",b.$slideTrack).on("dragstart",b.preventDefault),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show(),a.options.autoplay===!0&&a.autoPlay()},b.prototype.keyHandler=function(a){var b=this;a.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===a.keyCode&&b.options.accessibility===!0?b.changeSlide({data:{message:"previous"}}):39===a.keyCode&&b.options.accessibility===!0&&b.changeSlide({data:{message:"next"}}))},b.prototype.lazyLoad=function(){function g(b){a("img[data-lazy]",b).each(function(){var b=a(this),c=a(this).attr("data-lazy"),d=document.createElement("img");d.onload=function(){b.animate({opacity:0},100,function(){b.attr("src",c).animate({opacity:1},200,function(){b.removeAttr("data-lazy").removeClass("slick-loading")})})},d.src=c})}var c,d,e,f,b=this;b.options.centerMode===!0?b.options.infinite===!0?(e=b.currentSlide+(b.options.slidesToShow/2+1),f=e+b.options.slidesToShow+2):(e=Math.max(0,b.currentSlide-(b.options.slidesToShow/2+1)),f=2+(b.options.slidesToShow/2+1)+b.currentSlide):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=e+b.options.slidesToShow,b.options.fade===!0&&(e>0&&e--,f<=b.slideCount&&f++)),c=b.$slider.find(".slick-slide").slice(e,f),g(c),b.slideCount<=b.options.slidesToShow?(d=b.$slider.find(".slick-slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.next=b.prototype.slickNext=function(){var a=this;a.changeSlide({data:{message:"next"}})},b.prototype.orientationChange=function(){var a=this;a.checkResponsive(),a.setPosition()},b.prototype.pause=b.prototype.slickPause=function(){var a=this;a.autoPlayClear(),a.paused=!0},b.prototype.play=b.prototype.slickPlay=function(){var a=this;a.paused=!1,a.autoPlay()},b.prototype.postSlide=function(a){var b=this;b.$slider.trigger("afterChange",[b,a]),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay===!0&&b.paused===!1&&b.autoPlay(),b.options.accessibility===!0&&b.initADA()},b.prototype.prev=b.prototype.slickPrev=function(){var a=this;a.changeSlide({data:{message:"previous"}})},b.prototype.preventDefault=function(a){a.preventDefault()},b.prototype.progressiveLazyLoad=function(){var c,d,b=this;c=a("img[data-lazy]",b.$slider).length,c>0&&(d=a("img[data-lazy]",b.$slider).first(),d.attr("src",null),d.attr("src",d.attr("data-lazy")).removeClass("slick-loading").load(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad(),b.options.adaptiveHeight===!0&&b.setPosition()}).error(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad()}))},b.prototype.refresh=function(b){var d,e,c=this;e=c.slideCount-c.options.slidesToShow,c.options.infinite||(c.slideCount<=c.options.slidesToShow?c.currentSlide=0:c.currentSlide>e&&(c.currentSlide=e)),d=c.currentSlide,c.destroy(!0),a.extend(c,c.initials,{currentSlide:d}),c.init(),b||c.changeSlide({data:{message:"index",index:d}},!1)},b.prototype.registerBreakpoints=function(){var c,d,e,b=this,f=b.options.responsive||null;if("array"===a.type(f)&&f.length){b.respondTo=b.options.respondTo||"window";for(c in f)if(e=b.breakpoints.length-1,d=f[c].breakpoint,f.hasOwnProperty(c)){for(;e>=0;)b.breakpoints[e]&&b.breakpoints[e]===d&&b.breakpoints.splice(e,1),e--;b.breakpoints.push(d),b.breakpointSettings[d]=f[c].settings}b.breakpoints.sort(function(a,c){return b.options.mobileFirst?a-c:c-a})}},b.prototype.reinit=function(){var b=this;b.$slides=b.$slideTrack.children(b.options.slide).addClass("slick-slide"),b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.slideCount<=b.options.slidesToShow&&(b.currentSlide=0),b.registerBreakpoints(),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.checkResponsive(!1,!0),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),b.setSlideClasses(0),b.setPosition(),b.$slider.trigger("reInit",[b]),b.options.autoplay===!0&&b.focusHandler()},b.prototype.resize=function(){var b=this;a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.unslicked||b.setPosition()},50))},b.prototype.removeSlide=b.prototype.slickRemove=function(a,b,c){var d=this;return"boolean"==typeof a?(b=a,a=b===!0?0:d.slideCount-1):a=b===!0?--a:a,d.slideCount<1||0>a||a>d.slideCount-1?!1:(d.unload(),c===!0?d.$slideTrack.children().remove():d.$slideTrack.children(this.options.slide).eq(a).remove(),d.$slides=d.$slideTrack.children(this.options.slide),d.$slideTrack.children(this.options.slide).detach(),d.$slideTrack.append(d.$slides),d.$slidesCache=d.$slides,void d.reinit())},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a),d="left"==b.positionProp?Math.ceil(a)+"px":"0px",e="top"==b.positionProp?Math.ceil(a)+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.vertical===!1?a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding}):(a.$list.height(a.$slides.first().outerHeight(!0)*a.options.slidesToShow),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"})),a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.options.vertical===!1&&a.options.variableWidth===!1?(a.slideWidth=Math.ceil(a.listWidth/a.options.slidesToShow),a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children(".slick-slide").length))):a.options.variableWidth===!0?a.$slideTrack.width(5e3*a.slideCount):(a.slideWidth=Math.ceil(a.listWidth),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight(!0)*a.$slideTrack.children(".slick-slide").length)));var b=a.$slides.first().outerWidth(!0)-a.$slides.first().width();a.options.variableWidth===!1&&a.$slideTrack.children(".slick-slide").width(a.slideWidth-b)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=b.slideWidth*d*-1,b.options.rtl===!0?a(e).css({position:"relative",right:c,top:0,zIndex:b.options.zIndex-2,opacity:0}):a(e).css({position:"relative",left:c,top:0,zIndex:b.options.zIndex-2,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:b.options.zIndex-1,opacity:1})},b.prototype.setHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.css("height",b)}},b.prototype.setOption=b.prototype.slickSetOption=function(b,c,d){var f,g,e=this;if("responsive"===b&&"array"===a.type(c))for(g in c)if("array"!==a.type(e.options.responsive))e.options.responsive=[c[g]];else{for(f=e.options.responsive.length-1;f>=0;)e.options.responsive[f].breakpoint===c[g].breakpoint&&e.options.responsive.splice(f,1),f--;e.options.responsive.push(c[g])}else e.options[b]=c;d===!0&&(e.unload(),e.reinit())},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.setHeight(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade(),a.$slider.trigger("setPosition",[a])},b.prototype.setProps=function(){var a=this,b=document.body.style;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==b.WebkitTransition||void 0!==b.MozTransition||void 0!==b.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),a.options.fade&&("number"==typeof a.options.zIndex?a.options.zIndex<3&&(a.options.zIndex=3):a.options.zIndex=a.defaults.zIndex),void 0!==b.OTransform&&(a.animType="OTransform",a.transformType="-o-transform",a.transitionType="OTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition",void 0===b.perspectiveProperty&&void 0===b.MozPerspective&&(a.animType=!1)),void 0!==b.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition",void 0===b.msTransform&&(a.animType=!1)),void 0!==b.transform&&a.animType!==!1&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=a.options.useTransform&&null!==a.animType&&a.animType!==!1},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;d=b.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),b.$slides.eq(a).addClass("slick-current"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active").attr("aria-hidden","false"):(e=b.options.slidesToShow+a,d.slice(e-c+1,e+c+2).addClass("slick-active").attr("aria-hidden","false")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center")),b.$slides.eq(a).addClass("slick-center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):d.length<=b.options.slidesToShow?d.addClass("slick-active").attr("aria-hidden","false"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-a<b.options.slidesToShow?d.slice(e-(b.options.slidesToShow-f),e+f).addClass("slick-active").attr("aria-hidden","false"):d.slice(e,e+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false")),"ondemand"===b.options.lazyLoad&&b.lazyLoad()},b.prototype.setupInfinite=function(){var c,d,e,b=this;if(b.options.fade===!0&&(b.options.centerMode=!1),b.options.infinite===!0&&b.options.fade===!1&&(d=null,b.slideCount>b.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d-b.slideCount).prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d+b.slideCount).appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.setPaused=function(a){var b=this;b.options.autoplay===!0&&b.options.pauseOnHover===!0&&(b.paused=a,a?b.autoPlayClear():b.autoPlay())},b.prototype.selectHandler=function(b){var c=this,d=a(b.target).is(".slick-slide")?a(b.target):a(b.target).parents(".slick-slide"),e=parseInt(d.attr("data-slick-index"));return e||(e=0),c.slideCount<=c.options.slidesToShow?(c.setSlideClasses(e),void c.asNavFor(e)):void c.slideHandler(e)},b.prototype.slideHandler=function(a,b,c){var d,e,f,g,h=null,i=this;return b=b||!1,i.animating===!0&&i.options.waitForAnimate===!0||i.options.fade===!0&&i.currentSlide===a||i.slideCount<=i.options.slidesToShow?void 0:(b===!1&&i.asNavFor(a),d=a,h=i.getLeft(d),g=i.getLeft(i.currentSlide),i.currentLeft=null===i.swipeLeft?g:i.swipeLeft,i.options.infinite===!1&&i.options.centerMode===!1&&(0>a||a>i.getDotCount()*i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d); 22}):i.postSlide(d))):i.options.infinite===!1&&i.options.centerMode===!0&&(0>a||a>i.slideCount-i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):(i.options.autoplay===!0&&clearInterval(i.autoPlayTimer),e=0>d?i.slideCount%i.options.slidesToScroll!==0?i.slideCount-i.slideCount%i.options.slidesToScroll:i.slideCount+d:d>=i.slideCount?i.slideCount%i.options.slidesToScroll!==0?0:d-i.slideCount:d,i.animating=!0,i.$slider.trigger("beforeChange",[i,i.currentSlide,e]),f=i.currentSlide,i.currentSlide=e,i.setSlideClasses(i.currentSlide),i.updateDots(),i.updateArrows(),i.options.fade===!0?(c!==!0?(i.fadeSlideOut(f),i.fadeSlide(e,function(){i.postSlide(e)})):i.postSlide(e),void i.animateHeight()):void(c!==!0?i.animateSlide(h,function(){i.postSlide(e)}):i.postSlide(e))))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?e.options.rtl===!1?"left":"right":360>=d&&d>=315?e.options.rtl===!1?"left":"right":d>=135&&225>=d?e.options.rtl===!1?"right":"left":e.options.verticalSwiping===!0?d>=35&&135>=d?"left":"right":"vertical"},b.prototype.swipeEnd=function(a){var c,b=this;if(b.dragging=!1,b.shouldClick=b.touchObject.swipeLength>10?!1:!0,void 0===b.touchObject.curX)return!1;if(b.touchObject.edgeHit===!0&&b.$slider.trigger("edge",[b,b.swipeDirection()]),b.touchObject.swipeLength>=b.touchObject.minSwipe)switch(b.swipeDirection()){case"left":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide+b.getSlideCount()):b.currentSlide+b.getSlideCount(),b.slideHandler(c),b.currentDirection=0,b.touchObject={},b.$slider.trigger("swipe",[b,"left"]);break;case"right":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide-b.getSlideCount()):b.currentSlide-b.getSlideCount(),b.slideHandler(c),b.currentDirection=1,b.touchObject={},b.$slider.trigger("swipe",[b,"right"])}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||h&&1!==h.length?!1:(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.options.vertical===!1?b.swipeLeft=d+f*g:b.swipeLeft=d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):void b.setCSS(b.swipeLeft)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,void(b.dragging=!0))},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.remove(),b.$nextArrow&&b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(a){var b=this;b.$slider.trigger("unslick",[b,a]),b.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&!a.options.infinite&&(a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-1&&a.options.centerMode===!0&&(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active").attr("aria-hidden","true"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active").attr("aria-hidden","false"))},b.prototype.visibility=function(){var a=this;document[a.hidden]?(a.paused=!0,a.autoPlayClear()):a.options.autoplay===!0&&(a.paused=!1,a.autoPlay())},b.prototype.initADA=function(){var b=this;b.$slides.add(b.$slideTrack.find(".slick-cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),b.$slideTrack.attr("role","listbox"),b.$slides.not(b.$slideTrack.find(".slick-cloned")).each(function(c){a(this).attr({role:"option","aria-describedby":"slick-slide"+b.instanceUid+c})}),null!==b.$dots&&b.$dots.attr("role","tablist").find("li").each(function(c){a(this).attr({role:"presentation","aria-selected":"false","aria-controls":"navigation"+b.instanceUid+c,id:"slick-slide"+b.instanceUid+c})}).first().attr("aria-selected","true").end().find("button").attr("role","button").end().closest("div").attr("role","toolbar"),b.activateADA()},b.prototype.activateADA=function(){var a=this;a.$slideTrack.find(".slick-active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},b.prototype.focusHandler=function(){var b=this;b.$slider.on("focus.slick blur.slick","*",function(c){c.stopImmediatePropagation();var d=a(this);setTimeout(function(){b.isPlay&&(d.is(":focus")?(b.autoPlayClear(),b.paused=!0):(b.paused=!1,b.autoPlay()))},0)})},a.fn.slick=function(){var f,g,a=this,c=arguments[0],d=Array.prototype.slice.call(arguments,1),e=a.length;for(f=0;e>f;f++)if("object"==typeof c||"undefined"==typeof c?a[f].slick=new b(a[f],c):g=a[f].slick[c].apply(a[f].slick,d),"undefined"!=typeof g)return g;return a}});
22
vendor: 40,580 bytes, lines 23-1122
23/* 24== malihu jquery custom scrollbar plugin == 25Version: 3.1.5 26Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller 27Author: malihu 28Author URI: http://manos.malihu.gr 29License: MIT License (MIT) 30*/ 31 32/* 33Copyright Manos Malihutsakis (email: [email protected]) 34 35Permission is hereby granted, free of charge, to any person obtaining a copy 36of this software and associated documentation files (the "Software"), to deal 37in the Software without restriction, including without limitation the rights 38to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39copies of the Software, and to permit persons to whom the Software is 40furnished to do so, subject to the following conditions: 41 42The above copyright notice and this permission notice shall be included in 43all copies or substantial portions of the Software. 44 45THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 51THE SOFTWARE. 52*/ 53 54/* 55The code below is fairly long, fully commented and should be normally used in development. 56For production, use either the minified jquery.mCustomScrollbar.min.js script or 57the production-ready jquery.mCustomScrollbar.concat.min.js which contains the plugin 58and dependencies (minified). 59*/ 60 61(function(factory){ 62 if(typeof define==="function" && define.amd){ 63 define(["jquery"],factory); 64 }else if(typeof module!=="undefined" && module.exports){ 65 module.exports=factory; 66 }else{ 67 factory(jQuery,window,document); 68 } 69}(function($){ 70(function(init){ 71 var _rjs=typeof define==="function" && define.amd, /* RequireJS */ 72 _njs=typeof module !== "undefined" && module.exports, /* NodeJS */ 73 _dlp=("https:"==document.location.protocol) ? "https:" : "http:", /* location protocol */ 74 _url="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"; 75 if(!_rjs){ 76 if(_njs){ 77 require("jquery-mousewheel")($); 78 }else{ 79 /* load jquery-mousewheel plugin (via CDN) if it's not present or not loaded via RequireJS 80 (works when mCustomScrollbar fn is called on window load) */ 81 $.event.special.mousewheel || $("head").append(decodeURI("%3Cscript src="+_dlp+"//"+_url+"%3E%3C/script%3E")); 82 } 83 } 84 init(); 85}(function(){ 86 87 /* 88 ---------------------------------------- 89 PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) 90 ---------------------------------------- 91 */ 92 93 var pluginNS="mCustomScrollbar", 94 pluginPfx="mCS", 95 defaultSelector=".mCustomScrollbar", 96 97 98 99 100 101 /* 102 ---------------------------------------- 103 DEFAULT OPTIONS 104 ---------------------------------------- 105 */ 106 107 defaults={ 108 /* 109 set element/content width/height programmatically 110 values: boolean, pixels, percentage 111 option default 112 ------------------------------------- 113 setWidth false 114 setHeight false 115 */ 116 /* 117 set the initial css top property of content 118 values: string (e.g. "-100px", "10%" etc.) 119 */ 120 setTop:0, 121 /* 122 set the initial css left property of content 123 values: string (e.g. "-100px", "10%" etc.) 124 */ 125 setLeft:0, 126 /* 127 scrollbar axis (vertical and/or horizontal scrollbars) 128 values (string): "y", "x", "yx" 129 */ 130 axis:"y", 131 /* 132 position of scrollbar relative to content 133 values (string): "inside", "outside" ("outside" requires elements with position:relative) 134 */ 135 scrollbarPosition:"inside", 136 /* 137 scrolling inertia 138 values: integer (milliseconds) 139 */ 140 scrollInertia:950, 141 /* 142 auto-adjust scrollbar dragger length 143 values: boolean 144 */ 145 autoDraggerLength:true, 146 /* 147 auto-hide scrollbar when idle 148 values: boolean 149 option default 150 ------------------------------------- 151 autoHideScrollbar false 152 */ 153 /* 154 auto-expands scrollbar on mouse-over and dragging 155 values: boolean 156 option default 157 ------------------------------------- 158 autoExpandScrollbar false 159 */ 160 /* 161 always show scrollbar, even when there's nothing to scroll 162 values: integer (0=disable, 1=always show dragger rail and buttons, 2=always show dragger rail, dragger and buttons), boolean 163 */ 164 alwaysShowScrollbar:0, 165 /* 166 scrolling always snaps to a multiple of this number in pixels 167 values: integer, array ([y,x]) 168 option default 169 ------------------------------------- 170 snapAmount null 171 */ 172 /* 173 when snapping, snap with this number in pixels as an offset 174 values: integer 175 */ 176 snapOffset:0, 177 /* 178 mouse-wheel scrolling 179 */ 180 mouseWheel:{ 181 /* 182 enable mouse-wheel scrolling 183 values: boolean 184 */ 185 enable:true, 186 /* 187 scrolling amount in pixels 188 values: "auto", integer 189 */ 190 scrollAmount:"auto", 191 /* 192 mouse-wheel scrolling axis 193 the default scrolling direction when both vertical and horizontal scrollbars are present 194 values (string): "y", "x" 195 */ 196 axis:"y", 197 /* 198 prevent the default behaviour which automatically scrolls the parent element(s) when end of scrolling is reached 199 values: boolean 200 option default 201 ------------------------------------- 202 preventDefault null 203 */ 204 /* 205 the reported mouse-wheel delta value. The number of lines (translated to pixels) one wheel notch scrolls. 206 values: "auto", integer 207 "auto" uses the default OS/browser value 208 */ 209 deltaFactor:"auto", 210 /* 211 normalize mouse-wheel delta to -1 or 1 (disables mouse-wheel acceleration) 212 values: boolean 213 option default 214 ------------------------------------- 215 normalizeDelta null 216 */ 217 /* 218 invert mouse-wheel scrolling direction 219 values: boolean 220 option default 221 ------------------------------------- 222 invert null 223 */ 224 /* 225 the tags that disable mouse-wheel when cursor is over them 226 */ 227 disableOver:["select","option","keygen","datalist","textarea"] 228 }, 229 /* 230 scrollbar buttons 231 */ 232 scrollButtons:{ 233 /* 234 enable scrollbar buttons 235 values: boolean 236 option default 237 ------------------------------------- 238 enable null 239 */ 240 /* 241 scrollbar buttons scrolling type 242 values (string): "stepless", "stepped" 243 */ 244 scrollType:"stepless", 245 /* 246 scrolling amount in pixels 247 values: "auto", integer 248 */ 249 scrollAmount:"auto" 250 /* 251 tabindex of the scrollbar buttons 252 values: false, integer 253 option default 254 ------------------------------------- 255 tabindex null 256 */ 257 }, 258 /* 259 keyboard scrolling 260 */ 261 keyboard:{ 262 /* 263 enable scrolling via keyboard 264 values: boolean 265 */ 266 enable:true, 267 /* 268 keyboard scrolling type 269 values (string): "stepless", "stepped" 270 */ 271 scrollType:"stepless", 272 /* 273 scrolling amount in pixels 274 values: "auto", integer 275 */ 276 scrollAmount:"auto" 277 }, 278 /* 279 enable content touch-swipe scrolling 280 values: boolean, integer, string (number) 281 integer values define the axis-specific minimum amount required for scrolling momentum 282 */ 283 contentTouchScroll:25, 284 /* 285 enable/disable document (default) touch-swipe scrolling 286 */ 287 documentTouchScroll:true, 288 /* 289 advanced option parameters 290 */ 291 advanced:{ 292 /* 293 auto-expand content horizontally (for "x" or "yx" axis) 294 values: boolean, integer (the value 2 forces the non scrollHeight/scrollWidth method, the value 3 forces the scrollHeight/scrollWidth method) 295 option default 296 ------------------------------------- 297 autoExpandHorizontalScroll null 298 */ 299 /* 300 auto-scroll to elements with focus 301 */ 302 autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']", 303 /* 304 auto-update scrollbars on content, element or viewport resize 305 should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. 306 values: boolean 307 */ 308 updateOnContentResize:true, 309 /* 310 auto-update scrollbars each time each image inside the element is fully loaded 311 values: "auto", boolean 312 */ 313 updateOnImageLoad:"auto", 314 /* 315 auto-update scrollbars based on the amount and size changes of specific selectors 316 useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size 317 values: boolean, string (e.g. "ul li" will auto-update scrollbars each time list-items inside the element are changed) 318 a value of true (boolean) will auto-update scrollbars each time any element is changed 319 option default 320 ------------------------------------- 321 updateOnSelectorChange null 322 */ 323 /* 324 extra selectors that'll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc. (e.g. "selector-1, selector-2") 325 option default 326 ------------------------------------- 327 extraDraggableSelectors null 328 */ 329 /* 330 extra selectors that'll release scrollbar dragging upon mouseup, pointerup, touchend etc. (e.g. "selector-1, selector-2") 331 option default 332 ------------------------------------- 333 releaseDraggableSelectors null 334 */ 335 /* 336 auto-update timeout 337 values: integer (milliseconds) 338 */ 339 autoUpdateTimeout:60 340 }, 341 /* 342 scrollbar theme 343 values: string (see CSS/plugin URI for a list of ready-to-use themes) 344 */ 345 theme:"light", 346 /* 347 user defined callback functions 348 */ 349 callbacks:{ 350 /* 351 Available callbacks: 352 callback default 353 ------------------------------------- 354 onCreate null 355 onInit null 356 onScrollStart null 357 onScroll null 358 onTotalScroll null 359 onTotalScrollBack null 360 whileScrolling null 361 onOverflowY null 362 onOverflowX null 363 onOverflowYNone null 364 onOverflowXNone null 365 onImageLoad null 366 onSelectorChange null 367 onBeforeUpdate null 368 onUpdate null 369 */ 370 onTotalScrollOffset:0, 371 onTotalScrollBackOffset:0, 372 alwaysTriggerOffsets:true 373 } 374 /* 375 add scrollbar(s) on all elements matching the current selector, now and in the future 376 values: boolean, string 377 string values: "on" (enable), "once" (disable after first invocation), "off" (disable) 378 liveSelector values: string (selector) 379 option default 380 ------------------------------------- 381 live false 382 liveSelector null 383 */ 384 }, 385 386 387 388 389 390 /* 391 ---------------------------------------- 392 VARS, CONSTANTS 393 ---------------------------------------- 394 */ 395 396 totalInstances=0, /* plugin instances amount */ 397 liveTimers={}, /* live option timers */ 398 oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */ 399 touchActive=false,touchable, /* global touch vars (for touch and pointer events) */ 400 /* general plugin classes */ 401 classes=[ 402 "mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar", 403 "mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer", 404 "mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight" 405 ], 406 407 408 409 410 411 /* 412 ---------------------------------------- 413 METHODS 414 ---------------------------------------- 415 */ 416 417 methods={ 418 419 /* 420 plugin initialization method 421 creates the scrollbar(s), plugin data object and options 422 ---------------------------------------- 423 */ 424 425 init:function(options){ 426 427 var options=$.extend(true,{},defaults,options), 428 selector=_selector.call(this); /* validate selector */ 429 430 /* 431 if live option is enabled, monitor for elements matching the current selector and 432 apply scrollbar(s) when found (now and in the future) 433 */ 434 if(options.live){ 435 var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */ 436 $liveSelector=$(liveSelector); /* live selector(s) as jquery object */ 437 if(options.live==="off"){ 438 /* 439 disable live if requested 440 usage: $(selector).mCustomScrollbar({live:"off"}); 441 */ 442 removeLiveTimers(liveSelector); 443 return; 444 } 445 liveTimers[liveSelector]=setTimeout(function(){ 446 /* call mCustomScrollbar fn on live selector(s) every half-second */ 447 $liveSelector.mCustomScrollbar(options); 448 if(options.live==="once" && $liveSelector.length){ 449 /* disable live after first invocation */ 450 removeLiveTimers(liveSelector); 451 } 452 },500); 453 }else{ 454 removeLiveTimers(liveSelector); 455 } 456 457 /* options backward compatibility (for versions < 3.0.0) and normalization */ 458 options.setWidth=(options.set_width) ? options.set_width : options.setWidth; 459 options.setHeight=(options.set_height) ? options.set_height : options.setHeight; 460 options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis); 461 options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia; 462 if(typeof options.mouseWheel!=="object" && options.mouseWheel==true){ /* old school mouseWheel option (non-object) */ 463 options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false} 464 } 465 options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels; 466 options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta; 467 options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); 468 469 _theme(options); /* theme-specific options */ 470 471 /* plugin constructor */ 472 return $(selector).each(function(){ 473 474 var $this=$(this); 475 476 if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */ 477 478 /* store options and create objects in jquery data */ 479 $this.data(pluginPfx,{ 480 idx:++totalInstances, /* instance index */ 481 opt:options, /* options */ 482 scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */ 483 overflowed:null, /* overflowed axis */ 484 contentReset:{y:null,x:null}, /* object to check when content resets */ 485 bindEvents:false, /* object to check if events are bound */ 486 tweenRunning:false, /* object to check if tween is running */ 487 sequential:{}, /* sequential scrolling object */ 488 langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */ 489 cbOffsets:null, /* object to check whether callback offsets always trigger */ 490 /* 491 object to check how scrolling events where last triggered 492 "internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) 493 usage: object.data("mCS").trigger 494 */ 495 trigger:null, 496 /* 497 object to check for changes in elements in order to call the update method automatically 498 */ 499 poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}} 500 }); 501 502 var d=$this.data(pluginPfx),o=d.opt, 503 /* HTML data attributes */ 504 htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme"); 505 506 if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */ 507 if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */ 508 if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */ 509 o.theme=htmlDataTheme; 510 _theme(o); /* theme-specific options */ 511 } 512 513 _pluginMarkup.call(this); /* add plugin markup */ 514 515 if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */ 516 517 $("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */ 518 519 methods.update.call(null,$this); /* call the update method */ 520 521 } 522 523 }); 524 525 }, 526 /* ---------------------------------------- */ 527 528 529 530 /* 531 plugin update method 532 updates content and scrollbar(s) values, events and status 533 ---------------------------------------- 534 usage: $(selector).mCustomScrollbar("update"); 535 */ 536 537 update:function(el,cb){ 538 539 var selector=el || _selector.call(this); /* validate selector */ 540 541 return $(selector).each(function(){ 542 543 var $this=$(this); 544 545 if($this.data(pluginPfx)){ /* check if plugin has initialized */ 546 547 var d=$this.data(pluginPfx),o=d.opt, 548 mCSB_container=$("#mCSB_"+d.idx+"_container"), 549 mCustomScrollBox=$("#mCSB_"+d.idx), 550 mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; 551 552 if(!mCSB_container.length){return;} 553 554 if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */ 555 556 if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */ 557 558 /* if element was disabled or destroyed, remove class(es) */ 559 if($this.hasClass(classes[3])){$this.removeClass(classes[3]);} 560 if($this.hasClass(classes[4])){$this.removeClass(classes[4]);} 561 562 /* css flexbox fix, detect/set max-height */ 563 mCustomScrollBox.css("max-height","none"); 564 if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());} 565 566 _expandContentHorizontally.call(this); /* expand content horizontally */ 567 568 if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ 569 mCSB_container.css("width",_contentWidth(mCSB_container)); 570 } 571 572 d.overflowed=_overflowed.call(this); /* determine if scrolling is required */ 573 574 _scrollbarVisibility.call(this); /* show/hide scrollbar(s) */ 575 576 /* auto-adjust scrollbar dragger length analogous to content */ 577 if(o.autoDraggerLength){_setDraggerLength.call(this);} 578 579 _scrollRatio.call(this); /* calculate and store scrollbar to content ratio */ 580 581 _bindEvents.call(this); /* bind scrollbar events */ 582 583 /* reset scrolling position and/or events */ 584 var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)]; 585 if(o.axis!=="x"){ /* y/yx axis */ 586 if(!d.overflowed[0]){ /* y scrolling is not required */ 587 _resetContentPosition.call(this); /* reset content position */ 588 if(o.axis==="y"){ 589 _unbindEvents.call(this); 590 }else if(o.axis==="yx" && d.overflowed[1]){ 591 _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); 592 } 593 }else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){ 594 _resetContentPosition.call(this); /* reset content position */ 595 }else{ /* y scrolling is required */ 596 _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); 597 d.contentReset.y=null; 598 } 599 } 600 if(o.axis!=="y"){ /* x/yx axis */ 601 if(!d.overflowed[1]){ /* x scrolling is not required */ 602 _resetContentPosition.call(this); /* reset content position */ 603 if(o.axis==="x"){ 604 _unbindEvents.call(this); 605 }else if(o.axis==="yx" && d.overflowed[0]){ 606 _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); 607 } 608 }else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){ 609 _resetContentPosition.call(this); /* reset content position */ 610 }else{ /* x scrolling is required */ 611 _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); 612 d.contentReset.x=null; 613 } 614 } 615 616 /* callbacks: onImageLoad, onSelectorChange, onUpdate */ 617 if(cb && d){ 618 if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){ 619 o.callbacks.onImageLoad.call(this); 620 }else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){ 621 o.callbacks.onSelectorChange.call(this); 622 }else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){ 623 o.callbacks.onUpdate.call(this); 624 } 625 } 626 627 _autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */ 628 629 } 630 631 }); 632 633 }, 634 /* ---------------------------------------- */ 635 636 637 638 /* 639 plugin scrollTo method 640 triggers a scrolling event to a specific value 641 ---------------------------------------- 642 usage: $(selector).mCustomScrollbar("scrollTo",value,options); 643 */ 644 645 scrollTo:function(val,options){ 646 647 /* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */ 648 if(typeof val=="undefined" || val==null){return;} 649 650 var selector=_selector.call(this); /* validate selector */ 651 652 return $(selector).each(function(){ 653 654 var $this=$(this); 655 656 if($this.data(pluginPfx)){ /* check if plugin has initialized */ 657 658 var d=$this.data(pluginPfx),o=d.opt, 659 /* method default options */ 660 methodDefaults={ 661 trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */ 662 scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */ 663 scrollEasing:"mcsEaseInOut", /* animation easing */ 664 moveDragger:false, /* move dragger instead of content */ 665 timeout:60, /* scroll-to delay */ 666 callbacks:true, /* enable/disable callbacks */ 667 onStart:true, 668 onUpdate:true, 669 onComplete:true 670 }, 671 methodOptions=$.extend(true,{},methodDefaults,options), 672 to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia; 673 674 /* translate yx values to actual scroll-to positions */ 675 to[0]=_to.call(this,to[0],"y"); 676 to[1]=_to.call(this,to[1],"x"); 677 678 /* 679 check if scroll-to value moves the dragger instead of content. 680 Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) 681 */ 682 if(methodOptions.moveDragger){ 683 to[0]*=d.scrollRatio.y; 684 to[1]*=d.scrollRatio.x; 685 } 686 687 methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden 688 689 setTimeout(function(){ 690 /* do the scrolling */ 691 if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */ 692 methodOptions.dir="y"; 693 methodOptions.overwrite="all"; 694 _scrollTo($this,to[0].toString(),methodOptions); 695 } 696 if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */ 697 methodOptions.dir="x"; 698 methodOptions.overwrite="none"; 699 _scrollTo($this,to[1].toString(),methodOptions); 700 } 701 },methodOptions.timeout); 702 703 } 704 705 }); 706 707 }, 708 /* ---------------------------------------- */ 709 710 711 712 /* 713 plugin stop method 714 stops scrolling animation 715 ---------------------------------------- 716 usage: $(selector).mCustomScrollbar("stop"); 717 */ 718 stop:function(){ 719 720 var selector=_selector.call(this); /* validate selector */ 721 722 return $(selector).each(function(){ 723 724 var $this=$(this); 725 726 if($this.data(pluginPfx)){ /* check if plugin has initialized */ 727 728 _stop($this); 729 730 } 731 732 }); 733 734 }, 735 /* ---------------------------------------- */ 736 737 738 739 /* 740 plugin disable method 741 temporarily disables the scrollbar(s) 742 ---------------------------------------- 743 usage: $(selector).mCustomScrollbar("disable",reset); 744 reset (boolean): resets content position to 0 745 */ 746 disable:function(r){ 747 748 var selector=_selector.call(this); /* validate selector */ 749 750 return $(selector).each(function(){ 751 752 var $this=$(this); 753 754 if($this.data(pluginPfx)){ /* check if plugin has initialized */ 755 756 var d=$this.data(pluginPfx); 757 758 _autoUpdate.call(this,"remove"); /* remove automatic updating */ 759 760 _unbindEvents.call(this); /* unbind events */ 761 762 if(r){_resetContentPosition.call(this);} /* reset content position */ 763 764 _scrollbarVisibility.call(this,true); /* show/hide scrollbar(s) */ 765 766 $this.addClass(classes[3]); /* add disable class */ 767 768 } 769 770 }); 771 772 }, 773 /* ---------------------------------------- */ 774 775 776 777 /* 778 plugin destroy method 779 completely removes the scrollbar(s) and returns the element to its original state 780 ---------------------------------------- 781 usage: $(selector).mCustomScrollbar("destroy"); 782 */ 783 destroy:function(){ 784 785 var selector=_selector.call(this); /* validate selector */ 786 787 return $(selector).each(function(){ 788 789 var $this=$(this); 790 791 if($this.data(pluginPfx)){ /* check if plugin has initialized */ 792 793 var d=$this.data(pluginPfx),o=d.opt, 794 mCustomScrollBox=$("#mCSB_"+d.idx), 795 mCSB_container=$("#mCSB_"+d.idx+"_container"), 796 scrollbar=$(".mCSB_"+d.idx+"_scrollbar"); 797 798 if(o.live){removeLiveTimers(o.liveSelector || $(selector).selector);} /* remove live timers */ 799 800 _autoUpdate.call(this,"remove"); /* remove automatic updating */ 801 802 _unbindEvents.call(this); /* unbind events */ 803 804 _resetContentPosition.call(this); /* reset content position */ 805 806 $this.removeData(pluginPfx); /* remove plugin data object */ 807 808 _delete(this,"mcs"); /* delete callbacks object */ 809 810 /* remove plugin markup */ 811 scrollbar.remove(); /* remove scrollbar(s) first (those can be either inside or outside plugin's inner wrapper) */ 812 mCSB_container.find("img."+classes[2]).removeClass(classes[2]); /* remove loaded images flag */ 813 mCustomScrollBox.replaceWith(mCSB_container.contents()); /* replace plugin's inner wrapper with the original content */ 814 /* remove plugin classes from the element and add destroy class */ 815 $this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+classes[6]+" "+classes[7]+" "+classes[5]+" "+classes[3]).addClass(classes[4]); 816 817 } 818 819 }); 820 821 } 822 /* ---------------------------------------- */ 823 824 }, 825 826 827 828 829 830 /* 831 ---------------------------------------- 832 FUNCTIONS 833 ---------------------------------------- 834 */ 835 836 /* validates selector (if selector is invalid or undefined uses the default one) */ 837 _selector=function(){ 838 return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this; 839 }, 840 /* -------------------- */ 841 842 843 /* changes options according to theme */ 844 _theme=function(obj){ 845 var fixedSizeScrollbarThemes=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"], 846 nonExpandedScrollbarThemes=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"], 847 disabledScrollButtonsThemes=["minimal","minimal-dark"], 848 enabledAutoHideScrollbarThemes=["minimal","minimal-dark"], 849 scrollbarPositionOutsideThemes=["minimal","minimal-dark"]; 850 obj.autoDraggerLength=$.inArray(obj.theme,fixedSizeScrollbarThemes) > -1 ? false : obj.autoDraggerLength; 851 obj.autoExpandScrollbar=$.inArray(obj.theme,nonExpandedScrollbarThemes) > -1 ? false : obj.autoExpandScrollbar; 852 obj.scrollButtons.enable=$.inArray(obj.theme,disabledScrollButtonsThemes) > -1 ? false : obj.scrollButtons.enable; 853 obj.autoHideScrollbar=$.inArray(obj.theme,enabledAutoHideScrollbarThemes) > -1 ? true : obj.autoHideScrollbar; 854 obj.scrollbarPosition=$.inArray(obj.theme,scrollbarPositionOutsideThemes) > -1 ? "outside" : obj.scrollbarPosition; 855 }, 856 /* -------------------- */ 857 858 859 /* live option timers removal */ 860 removeLiveTimers=function(selector){ 861 if(liveTimers[selector]){ 862 clearTimeout(liveTimers[selector]); 863 _delete(liveTimers,selector); 864 } 865 }, 866 /* -------------------- */ 867 868 869 /* normalizes axis option to valid values: "y", "x", "yx" */ 870 _findAxis=function(val){ 871 return (val==="yx" || val==="xy" || val==="auto") ? "yx" : (val==="x" || val==="horizontal") ? "x" : "y"; 872 }, 873 /* -------------------- */ 874 875 876 /* normalizes scrollButtons.scrollType option to valid values: "stepless", "stepped" */ 877 _findScrollButtonsType=function(val){ 878 return (val==="stepped" || val==="pixels" || val==="step" || val==="click") ? "stepped" : "stepless"; 879 }, 880 /* -------------------- */ 881 882 883 /* generates plugin markup */ 884 _pluginMarkup=function(){ 885 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 886 expandClass=o.autoExpandScrollbar ? " "+classes[1]+"_expand" : "", 887 scrollbar=["<div id='mCSB_"+d.idx+"_scrollbar_vertical' class='mCSB_scrollTools mCSB_"+d.idx+"_scrollbar mCS-"+o.theme+" mCSB_scrollTools_vertical"+expandClass+"'><div class='"+classes[12]+"'><div id='mCSB_"+d.idx+"_dragger_vertical' class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>","<div id='mCSB_"+d.idx+"_scrollbar_horizontal' class='mCSB_scrollTools mCSB_"+d.idx+"_scrollbar mCS-"+o.theme+" mCSB_scrollTools_horizontal"+expandClass+"'><div class='"+classes[12]+"'><div id='mCSB_"+d.idx+"_dragger_horizontal' class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>"], 888 wrapperClass=o.axis==="yx" ? "mCSB_vertical_horizontal" : o.axis==="x" ? "mCSB_horizontal" : "mCSB_vertical", 889 scrollbars=o.axis==="yx" ? scrollbar[0]+scrollbar[1] : o.axis==="x" ? scrollbar[1] : scrollbar[0], 890 contentWrapper=o.axis==="yx" ? "<div id='mCSB_"+d.idx+"_container_wrapper' class='mCSB_container_wrapper' />" : "", 891 autoHideClass=o.autoHideScrollbar ? " "+classes[6] : "", 892 scrollbarDirClass=(o.axis!=="x" && d.langDir==="rtl") ? " "+classes[7] : ""; 893 if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */ 894 if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */ 895 o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "989999px" : o.setLeft; /* adjust left position for rtl direction */ 896 $this.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+autoHideClass+scrollbarDirClass).wrapInner("<div id='mCSB_"+d.idx+"' class='mCustomScrollBox mCS-"+o.theme+" "+wrapperClass+"'><div id='mCSB_"+d.idx+"_container' class='mCSB_container' style='position:relative; top:"+o.setTop+"; left:"+o.setLeft+";' dir='"+d.langDir+"' /></div>"); 897 var mCustomScrollBox=$("#mCSB_"+d.idx), 898 mCSB_container=$("#mCSB_"+d.idx+"_container"); 899 if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ 900 mCSB_container.css("width",_contentWidth(mCSB_container)); 901 } 902 if(o.scrollbarPosition==="outside"){ 903 if($this.css("position")==="static"){ /* requires elements with non-static position */ 904 $this.css("position","relative"); 905 } 906 $this.css("overflow","visible"); 907 mCustomScrollBox.addClass("mCSB_outside").after(scrollbars); 908 }else{ 909 mCustomScrollBox.addClass("mCSB_inside").append(scrollbars); 910 mCSB_container.wrap(contentWrapper); 911 } 912 _scrollButtons.call(this); /* add scrollbar buttons */ 913 /* minimum dragger length */ 914 var mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; 915 mCSB_dragger[0].css("min-height",mCSB_dragger[0].height()); 916 mCSB_dragger[1].css("min-width",mCSB_dragger[1].width()); 917 }, 918 /* -------------------- */ 919 920 921 /* calculates content width */ 922 _contentWidth=function(el){ 923 var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width(); 924 return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%"; 925 }, 926 /* -------------------- */ 927 928 929 /* expands content horizontally */ 930 _expandContentHorizontally=function(){ 931 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 932 mCSB_container=$("#mCSB_"+d.idx+"_container"); 933 if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){ 934 /* calculate scrollWidth */ 935 mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"}); 936 var w=Math.ceil(mCSB_container[0].scrollWidth); 937 if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){ 938 mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"}); 939 }else{ 940 /* 941 wrap content with an infinite width div and set its position to absolute and width to auto. 942 Setting width to auto before calculating the actual width is important! 943 We must let the browser set the width as browser zoom values are impossible to calculate. 944 */ 945 mCSB_container.css({"overflow-x":"inherit","position":"absolute"}) 946 .wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />") 947 .css({ /* set actual width, original position and un-wrap */ 948 /* 949 get the exact width (with decimals) and then round-up. 950 Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width 951 */ 952 "width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)), 953 "min-width":"100%", 954 "position":"relative" 955 }).unwrap(); 956 } 957 } 958 }, 959 /* -------------------- */ 960 961 962 /* adds scrollbar buttons */ 963 _scrollButtons=function(){ 964 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 965 mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"), 966 tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'", 967 btnHTML=[ 968 "<a href='#' class='"+classes[13]+"' "+tabindex+" />", 969 "<a href='#' class='"+classes[14]+"' "+tabindex+" />", 970 "<a href='#' class='"+classes[15]+"' "+tabindex+" />", 971 "<a href='#' class='"+classes[16]+"' "+tabindex+" />" 972 ], 973 btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]]; 974 if(o.scrollButtons.enable){ 975 mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]); 976 } 977 }, 978 /* -------------------- */ 979 980 981 /* auto-adjusts scrollbar dragger length */ 982 _setDraggerLength=function(){ 983 var $this=$(this),d=$this.data(pluginPfx), 984 mCustomScrollBox=$("#mCSB_"+d.idx), 985 mCSB_container=$("#mCSB_"+d.idx+"_container"), 986 mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], 987 ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)], 988 l=[ 989 parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()), 990 parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width()) 991 ], 992 h=oldIE && (l[1]<l[0]) ? l[0] : l[1],w=oldIE && (l[3]<l[2]) ? l[2] : l[3]; 993 mCSB_dragger[0].css({ 994 "height":h,"max-height":(mCSB_dragger[0].parent().height()-10) 995 }).find(".mCSB_dragger_bar").css({"line-height":l[0]+"px"}); 996 mCSB_dragger[1].css({ 997 "width":w,"max-width":(mCSB_dragger[1].parent().width()-10) 998 }); 999 }, 1000 /* -------------------- */ 1001 1002 1003 /* calculates scrollbar to content ratio */ 1004 _scrollRatio=function(){ 1005 var $this=$(this),d=$this.data(pluginPfx), 1006 mCustomScrollBox=$("#mCSB_"+d.idx), 1007 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1008 mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], 1009 scrollAmount=[mCSB_container.outerHeight(false)-mCustomScrollBox.height(),mCSB_container.outerWidth(false)-mCustomScrollBox.width()], 1010 ratio=[ 1011 scrollAmount[0]/(mCSB_dragger[0].parent().height()-mCSB_dragger[0].height()), 1012 scrollAmount[1]/(mCSB_dragger[1].parent().width()-mCSB_dragger[1].width()) 1013 ]; 1014 d.scrollRatio={y:ratio[0],x:ratio[1]}; 1015 }, 1016 /* -------------------- */ 1017 1018 1019 /* toggles scrolling classes */ 1020 _onDragClasses=function(el,action,xpnd){ 1021 var expandClass=xpnd ? classes[0]+"_expanded" : "", 1022 scrollbar=el.closest(".mCSB_scrollTools"); 1023 if(action==="active"){ 1024 el.toggleClass(classes[0]+" "+expandClass); scrollbar.toggleClass(classes[1]); 1025 el[0]._draggable=el[0]._draggable ? 0 : 1; 1026 }else{ 1027 if(!el[0]._draggable){ 1028 if(action==="hide"){ 1029 el.removeClass(classes[0]); scrollbar.removeClass(classes[1]); 1030 }else{ 1031 el.addClass(classes[0]); scrollbar.addClass(classes[1]); 1032 } 1033 } 1034 } 1035 }, 1036 /* -------------------- */ 1037 1038 1039 /* checks if content overflows its container to determine if scrolling is required */ 1040 _overflowed=function(){ 1041 var $this=$(this),d=$this.data(pluginPfx), 1042 mCustomScrollBox=$("#mCSB_"+d.idx), 1043 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1044 contentHeight=d.overflowed==null ? mCSB_container.height() : mCSB_container.outerHeight(false), 1045 contentWidth=d.overflowed==null ? mCSB_container.width() : mCSB_container.outerWidth(false), 1046 h=mCSB_container[0].scrollHeight,w=mCSB_container[0].scrollWidth; 1047 if(h>contentHeight){contentHeight=h;} 1048 if(w>contentWidth){contentWidth=w;} 1049 return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()]; 1050 }, 1051 /* -------------------- */ 1052 1053 1054 /* resets content position to 0 */ 1055 _resetContentPosition=function(){ 1056 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1057 mCustomScrollBox=$("#mCSB_"+d.idx), 1058 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1059 mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; 1060 _stop($this); /* stop any current scrolling before resetting */ 1061 if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */ 1062 mCSB_dragger[0].add(mCSB_container).css("top",0); 1063 _scrollTo($this,"_resetY"); 1064 } 1065 if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */ 1066 var cx=dx=0; 1067 if(d.langDir==="rtl"){ /* adjust left position for rtl direction */ 1068 cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false); 1069 dx=Math.abs(cx/d.scrollRatio.x); 1070 } 1071 mCSB_container.css("left",cx); 1072 mCSB_dragger[1].css("left",dx); 1073 _scrollTo($this,"_resetX"); 1074 } 1075 }, 1076 /* -------------------- */ 1077 1078 1079 /* binds scrollbar events */ 1080 _bindEvents=function(){ 1081 var $this=$(this),d=$this.data(pluginPfx),o=d.opt; 1082 if(!d.bindEvents){ /* check if events are already bound */ 1083 _draggable.call(this); 1084 if(o.contentTouchScroll){_contentDraggable.call(this);} 1085 _selectable.call(this); 1086 if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */ 1087 function _mwt(){ 1088 mousewheelTimeout=setTimeout(function(){ 1089 if(!$.event.special.mousewheel){ 1090 _mwt(); 1091 }else{ 1092 clearTimeout(mousewheelTimeout); 1093 _mousewheel.call($this[0]); 1094 } 1095 },100); 1096 } 1097 var mousewheelTimeout; 1098 _mwt(); 1099 } 1100 _draggerRail.call(this); 1101 _wrapperScroll.call(this); 1102 if(o.advanced.autoScrollOnFocus){_focus.call(this);} 1103 if(o.scrollButtons.enable){_buttons.call(this);} 1104 if(o.keyboard.enable){_keyboard.call(this);} 1105 d.bindEvents=true; 1106 } 1107 }, 1108 /* -------------------- */ 1109 1110 1111 /* unbinds scrollbar events */ 1112 _unbindEvents=function(){ 1113 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1114 namespace=pluginPfx+"_"+d.idx, 1115 sb=".mCSB_"+d.idx+"_scrollbar", 1116 sel=$("#mCSB_"+d.idx+",#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,"+sb+" ."+classes[12]+",#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal,"+sb+">a"), 1117 mCSB_container=$("#mCSB_"+d.idx+"_container"); 1118 if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));} 1119 if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));} 1120 if(d.bindEvents){ /* check if events are bound */ 1121 /* unbind namespaced events from document/selectors */ 1122
1122$(document).add($(!_canAccessIFrame() || top.document
vendor: 3,898 bytes, lines 1122-1214
1122)).unbind("."+namespace); 1123 sel.each(function(){ 1124 $(this).unbind("."+namespace); 1125 }); 1126 /* clear and delete timeouts/objects */ 1127 clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout"); 1128 clearTimeout(d.sequential.step); _delete(d.sequential,"step"); 1129 clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout"); 1130 d.bindEvents=false; 1131 } 1132 }, 1133 /* -------------------- */ 1134 1135 1136 /* toggles scrollbar visibility */ 1137 _scrollbarVisibility=function(disabled){ 1138 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1139 contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"), 1140 content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"), 1141 scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")], 1142 mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")]; 1143 if(o.axis!=="x"){ 1144 if(d.overflowed[0] && !disabled){ 1145 scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block"); 1146 content.removeClass(classes[8]+" "+classes[10]); 1147 }else{ 1148 if(o.alwaysShowScrollbar){ 1149 if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");} 1150 content.removeClass(classes[10]); 1151 }else{ 1152 scrollbar[0].css("display","none"); 1153 content.addClass(classes[10]); 1154 } 1155 content.addClass(classes[8]); 1156 } 1157 } 1158 if(o.axis!=="y"){ 1159 if(d.overflowed[1] && !disabled){ 1160 scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block"); 1161 content.removeClass(classes[9]+" "+classes[11]); 1162 }else{ 1163 if(o.alwaysShowScrollbar){ 1164 if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");} 1165 content.removeClass(classes[11]); 1166 }else{ 1167 scrollbar[1].css("display","none"); 1168 content.addClass(classes[11]); 1169 } 1170 content.addClass(classes[9]); 1171 } 1172 } 1173 if(!d.overflowed[0] && !d.overflowed[1]){ 1174 $this.addClass(classes[5]); 1175 }else{ 1176 $this.removeClass(classes[5]); 1177 } 1178 }, 1179 /* -------------------- */ 1180 1181 1182 /* returns input coordinates of pointer, touch and mouse events (relative to document) */ 1183 _coordinates=function(e){ 1184 var t=e.type,o=e.target.ownerDocument!==document && frameElement!==null ? [$(frameElement).offset().top,$(frameElement).offset().left] : null, 1185 io=_canAccessIFrame() && e.target.ownerDocument!==top.document && frameElement!==null ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0]; 1186 switch(t){ 1187 case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp": 1188 return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false]; 1189 break; 1190 case "touchstart": case "touchmove": case "touchend": 1191 var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], 1192 touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length; 1193 return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1]; 1194 break; 1195 default: 1196 return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false]; 1197 } 1198 }, 1199 /* -------------------- */ 1200 1201 1202 /* 1203 SCROLLBAR DRAG EVENTS 1204 scrolls content via scrollbar dragging 1205 */ 1206 _draggable=function(){ 1207 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1208 namespace=pluginPfx+"_"+d.idx, 1209 draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"], 1210 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1211 mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]), 1212 draggable,dragY,dragX, 1213 rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger, 1214
1214eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document
vendor: 48,256 bytes, lines 1214-2480
1214); 1215 mCSB_dragger.bind("contextmenu."+namespace,function(e){ 1216 e.preventDefault(); //prevent right click 1217 }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ 1218 e.stopImmediatePropagation(); 1219 e.preventDefault(); 1220 if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ 1221 touchActive=true; 1222 if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */ 1223 _iframe.call(mCSB_container,false); /* enable scrollbar dragging over iframes by disabling their events */ 1224 _stop($this); 1225 draggable=$(this); 1226 var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, 1227 h=draggable.height()+offset.top,w=draggable.width()+offset.left; 1228 if(y<h && y>0 && x<w && x>0){ 1229 dragY=y; 1230 dragX=x; 1231 } 1232 _onDragClasses(draggable,"active",o.autoExpandScrollbar); 1233 }).bind("touchmove."+namespace,function(e){ 1234 e.stopImmediatePropagation(); 1235 e.preventDefault(); 1236 var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; 1237 _drag(dragY,dragX,y,x); 1238 }); 1239 $(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){ 1240 if(draggable){ 1241 var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; 1242 if(dragY===y && dragX===x){return;} /* has it really moved? */ 1243 _drag(dragY,dragX,y,x); 1244 } 1245 }).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ 1246 if(draggable){ 1247 _onDragClasses(draggable,"active",o.autoExpandScrollbar); 1248 draggable=null; 1249 } 1250 touchActive=false; 1251 if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */ 1252 _iframe.call(mCSB_container,true); /* enable iframes events */ 1253 }); 1254 function _drag(dragY,dragX,y,x){ 1255 mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0; 1256 if(draggable.attr("id")===draggerId[1]){ 1257 var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x; 1258 }else{ 1259 var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y; 1260 } 1261 _scrollTo($this,to.toString(),{dir:dir,drag:true}); 1262 } 1263 }, 1264 /* -------------------- */ 1265 1266 1267 /* 1268 TOUCH SWIPE EVENTS 1269 scrolls content via touch swipe 1270 Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices 1271 */ 1272 _contentDraggable=function(){ 1273 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1274 namespace=pluginPfx+"_"+d.idx, 1275 mCustomScrollBox=$("#mCSB_"+d.idx), 1276 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1277 mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], 1278 draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount, 1279 durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag, 1280 iframe=mCSB_container.find("iframe"), 1281 events=[ 1282 "touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start 1283 "touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move 1284 "touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end 1285 ], 1286 touchAction=document.body.style.touchAction!==undefined && document.body.style.touchAction!==""; 1287 mCSB_container.bind(events[0],function(e){ 1288 _onTouchstart(e); 1289 }).bind(events[1],function(e){ 1290 _onTouchmove(e); 1291 }); 1292 mCustomScrollBox.bind(events[0],function(e){ 1293 _onTouchstart2(e); 1294 }).bind(events[2],function(e){ 1295 _onTouchend(e); 1296 }); 1297 if(iframe.length){ 1298 iframe.each(function(){ 1299 $(this).bind("load",function(){ 1300 /* bind events on accessible iframes */ 1301 if(_canAccessIFrame(this)){ 1302 $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ 1303 _onTouchstart(e); 1304 _onTouchstart2(e); 1305 }).bind(events[1],function(e){ 1306 _onTouchmove(e); 1307 }).bind(events[2],function(e){ 1308 _onTouchend(e); 1309 }); 1310 } 1311 }); 1312 }); 1313 } 1314 function _onTouchstart(e){ 1315 if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;} 1316 touchable=1; touchDrag=0; docDrag=0; draggable=1; 1317 $this.removeClass("mCS_touch_action"); 1318 var offset=mCSB_container.offset(); 1319 dragY=_coordinates(e)[0]-offset.top; 1320 dragX=_coordinates(e)[1]-offset.left; 1321 touchIntent=[_coordinates(e)[0],_coordinates(e)[1]]; 1322 } 1323 function _onTouchmove(e){ 1324 if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;} 1325 if(!o.documentTouchScroll){e.preventDefault();} 1326 e.stopImmediatePropagation(); 1327 if(docDrag && !touchDrag){return;} 1328 if(draggable){ 1329 runningTime=_getTime(); 1330 var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, 1331 easing="mcsLinearOut"; 1332 touchMoveY.push(y); 1333 touchMoveX.push(x); 1334 touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]); 1335 if(d.overflowed[0]){ 1336 var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), 1337 prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*2<touchIntent[2] || o.axis==="yx")); 1338 } 1339 if(d.overflowed[1]){ 1340 var limitX=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(), 1341 preventX=((dragX-x)>0 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*2<touchIntent[3] || o.axis==="yx")); 1342 } 1343 if(prevent || preventX){ /* prevent native document scrolling */ 1344 if(!touchAction){e.preventDefault();} 1345 touchDrag=1; 1346 }else{ 1347 docDrag=1; 1348 $this.addClass("mCS_touch_action"); 1349 } 1350 if(touchAction){e.preventDefault();} 1351 amount=o.axis==="yx" ? [(dragY-y),(dragX-x)] : o.axis==="x" ? [null,(dragX-x)] : [(dragY-y),null]; 1352 mCSB_container[0].idleTimer=250; 1353 if(d.overflowed[0]){_drag(amount[0],durA,easing,"y","all",true);} 1354 if(d.overflowed[1]){_drag(amount[1],durA,easing,"x",overwrite,true);} 1355 } 1356 } 1357 function _onTouchstart2(e){ 1358 if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;} 1359 touchable=1; 1360 e.stopImmediatePropagation(); 1361 _stop($this); 1362 startTime=_getTime(); 1363 var offset=mCustomScrollBox.offset(); 1364 touchStartY=_coordinates(e)[0]-offset.top; 1365 touchStartX=_coordinates(e)[1]-offset.left; 1366 touchMoveY=[]; touchMoveX=[]; 1367 } 1368 function _onTouchend(e){ 1369 if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;} 1370 draggable=0; 1371 e.stopImmediatePropagation(); 1372 touchDrag=0; docDrag=0; 1373 endTime=_getTime(); 1374 var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; 1375 if((endTime-runningTime)>30){return;} 1376 speed=1000/(endTime-startTime); 1377 var easing="mcsEaseOut",slow=speed<2.5, 1378 diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0]; 1379 distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX]; 1380 var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])]; 1381 speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed]; 1382 var a=[ 1383 Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])), 1384 Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1])) 1385 ]; 1386 amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null]; 1387 durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia]; 1388 var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */ 1389 amount[0]=absDistance[0]>md ? amount[0] : 0; 1390 amount[1]=absDistance[1]>md ? amount[1] : 0; 1391 if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);} 1392 if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);} 1393 } 1394 function _m(ds,s){ 1395 var r=[s*1.5,s*2,s/1.5,s/2]; 1396 if(ds>90){ 1397 return s>4 ? r[0] : r[3]; 1398 }else if(ds>60){ 1399 return s>3 ? r[3] : r[2]; 1400 }else if(ds>30){ 1401 return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2]; 1402 }else{ 1403 return s>8 ? s : r[3]; 1404 } 1405 } 1406 function _drag(amount,dur,easing,dir,overwrite,drag){ 1407 if(!amount){return;} 1408 _scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag}); 1409 } 1410 }, 1411 /* -------------------- */ 1412 1413 1414 /* 1415 SELECT TEXT EVENTS 1416 scrolls content when text is selected 1417 */ 1418 _selectable=function(){ 1419 var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, 1420 namespace=pluginPfx+"_"+d.idx, 1421 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1422 wrapper=mCSB_container.parent(), 1423 action; 1424 mCSB_container.bind("mousedown."+namespace,function(e){ 1425 if(touchable){return;} 1426 if(!action){action=1; touchActive=true;} 1427 }).add(document).bind("mousemove."+namespace,function(e){ 1428 if(!touchable && action && _sel()){ 1429 var offset=mCSB_container.offset(), 1430 y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft; 1431 if(y>0 && y<wrapper.height() && x>0 && x<wrapper.width()){ 1432 if(seq.step){_seq("off",null,"stepped");} 1433 }else{ 1434 if(o.axis!=="x" && d.overflowed[0]){ 1435 if(y<0){ 1436 _seq("on",38); 1437 }else if(y>wrapper.height()){ 1438 _seq("on",40); 1439 } 1440 } 1441 if(o.axis!=="y" && d.overflowed[1]){ 1442 if(x<0){ 1443 _seq("on",37); 1444 }else if(x>wrapper.width()){ 1445 _seq("on",39); 1446 } 1447 } 1448 } 1449 } 1450 }).bind("mouseup."+namespace+" dragend."+namespace,function(e){ 1451 if(touchable){return;} 1452 if(action){action=0; _seq("off",null);} 1453 touchActive=false; 1454 }); 1455 function _sel(){ 1456 return window.getSelection ? window.getSelection().toString() : 1457 document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0; 1458 } 1459 function _seq(a,c,s){ 1460 seq.type=s && action ? "stepped" : "stepless"; 1461 seq.scrollAmount=10; 1462 _sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null); 1463 } 1464 }, 1465 /* -------------------- */ 1466 1467 1468 /* 1469 MOUSE WHEEL EVENT 1470 scrolls content via mouse-wheel 1471 via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel) 1472 */ 1473 _mousewheel=function(){ 1474 if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */ 1475 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1476 namespace=pluginPfx+"_"+d.idx, 1477 mCustomScrollBox=$("#mCSB_"+d.idx), 1478 mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], 1479 iframe=$("#mCSB_"+d.idx+"_container").find("iframe"); 1480 if(iframe.length){ 1481 iframe.each(function(){ 1482 $(this).bind("load",function(){ 1483 /* bind events on accessible iframes */ 1484 if(_canAccessIFrame(this)){ 1485 $(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){ 1486 _onMousewheel(e,delta); 1487 }); 1488 } 1489 }); 1490 }); 1491 } 1492 mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){ 1493 _onMousewheel(e,delta); 1494 }); 1495 function _onMousewheel(e,delta){ 1496 _stop($this); 1497 if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */ 1498 var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100, 1499 dur=o.scrollInertia; 1500 if(o.axis==="x" || o.mouseWheel.axis==="x"){ 1501 var dir="x", 1502 px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)], 1503 amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0], 1504 contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft), 1505 draggerPos=mCSB_dragger[1][0].offsetLeft, 1506 limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(), 1507 dlt=o.mouseWheel.axis==="y" ? (e.deltaY || delta) : e.deltaX; 1508 }else{ 1509 var dir="y", 1510 px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)], 1511 amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0], 1512 contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop), 1513 draggerPos=mCSB_dragger[0][0].offsetTop, 1514 limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), 1515 dlt=e.deltaY || delta; 1516 } 1517 if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;} 1518 if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;} 1519 if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;} 1520 if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){ 1521 e.stopImmediatePropagation(); 1522 e.preventDefault(); 1523 } 1524 if(e.deltaFactor<5 && !o.mouseWheel.normalizeDelta){ 1525 //very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly 1526 amount=e.deltaFactor; dur=17; 1527 } 1528 _scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur}); 1529 } 1530 }, 1531 /* -------------------- */ 1532 1533 1534 /* checks if iframe can be accessed */ 1535 _canAccessIFrameCache=new Object(), 1536 _canAccessIFrame=function(iframe){ 1537 var result=false,cacheKey=false,html=null; 1538 if(iframe===undefined){ 1539 cacheKey="#empty"; 1540 }else if($(iframe).attr("id")!==undefined){ 1541 cacheKey=$(iframe).attr("id"); 1542 } 1543 if(cacheKey!==false && _canAccessIFrameCache[cacheKey]!==undefined){ 1544 return _canAccessIFrameCache[cacheKey]; 1545 } 1546 if(!iframe){ 1547 try{ 1548 var doc=top.document; 1549 html=doc.body.innerHTML; 1550 }catch(err){/* do nothing */} 1551 result=(html!==null); 1552 }else{ 1553 try{ 1554 var doc=iframe.contentDocument || iframe.contentWindow.document; 1555 html=doc.body.innerHTML; 1556 }catch(err){/* do nothing */} 1557 result=(html!==null); 1558 } 1559 if(cacheKey!==false){_canAccessIFrameCache[cacheKey]=result;} 1560 return result; 1561 }, 1562 /* -------------------- */ 1563 1564 1565 /* switches iframe's pointer-events property (drag, mousewheel etc. over cross-domain iframes) */ 1566 _iframe=function(evt){ 1567 var el=this.find("iframe"); 1568 if(!el.length){return;} /* check if content contains iframes */ 1569 var val=!evt ? "none" : "auto"; 1570 el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */ 1571 }, 1572 /* -------------------- */ 1573 1574 1575 /* disables mouse-wheel when hovering specific elements like select, datalist etc. */ 1576 _disableMousewheel=function(el,target){ 1577 var tag=target.nodeName.toLowerCase(), 1578 tags=el.data(pluginPfx).opt.mouseWheel.disableOver, 1579 /* elements that require focus */ 1580 focusTags=["select","textarea"]; 1581 return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus")); 1582 }, 1583 /* -------------------- */ 1584 1585 1586 /* 1587 DRAGGER RAIL CLICK EVENT 1588 scrolls content via dragger rail 1589 */ 1590 _draggerRail=function(){ 1591 var $this=$(this),d=$this.data(pluginPfx), 1592 namespace=pluginPfx+"_"+d.idx, 1593 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1594 wrapper=mCSB_container.parent(), 1595 mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]), 1596 clickable; 1597 mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ 1598 touchActive=true; 1599 if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;} 1600 }).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ 1601 touchActive=false; 1602 }).bind("click."+namespace,function(e){ 1603 if(!clickable){return;} 1604 clickable=0; 1605 if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){ 1606 _stop($this); 1607 var el=$(this),mCSB_dragger=el.find(".mCSB_dragger"); 1608 if(el.parent(".mCSB_scrollTools_horizontal").length>0){ 1609 if(!d.overflowed[1]){return;} 1610 var dir="x", 1611 clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1, 1612 to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9)); 1613 }else{ 1614 if(!d.overflowed[0]){return;} 1615 var dir="y", 1616 clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1, 1617 to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9)); 1618 } 1619 _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); 1620 } 1621 }); 1622 }, 1623 /* -------------------- */ 1624 1625 1626 /* 1627 FOCUS EVENT 1628 scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.) 1629 */ 1630 _focus=function(){ 1631 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1632 namespace=pluginPfx+"_"+d.idx, 1633 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1634 wrapper=mCSB_container.parent(); 1635 mCSB_container.bind("focusin."+namespace,function(e){ 1636 var el=$(document.activeElement), 1637 nested=mCSB_container.find(".mCustomScrollBox").length, 1638 dur=0; 1639 if(!el.is(o.advanced.autoScrollOnFocus)){return;} 1640 _stop($this); 1641 clearTimeout($this[0]._focusTimeout); 1642 $this[0]._focusTimer=nested ? (dur+17)*nested : 0; 1643 $this[0]._focusTimeout=setTimeout(function(){ 1644 var to=[_childPos(el)[0],_childPos(el)[1]], 1645 contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], 1646 isVisible=[ 1647 (contentPos[0]+to[0]>=0 && contentPos[0]+to[0]<wrapper.height()-el.outerHeight(false)), 1648 (contentPos[1]+to[1]>=0 && contentPos[0]+to[1]<wrapper.width()-el.outerWidth(false)) 1649 ], 1650 overwrite=(o.axis==="yx" && !isVisible[0] && !isVisible[1]) ? "none" : "all"; 1651 if(o.axis!=="x" && !isVisible[0]){ 1652 _scrollTo($this,to[0].toString(),{dir:"y",scrollEasing:"mcsEaseInOut",overwrite:overwrite,dur:dur}); 1653 } 1654 if(o.axis!=="y" && !isVisible[1]){ 1655 _scrollTo($this,to[1].toString(),{dir:"x",scrollEasing:"mcsEaseInOut",overwrite:overwrite,dur:dur}); 1656 } 1657 },$this[0]._focusTimer); 1658 }); 1659 }, 1660 /* -------------------- */ 1661 1662 1663 /* sets content wrapper scrollTop/scrollLeft always to 0 */ 1664 _wrapperScroll=function(){ 1665 var $this=$(this),d=$this.data(pluginPfx), 1666 namespace=pluginPfx+"_"+d.idx, 1667 wrapper=$("#mCSB_"+d.idx+"_container").parent(); 1668 wrapper.bind("scroll."+namespace,function(e){ 1669 if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ 1670 $(".mCSB_"+d.idx+"_scrollbar").css("visibility","hidden"); /* hide scrollbar(s) */ 1671 } 1672 }); 1673 }, 1674 /* -------------------- */ 1675 1676 1677 /* 1678 BUTTONS EVENTS 1679 scrolls content via up, down, left and right buttons 1680 */ 1681 _buttons=function(){ 1682 var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, 1683 namespace=pluginPfx+"_"+d.idx, 1684 sel=".mCSB_"+d.idx+"_scrollbar", 1685 btn=$(sel+">a"); 1686 btn.bind("contextmenu."+namespace,function(e){ 1687 e.preventDefault(); //prevent right click 1688 }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace+" mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace+" mouseout."+namespace+" pointerout."+namespace+" MSPointerOut."+namespace+" click."+namespace,function(e){ 1689 e.preventDefault(); 1690 if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ 1691 var btnClass=$(this).attr("class"); 1692 seq.type=o.scrollButtons.scrollType; 1693 switch(e.type){ 1694 case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown": 1695 if(seq.type==="stepped"){return;} 1696 touchActive=true; 1697 d.tweenRunning=false; 1698 _seq("on",btnClass); 1699 break; 1700 case "mouseup": case "touchend": case "pointerup": case "MSPointerUp": 1701 case "mouseout": case "pointerout": case "MSPointerOut": 1702 if(seq.type==="stepped"){return;} 1703 touchActive=false; 1704 if(seq.dir){_seq("off",btnClass);} 1705 break; 1706 case "click": 1707 if(seq.type!=="stepped" || d.tweenRunning){return;} 1708 _seq("on",btnClass); 1709 break; 1710 } 1711 function _seq(a,c){ 1712 seq.scrollAmount=o.scrollButtons.scrollAmount; 1713 _sequentialScroll($this,a,c); 1714 } 1715 }); 1716 }, 1717 /* -------------------- */ 1718 1719 1720 /* 1721 KEYBOARD EVENTS 1722 scrolls content via keyboard 1723 Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End 1724 */ 1725 _keyboard=function(){ 1726 var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, 1727 namespace=pluginPfx+"_"+d.idx, 1728 mCustomScrollBox=$("#mCSB_"+d.idx), 1729 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1730 wrapper=mCSB_container.parent(), 1731 editables="input,textarea,select,datalist,keygen,[contenteditable='true']", 1732 iframe=mCSB_container.find("iframe"), 1733 events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace]; 1734 if(iframe.length){ 1735 iframe.each(function(){ 1736 $(this).bind("load",function(){ 1737 /* bind events on accessible iframes */ 1738 if(_canAccessIFrame(this)){ 1739 $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ 1740 _onKeyboard(e); 1741 }); 1742 } 1743 }); 1744 }); 1745 } 1746 mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){ 1747 _onKeyboard(e); 1748 }); 1749 function _onKeyboard(e){ 1750 switch(e.type){ 1751 case "blur": 1752 if(d.tweenRunning && seq.dir){_seq("off",null);} 1753 break; 1754 case "keydown": case "keyup": 1755 var code=e.keyCode ? e.keyCode : e.which,action="on"; 1756 if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){ 1757 /* up (38), down (40), left (37), right (39) arrows */ 1758 if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;} 1759 if(e.type==="keyup"){action="off";} 1760 if(!$(document.activeElement).is(editables)){ 1761 e.preventDefault(); 1762 e.stopImmediatePropagation(); 1763 _seq(action,code); 1764 } 1765 }else if(code===33 || code===34){ 1766 /* PgUp (33), PgDn (34) */ 1767 if(d.overflowed[0] || d.overflowed[1]){ 1768 e.preventDefault(); 1769 e.stopImmediatePropagation(); 1770 } 1771 if(e.type==="keyup"){ 1772 _stop($this); 1773 var keyboardDir=code===34 ? -1 : 1; 1774 if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ 1775 var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9)); 1776 }else{ 1777 var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9)); 1778 } 1779 _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); 1780 } 1781 }else if(code===35 || code===36){ 1782 /* End (35), Home (36) */ 1783 if(!$(document.activeElement).is(editables)){ 1784 if(d.overflowed[0] || d.overflowed[1]){ 1785 e.preventDefault(); 1786 e.stopImmediatePropagation(); 1787 } 1788 if(e.type==="keyup"){ 1789 if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ 1790 var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0; 1791 }else{ 1792 var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0; 1793 } 1794 _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); 1795 } 1796 } 1797 } 1798 break; 1799 } 1800 function _seq(a,c){ 1801 seq.type=o.keyboard.scrollType; 1802 seq.scrollAmount=o.keyboard.scrollAmount; 1803 if(seq.type==="stepped" && d.tweenRunning){return;} 1804 _sequentialScroll($this,a,c); 1805 } 1806 } 1807 }, 1808 /* -------------------- */ 1809 1810 1811 /* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */ 1812 _sequentialScroll=function(el,action,trigger,e,s){ 1813 var d=el.data(pluginPfx),o=d.opt,seq=d.sequential, 1814 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1815 once=seq.type==="stepped" ? true : false, 1816 steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */ 1817 steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia; 1818 switch(action){ 1819 case "on": 1820 seq.dir=[ 1821 (trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"), 1822 (trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1) 1823 ]; 1824 _stop(el); 1825 if(_isNumeric(trigger) && seq.type==="stepped"){return;} 1826 _on(once); 1827 break; 1828 case "off": 1829 _off(); 1830 if(once || (d.tweenRunning && seq.dir)){ 1831 _on(true); 1832 } 1833 break; 1834 } 1835 1836 /* starts sequence */ 1837 function _on(once){ 1838 if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */ 1839 var c=seq.type!=="stepped", /* continuous scrolling */ 1840 t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */ 1841 m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */ 1842 contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)], 1843 ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x], 1844 amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)), 1845 px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)), 1846 to=seq.scrollAmount!=="auto" ? px : amount, 1847 easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut", 1848 onComplete=!once ? false : true; 1849 if(once && t<17){ 1850 to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0]; 1851 } 1852 _scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete}); 1853 if(once){ 1854 seq.dir=false; 1855 return; 1856 } 1857 clearTimeout(seq.step); 1858 seq.step=setTimeout(function(){ 1859 _on(); 1860 },t); 1861 } 1862 /* stops sequence */ 1863 function _off(){ 1864 clearTimeout(seq.step); 1865 _delete(seq,"step"); 1866 _stop(el); 1867 } 1868 }, 1869 /* -------------------- */ 1870 1871 1872 /* returns a yx array from value */ 1873 _arr=function(val){ 1874 var o=$(this).data(pluginPfx).opt,vals=[]; 1875 if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */ 1876 /* check if value is object or array, its length and create an array with yx values */ 1877 if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */ 1878 vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val; 1879 vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val; 1880 }else{ /* array value (e.g. [100,100]) */ 1881 vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null]; 1882 } 1883 /* check if array values are anonymous functions */ 1884 if(typeof vals[0]==="function"){vals[0]=vals[0]();} 1885 if(typeof vals[1]==="function"){vals[1]=vals[1]();} 1886 return vals; 1887 }, 1888 /* -------------------- */ 1889 1890 1891 /* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */ 1892 _to=function(val,dir){ 1893 if(val==null || typeof val=="undefined"){return;} 1894 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1895 mCSB_container=$("#mCSB_"+d.idx+"_container"), 1896 wrapper=mCSB_container.parent(), 1897 t=typeof val; 1898 if(!dir){dir=o.axis==="x" ? "x" : "y";} 1899 var contentLength=dir==="x" ? mCSB_container.outerWidth(false)-wrapper.width() : mCSB_container.outerHeight(false)-wrapper.height(), 1900 contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop, 1901 cssProp=dir==="x" ? "left" : "top"; 1902 switch(t){ 1903 case "function": /* this currently is not used. Consider removing it */ 1904 return val(); 1905 break; 1906 case "object": /* js/jquery object */ 1907 var obj=val.jquery ? val : $(val); 1908 if(!obj.length){return;} 1909 return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; 1910 break; 1911 case "string": case "number": 1912 if(_isNumeric(val)){ /* numeric value */ 1913 return Math.abs(val); 1914 }else if(val.indexOf("%")!==-1){ /* percentage value */ 1915 return Math.abs(contentLength*parseInt(val)/100); 1916 }else if(val.indexOf("-=")!==-1){ /* decrease value */ 1917 return Math.abs(contentPos-parseInt(val.split("-=")[1])); 1918 }else if(val.indexOf("+=")!==-1){ /* inrease value */ 1919 var p=(contentPos+parseInt(val.split("+=")[1])); 1920 return p>=0 ? 0 : Math.abs(p); 1921 }else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */ 1922 return Math.abs(val.split("px")[0]); 1923 }else{ 1924 if(val==="top" || val==="left"){ /* special strings */ 1925 return 0; 1926 }else if(val==="bottom"){ 1927 return Math.abs(wrapper.height()-mCSB_container.outerHeight(false)); 1928 }else if(val==="right"){ 1929 return Math.abs(wrapper.width()-mCSB_container.outerWidth(false)); 1930 }else if(val==="first" || val==="last"){ 1931 var obj=mCSB_container.find(":"+val); 1932 return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; 1933 }else{ 1934 if($(val).length){ /* jquery selector */ 1935 return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0]; 1936 }else{ /* other values (e.g. "100em") */ 1937 mCSB_container.css(cssProp,val); 1938 methods.update.call(null,$this[0]); 1939 return; 1940 } 1941 } 1942 } 1943 break; 1944 } 1945 }, 1946 /* -------------------- */ 1947 1948 1949 /* calls the update method automatically */ 1950 _autoUpdate=function(rem){ 1951 var $this=$(this),d=$this.data(pluginPfx),o=d.opt, 1952 mCSB_container=$("#mCSB_"+d.idx+"_container"); 1953 if(rem){ 1954 /* 1955 removes autoUpdate timer 1956 usage: _autoUpdate.call(this,"remove"); 1957 */ 1958 clearTimeout(mCSB_container[0].autoUpdate); 1959 _delete(mCSB_container[0],"autoUpdate"); 1960 return; 1961 } 1962 upd(); 1963 function upd(){ 1964 clearTimeout(mCSB_container[0].autoUpdate); 1965 if($this.parents("html").length===0){ 1966 /* check element in dom tree */ 1967 $this=null; 1968 return; 1969 } 1970 mCSB_container[0].autoUpdate=setTimeout(function(){ 1971 /* update on specific selector(s) length and size change */ 1972 if(o.advanced.updateOnSelectorChange){ 1973 d.poll.change.n=sizesSum(); 1974 if(d.poll.change.n!==d.poll.change.o){ 1975 d.poll.change.o=d.poll.change.n; 1976 doUpd(3); 1977 return; 1978 } 1979 } 1980 /* update on main element and scrollbar size changes */ 1981 if(o.advanced.updateOnContentResize){ 1982 d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth; 1983 if(d.poll.size.n!==d.poll.size.o){ 1984 d.poll.size.o=d.poll.size.n; 1985 doUpd(1); 1986 return; 1987 } 1988 } 1989 /* update on image load */ 1990 if(o.advanced.updateOnImageLoad){ 1991 if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content 1992 d.poll.img.n=mCSB_container.find("img").length; 1993 if(d.poll.img.n!==d.poll.img.o){ 1994 d.poll.img.o=d.poll.img.n; 1995 mCSB_container.find("img").each(function(){ 1996 imgLoader(this); 1997 }); 1998 return; 1999 } 2000 } 2001 } 2002 if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();} 2003 },o.advanced.autoUpdateTimeout); 2004 } 2005 /* a tiny image loader */ 2006 function imgLoader(el){ 2007 if($(el).hasClass(classes[2])){doUpd(); return;} 2008 var img=new Image(); 2009 function createDelegate(contextObject,delegateMethod){ 2010 return function(){return delegateMethod.apply(contextObject,arguments);} 2011 } 2012 function imgOnLoad(){ 2013 this.onload=null; 2014 $(el).addClass(classes[2]); 2015 doUpd(2); 2016 } 2017 img.onload=createDelegate(img,imgOnLoad); 2018 img.src=el.src; 2019 } 2020 /* returns the total height and width sum of all elements matching the selector */ 2021 function sizesSum(){ 2022 if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";} 2023 var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange); 2024 if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});} 2025 return total; 2026 } 2027 /* calls the update method */ 2028 function doUpd(cb){ 2029 clearTimeout(mCSB_container[0].autoUpdate); 2030 methods.update.call(null,$this[0],cb); 2031 } 2032 }, 2033 /* -------------------- */ 2034 2035 2036 /* snaps scrolling to a multiple of a pixels number */ 2037 _snapAmount=function(to,amount,offset){ 2038 return (Math.round(to/amount)*amount-offset); 2039 }, 2040 /* -------------------- */ 2041 2042 2043 /* stops content and scrollbar animations */ 2044 _stop=function(el){ 2045 var d=el.data(pluginPfx), 2046 sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal"); 2047 sel.each(function(){ 2048 _stopTween.call(this); 2049 }); 2050 }, 2051 /* -------------------- */ 2052 2053 2054 /* 2055 ANIMATES CONTENT 2056 This is where the actual scrolling happens 2057 */ 2058 _scrollTo=function(el,to,options){ 2059 var d=el.data(pluginPfx),o=d.opt, 2060 defaults={ 2061 trigger:"internal", 2062 dir:"y", 2063 scrollEasing:"mcsEaseOut", 2064 drag:false, 2065 dur:o.scrollInertia, 2066 overwrite:"all", 2067 callbacks:true, 2068 onStart:true, 2069 onUpdate:true, 2070 onComplete:true 2071 }, 2072 options=$.extend(defaults,options), 2073 dur=[options.dur,(options.drag ? 0 : options.dur)], 2074 mCustomScrollBox=$("#mCSB_"+d.idx), 2075 mCSB_container=$("#mCSB_"+d.idx+"_container"), 2076 wrapper=mCSB_container.parent(), 2077 totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0], 2078 totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0]; 2079 d.trigger=options.trigger; 2080 if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */ 2081 $(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible"); 2082 wrapper.scrollTop(0).scrollLeft(0); 2083 } 2084 if(to==="_resetY" && !d.contentReset.y){ 2085 /* callbacks: onOverflowYNone */ 2086 if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);} 2087 d.contentReset.y=1; 2088 } 2089 if(to==="_resetX" && !d.contentReset.x){ 2090 /* callbacks: onOverflowXNone */ 2091 if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);} 2092 d.contentReset.x=1; 2093 } 2094 if(to==="_resetY" || to==="_resetX"){return;} 2095 if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){ 2096 /* callbacks: onOverflowY */ 2097 if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);} 2098 d.contentReset.x=null; 2099 } 2100 if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){ 2101 /* callbacks: onOverflowX */ 2102 if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);} 2103 d.contentReset.x=null; 2104 } 2105 if(o.snapAmount){ /* scrolling snapping */ 2106 var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0]; 2107 to=_snapAmount(to,snapAmount,o.snapOffset); 2108 } 2109 switch(options.dir){ 2110 case "x": 2111 var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"), 2112 property="left", 2113 contentPos=mCSB_container[0].offsetLeft, 2114 limit=[ 2115 mCustomScrollBox.width()-mCSB_container.outerWidth(false), 2116 mCSB_dragger.parent().width()-mCSB_dragger.width() 2117 ], 2118 scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)], 2119 tso=totalScrollOffsets[1], 2120 tsbo=totalScrollBackOffsets[1], 2121 totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0, 2122 totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0; 2123 break; 2124 case "y": 2125 var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"), 2126 property="top", 2127 contentPos=mCSB_container[0].offsetTop, 2128 limit=[ 2129 mCustomScrollBox.height()-mCSB_container.outerHeight(false), 2130 mCSB_dragger.parent().height()-mCSB_dragger.height() 2131 ], 2132 scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)], 2133 tso=totalScrollOffsets[0], 2134 tsbo=totalScrollBackOffsets[0], 2135 totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0, 2136 totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0; 2137 break; 2138 } 2139 if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){ 2140 scrollTo=[0,0]; 2141 }else if(scrollTo[1]>=limit[1]){ 2142 scrollTo=[limit[0],limit[1]]; 2143 }else{ 2144 scrollTo[0]=-scrollTo[0]; 2145 } 2146 if(!el[0].mcs){ 2147 _mcs(); /* init mcs object (once) to make it available before callbacks */ 2148 if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */ 2149 } 2150 clearTimeout(mCSB_container[0].onCompleteTimeout); 2151 _tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing); 2152 if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;} 2153 _tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{ 2154 onStart:function(){ 2155 if(options.callbacks && options.onStart && !d.tweenRunning){ 2156 /* callbacks: onScrollStart */ 2157 if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);} 2158 d.tweenRunning=true; 2159 _onDragClasses(mCSB_dragger); 2160 d.cbOffsets=_cbOffsets(); 2161 } 2162 },onUpdate:function(){ 2163 if(options.callbacks && options.onUpdate){ 2164 /* callbacks: whileScrolling */ 2165 if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);} 2166 } 2167 },onComplete:function(){ 2168 if(options.callbacks && options.onComplete){ 2169 if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);} 2170 var t=mCSB_container[0].idleTimer || 0; 2171 mCSB_container[0].onCompleteTimeout=setTimeout(function(){ 2172 /* callbacks: onScroll, onTotalScroll, onTotalScrollBack */ 2173 if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);} 2174 if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);} 2175 if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);} 2176 d.tweenRunning=false; 2177 mCSB_container[0].idleTimer=0; 2178 _onDragClasses(mCSB_dragger,"hide"); 2179 },t); 2180 } 2181 } 2182 }); 2183 /* checks if callback function exists */ 2184 function _cb(cb){ 2185 return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function"; 2186 } 2187 /* checks whether callback offsets always trigger */ 2188 function _cbOffsets(){ 2189 return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo]; 2190 } 2191 /* 2192 populates object with useful values for the user 2193 values: 2194 content: this.mcs.content 2195 content top position: this.mcs.top 2196 content left position: this.mcs.left 2197 dragger top position: this.mcs.draggerTop 2198 dragger left position: this.mcs.draggerLeft 2199 scrolling y percentage: this.mcs.topPct 2200 scrolling x percentage: this.mcs.leftPct 2201 scrolling direction: this.mcs.direction 2202 */ 2203 function _mcs(){ 2204 var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */ 2205 dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */ 2206 cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */ 2207 pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */ 2208 el[0].mcs={ 2209 content:mCSB_container, /* original content wrapper as jquery object */ 2210 top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1], 2211 topPct:Math.round((100*Math.abs(cp[0]))/(Math.abs(cl[0])-pl[0])),leftPct:Math.round((100*Math.abs(cp[1]))/(Math.abs(cl[1])-pl[1])), 2212 direction:options.dir 2213 }; 2214 /* 2215 this refers to the original element containing the scrollbar(s) 2216 usage: this.mcs.top, this.mcs.leftPct etc. 2217 */ 2218 } 2219 }, 2220 /* -------------------- */ 2221 2222 2223 /* 2224 CUSTOM JAVASCRIPT ANIMATION TWEEN 2225 Lighter and faster than jquery animate() and css transitions 2226 Animates top/left properties and includes easings 2227 */ 2228 _tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){ 2229 if(!el._mTween){el._mTween={top:{},left:{}};} 2230 var callbacks=callbacks || {}, 2231 onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){}, 2232 startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop]; 2233 if(prop==="left"){from=el.offsetLeft;} 2234 var diff=to-from; 2235 tobj.stop=0; 2236 if(overwrite!=="none"){_cancelTween();} 2237 _startTween(); 2238 function _step(){ 2239 if(tobj.stop){return;} 2240 if(!progress){onStart.call();} 2241 progress=_getTime()-startTime; 2242 _tween(); 2243 if(progress>=tobj.time){ 2244 tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1; 2245 if(tobj.time<progress+1){tobj.time=progress+1;} 2246 } 2247 if(tobj.time<duration){tobj.id=_request(_step);}else{onComplete.call();} 2248 } 2249 function _tween(){ 2250 if(duration>0){ 2251 tobj.currVal=_ease(tobj.time,from,diff,duration,easing); 2252 elStyle[prop]=Math.round(tobj.currVal)+"px"; 2253 }else{ 2254 elStyle[prop]=to+"px"; 2255 } 2256 onUpdate.call(); 2257 } 2258 function _startTween(){ 2259 _delay=1000/60; 2260 tobj.time=progress+_delay; 2261 _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; 2262 tobj.id=_request(_step); 2263 } 2264 function _cancelTween(){ 2265 if(tobj.id==null){return;} 2266 if(!window.requestAnimationFrame){clearTimeout(tobj.id); 2267 }else{window.cancelAnimationFrame(tobj.id);} 2268 tobj.id=null; 2269 } 2270 function _ease(t,b,c,d,type){ 2271 switch(type){ 2272 case "linear": case "mcsLinear": 2273 return c*t/d + b; 2274 break; 2275 case "mcsLinearOut": 2276 t/=d; t--; return c * Math.sqrt(1 - t*t) + b; 2277 break; 2278 case "easeInOutSmooth": 2279 t/=d/2; 2280 if(t<1) return c/2*t*t + b; 2281 t--; 2282 return -c/2 * (t*(t-2) - 1) + b; 2283 break; 2284 case "easeInOutStrong": 2285 t/=d/2; 2286 if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b; 2287 t--; 2288 return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b; 2289 break; 2290 case "easeInOut": case "mcsEaseInOut": 2291 t/=d/2; 2292 if(t<1) return c/2*t*t*t + b; 2293 t-=2; 2294 return c/2*(t*t*t + 2) + b; 2295 break; 2296 case "easeOutSmooth": 2297 t/=d; t--; 2298 return -c * (t*t*t*t - 1) + b; 2299 break; 2300 case "easeOutStrong": 2301 return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b; 2302 break; 2303 case "easeOut": case "mcsEaseOut": default: 2304 var ts=(t/=d)*t,tc=ts*t; 2305 return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); 2306 } 2307 } 2308 }, 2309 /* -------------------- */ 2310 2311 2312 /* returns current time */ 2313 _getTime=function(){ 2314 if(window.performance && window.performance.now){ 2315 return window.performance.now(); 2316 }else{ 2317 if(window.performance && window.performance.webkitNow){ 2318 return window.performance.webkitNow(); 2319 }else{ 2320 if(Date.now){return Date.now();}else{return new Date().getTime();} 2321 } 2322 } 2323 }, 2324 /* -------------------- */ 2325 2326 2327 /* stops a tween */ 2328 _stopTween=function(){ 2329 var el=this; 2330 if(!el._mTween){el._mTween={top:{},left:{}};} 2331 var props=["top","left"]; 2332 for(var i=0; i<props.length; i++){ 2333 var prop=props[i]; 2334 if(el._mTween[prop].id){ 2335 if(!window.requestAnimationFrame){clearTimeout(el._mTween[prop].id); 2336 }else{window.cancelAnimationFrame(el._mTween[prop].id);} 2337 el._mTween[prop].id=null; 2338 el._mTween[prop].stop=1; 2339 } 2340 } 2341 }, 2342 /* -------------------- */ 2343 2344 2345 /* deletes a property (avoiding the exception thrown by IE) */ 2346 _delete=function(c,m){ 2347 try{delete c[m];}catch(e){c[m]=null;} 2348 }, 2349 /* -------------------- */ 2350 2351 2352 /* detects left mouse button */ 2353 _mouseBtnLeft=function(e){ 2354 return !(e.which && e.which!==1); 2355 }, 2356 /* -------------------- */ 2357 2358 2359 /* detects if pointer type event is touch */ 2360 _pointerTouch=function(e){ 2361 var t=e.originalEvent.pointerType; 2362 return !(t && t!=="touch" && t!==2); 2363 }, 2364 /* -------------------- */ 2365 2366 2367 /* checks if value is numeric */ 2368 _isNumeric=function(val){ 2369 return !isNaN(parseFloat(val)) && isFinite(val); 2370 }, 2371 /* -------------------- */ 2372 2373 2374 /* returns element position according to content */ 2375 _childPos=function(el){ 2376 var p=el.parents(".mCSB_container"); 2377 return [el.offset().top-p.offset().top,el.offset().left-p.offset().left]; 2378 }, 2379 /* -------------------- */ 2380 2381 2382 /* checks if browser tab is hidden/inactive via Page Visibility API */ 2383 _isTabHidden=function(){ 2384 var prop=_getHiddenProp(); 2385 if(!prop) return false; 2386 return document[prop]; 2387 function _getHiddenProp(){ 2388 var pfx=["webkit","moz","ms","o"]; 2389 if("hidden" in document) return "hidden"; //natively supported 2390 for(var i=0; i<pfx.length; i++){ //prefixed 2391 if((pfx[i]+"Hidden") in document) 2392 return pfx[i]+"Hidden"; 2393 } 2394 return null; //not supported 2395 } 2396 }; 2397 /* -------------------- */ 2398 2399 2400 2401 2402 2403 /* 2404 ---------------------------------------- 2405 PLUGIN SETUP 2406 ---------------------------------------- 2407 */ 2408 2409 /* plugin constructor functions */ 2410 $.fn[pluginNS]=function(method){ /* usage: $(selector).mCustomScrollbar(); */ 2411 if(methods[method]){ 2412 return methods[method].apply(this,Array.prototype.slice.call(arguments,1)); 2413 }else if(typeof method==="object" || !method){ 2414 return methods.init.apply(this,arguments); 2415 }else{ 2416 $.error("Method "+method+" does not exist"); 2417 } 2418 }; 2419 $[pluginNS]=function(method){ /* usage: $.mCustomScrollbar(); */ 2420 if(methods[method]){ 2421 return methods[method].apply(this,Array.prototype.slice.call(arguments,1)); 2422 }else if(typeof method==="object" || !method){ 2423 return methods.init.apply(this,arguments); 2424 }else{ 2425 $.error("Method "+method+" does not exist"); 2426 } 2427 }; 2428 2429 /* 2430 allow setting plugin default options. 2431 usage: $.mCustomScrollbar.defaults.scrollInertia=500; 2432 to apply any changed default options on default selectors (below), use inside document ready fn 2433 e.g.: $(document).ready(function(){ $.mCustomScrollbar.defaults.scrollInertia=500; }); 2434 */ 2435 $[pluginNS].defaults=defaults; 2436 2437 /* 2438 add window object (window.mCustomScrollbar) 2439 usage: if(window.mCustomScrollbar){console.log("custom scrollbar plugin loaded");} 2440 */ 2441 window[pluginNS]=true; 2442 2443 $(window).bind("load",function(){ 2444 2445 $(defaultSelector)[pluginNS](); /* add scrollbars automatically on default selector */ 2446 2447 /* extend jQuery expressions */ 2448 $.extend($.expr[":"],{ 2449 /* checks if element is within scrollable viewport */ 2450 mcsInView:$.expr[":"].mcsInView || function(el){ 2451 var $el=$(el),content=$el.parents(".mCSB_container"),wrapper,cPos; 2452 if(!content.length){return;} 2453 wrapper=content.parent(); 2454 cPos=[content[0].offsetTop,content[0].offsetLeft]; 2455 return cPos[0]+_childPos($el)[0]>=0 && cPos[0]+_childPos($el)[0]<wrapper.height()-$el.outerHeight(false) && 2456 cPos[1]+_childPos($el)[1]>=0 && cPos[1]+_childPos($el)[1]<wrapper.width()-$el.outerWidth(false); 2457 }, 2458 /* checks if element or part of element is in view of scrollable viewport */ 2459 mcsInSight:$.expr[":"].mcsInSight || function(el,i,m){ 2460 var $el=$(el),elD,content=$el.parents(".mCSB_container"),wrapperView,pos,wrapperViewPct, 2461 pctVals=m[3]==="exact" ? [[1,0],[1,0]] : [[0.9,0.1],[0.6,0.4]]; 2462 if(!content.length){return;} 2463 elD=[$el.outerHeight(false),$el.outerWidth(false)]; 2464 pos=[content[0].offsetTop+_childPos($el)[0],content[0].offsetLeft+_childPos($el)[1]]; 2465 wrapperView=[content.parent()[0].offsetHeight,content.parent()[0].offsetWidth]; 2466 wrapperViewPct=[elD[0]<wrapperView[0] ? pctVals[0] : pctVals[1],elD[1]<wrapperView[1] ? pctVals[0] : pctVals[1]]; 2467 return pos[0]-(wrapperView[0]*wrapperViewPct[0][0])<0 && pos[0]+elD[0]-(wrapperView[0]*wrapperViewPct[0][1])>=0 && 2468 pos[1]-(wrapperView[1]*wrapperViewPct[1][0])<0 && pos[1]+elD[1]-(wrapperView[1]*wrapperViewPct[1][1])>=0; 2469 }, 2470 /* checks if element is overflowed having visible scrollbar(s) */ 2471 mcsOverflow:$.expr[":"].mcsOverflow || function(el){ 2472 var d=$(el).data(pluginPfx); 2473 if(!d){return;} 2474 return d.overflowed[0] || d.overflowed[1]; 2475 } 2476 }); 2477 2478 }); 2479 2480}))}));
2480 2481// THIS FILE IS GENERATED - DO NOT EDIT! 2482/*!mobile-detect v1.4.5 2021-03-13*/ 2483/*global module:false, define:false*/ 2484/*jshint latedef:false*/ 2485/*!@license Copyright 2013, Heinrich Goebl, License: MIT, see https://github.com/hgoebl/mobile-detect.js*/ 2486(function (define, undefined) { 2487define(function () { 2488 'use strict'; 2489 2490 var impl = {}; 2491 2492 impl.mobileDetectRules = { 2493 "phones": { 2494 "iPhone": "\\biPhone\\b|\\biPod\\b", 2495 "BlackBerry": "BlackBerry|\\bBB10\\b|rim[0-9]+|\\b(BBA100|BBB100|BBD100|BBE100|BBF100|STH100)\\b-[0-9]+", 2496 "Pixel": "; \\bPixel\\b", 2497 "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", 2498 "Nexus": "Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 5X|Nexus 6", 2499 "Dell": "Dell[;]? (Streak|Aero|Venue|Venue Pro|Flash|Smoke|Mini 3iX)|XCD28|XCD35|\\b001DL\\b|\\b101DL\\b|\\bGS01\\b", 2500 "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", 2501 "Samsung":
vendor: 4,913 bytes, line 2501
2501"\\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-
vendor: 63,412 bytes, lines 2501-3491
2501I8262|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|SM-G610F|SM-G981B|SM-G892A|SM-A530F", 2502 "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", 2503 "Sony": "SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533|SOV34|601SO|F8332", 2504 "Asus": "Asus.*Galaxy|PadFone.*Mobile", 2505 "Xiaomi": "^(?!.*\\bx11\\b).*xiaomi.*$|POCOPHONE F1|MI 8|Redmi Note 9S|Redmi Note 5A Prime|N2G47H|M2001J2G|M2001J2I|M1805E10A|M2004J11G|M1902F1G|M2002J9G|M2004J19G|M2003J6A1G", 2506 "NokiaLumia": "Lumia [0-9]{3,4}", 2507 "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", 2508 "Palm": "PalmSource|Palm", 2509 "Vertu": "Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature", 2510 "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", 2511 "Fly": "IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250", 2512 "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 SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM", 2513 "iMobile": "i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)", 2514 "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", 2515 "Wolfgang": "AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q", 2516 "Alcatel": "Alcatel", 2517 "Nintendo": "Nintendo (3DS|Switch)", 2518 "Amoi": "Amoi", 2519 "INQ": "INQ", 2520 "OnePlus": "ONEPLUS", 2521 "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" 2522 }, 2523 "tablets": { 2524 "iPad": "iPad|iPad.*Mobile", 2525 "NexusTablet": "Android.*Nexus[\\s]+(7|9|10)", 2526 "GoogleTablet": "Android.*Pixel C", 2527 "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|SM-P610|SM-T290|SM-T515|SM-T590|SM-T595|SM-T725|SM-T817P|SM-P585N0|SM-T395|SM-T295|SM-T865|SM-P610N|SM-P615|SM-T970|SM-T380|SM-T5950|SM-T905|SM-T231|SM-T500|SM-T860", 2528 "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)", 2529 "SurfaceTablet": "Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)", 2530 "HPTablet": "HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10", 2531 "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", 2532 "BlackBerryTablet": "PlayBook|RIM Tablet", 2533 "HTCtablet": "HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410", 2534 "MotorolaTablet": "xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617", 2535 "NookTablet": "Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2", 2536 "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|A3-A40", 2537 "ToshibaTablet": "Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO", 2538 "LGTablet": "\\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\\b", 2539 "FujitsuTablet": "Android.*\\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\\b", 2540 "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", 2541 "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|TB-X704F|TB-X104F|TB3-X70F|TB-X705F|TB-8504F|TB3-X70L|TB3-710F|TB-X704L", 2542 "DellTablet": "Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7", 2543 "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", 2544 "MedionTablet": "Android.*\\bOYO\\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB", 2545 "ArnovaTablet": "97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2", 2546 "IntensoTablet": "INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004", 2547 "IRUTablet": "M702pro", 2548 "MegafonTablet": "MegaFon V9|\\bZTE V9\\b|Android.*\\bMT7A\\b", 2549 "EbodaTablet": "E-Boda (Supreme|Impresspeed|Izzycomm|Essential)", 2550 "AllViewTablet": "Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)", 2551 "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", 2552 "AinolTablet": "NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark", 2553 "NokiaLumiaTablet": "Lumia 2520", 2554 "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", 2555 "PhilipsTablet": "\\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\\b", 2556 "CubeTablet": "Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT", 2557 "CobyTablet": "MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010", 2558 "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", 2559 "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", 2560 "SMiTTablet": "Android.*(\\bMID\\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)", 2561 "RockChipTablet": "Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A", 2562 "FlyTablet": "IQ310|Fly Vision", 2563 "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", 2564 "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", 2565 "NecTablet": "\\bN-06D|\\bN-08D", 2566 "PantechTablet": "Pantech.*P4100", 2567 "BronchoTablet": "Broncho.*(N701|N708|N802|a710)", 2568 "VersusTablet": "TOUCHPAD.*[78910]|\\bTOUCHTAB\\b", 2569 "ZyncTablet": "z1000|Z99 2G|z930|z990|z909|Z919|z900", 2570 "PositivoTablet": "TB07STA|TB10STA|TB07FTA|TB10FTA", 2571 "NabiTablet": "Android.*\\bNabi", 2572 "KoboTablet": "Kobo Touch|\\bK080\\b|\\bVox\\b Build|\\bArc\\b Build", 2573 "DanewTablet": "DSlide.*\\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\\b", 2574 "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", 2575 "PlaystationTablet": "Playstation.*(Portable|Vita)", 2576 "TrekstorTablet": "ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab", 2577 "PyleAudioTablet": "\\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\\b", 2578 "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 ", 2579 "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", 2580 "GalapadTablet": "Android [0-9.]+; [a-z-]+; \\bG1\\b", 2581 "MicromaxTablet": "Funbook|Micromax.*\\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\\b", 2582 "KarbonnTablet": "Android.*\\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\\b", 2583 "AllFineTablet": "Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide", 2584 "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", 2585 "YONESTablet": "BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026", 2586 "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", 2587 "GUTablet": "TX-A1301|TX-M9002|Q702|kf026", 2588 "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", 2589 "OvermaxTablet": "OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)|Qualcore 1027", 2590 "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", 2591 "DPSTablet": "DPS Dream 9|DPS Dual 7", 2592 "VistureTablet": "V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10", 2593 "CrestaTablet": "CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989", 2594 "MediatekTablet": "\\bMT8125|MT8389|MT8135|MT8377\\b", 2595 "ConcordeTablet": "Concorde([ ]+)?Tab|ConCorde ReadMan", 2596 "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", 2597 "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", 2598 "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", 2599 "ECSTablet": "V07OT2|TM105A|S10OT1|TR10CS1", 2600 "StorexTablet": "eZee[_']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab", 2601 "VodafoneTablet": "SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497|VFD 1400", 2602 "EssentielBTablet": "Smart[ ']?TAB[ ]+?[0-9]+|Family[ ']?TAB2", 2603 "RossMoorTablet": "RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711", 2604 "iMobileTablet": "i-mobile i-note", 2605 "TolinoTablet": "tolino tab [0-9.]+|tolino shine", 2606 "AudioSonicTablet": "\\bC-22Q|T7-QC|T-17B|T-17P\\b", 2607 "AMPETablet": "Android.* A78 ", 2608 "SkkTablet": "Android.* (SKYPAD|PHOENIX|CYCLOPS)", 2609 "TecnoTablet": "TECNO P9|TECNO DP8D", 2610 "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", 2611 "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)", 2612 "FX2Tablet": "FX2 PAD7|FX2 PAD10", 2613 "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", 2614 "ViewsonicTablet": "ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a", 2615 "VerizonTablet": "QTAQZ3|QTAIR7|QTAQTZ3|QTASUN1|QTASUN2|QTAXIA1", 2616 "OdysTablet": "LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\\bXELIO\\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10", 2617 "CaptivaTablet": "CAPTIVA PAD", 2618 "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", 2619 "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", 2620 "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", 2621 "JaytechTablet": "TPC-PA762", 2622 "BlaupunktTablet": "Endeavour 800NG|Endeavour 1010", 2623 "DigmaTablet": "\\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\\b", 2624 "EvolioTablet": "ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\\bEvotab\\b|\\bNeura\\b", 2625 "LavaTablet": "QPAD E704|\\bIvoryS\\b|E-TAB IVORY|\\bE-TAB\\b", 2626 "AocTablet": "MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712", 2627 "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", 2628 "CelkonTablet": "CT695|CT888|CT[\\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\\bCT-1\\b", 2629 "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", 2630 "MediacomTablet": "M-MPI10C3G|M-SP10EG|M-SP10EGP|M-SP10HXAH|M-SP7HXAH|M-SP10HXBH|M-SP8HXAH|M-SP8MXA", 2631 "MiTablet": "\\bMI PAD\\b|\\bHM NOTE 1W\\b", 2632 "NibiruTablet": "Nibiru M1|Nibiru Jupiter One", 2633 "NexoTablet": "NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI", 2634 "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", 2635 "UbislateTablet": "UbiSlate[\\s]?7C", 2636 "PocketBookTablet": "Pocketbook", 2637 "KocasoTablet": "\\b(TB-1207)\\b", 2638 "HisenseTablet": "\\b(F5281|E2371)\\b", 2639 "Hudl": "Hudl HT7S3|Hudl 2", 2640 "TelstraTablet": "T-Hub2", 2641 "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" 2642 }, 2643 "oss": { 2644 "AndroidOS": "Android", 2645 "BlackBerryOS": "blackberry|\\bBB10\\b|rim tablet os", 2646 "PalmOS": "PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino", 2647 "SymbianOS": "Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\\bS60\\b", 2648 "WindowsMobileOS": "Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Windows Mobile|Windows Phone [0-9.]+|WCE;", 2649 "WindowsPhoneOS": "Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;", 2650 "iOS": "\\biPhone.*Mobile|\\biPod|\\biPad|AppleCoreMedia", 2651 "iPadOS": "CPU OS 13", 2652 "SailfishOS": "Sailfish", 2653 "MeeGoOS": "MeeGo", 2654 "MaemoOS": "Maemo", 2655 "JavaOS": "J2ME\/|\\bMIDP\\b|\\bCLDC\\b", 2656 "webOS": "webOS|hpwOS", 2657 "badaOS": "\\bBada\\b", 2658 "BREWOS": "BREW" 2659 }, 2660 "uas": { 2661 "Chrome": "\\bCrMo\\b|CriOS|Android.*Chrome\/[.0-9]* (Mobile)?", 2662 "Dolfin": "\\bDolfin\\b", 2663 "Opera": "Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR\/[0-9.]+$|Coast\/[0-9.]+", 2664 "Skyfire": "Skyfire", 2665 "Edge": "\\bEdgiOS\\b|Mobile Safari\/[.0-9]* Edge", 2666 "IE": "IEMobile|MSIEMobile", 2667 "Firefox": "fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS", 2668 "Bolt": "bolt", 2669 "TeaShark": "teashark", 2670 "Blazer": "Blazer", 2671 "Safari": "Version((?!\\bEdgiOS\\b).)*Mobile.*Safari|Safari.*Mobile|MobileSafari", 2672 "WeChat": "\\bMicroMessenger\\b", 2673 "UCBrowser": "UC.*Browser|UCWEB", 2674 "baiduboxapp": "baiduboxapp", 2675 "baidubrowser": "baidubrowser", 2676 "DiigoBrowser": "DiigoBrowser", 2677 "Mercury": "\\bMercury\\b", 2678 "ObigoBrowser": "Obigo", 2679 "NetFront": "NF-Browser", 2680 "GenericBrowser": "NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger", 2681 "PaleMoon": "Android.*PaleMoon|Mobile.*PaleMoon" 2682 }, 2683 "props": { 2684 "Mobile": "Mobile\/[VER]", 2685 "Build": "Build\/[VER]", 2686 "Version": "Version\/[VER]", 2687 "VendorID": "VendorID\/[VER]", 2688 "iPad": "iPad.*CPU[a-z ]+[VER]", 2689 "iPhone": "iPhone.*CPU[a-z ]+[VER]", 2690 "iPod": "iPod.*CPU[a-z ]+[VER]", 2691 "Kindle": "Kindle\/[VER]", 2692 "Chrome": [ 2693 "Chrome\/[VER]", 2694 "CriOS\/[VER]", 2695 "CrMo\/[VER]" 2696 ], 2697 "Coast": [ 2698 "Coast\/[VER]" 2699 ], 2700 "Dolfin": "Dolfin\/[VER]", 2701 "Firefox": [ 2702 "Firefox\/[VER]", 2703 "FxiOS\/[VER]" 2704 ], 2705 "Fennec": "Fennec\/[VER]", 2706 "Edge": "Edge\/[VER]", 2707 "IE": [ 2708 "IEMobile\/[VER];", 2709 "IEMobile [VER]", 2710 "MSIE [VER];", 2711 "Trident\/[0-9.]+;.*rv:[VER]" 2712 ], 2713 "NetFront": "NetFront\/[VER]", 2714 "NokiaBrowser": "NokiaBrowser\/[VER]", 2715 "Opera": [ 2716 " OPR\/[VER]", 2717 "Opera Mini\/[VER]", 2718 "Version\/[VER]" 2719 ], 2720 "Opera Mini": "Opera Mini\/[VER]", 2721 "Opera Mobi": "Version\/[VER]", 2722 "UCBrowser": [ 2723 "UCWEB[VER]", 2724 "UC.*Browser\/[VER]" 2725 ], 2726 "MQQBrowser": "MQQBrowser\/[VER]", 2727 "MicroMessenger": "MicroMessenger\/[VER]", 2728 "baiduboxapp": "baiduboxapp\/[VER]", 2729 "baidubrowser": "baidubrowser\/[VER]", 2730 "SamsungBrowser": "SamsungBrowser\/[VER]", 2731 "Iron": "Iron\/[VER]", 2732 "Safari": [ 2733 "Version\/[VER]", 2734 "Safari\/[VER]" 2735 ], 2736 "Skyfire": "Skyfire\/[VER]", 2737 "Tizen": "Tizen\/[VER]", 2738 "Webkit": "webkit[ \/][VER]", 2739 "PaleMoon": "PaleMoon\/[VER]", 2740 "SailfishBrowser": "SailfishBrowser\/[VER]", 2741 "Gecko": "Gecko\/[VER]", 2742 "Trident": "Trident\/[VER]", 2743 "Presto": "Presto\/[VER]", 2744 "Goanna": "Goanna\/[VER]", 2745 "iOS": " \\bi?OS\\b [VER][ ;]{1}", 2746 "Android": "Android [VER]", 2747 "Sailfish": "Sailfish [VER]", 2748 "BlackBerry": [ 2749 "BlackBerry[\\w]+\/[VER]", 2750 "BlackBerry.*Version\/[VER]", 2751 "Version\/[VER]" 2752 ], 2753 "BREW": "BREW [VER]", 2754 "Java": "Java\/[VER]", 2755 "Windows Phone OS": [ 2756 "Windows Phone OS [VER]", 2757 "Windows Phone [VER]" 2758 ], 2759 "Windows Phone": "Windows Phone [VER]", 2760 "Windows CE": "Windows CE\/[VER]", 2761 "Windows NT": "Windows NT [VER]", 2762 "Symbian": [ 2763 "SymbianOS\/[VER]", 2764 "Symbian\/[VER]" 2765 ], 2766 "webOS": [ 2767 "webOS\/[VER]", 2768 "hpwOS\/[VER];" 2769 ] 2770 }, 2771 "utils": { 2772 "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|AspiegelBot", 2773 "MobileBot": "Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker\/M1A1-R2D2", 2774 "DesktopMode": "WPDesktop", 2775 "TV": "SonyDTV|HbbTV", 2776 "WebKit": "(webkit)[ \/]([\\w.]+)", 2777 "Console": "\\b(Nintendo|Nintendo WiiU|Nintendo 3DS|Nintendo Switch|PLAYSTATION|Xbox)\\b", 2778 "Watch": "SM-V700" 2779 } 2780}; 2781 2782 // following patterns come from http://detectmobilebrowsers.com/ 2783 impl.detectMobileBrowsers = { 2784 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, 2785 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, 2786 tabletPattern: /android|ipad|playbook|silk/i 2787 }; 2788 2789 var hasOwnProp = Object.prototype.hasOwnProperty, 2790 isArray; 2791 2792 impl.FALLBACK_PHONE = 'UnknownPhone'; 2793 impl.FALLBACK_TABLET = 'UnknownTablet'; 2794 impl.FALLBACK_MOBILE = 'UnknownMobile'; 2795 2796 isArray = ('isArray' in Array) ? 2797 Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; }; 2798 2799 function equalIC(a, b) { 2800 return a != null && b != null && a.toLowerCase() === b.toLowerCase(); 2801 } 2802 2803 function containsIC(array, value) { 2804 var valueLC, i, len = array.length; 2805 if (!len || !value) { 2806 return false; 2807 } 2808 valueLC = value.toLowerCase(); 2809 for (i = 0; i < len; ++i) { 2810 if (valueLC === array[i].toLowerCase()) { 2811 return true; 2812 } 2813 } 2814 return false; 2815 } 2816 2817 function convertPropsToRegExp(object) { 2818 for (var key in object) { 2819 if (hasOwnProp.call(object, key)) { 2820 object[key] = new RegExp(object[key], 'i'); 2821 } 2822 } 2823 } 2824 2825 function prepareUserAgent(userAgent) { 2826 return (userAgent || '').substr(0, 500); // mitigate vulnerable to ReDoS 2827 } 2828 2829 (function init() { 2830 var key, values, value, i, len, verPos, mobileDetectRules = impl.mobileDetectRules; 2831 for (key in mobileDetectRules.props) { 2832 if (hasOwnProp.call(mobileDetectRules.props, key)) { 2833 values = mobileDetectRules.props[key]; 2834 if (!isArray(values)) { 2835 values = [values]; 2836 } 2837 len = values.length; 2838 for (i = 0; i < len; ++i) { 2839 value = values[i]; 2840 verPos = value.indexOf('[VER]'); 2841 if (verPos >= 0) { 2842 value = value.substring(0, verPos) + '([\\w._\\+]+)' + value.substring(verPos + 5); 2843 } 2844 values[i] = new RegExp(value, 'i'); 2845 } 2846 mobileDetectRules.props[key] = values; 2847 } 2848 } 2849 convertPropsToRegExp(mobileDetectRules.oss); 2850 convertPropsToRegExp(mobileDetectRules.phones); 2851 convertPropsToRegExp(mobileDetectRules.tablets); 2852 convertPropsToRegExp(mobileDetectRules.uas); 2853 convertPropsToRegExp(mobileDetectRules.utils); 2854 2855 // copy some patterns to oss0 which are tested first (see issue#15) 2856 mobileDetectRules.oss0 = { 2857 WindowsPhoneOS: mobileDetectRules.oss.WindowsPhoneOS, 2858 WindowsMobileOS: mobileDetectRules.oss.WindowsMobileOS 2859 }; 2860 }()); 2861 2862 /** 2863 * Test userAgent string against a set of rules and find the first matched key. 2864 * @param {Object} rules (key is String, value is RegExp) 2865 * @param {String} userAgent the navigator.userAgent (or HTTP-Header 'User-Agent'). 2866 * @returns {String|null} the matched key if found, otherwise <tt>null</tt> 2867 * @private 2868 */ 2869 impl.findMatch = function(rules, userAgent) { 2870 for (var key in rules) { 2871 if (hasOwnProp.call(rules, key)) { 2872 if (rules[key].test(userAgent)) { 2873 return key; 2874 } 2875 } 2876 } 2877 return null; 2878 }; 2879 2880 /** 2881 * Test userAgent string against a set of rules and return an array of matched keys. 2882 * @param {Object} rules (key is String, value is RegExp) 2883 * @param {String} userAgent the navigator.userAgent (or HTTP-Header 'User-Agent'). 2884 * @returns {Array} an array of matched keys, may be empty when there is no match, but not <tt>null</tt> 2885 * @private 2886 */ 2887 impl.findMatches = function(rules, userAgent) { 2888 var result = []; 2889 for (var key in rules) { 2890 if (hasOwnProp.call(rules, key)) { 2891 if (rules[key].test(userAgent)) { 2892 result.push(key); 2893 } 2894 } 2895 } 2896 return result; 2897 }; 2898 2899 /** 2900 * Check the version of the given property in the User-Agent. 2901 * 2902 * @param {String} propertyName 2903 * @param {String} userAgent 2904 * @return {String} version or <tt>null</tt> if version not found 2905 * @private 2906 */ 2907 impl.getVersionStr = function (propertyName, userAgent) { 2908 var props = impl.mobileDetectRules.props, patterns, i, len, match; 2909 if (hasOwnProp.call(props, propertyName)) { 2910 patterns = props[propertyName]; 2911 len = patterns.length; 2912 for (i = 0; i < len; ++i) { 2913 match = patterns[i].exec(userAgent); 2914 if (match !== null) { 2915 return match[1]; 2916 } 2917 } 2918 } 2919 return null; 2920 }; 2921 2922 /** 2923 * Check the version of the given property in the User-Agent. 2924 * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31) 2925 * 2926 * @param {String} propertyName 2927 * @param {String} userAgent 2928 * @return {Number} version or <tt>NaN</tt> if version not found 2929 * @private 2930 */ 2931 impl.getVersion = function (propertyName, userAgent) { 2932 var version = impl.getVersionStr(propertyName, userAgent); 2933 return version ? impl.prepareVersionNo(version) : NaN; 2934 }; 2935 2936 /** 2937 * Prepare the version number. 2938 * 2939 * @param {String} version 2940 * @return {Number} the version number as a floating number 2941 * @private 2942 */ 2943 impl.prepareVersionNo = function (version) { 2944 var numbers; 2945 2946 numbers = version.split(/[a-z._ \/\-]/i); 2947 if (numbers.length === 1) { 2948 version = numbers[0]; 2949 } 2950 if (numbers.length > 1) { 2951 version = numbers[0] + '.'; 2952 numbers.shift(); 2953 version += numbers.join(''); 2954 } 2955 return Number(version); 2956 }; 2957 2958 impl.isMobileFallback = function (userAgent) { 2959 return impl.detectMobileBrowsers.fullPattern.test(userAgent) || 2960 impl.detectMobileBrowsers.shortPattern.test(userAgent.substr(0,4)); 2961 }; 2962 2963 impl.isTabletFallback = function (userAgent) { 2964 return impl.detectMobileBrowsers.tabletPattern.test(userAgent); 2965 }; 2966 2967 impl.prepareDetectionCache = function (cache, userAgent, maxPhoneWidth) { 2968 if (cache.mobile !== undefined) { 2969 return; 2970 } 2971 var phone, tablet, phoneSized; 2972 2973 // first check for stronger tablet rules, then phone (see issue#5) 2974 tablet = impl.findMatch(impl.mobileDetectRules.tablets, userAgent); 2975 if (tablet) { 2976 cache.mobile = cache.tablet = tablet; 2977 cache.phone = null; 2978 return; // unambiguously identified as tablet 2979 } 2980 2981 phone = impl.findMatch(impl.mobileDetectRules.phones, userAgent); 2982 if (phone) { 2983 cache.mobile = cache.phone = phone; 2984 cache.tablet = null; 2985 return; // unambiguously identified as phone 2986 } 2987 2988 // our rules haven't found a match -> try more general fallback rules 2989 if (impl.isMobileFallback(userAgent)) { 2990 phoneSized = MobileDetect.isPhoneSized(maxPhoneWidth); 2991 if (phoneSized === undefined) { 2992 cache.mobile = impl.FALLBACK_MOBILE; 2993 cache.tablet = cache.phone = null; 2994 } else if (phoneSized) { 2995 cache.mobile = cache.phone = impl.FALLBACK_PHONE; 2996 cache.tablet = null; 2997 } else { 2998 cache.mobile = cache.tablet = impl.FALLBACK_TABLET; 2999 cache.phone = null; 3000 } 3001 } else if (impl.isTabletFallback(userAgent)) { 3002 cache.mobile = cache.tablet = impl.FALLBACK_TABLET; 3003 cache.phone = null; 3004 } else { 3005 // not mobile at all! 3006 cache.mobile = cache.tablet = cache.phone = null; 3007 } 3008 }; 3009 3010 // t is a reference to a MobileDetect instance 3011 impl.mobileGrade = function (t) { 3012 // impl note: 3013 // To keep in sync w/ Mobile_Detect.php easily, the following code is tightly aligned to the PHP version. 3014 // When changes are made in Mobile_Detect.php, copy this method and replace: 3015 // $this-> / t. 3016 // self::MOBILE_GRADE_(.) / '$1' 3017 // , self::VERSION_TYPE_FLOAT / (nothing) 3018 // isIOS() / os('iOS') 3019 // [reg] / (nothing) <-- jsdelivr complaining about unescaped unicode character U+00AE 3020 var $isMobile = t.mobile() !== null; 3021 3022 if ( 3023 // Apple iOS 3.2-5.1 - Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3), iPad 3 (5.1), original iPhone (3.1), iPhone 3 (3.2), 3GS (4.3), 4 (4.3 / 5.0), and 4S (5.1) 3024 t.os('iOS') && t.version('iPad')>=4.3 || 3025 t.os('iOS') && t.version('iPhone')>=3.1 || 3026 t.os('iOS') && t.version('iPod')>=3.1 || 3027 3028 // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5) 3029 // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM 3030 // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices 3031 // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7 3032 ( t.version('Android')>2.1 && t.is('Webkit') ) || 3033 3034 // Windows Phone 7-7.5 - Tested on the HTC Surround (7.0) HTC Trophy (7.5), LG-E900 (7.5), Nokia Lumia 800 3035 t.version('Windows Phone OS')>=7.0 || 3036 3037 // Blackberry 7 - Tested on BlackBerry Torch 9810 3038 // Blackberry 6.0 - Tested on the Torch 9800 and Style 9670 3039 t.is('BlackBerry') && t.version('BlackBerry')>=6.0 || 3040 // Blackberry Playbook (1.0-2.0) - Tested on PlayBook 3041 t.match('Playbook.*Tablet') || 3042 3043 // Palm WebOS (1.4-2.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0) 3044 ( t.version('webOS')>=1.4 && t.match('Palm|Pre|Pixi') ) || 3045 // Palm WebOS 3.0 - Tested on HP TouchPad 3046 t.match('hp.*TouchPad') || 3047 3048 // Firefox Mobile (12 Beta) - Tested on Android 2.3 device 3049 ( t.is('Firefox') && t.version('Firefox')>=12 ) || 3050 3051 // Chrome for Android - Tested on Android 4.0, 4.1 device 3052 ( t.is('Chrome') && t.is('AndroidOS') && t.version('Android')>=4.0 ) || 3053 3054 // Skyfire 4.1 - Tested on Android 2.3 device 3055 ( t.is('Skyfire') && t.version('Skyfire')>=4.1 && t.is('AndroidOS') && t.version('Android')>=2.3 ) || 3056 3057 // Opera Mobile 11.5-12: Tested on Android 2.3 3058 ( t.is('Opera') && t.version('Opera Mobi')>11 && t.is('AndroidOS') ) || 3059 3060 // Meego 1.2 - Tested on Nokia 950 and N9 3061 t.is('MeeGoOS') || 3062 3063 // Tizen (pre-release) - Tested on early hardware 3064 t.is('Tizen') || 3065 3066 // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser 3067 // @todo: more tests here! 3068 t.is('Dolfin') && t.version('Bada')>=2.0 || 3069 3070 // UC Browser - Tested on Android 2.3 device 3071 ( (t.is('UC Browser') || t.is('Dolfin')) && t.version('Android')>=2.3 ) || 3072 3073 // Kindle 3 and Fire - Tested on the built-in WebKit browser for each 3074 ( t.match('Kindle Fire') || 3075 t.is('Kindle') && t.version('Kindle')>=3.0 ) || 3076 3077 // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet 3078 t.is('AndroidOS') && t.is('NookTablet') || 3079 3080 // Chrome Desktop 11-21 - Tested on OS X 10.7 and Windows 7 3081 t.version('Chrome')>=11 && !$isMobile || 3082 3083 // Safari Desktop 4-5 - Tested on OS X 10.7 and Windows 7 3084 t.version('Safari')>=5.0 && !$isMobile || 3085 3086 // Firefox Desktop 4-13 - Tested on OS X 10.7 and Windows 7 3087 t.version('Firefox')>=4.0 && !$isMobile || 3088 3089 // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7 3090 t.version('MSIE')>=7.0 && !$isMobile || 3091 3092 // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7 3093 // @reference: http://my.opera.com/community/openweb/idopera/ 3094 t.version('Opera')>=10 && !$isMobile 3095 3096 ){ 3097 return 'A'; 3098 } 3099 3100 if ( 3101 t.os('iOS') && t.version('iPad')<4.3 || 3102 t.os('iOS') && t.version('iPhone')<3.1 || 3103 t.os('iOS') && t.version('iPod')<3.1 || 3104 3105 // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770 3106 t.is('Blackberry') && t.version('BlackBerry')>=5 && t.version('BlackBerry')<6 || 3107 3108 //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3 3109 ( t.version('Opera Mini')>=5.0 && t.version('Opera Mini')<=6.5 && 3110 (t.version('Android')>=2.3 || t.is('iOS')) ) || 3111 3112 // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1) 3113 t.match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') || 3114 3115 // @todo: report this (tested on Nokia N71) 3116 t.version('Opera Mobi')>=11 && t.is('SymbianOS') 3117 ){ 3118 return 'B'; 3119 } 3120 3121 if ( 3122 // Blackberry 4.x - Tested on the Curve 8330 3123 t.version('BlackBerry')<5.0 || 3124 // Windows Mobile - Tested on the HTC Leo (WinMo 5.2) 3125 t.match('MSIEMobile|Windows CE.*Mobile') || t.version('Windows Mobile')<=5.2 3126 3127 ){ 3128 return 'C'; 3129 } 3130 3131 //All older smartphone platforms and featurephones - Any device that doesn't support media queries 3132 //will receive the basic, C grade experience. 3133 return 'C'; 3134 }; 3135 3136 impl.detectOS = function (ua) { 3137 return impl.findMatch(impl.mobileDetectRules.oss0, ua) || 3138 impl.findMatch(impl.mobileDetectRules.oss, ua); 3139 }; 3140 3141 impl.getDeviceSmallerSide = function () { 3142 return window.screen.width < window.screen.height ? 3143 window.screen.width : 3144 window.screen.height; 3145 }; 3146 3147 /** 3148 * Constructor for MobileDetect object. 3149 * <br> 3150 * Such an object will keep a reference to the given user-agent string and cache most of the detect queries.<br> 3151 * <div style="background-color: #d9edf7; border: 1px solid #bce8f1; color: #3a87ad; padding: 14px; border-radius: 2px; margin-top: 20px"> 3152 * <strong>Find information how to download and install:</strong> 3153 * <a href="https://github.com/hgoebl/mobile-detect.js/">github.com/hgoebl/mobile-detect.js/</a> 3154 * </div> 3155 * 3156 * @example <pre> 3157 * var md = new MobileDetect(window.navigator.userAgent); 3158 * if (md.mobile()) { 3159 * location.href = (md.mobileGrade() === 'A') ? '/mobile/' : '/lynx/'; 3160 * } 3161 * </pre> 3162 * 3163 * @param {string} userAgent typically taken from window.navigator.userAgent or http_header['User-Agent'] 3164 * @param {number} [maxPhoneWidth=600] <strong>only for browsers</strong> specify a value for the maximum 3165 * width of smallest device side (in logical "CSS" pixels) until a device detected as mobile will be handled 3166 * as phone. 3167 * This is only used in cases where the device cannot be classified as phone or tablet.<br> 3168 * See <a href="http://developer.android.com/guide/practices/screens_support.html">Declaring Tablet Layouts 3169 * for Android</a>.<br> 3170 * If you provide a value < 0, then this "fuzzy" check is disabled. 3171 * @constructor 3172 * @global 3173 */ 3174 function MobileDetect(userAgent, maxPhoneWidth) { 3175 this.ua = prepareUserAgent(userAgent); 3176 this._cache = {}; 3177 //600dp is typical 7" tablet minimum width 3178 this.maxPhoneWidth = maxPhoneWidth || 600; 3179 } 3180 3181 MobileDetect.prototype = { 3182 constructor: MobileDetect, 3183 3184 /** 3185 * Returns the detected phone or tablet type or <tt>null</tt> if it is not a mobile device. 3186 * <br> 3187 * For a list of possible return values see {@link MobileDetect#phone} and {@link MobileDetect#tablet}.<br> 3188 * <br> 3189 * If the device is not detected by the regular expressions from Mobile-Detect, a test is made against 3190 * the patterns of <a href="http://detectmobilebrowsers.com/">detectmobilebrowsers.com</a>. If this test 3191 * is positive, a value of <code>UnknownPhone</code>, <code>UnknownTablet</code> or 3192 * <code>UnknownMobile</code> is returned.<br> 3193 * When used in browser, the decision whether phone or tablet is made based on <code>screen.width/height</code>.<br> 3194 * <br> 3195 * When used server-side (node.js), there is no way to tell the difference between <code>UnknownTablet</code> 3196 * and <code>UnknownMobile</code>, so you will get <code>UnknownMobile</code> here.<br> 3197 * Be aware that since v1.0.0 in this special case you will get <code>UnknownMobile</code> only for: 3198 * {@link MobileDetect#mobile}, not for {@link MobileDetect#phone} and {@link MobileDetect#tablet}. 3199 * In versions before v1.0.0 all 3 methods returned <code>UnknownMobile</code> which was tedious to use. 3200 * <br> 3201 * In most cases you will use the return value just as a boolean. 3202 * 3203 * @returns {String} the key for the phone family or tablet family, e.g. "Nexus". 3204 * @function MobileDetect#mobile 3205 */ 3206 mobile: function () { 3207 impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); 3208 return this._cache.mobile; 3209 }, 3210 3211 /** 3212 * Returns the detected phone type/family string or <tt>null</tt>. 3213 * <br> 3214 * The returned tablet (family or producer) is one of following keys:<br> 3215 * <br><tt>iPhone, BlackBerry, Pixel, HTC, Nexus, Dell, Motorola, Samsung, LG, Sony, Asus, 3216 * Xiaomi, NokiaLumia, Micromax, Palm, Vertu, Pantech, Fly, Wiko, iMobile, 3217 * SimValley, Wolfgang, Alcatel, Nintendo, Amoi, INQ, OnePlus, GenericPhone</tt><br> 3218 * <br> 3219 * If the device is not detected by the regular expressions from Mobile-Detect, a test is made against 3220 * the patterns of <a href="http://detectmobilebrowsers.com/">detectmobilebrowsers.com</a>. If this test 3221 * is positive, a value of <code>UnknownPhone</code> or <code>UnknownMobile</code> is returned.<br> 3222 * When used in browser, the decision whether phone or tablet is made based on <code>screen.width/height</code>.<br> 3223 * <br> 3224 * When used server-side (node.js), there is no way to tell the difference between <code>UnknownTablet</code> 3225 * and <code>UnknownMobile</code>, so you will get <code>null</code> here, while {@link MobileDetect#mobile} 3226 * will return <code>UnknownMobile</code>.<br> 3227 * Be aware that since v1.0.0 in this special case you will get <code>UnknownMobile</code> only for: 3228 * {@link MobileDetect#mobile}, not for {@link MobileDetect#phone} and {@link MobileDetect#tablet}. 3229 * In versions before v1.0.0 all 3 methods returned <code>UnknownMobile</code> which was tedious to use. 3230 * <br> 3231 * In most cases you will use the return value just as a boolean. 3232 * 3233 * @returns {String} the key of the phone family or producer, e.g. "iPhone" 3234 * @function MobileDetect#phone 3235 */ 3236 phone: function () { 3237 impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); 3238 return this._cache.phone; 3239 }, 3240 3241 /** 3242 * Returns the detected tablet type/family string or <tt>null</tt>. 3243 * <br> 3244 * The returned tablet (family or producer) is one of following keys:<br> 3245 * <br><tt>iPad, NexusTablet, GoogleTablet, SamsungTablet, Kindle, SurfaceTablet, 3246 * HPTablet, AsusTablet, BlackBerryTablet, HTCtablet, MotorolaTablet, NookTablet, 3247 * AcerTablet, ToshibaTablet, LGTablet, FujitsuTablet, PrestigioTablet, 3248 * LenovoTablet, DellTablet, YarvikTablet, MedionTablet, ArnovaTablet, 3249 * IntensoTablet, IRUTablet, MegafonTablet, EbodaTablet, AllViewTablet, 3250 * ArchosTablet, AinolTablet, NokiaLumiaTablet, SonyTablet, PhilipsTablet, 3251 * CubeTablet, CobyTablet, MIDTablet, MSITablet, SMiTTablet, RockChipTablet, 3252 * FlyTablet, bqTablet, HuaweiTablet, NecTablet, PantechTablet, BronchoTablet, 3253 * VersusTablet, ZyncTablet, PositivoTablet, NabiTablet, KoboTablet, DanewTablet, 3254 * TexetTablet, PlaystationTablet, TrekstorTablet, PyleAudioTablet, AdvanTablet, 3255 * DanyTechTablet, GalapadTablet, MicromaxTablet, KarbonnTablet, AllFineTablet, 3256 * PROSCANTablet, YONESTablet, ChangJiaTablet, GUTablet, PointOfViewTablet, 3257 * OvermaxTablet, HCLTablet, DPSTablet, VistureTablet, CrestaTablet, 3258 * MediatekTablet, ConcordeTablet, GoCleverTablet, ModecomTablet, VoninoTablet, 3259 * ECSTablet, StorexTablet, VodafoneTablet, EssentielBTablet, RossMoorTablet, 3260 * iMobileTablet, TolinoTablet, AudioSonicTablet, AMPETablet, SkkTablet, 3261 * TecnoTablet, JXDTablet, iJoyTablet, FX2Tablet, XoroTablet, ViewsonicTablet, 3262 * VerizonTablet, OdysTablet, CaptivaTablet, IconbitTablet, TeclastTablet, 3263 * OndaTablet, JaytechTablet, BlaupunktTablet, DigmaTablet, EvolioTablet, 3264 * LavaTablet, AocTablet, MpmanTablet, CelkonTablet, WolderTablet, MediacomTablet, 3265 * MiTablet, NibiruTablet, NexoTablet, LeaderTablet, UbislateTablet, 3266 * PocketBookTablet, KocasoTablet, HisenseTablet, Hudl, TelstraTablet, 3267 * GenericTablet</tt><br> 3268 * <br> 3269 * If the device is not detected by the regular expressions from Mobile-Detect, a test is made against 3270 * the patterns of <a href="http://detectmobilebrowsers.com/">detectmobilebrowsers.com</a>. If this test 3271 * is positive, a value of <code>UnknownTablet</code> or <code>UnknownMobile</code> is returned.<br> 3272 * When used in browser, the decision whether phone or tablet is made based on <code>screen.width/height</code>.<br> 3273 * <br> 3274 * When used server-side (node.js), there is no way to tell the difference between <code>UnknownTablet</code> 3275 * and <code>UnknownMobile</code>, so you will get <code>null</code> here, while {@link MobileDetect#mobile} 3276 * will return <code>UnknownMobile</code>.<br> 3277 * Be aware that since v1.0.0 in this special case you will get <code>UnknownMobile</code> only for: 3278 * {@link MobileDetect#mobile}, not for {@link MobileDetect#phone} and {@link MobileDetect#tablet}. 3279 * In versions before v1.0.0 all 3 methods returned <code>UnknownMobile</code> which was tedious to use. 3280 * <br> 3281 * In most cases you will use the return value just as a boolean. 3282 * 3283 * @returns {String} the key of the tablet family or producer, e.g. "SamsungTablet" 3284 * @function MobileDetect#tablet 3285 */ 3286 tablet: function () { 3287 impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); 3288 return this._cache.tablet; 3289 }, 3290 3291 /** 3292 * Returns the (first) detected user-agent string or <tt>null</tt>. 3293 * <br> 3294 * The returned user-agent is one of following keys:<br> 3295 * <br><tt>Chrome, Dolfin, Opera, Skyfire, Edge, IE, Firefox, Bolt, TeaShark, Blazer, 3296 * Safari, WeChat, UCBrowser, baiduboxapp, baidubrowser, DiigoBrowser, Mercury, 3297 * ObigoBrowser, NetFront, GenericBrowser, PaleMoon</tt><br> 3298 * <br> 3299 * In most cases calling {@link MobileDetect#userAgent} will be sufficient. But there are rare 3300 * cases where a mobile device pretends to be more than one particular browser. You can get the 3301 * list of all matches with {@link MobileDetect#userAgents} or check for a particular value by 3302 * providing one of the defined keys as first argument to {@link MobileDetect#is}. 3303 * 3304 * @returns {String} the key for the detected user-agent or <tt>null</tt> 3305 * @function MobileDetect#userAgent 3306 */ 3307 userAgent: function () { 3308 if (this._cache.userAgent === undefined) { 3309 this._cache.userAgent = impl.findMatch(impl.mobileDetectRules.uas, this.ua); 3310 } 3311 return this._cache.userAgent; 3312 }, 3313 3314 /** 3315 * Returns all detected user-agent strings. 3316 * <br> 3317 * The array is empty or contains one or more of following keys:<br> 3318 * <br><tt>Chrome, Dolfin, Opera, Skyfire, Edge, IE, Firefox, Bolt, TeaShark, Blazer, 3319 * Safari, WeChat, UCBrowser, baiduboxapp, baidubrowser, DiigoBrowser, Mercury, 3320 * ObigoBrowser, NetFront, GenericBrowser, PaleMoon</tt><br> 3321 * <br> 3322 * In most cases calling {@link MobileDetect#userAgent} will be sufficient. But there are rare 3323 * cases where a mobile device pretends to be more than one particular browser. You can get the 3324 * list of all matches with {@link MobileDetect#userAgents} or check for a particular value by 3325 * providing one of the defined keys as first argument to {@link MobileDetect#is}. 3326 * 3327 * @returns {Array} the array of detected user-agent keys or <tt>[]</tt> 3328 * @function MobileDetect#userAgents 3329 */ 3330 userAgents: function () { 3331 if (this._cache.userAgents === undefined) { 3332 this._cache.userAgents = impl.findMatches(impl.mobileDetectRules.uas, this.ua); 3333 } 3334 return this._cache.userAgents; 3335 }, 3336 3337 /** 3338 * Returns the detected operating system string or <tt>null</tt>. 3339 * <br> 3340 * The operating system is one of following keys:<br> 3341 * <br><tt>AndroidOS, BlackBerryOS, PalmOS, SymbianOS, WindowsMobileOS, WindowsPhoneOS, 3342 * iOS, iPadOS, SailfishOS, MeeGoOS, MaemoOS, JavaOS, webOS, badaOS, BREWOS</tt><br> 3343 * 3344 * @returns {String} the key for the detected operating system. 3345 * @function MobileDetect#os 3346 */ 3347 os: function () { 3348 if (this._cache.os === undefined) { 3349 this._cache.os = impl.detectOS(this.ua); 3350 } 3351 return this._cache.os; 3352 }, 3353 3354 /** 3355 * Get the version (as Number) of the given property in the User-Agent. 3356 * <br> 3357 * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31) 3358 * 3359 * @param {String} key a key defining a thing which has a version.<br> 3360 * You can use one of following keys:<br> 3361 * <br><tt>Mobile, Build, Version, VendorID, iPad, iPhone, iPod, Kindle, Chrome, Coast, 3362 * Dolfin, Firefox, Fennec, Edge, IE, NetFront, NokiaBrowser, Opera, Opera Mini, 3363 * Opera Mobi, UCBrowser, MQQBrowser, MicroMessenger, baiduboxapp, baidubrowser, 3364 * SamsungBrowser, Iron, Safari, Skyfire, Tizen, Webkit, PaleMoon, 3365 * SailfishBrowser, Gecko, Trident, Presto, Goanna, iOS, Android, Sailfish, 3366 * BlackBerry, BREW, Java, Windows Phone OS, Windows Phone, Windows CE, Windows 3367 * NT, Symbian, webOS</tt><br> 3368 * 3369 * @returns {Number} the version as float or <tt>NaN</tt> if User-Agent doesn't contain this version. 3370 * Be careful when comparing this value with '==' operator! 3371 * @function MobileDetect#version 3372 */ 3373 version: function (key) { 3374 return impl.getVersion(key, this.ua); 3375 }, 3376 3377 /** 3378 * Get the version (as String) of the given property in the User-Agent. 3379 * <br> 3380 * 3381 * @param {String} key a key defining a thing which has a version.<br> 3382 * You can use one of following keys:<br> 3383 * <br><tt>Mobile, Build, Version, VendorID, iPad, iPhone, iPod, Kindle, Chrome, Coast, 3384 * Dolfin, Firefox, Fennec, Edge, IE, NetFront, NokiaBrowser, Opera, Opera Mini, 3385 * Opera Mobi, UCBrowser, MQQBrowser, MicroMessenger, baiduboxapp, baidubrowser, 3386 * SamsungBrowser, Iron, Safari, Skyfire, Tizen, Webkit, PaleMoon, 3387 * SailfishBrowser, Gecko, Trident, Presto, Goanna, iOS, Android, Sailfish, 3388 * BlackBerry, BREW, Java, Windows Phone OS, Windows Phone, Windows CE, Windows 3389 * NT, Symbian, webOS</tt><br> 3390 * 3391 * @returns {String} the "raw" version as String or <tt>null</tt> if User-Agent doesn't contain this version. 3392 * 3393 * @function MobileDetect#versionStr 3394 */ 3395 versionStr: function (key) { 3396 return impl.getVersionStr(key, this.ua); 3397 }, 3398 3399 /** 3400 * Global test key against userAgent, os, phone, tablet and some other properties of userAgent string. 3401 * 3402 * @param {String} key the key (case-insensitive) of a userAgent, an operating system, phone or 3403 * tablet family.<br> 3404 * For a complete list of possible values, see {@link MobileDetect#userAgent}, 3405 * {@link MobileDetect#os}, {@link MobileDetect#phone}, {@link MobileDetect#tablet}.<br> 3406 * Additionally you have following keys:<br> 3407 * <br><tt>Bot, MobileBot, DesktopMode, TV, WebKit, Console, Watch</tt><br> 3408 * 3409 * @returns {boolean} <tt>true</tt> when the given key is one of the defined keys of userAgent, os, phone, 3410 * tablet or one of the listed additional keys, otherwise <tt>false</tt> 3411 * @function MobileDetect#is 3412 */ 3413 is: function (key) { 3414 return containsIC(this.userAgents(), key) || 3415 equalIC(key, this.os()) || 3416 equalIC(key, this.phone()) || 3417 equalIC(key, this.tablet()) || 3418 containsIC(impl.findMatches(impl.mobileDetectRules.utils, this.ua), key); 3419 }, 3420 3421 /** 3422 * Do a quick test against navigator::userAgent. 3423 * 3424 * @param {String|RegExp} pattern the pattern, either as String or RegExp 3425 * (a string will be converted to a case-insensitive RegExp). 3426 * @returns {boolean} <tt>true</tt> when the pattern matches, otherwise <tt>false</tt> 3427 * @function MobileDetect#match 3428 */ 3429 match: function (pattern) { 3430 if (!(pattern instanceof RegExp)) { 3431 pattern = new RegExp(pattern, 'i'); 3432 } 3433 return pattern.test(this.ua); 3434 }, 3435 3436 /** 3437 * Checks whether the mobile device can be considered as phone regarding <code>screen.width</code>. 3438 * <br> 3439 * Obviously this method makes sense in browser environments only (not for Node.js)! 3440 * @param {number} [maxPhoneWidth] the maximum logical pixels (aka. CSS-pixels) to be considered as phone.<br> 3441 * The argument is optional and if not present or falsy, the value of the constructor is taken. 3442 * @returns {boolean|undefined} <code>undefined</code> if screen size wasn't detectable, else <code>true</code> 3443 * when screen.width is less or equal to maxPhoneWidth, otherwise <code>false</code>.<br> 3444 * Will always return <code>undefined</code> server-side. 3445 */ 3446 isPhoneSized: function (maxPhoneWidth) { 3447 return MobileDetect.isPhoneSized(maxPhoneWidth || this.maxPhoneWidth); 3448 }, 3449 3450 /** 3451 * Returns the mobile grade ('A', 'B', 'C'). 3452 * 3453 * @returns {String} one of the mobile grades ('A', 'B', 'C'). 3454 * @function MobileDetect#mobileGrade 3455 */ 3456 mobileGrade: function () { 3457 if (this._cache.grade === undefined) { 3458 this._cache.grade = impl.mobileGrade(this); 3459 } 3460 return this._cache.grade; 3461 } 3462 }; 3463 3464 // environment-dependent 3465 if (typeof window !== 'undefined' && window.screen) { 3466 MobileDetect.isPhoneSized = function (maxPhoneWidth) { 3467 return maxPhoneWidth < 0 ? undefined : impl.getDeviceSmallerSide() <= maxPhoneWidth; 3468 }; 3469 } else { 3470 MobileDetect.isPhoneSized = function () {}; 3471 } 3472 3473 // should not be replaced by a completely new object - just overwrite existing methods 3474 MobileDetect._impl = impl; 3475 3476 MobileDetect.version = '1.4.5 2021-03-13'; 3477 3478 return MobileDetect; 3479}); // end of call of define() 3480})((function (undefined) { 3481 if (typeof module !== 'undefined' && module.exports) { 3482 return function (factory) { module.exports = factory(); }; 3483 } else if (typeof define === 'function' && define.amd) { 3484 return define; 3485 } else if (typeof window !== 'undefined') { 3486 return function (factory) { window.MobileDetect = factory(); }; 3487 } else { 3488 // please file a bug if you get this error! 3489 throw new Error('unknown environment'); 3490 } 3491})());
3491 3492// @license http://opensource.org/licenses/MIT 3493// copyright Paul Irish 2015 3494 3495 3496// Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill 3497// github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js 3498// as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values 3499 3500// if you want values similar to what you'd get with real perf.now, place this towards the head of the page 3501// but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed 3502 3503 3504(function () { 3505 3506 if ("performance" in window == false) { 3507 window.performance = {}; 3508 } 3509 3510 Date.now = (Date.now || function () { // thanks IE8 3511 return new Date().getTime(); 3512 }); 3513 3514 if ("now" in window.performance == false) { 3515 3516 var nowOffset = Date.now(); 3517 3518 if (performance.timing && performance.timing.navigationStart) { 3519 nowOffset = performance.timing.navigationStart 3520 } 3521 3522 window.performance.now = function now() { 3523 return Date.now() - nowOffset; 3524 } 3525 } 3526 3527})(); 3528/*** Copyright 2013 Teun Duynstee Licensed under the Apache License, Version 2.0 ***/ 3529firstBy = function () { 3530 function n(n, t) { 3531 if ("function" != typeof n) { 3532 var r = n; 3533 n = function (n, t) { 3534 return n[r] < t[r] ? -1 : n[r] > t[r] ? 1 : 0 3535 } 3536 } 3537 if (1 === n.length) { 3538 var u = n; 3539 n = function (n, t) { 3540 return u(n) < u(t) ? -1 : u(n) > u(t) ? 1 : 0 3541 } 3542 } 3543 return -1 === t ? function (t, r) { 3544 return -n(t, r) 3545 } : n 3546 } 3547 3548 function t(t, u) { 3549 return t = n(t, u), t.thenBy = r, t 3550 } 3551 3552 function r(r, u) { 3553 var f = this; 3554 return r = n(r, u), t(function (n, t) { 3555 return f(n, t) || r(n, t) 3556 }) 3557 } 3558 3559 return t 3560}(); 3561// Global hp object 3562window.hp = {}; 3563 3564hp.addClass = function ($el, cssClass) { 3565 3566 if (typeof $el === 'undefined' || typeof cssClass === 'undefined') { 3567 3568 return false; 3569 3570 } 3571 3572 3573 3574 if ($el.is(cssClass)) { 3575 3576 return false; 3577 3578 } 3579 3580 // remove classes starting with `hp-` 3581 3582 $el.attr('class', function (i, c) { 3583 3584 return c.replace(/(^|\s)hp-\S+/g, ''); 3585 3586 }); 3587 3588 3589 3590 $el.addClass(cssClass); 3591 3592}; 3593 3594 3595hp.anchorLink = function (params) { 3596 3597 var options = $.extend({}, params); 3598 3599 var hash = window.location.hash.replace('#!', ''); 3600 3601 var $window = $(window); 3602 3603 var hashIsLocked = false; 3604 3605 3606 3607 function _setHash(newHash) { 3608 3609 if (hashIsLocked) { 3610 3611 return false; 3612 3613 } 3614 3615 window.location.hash = '#!' + newHash; 3616 3617 } 3618 3619 3620 3621 function _setActive(index) { 3622 3623 $('[data-hp-anchor-link]').removeClass('active'); 3624 3625 var $link = $('[data-hp-anchor-link]:eq(' + index + ')'); 3626 3627 3628 3629 if ($link.length) { 3630 3631 $link.addClass('active'); 3632 3633 _setHash($link.data('hpAnchorLink')); 3634 3635 } 3636 3637 } 3638 3639 3640 3641 $(document).on('click', '[data-hp-anchor-link]', function (e) { 3642 3643 3644 3645 var anchorLink = $(this).data('hpAnchorLink'); 3646 3647 var $target = $($(this).data('hpAnchorTarget')); 3648 3649 if (!$target.length || !anchorLink || anchorLink === '') { 3650 3651 return true; 3652 3653 } 3654 3655 3656 3657 $('[data-hp-anchor-link]').removeClass('active'); 3658 3659 $(this).addClass('active'); 3660 3661 3662 3663 var offset = $target.offset().top; 3664 3665 if (options.header instanceof jQuery) { 3666 3667 offset -= options.header.height(); 3668 3669 } 3670 3671 3672 3673 hashIsLocked = true; // to prevent the on scroll event to change the hash 3674 3675 hp.scrollTo({ 3676 3677 offset: offset, 3678 3679 callback: function () { 3680 3681 hashIsLocked = false; 3682 3683 _setHash(anchorLink); 3684 3685 } 3686 3687 }); 3688 3689 }); 3690 3691 3692 3693 $window.on('scroll', function () { 3694 3695 if ($window.scrollTop() <= 50 && hashIsLocked === false) { 3696 3697 _setActive(0); 3698 3699 } 3700 3701 }); 3702 3703 3704 3705 $window.on('load', function () { 3706 3707 if (hash.length) { 3708 3709 $('[data-hp-anchor-link="' + hash + '"]').trigger('click'); 3710 3711 } 3712 3713 }); 3714 3715}; 3716 3717 3718hp.browserVersion = function () { 3719 3720 3721 3722 var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; 3723 3724 if (/trident/i.test(M[1])) { 3725 3726 tem = /\brv[ :]+(\d+)/g.exec(ua) || []; 3727 3728 return {name: 'IE', version: (tem[1] || '')}; 3729 3730 } 3731 3732 if (M[1] === 'Chrome') { 3733 3734 tem = ua.match(/\bOPR\/(\d+)/) 3735 3736 if (tem != null) { 3737 3738 return {name: 'Opera', version: tem[1]}; 3739 3740 } 3741 3742 } 3743 3744 M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?']; 3745 3746 if ((tem = ua.match(/version\/(\d+)/i)) != null) { 3747 3748 M.splice(1, 1, tem[1]); 3749 3750 } 3751 3752 return { 3753 3754 name: M[0], 3755 3756 version: M[1] 3757 3758 }; 3759 3760}; 3761 3762 3763hp.calculateTop = function ($element, margin) { 3764 3765 margin = margin || 120; 3766 3767 return $element.parent().offset().top - $(window).scrollTop() + margin; 3768 3769}; 3770 3771 3772hp.clearCache = function () { 3773 3774 // clear overloaded IBE cache 3775 3776 BookwizeLiquid.cache.clear(); 3777 3778 3779 3780 if (hp.isCheckRatesPage()) { 3781 3782 window.location.href = IBE.Config.websiteUrl; 3783 3784 } else { 3785 3786 window.location.hash = ''; 3787 3788 window.location.href = hp.removeParam('clearCache', window.location.href); 3789 3790 window.location.reload(); 3791 3792 } 3793 3794}; 3795 3796 3797hp.closeOverlays = function () { 3798 3799 3800
3801 var $overlay = $('.hp-toggle--open'); 3802 3803 3804 3805 try { 3806 3807 3808 3809 $overlay.fadeOut().removeClass('hp-toggle--open'); 3810 3811 $('.hp-backdrop').remove(); 3812 3813 $('.datepick-popup').remove(); 3814 3815 $('body').removeClass('step1-open'); 3816 3817 3818 3819 BookwizeLiquid.popup.close(); 3820 3821 if($('.single-gallery__slider')){ 3822 3823 $('.single-gallery__slider').slick('refresh'); 3824 3825 } 3826 3827 3828 3829 if (BookwizeLiquid.isMultiProperty === true) { 3830 3831 ko.utils.arrayForEach(BookwizeLiquid.vm.step2.properties(), function (item) { 3832 3833 item.removeLastRoom(); 3834 3835 }); 3836 3837 } else { 3838 3839 BookwizeLiquid.vm.step2.removeLastRoom(); 3840 3841 } 3842 3843 } catch (e) { 3844 3845 // we do not anything to log here 3846 3847 } 3848 3849 3850 3851 $overlay.trigger('hp/overlayClosed', { 3852 3853 source: $overlay 3854 3855 }); 3856 3857}; 3858 3859 3860 3861 3862 3863 3864// ci=2014-08-08&co=2014-08-12&r=2^3/3/0/0^4/3/0^1/0&couponCode=&board=&rp= 3865 3866hp.deepLink = function (sessionData, returnType) { 3867 3868 var data = ko.toJS(sessionData); 3869 3870 var preferences = { 3871 3872 ci: data.checkIn, 3873 3874 co: data.checkOut, 3875 3876 board: data.board, 3877 3878 lang: data.lang, 3879 3880 cur: data.currency, 3881 3882 couponCode: data.couponCode 3883 3884 }; 3885 3886 var rooms = ''; 3887 3888 ko.utils.arrayForEach(data.rooms, function (item) { 3889 3890 var adults = ko.utils.arrayFilter(item, function (guest) { 3891 3892 return guest.ageCategory === 'Adult'; 3893 3894 }); 3895 3896 var children = ko.utils.arrayFilter(item, function (guest) { 3897 3898 return guest.ageCategory === 'Children'; 3899 3900 }); 3901 3902 var infants = ko.utils.arrayFilter(item, function (guest) { 3903 3904 return guest.ageCategory === 'Infant'; 3905 3906 }); 3907 3908 3909 3910 if (adults.length && adults[0].pax > 0) { 3911 3912 rooms += adults[0].pax; 3913 3914 } 3915 3916 3917 3918 if ((children.length && children[0].pax > 0) || (infants.length && infants[0].pax > 0)) { 3919 3920 rooms += '/'; 3921 3922 } 3923 3924 if (children.length && children[0].pax > 0) { 3925 3926 for (var i = 0; i < children[0].pax; i++) { 3927 3928 rooms += children[0].fromAge + '/'; 3929 3930 } 3931 3932 } 3933 3934 if (infants.length && infants[0].pax > 0) { 3935 3936 for (var i = 0; i < infants[0].pax; i++) { 3937 3938 rooms += infants[0].fromAge + '/'; 3939 3940 } 3941 3942 } 3943 3944 rooms += '^'; 3945 3946 }); 3947 3948 3949 3950 rooms = rooms.slice(0, -1); 3951 3952 // preferences.r = rooms; 3953 3954 preferences.r = 1; 3955 3956 3957 3958 return (typeof returnType === 'undefined') ? $.param(preferences) : preferences; 3959 3960}; 3961 3962 3963hp.disable = function ($el) { 3964 3965 if (typeof $el === 'undefined' || $el.length == 0) { 3966 3967 return false; 3968 3969 } 3970 3971 $el.attr('disabled', 'disabled'); 3972 3973}; 3974 3975 3976hp.dropdown = function () { 3977 3978 3979 3980 $(document).on('click', '.hp-dropdown-toggle', function (e) { 3981 3982 $($(this).data('hpDropdown')).toggleClass('active'); 3983 3984 }); 3985 3986 3987 3988 $(document).on('click', '.hp-dropdown li', function (e) { 3989 3990 $(this).parent().removeClass('active'); 3991 3992 }); 3993 3994 3995 3996 $(window).on('scroll', function(){ 3997 3998 $('.hp-dropdown.active').removeClass('active'); 3999 4000 }); 4001 4002}; 4003 4004 4005hp.enable = function ($el) { 4006 4007 if (typeof $el === 'undefined' || $el.length == 0) { 4008 4009 return false; 4010 4011 } 4012 4013 var t = setTimeout(function () { 4014 4015 $el.removeAttr('disabled'); 4016 4017 clearTimeout(t); 4018 4019 }, 377); 4020 4021}; 4022 4023 4024hp.escapeKeyUp = function () { 4025 4026 $(document).keyup(function (e) { 4027 4028 if (e.keyCode == 27) { 4029 4030 hp.closeOverlays(); 4031 4032 return true; 4033 4034 } 4035 4036 }); 4037 4038}; 4039 4040 4041 4042 4043hp.getHotelCredentialsFromRoomId = function (id, properties) { 4044 4045 var returnValue = {}; 4046 4047 4048 4049 var hotel = hp.getHotelInfoFromRoomId(id, properties); 4050 4051 4052 4053 if (hotel) { 4054 4055 var params = ko.utils.arrayFilter(properties, function (item) { 4056 4057 return item.hotelId == hotel.hotelId; 4058 4059 })[0]; 4060 4061 returnValue.hotelId = params.hotelId; 4062 4063 returnValue.apiKey = params.apiKey; 4064 4065 } 4066 4067 4068 4069 return returnValue; 4070 4071}; 4072 4073 4074hp.getHotelInfoFromRoomId = function (id, properties) { 4075 4076 var returnValue = {}; 4077 4078 4079 4080 var hotelId = 0; 4081 4082 4083 4084 ko.utils.arrayForEach(properties, function (item) { 4085 4086 if (hotelId > 0) { 4087 4088 return true; 4089 4090 } 4091 4092 var room = ko.utils.arrayFilter(item.vm.step1.rooms(), function (room) { 4093 4094 return room.id === id; 4095 4096 }); 4097 4098 if (room.length) { 4099 4100 returnValue = item.vm.step1.hotel().info; 4101 4102 } 4103 4104 }); 4105 4106 4107 4108 return returnValue; 4109 4110}; 4111 4112 4113hp.hash = function (value) { 4114 4115 4116 4117 if (typeof value === 'undefined' || value == false) { 4118 4119 if (history.pushState) { 4120 4121 history.pushState(null, null, '#'); 4122 4123 } else { 4124 4125 window.location.hash = ''; 4126 4127 } 4128 4129 return; 4130 4131 } 4132 4133 4134 4135 if (history.pushState) { 4136 4137 history.pushState(null, null, '#' + value); 4138 4139 } else { 4140 4141 window.location.hash = '#' + value; 4142 4143 } 4144 4145}; 4146 4147 4148hp.isBound = function (id) { 4149 4150 return !!ko.dataFor(document.getElementById(id)); 4151 4152}; 4153 4154 4155hp.isCheckRatesPage = function () { 4156 4157 var page = BookwizeLiquid.getPostByBookwizeLiquidPageType('checkrates'); 4158 4159 return page.ID === IBE.Config.post.ID; 4160 4161}; 4162 4163 4164 4165 4166hp.isMobile = function () { 4167 4168 var md = new MobileDetect(window.navigator.userAgent); 4169 4170 // alert('md.phone(): ' + md.phone() + ', md.tablet(): ' + md.tablet()); 4171 4172 4173 4174 return (md.phone() !== null && md.tablet() === null); 4175 4176}; 4177 4178 4179hp.isOfferPage = function (id) { 4180 4181 if (typeof id === 'undefined') { 4182 4183 id = IBE.Config.post.ID; 4184 4185 } 4186 4187 var page = BookwizeLiquid.getOfferByPostId(id); 4188 4189 return page.ID === IBE.Config.post.ID; 4190 4191}; 4192 4193 4194hp.isRoomPage = function (id) { 4195 4196 if (typeof id === 'undefined') { 4197 4198 id = IBE.Config.post.ID; 4199 4200 } 4201 4202 var page = BookwizeLiquid.getRoomByPostId(id); 4203 4204 return page.ID === IBE.Config.post.ID; 4205 4206}; 4207 4208 4209 4210 4211hp.legacy = function (mobile) { 4212 4213 var $hpLegacy = $('.hp-legacy'); 4214 4215 4216 4217 // remove all booking engine elements 4218 4219 $('[id^="hp-"], [class^="hp-"]').remove(); 4220 4221 4222 4223 // show legacy booking link 4224 4225 $('.header__book').append($hpLegacy); 4226 4227 if (typeof mobile !== 'undefined') { 4228 4229 $('.hp-legacy-booking-link--mobile').addClass('active'); 4230 4231 4232 4233 } else { 4234 4235 $('.hp-legacy-booking-link').addClass('active'); 4236 4237 } 4238 4239 4240 4241 $('.hp-legacy-booking-link[data-toggle]').on('click', function () { 4242 4243 var $sidebarHotel = $('.sidebar__hotel'); 4244 4245 if ($sidebarHotel.length && $sidebarHotel.data('hotelId')) { 4246 4247 var hotelId = $sidebarHotel.data('hotelId'); 4248 4249 window.open( 4250 4251 $('.hp-legacy-booking-link[data-hotel-id="' + hotelId + '"]').attr('href'), 4252 4253 '_blank' 4254 4255 ); 4256 4257 4258 4259 setTimeout(function () { 4260 4261 $('.dropdown__list--book').removeClass('opened'); 4262 4263 }, 200); 4264 4265 } 4266 4267 }); 4268 4269}; 4270 4271 4272hp.removeParam = function (key, sourceURL) { 4273 4274 var rtn = sourceURL.split("?")[0], 4275 4276 param, 4277 4278 params_arr = [], 4279 4280 queryString = (sourceURL.indexOf("?") !== -1) ? sourceURL.split("?")[1] : ""; 4281 4282 if (queryString !== "") { 4283 4284 params_arr = queryString.split("&"); 4285 4286 for (var i = params_arr.length - 1; i >= 0; i -= 1) { 4287 4288 param = params_arr[i].split("=")[0]; 4289 4290 if (param === key) { 4291 4292 params_arr.splice(i, 1); 4293 4294 } 4295 4296 } 4297 4298 rtn = rtn + "?" + params_arr.join("&"); 4299 4300 } 4301 4302 return rtn; 4303 4304}; 4305 4306 4307hp.scrollTo = function (options) { 4308 4309 options = $.extend({ 4310 4311 offset: 0, 4312 4313 duration: 777, 4314 4315 callback: function () { 4316 4317 } 4318 4319 }, options); 4320 4321 4322 4323 $('html:not(:animated),body:not(:animated)').animate( 4324 4325 {scrollTop: options.offset}, 4326 4327 { 4328 4329 duration: options.duration, 4330 4331 complete: function () { 4332 4333 options.callback(); 4334 4335 } 4336 4337 } 4338 4339 ); 4340 4341}; 4342 4343 4344hp.setHotelApiConfig = function(params) { 4345 4346 if (typeof params !== 'undefined') { 4347 4348 if (params.hotelId) { 4349 4350 IBE.Config.hotelId = params.hotelId; 4351 4352 } 4353 4354 if (params.apiKey) { 4355 4356 IBE.Config.apiKey = params.apiKey; 4357 4358 } 4359 4360 } 4361 4362}; 4363 4364 4365hp.setOverlayDefaults = function (viewModel, session) { 4366 4367 if (session === false) { 4368 4369 return; 4370 4371 } 4372 4373 var currentValues = ko.toJS({ 4374 4375 checkIn: ko.unwrap(viewModel.checkIn).format('YYYY-MM-DD'), 4376 4377 checkOut: ko.unwrap(viewModel.checkOut).format('YYYY-MM-DD'), 4378 4379 guests: ko.unwrap(viewModel.guests), 4380 4381 boardType: ko.unwrap(viewModel.boardType), 4382 4383 currency: ko.unwrap(viewModel.currency), 4384 4385 couponCode: ko.unwrap(viewModel.couponCode), 4386 4387 lang: ko.unwrap(viewModel.lang) 4388 4389 }); 4390 4391 4392 4393 if (currentValues.checkIn !== session.checkIn) { 4394 4395 viewModel.checkIn(session.checkIn); 4396 4397 } 4398 4399 4400 4401 if (currentValues.checkOut !== session.checkOut) { 4402 4403 viewModel.checkOut(session.checkOut); 4404 4405 } 4406 4407 4408 4409 if (currentValues.boardType !== session.board) { 4410 4411 viewModel.boardType(session.board); 4412 4413 } 4414 4415 4416 4417 if (currentValues.currency !== session.currency) { 4418 4419 viewModel.currency(session.currency); 4420 4421 } 4422 4423 4424 4425 if (currentValues.lang !== session.lang) { 4426 4427 viewModel.lang(session.lang); 4428 4429 } 4430 4431 4432 4433 if (currentValues.couponCode !== session.couponCode) { 4434 4435 viewModel.couponCode(session.couponCode); 4436 4437 } 4438 4439 4440 4441 ko.utils.arrayForEach(currentValues.guests, function (guest) { 4442
4443 ko.utils.arrayForEach(session.rooms[0], function (sessionGuest) { 4444 4445 if (guest.pax !== sessionGuest.pax) { 4446 4447 var viewModelGuestType = ko.utils.arrayFilter(viewModel.guests, function (item) { 4448 4449 return item.ageCategory() === sessionGuest.ageCategory && item.fromAge() == sessionGuest.fromAge 4450 4451 }); 4452 4453 if (viewModelGuestType.length) { 4454 4455 viewModelGuestType[0].pax(sessionGuest.pax); 4456 4457 } 4458 4459 } 4460 4461 }); 4462 4463 }); 4464 4465}; 4466 4467 4468hp.setOverlayHash = function () { 4469 4470 var self = this; 4471 4472 var $window = $(window); 4473 4474 var overlayHash = 'booking-preferences'; 4475 4476 4477 4478 self.hash = window.location.hash.replace('#!', ''); 4479 4480 4481 4482 self.setHash = function (newHash) { 4483 4484 var hash = overlayHash; 4485 4486 if (typeof newHash !== 'undefined') { 4487 4488 hash = newHash; 4489 4490 } 4491 4492 window.location.hash = '#!' + hash; 4493 4494 }; 4495 4496 4497 4498 self.init = function () { 4499 4500 4501 $window.on('load', function () { 4502 setTimeout(function() { 4503 var $el = $('[data-hp-toggle=".hp-step1"]'); 4504 if (self.hash === overlayHash && $el.length) { 4505 $el[0].click(); 4506 } 4507 }, 1000); 4508 }); 4509 4510 $(document).on('hp/overlayClosed', function (e, data) { 4511 4512 self.setHash(''); 4513 4514 }); 4515 4516 }; 4517 4518 4519 4520 return self; 4521 4522}; 4523 4524 4525hp.timestampToDate = function (UNIX_timestamp) { 4526 4527 var a = new Date(UNIX_timestamp * 1000); 4528 4529 var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 4530 4531 var year = a.getFullYear(); 4532 4533 var month = months[a.getMonth()]; 4534 4535 var date = a.getDate(); 4536 4537 var hour = a.getHours(); 4538 4539 var min = a.getMinutes(); 4540 4541 var sec = a.getSeconds(); 4542 4543 return date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec; 4544 4545}; 4546 4547 4548hp.toDash = function (str, replacement) { 4549 4550 replacement = replacement || '-'; 4551 4552 4553 4554 return str.replace(/([a-z])([A-Z])/g, '$1' + replacement + '$2').toLowerCase(); 4555 4556}; 4557 4558 4559hp.toggle = function () { 4560 4561 4562 4563 var self = this; 4564 4565 4566 4567 self.toggleOverlays = function ($el, e) { 4568 4569 var $target = $($el.data('hpToggle')); 4570 4571 var margin = $el.data('hpMarginTop') || undefined; 4572 4573 var useBackDrop = ($el.data('hpBackdrop') === undefined) ? true : $el.data('hpBackdrop'); 4574 4575 4576 4577 if ($(e.target).parents('.hp-toggle').length && $target.hasClass("hp-toggle--open")) { 4578 4579 // if current clicked element is child of hp-toggle, don't close the overlay 4580 4581 return; 4582 4583 } 4584 4585 $('.hp-wait').hide(); 4586 4587 $('.hp-toggle-open').slideUp(); 4588 4589 $target.removeClass('hp-toggle--open'); 4590 4591 $('body').removeClass('step1-open'); 4592 4593 if ($target.is(':hidden')) { 4594 4595 if ($target.hasClass('hp-step1')){ 4596 4597 $('body').addClass('step1-open'); 4598 4599 } 4600 4601 if (typeof margin !== 'undefined') { 4602 4603 $target.css({top: hp.calculateTop($target, margin)}); 4604 4605 } 4606 4607 $target.stop(true, true).fadeIn(100); 4608 4609 $target.addClass('hp-toggle--open'); 4610 4611 if (useBackDrop) { 4612 4613 $('body').append('<div class="hp-backdrop"></div>'); 4614 4615 } 4616 4617 4618 4619 $target.trigger('hp/overlayOpened', { 4620 4621 source: $el 4622 4623 }); 4624 4625 4626 4627 } else { 4628 4629 $target.stop(true, true).fadeOut(100); 4630 4631 $target.removeClass('hp-toggle--open'); 4632 4633 $('body').removeClass('step1-open'); 4634 4635 $('.hp-wait').hide(); 4636 4637 if (useBackDrop) { 4638 4639 $('.hp-backdrop').remove(); 4640 4641 } 4642 4643 4644 4645 $target.trigger('hp/overlayClosed', { 4646 4647 source: $el 4648 4649 }); 4650 4651 } 4652 4653 }; 4654 4655 4656 4657 $(document).on('click', '[data-hp-toggle]', function (e) { 4658 4659 self.toggleOverlays($(this), e); 4660 4661 }); 4662 4663 4664 4665 return self; 4666 4667}; 4668ko.bindingHandlers.affiliate = { 4669 init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4670 if (bindingContext.$root.cache.read('AllowAnalyticsTracking') === false) { 4671 return true; 4672 } 4673 4674 var val = ko.unwrap(valueAccessor()); 4675 4676 if (typeof val.vendor === 'undefined' || typeof val.affiliateId === 'undefined') { 4677 return true; 4678 } 4679 4680 // find price and reservation id 4681 var affiliateId = val.affiliateId || 0; 4682 var reservationId = val.reservation.id; 4683 var totalCost = val.reservation.totalCost(); 4684 var charatsee = 1 + val.taxPercentage; 4685 var totalCostWithoutTax = (totalCost / charatsee).toFixed(2); 4686 4687 switch (val.vendor.toLowerCase()) { 4688 case 'linkwise': 4689 var $body = $('body'); 4690 // first load any external libraries 4691 var html = [ 4692 '<img src="https://affiliate.linkwise.gr/i_track_sale/{AFFILIATE_ID}/:prod:{PRICE_WITHOUT_TAX}:qty:1/{RESERVATION_ID}/&sale_status=P">', 4693 '<script type="text/javascript">Linkwise.load_action("{AFFILIATE_ID}", "{RESERVATION_ID}", "1::{PRICE_WITHOUT_TAX}", "", "pending"); </script>', 4694 '<noscript>', 4695 '<img src="https://gr.linkwi.se/delivery/acl.php?cam_id={AFFILIATE_ID}&trans_id={RESERVATION_ID}&sale_amount=1::{PRICE_WITHOUT_TAX}&adv_subid=&status=pending" style="width:0px;height:0px;\"/>', 4696 '</noscript>' 4697 ].join(''); 4698 4699 // replace 4700 html = html.replace(/{PRICE_WITHOUT_TAX}/g, totalCostWithoutTax); 4701 html = html.replace(/{RESERVATION_ID}/g, reservationId); 4702 html = html.replace(/{AFFILIATE_ID}/g, affiliateId); 4703 4704 // save old document.write 4705 // http://www.jakobbeyer.de/asynchronous-google-adwords-conversion-tracking 4706 var oldDocumentWrite = document.write; 4707 document.write = function (node) { 4708 $body.append(node); 4709 }; 4710 4711 $.getScript('https://gr.linkwi.se/delivery/lwc/lwc.js', function (data, textStatus, jqxhr) { 4712 setTimeout(function () { 4713 $body.append(html); 4714 bindingContext.$root.cache.clear('AllowAnalyticsTracking'); 4715 document.write = oldDocumentWrite; 4716 }, 100); 4717 }); 4718 4719 break; 4720 default: 4721 break; 4722 } 4723 } 4724}; 4725ko.bindingHandlers.ga = { 4726 init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4727 if ('function' !== typeof ga) { 4728 return; 4729 } 4730 var options = ko.utils.extend({ 4731 category: '', 4732 action: '', 4733 label: '' 4734 }, valueAccessor()); 4735 4736 $(element).on('click', function () { 4737 ga('send', 'event', options.category, options.action, options.label); 4738 }); 4739 } 4740}; 4741 4742ko.bindingHandlers.hover = { 4743 update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4744 var value = valueAccessor(); 4745 if (typeof(value.element) === 'undefined') { 4746 value.element = element; 4747 } 4748 ko.applyBindingsToNode(element, { 4749 event: { 4750 mouseenter: function () { 4751 if (value.element && value.css) { 4752 // toggle class on element 4753 $(value.element).toggleClass(value.css); 4754 } 4755 // togggle observable value 4756 value.value(!value.value()); 4757 }, 4758 mouseleave: function () { 4759 if (value.element && value.css) { 4760 // toggle class on element 4761 $(value.element).toggleClass(value.css); 4762 } 4763 // togggle observable value 4764 value.value(!value.value()); 4765 } 4766 } 4767 }); 4768 } 4769}; 4770ko.bindingHandlers.loadingWhen = { 4771 init: function (element) { 4772 //unchanged 4773 }, 4774 update: function (element, valueAccessor) { 4775 var 4776 //unwrap the value of the flag using knockout utilities 4777 isLoading = ko.utils.unwrapObservable(valueAccessor()), 4778 4779 //get a reference to the parent element 4780 $element = $(element), 4781 4782 //get a reference to the loader 4783 $loader = $element.find("div.loader") 4784 4785 //get a reference to every *other* element 4786 $childrenToHide = $element.children(":not(div.loader)"); 4787 4788 //if we are currently loading... 4789 if (isLoading) { 4790 //...hide and disable the children... 4791 $childrenToHide.css("visibility", "hidden").attr("disabled", "disabled"); 4792 //...and show the loader 4793 $loader.show(); 4794 } 4795 else { 4796 //otherwise, fade out the loader 4797 $loader.fadeOut("fast"); 4798 //and re-display and enable the children 4799 $childrenToHide.css("visibility", "visible").removeAttr("disabled"); 4800 } 4801 } 4802}; 4803ko.bindingHandlers.log = { 4804 update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4805 4806 // store a counter with this element 4807 var count = ko.utils.domData.get(element, "_ko_logger") || 0; 4808 var data = ko.toJS(ko.unwrap(valueAccessor()) || allBindings()); 4809 4810 ko.utils.domData.set(element, "_ko_logger", ++count); 4811 4812 if (window.console && console.log) { 4813 console.log(count, element, data); 4814 } 4815 } 4816}; 4817ko.bindingHandlers.scroll = { 4818 init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4819 var $el = $(element); 4820 var val = ko.unwrap(valueAccessor()); 4821 var _defaults = { 4822 advanced: { 4823 updateOnContentResize: true, 4824 updateOnSelectorChange: "ul li" 4825 } 4826 }; 4827 var options = $.extend(true, _defaults, val); 4828 $el.mCustomScrollbar(options); 4829 } 4830}; 4831ko.bindingHandlers.selectBoxIt = { 4832 listenBindings: ['value', 'disable', 'options', 'foreach'], 4833 init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4834 setTimeout(function () { 4835 var options = ko.unwrap(valueAccessor()); 4836 var $el = $(element); 4837 4838 $el.selectBoxIt($.extend(options, { 4839 isMobile: function () { 4840 // Adapted from http://www.detectmobilebrowsers.com 4841 var ua = navigator.userAgent || navigator.vendor || window.opera; 4842 // Checks for iOs mobile devices 4843 return (/iPhone|iPod|iPad/).test(ua); 4844 }, 4845 downArrowIcon: 'fa fa-angle-down', 4846 defaultText: ('undefined' !== typeof $el.data('placeholder')) ? $el.data('placeholder') : '', 4847 'native': ('undefined' !== typeof $el.data('native')) ? $el.data('native') : false 4848 })); 4849 4850 ko.computed(function () { 4851 4852 $.each(ko.bindingHandlers.selectBoxIt.listenBindings, function (i, binding) { 4853 var b = allBindings.get(binding); 4854 b = $.isFunction(b) ? b() : b; 4855 ko.unwrap(b); 4856 $el.data('selectBox-selectBoxIt').refresh(); 4857 }); 4858 4859 }, null, {disposeWhenNodeIsRemoved: element}); 4860 4861 4862 $el.change(function(e) { 4863 if(!$(this).hasClass('hp-guests-select')) { 4864 return; 4865 } 4866
4867 existingValue = this.value; 4868 4869 var step1 = bindingContext.$parents[1]; 4870 var requestedRoom = bindingContext.$parent; 4871 4872 if(!requestedRoom.canAddGuest( step1.hotel().conditions.maxGuests + 1)){ 4873 $(this).val($.data(this, 'val')); //set back; 4874 return; 4875 } 4876 4877 }); 4878 4879 $el.on('change', function (e) { 4880 var value = allBindings.get('value'); 4881 value(parseInt($(this).val())); 4882 }); 4883 ko.utils.domNodeDisposal.addDisposeCallback(element, function (node) { 4884 $(node).data('selectBox-selectBoxIt').destroy(); 4885 }); 4886 }, 500); 4887 } 4888 4889}; 4890ko.bindingHandlers.slick = { 4891 init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4892 var $el = $(element); 4893 $(document).on('click', '.hp-slick-prev', function () { 4894 $el.slick('slickPrev'); 4895 }); 4896 4897 $(document).on('click', '.hp-slick-next', function () { 4898 if ($(this).data('validate')) { 4899 if (bindingContext.$root.vm.step3.validateCustomer() === false) { 4900 return false; 4901 } 4902 } 4903 $el.slick('slickNext'); 4904 }); 4905 4906 $el.on('beforeChange', function (event, slick, currentSlide, nextSlide) { 4907 $(document).find('.hp-checkout-nav span').removeClass('active'); 4908 $(document).find('.hp-checkout-nav span:eq(' + nextSlide + ')').addClass('active'); 4909 }); 4910 4911 if (bindingContext.$root.isMultiProperty){ 4912 var selectedStep2ViewModel = ko.utils.arrayFilter(bindingContext.$root.vm.step2.properties(), function(item){ 4913 return item.selectedRooms().length > 0 4914 }); 4915 if (selectedStep2ViewModel.length) { 4916 selectedStep2ViewModel[0].selectedRooms.subscribe(function (value) { 4917 $el.slick('slickGoTo', 0); 4918 }); 4919 } 4920 } else { 4921 bindingContext.$root.vm.step2.selectedRooms.subscribe(function (value) { 4922 $el.slick('slickGoTo', 0); 4923 }); 4924 } 4925 4926 window.setTimeout(function(){ 4927 $el.slick({ 4928 infinite: false, 4929 dots: true, 4930 arrows: false, 4931 speed: 277, 4932 swipe: false, 4933 slidesToShow: 1, 4934 draggable: false, 4935 fade: true, 4936 cssEase: 'linear' 4937 }); 4938 }, 50); 4939 } 4940}; 4941ko.bindingHandlers.src = { 4942 update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4943 ko.bindingHandlers.attr.update(element, function () { 4944 return {src: valueAccessor()} 4945 }); 4946 } 4947}; 4948ko.bindingHandlers.timeAgo = { 4949 toTimeAgo: function (dt) { 4950 var secs = (((new Date()).getTime() - dt.getTime()) / 1000), 4951 days = Math.floor(secs / 86400); 4952 4953 return days === 0 && ( 4954 secs < 60 && "just now" || 4955 secs < 120 && "a minute ago" || 4956 secs < 3600 && Math.floor(secs / 60) + " minutes ago" || 4957 secs < 7200 && "an hour ago" || 4958 secs < 86400 && Math.floor(secs / 3600) + " hours ago") || 4959 days === 1 && "yesterday" || 4960 days < 31 && days + " days ago" || 4961 days < 60 && "one month ago" || 4962 days < 365 && Math.ceil(days / 30) + " months ago" || 4963 days < 730 && "one year ago" || 4964 Math.ceil(days / 365) + " years ago"; 4965 }, 4966 update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4967 var val = ko.unwrap(valueAccessor()); 4968 var date = new Date(val); // WARNING: this is not compatibile with IE8 4969 var timeAgo = ko.bindingHandlers.timeAgo.toTimeAgo(date); 4970 4971 return ko.bindingHandlers.html.update(element, function () { 4972 return '<time datetime="' + encodeURIComponent(val) + '">' + timeAgo + '</time>'; 4973 }); 4974 } 4975}; 4976ko.bindingHandlers.toggleActive = { 4977 update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4978 var $el = $(element); 4979 4980 $el.on('click', function(e){ 4981 $el.attr('disabled', 'disabled'); 4982 4983 var data = ko.toJS(ko.unwrap(valueAccessor())); 4984 if (data === true) { 4985 $el.removeAttr('disabled'); 4986 } 4987 }); 4988 } 4989}; 4990ko.bindingHandlers.uppercase = { 4991 update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 4992 ko.bindingHandlers.text.update(element, function () { 4993 return valueAccessor().toLocaleUpperCase(); 4994 }); 4995 } 4996}; 4997function BookwizeLiquidAppViewModel(options) { 4998 var self = this; 4999 self.lang = ko.observable(); 5000 self.currency = ko.observable(); 5001 self.phoneCountryCode = ko.observable(); 5002 // the localstoreage cache key for storing Customer Selection 5003 self.customerPreferencesCacheKey = 'BookwizeLiquid_CustomerPreferences'; 5004
5005 // used for localstorage cache 5006 self.cachePrefix = ''; 5007 5008 // stores all hotel IDs/API Keys 5009 self.properties = IBE.Config.properties; 5010 5011 // keeps customer preferences and cached the in Cache engine 5012 self.session = ko.observable(false); 5013 5014 // each time a session variable changes, we update the session in cache 5015 self.session.subscribe(function (value) { 5016 var data = self.cache.read(self.customerPreferencesCacheKey); 5017 data = value; 5018 self.cache.write(self.customerPreferencesCacheKey, data); 5019 }); 5020// sort rooms based on availability / price 5021 self.sort = function (rooms) { 5022 var available = []; 5023 var onrequest = []; 5024 var other = []; 5025 5026 ko.utils.arrayForEach(rooms, function (item) { 5027 if (item.availability === IBE.Config.roomAvailability.Available) { 5028 available.push(item); 5029 } else if ((item.availability === IBE.Config.roomAvailability.UponRequest || item.availability === IBE.Config.roomAvailability.NoAvailability ) 5030 && item.minPrice() > 0) { 5031 onrequest.push(item); 5032 } else { 5033 other.push(item); 5034 } 5035 }); 5036 available.sort(firstBy(function (v1, v2) { 5037 return v1.minPrice() - v2.minPrice(); 5038 })).reverse().reverse(); 5039 5040 onrequest.sort(firstBy(function (v1, v2) { 5041 return v1.minPrice() - v2.minPrice() 5042 })).reverse().reverse(); 5043 5044 other.sort(firstBy(function (v1, v2) { 5045 return v2.minPrice() - v1.minPrice(); 5046 })); 5047 5048 return available.concat(onrequest).concat(other); 5049 }; 5050 5051 // used to render the HTML after VMs have data 5052 self.ready = ko.observable(false); 5053 self.ready.subscribe(function (value) { 5054 if (value) { 5055 $('.hp-legacy-booking-link--loading').removeClass('hp-legacy-booking-link--loading'); 5056 self.acceptedCookies(); 5057 } 5058 }, this); 5059 5060 self.acceptedCookies = function () { 5061 if (!window.OnetrustActiveGroups) { 5062 return; 5063 } 5064 if (window.OnetrustActiveGroups.includes('C0004')) { // targeting Cookies 5065 IBE.Config.userCookieAcceptance = true; 5066 } 5067 } 5068 5069 // used to disable the submit buttons of step1 5070 self.submitting = ko.observable(false); 5071 5072 // used in rooms internal page 5073 self.currentRoom = ko.observable(false); 5074 5075 // used in offers internal page 5076 self.currentOffer = ko.observable(false); 5077 5078 // used inside room page to show hotel's room's rateplans 5079 self.currentHotel = ko.observable({}); 5080 5081 // tha instance of Magnific popup 5082 self.popup = {}; 5083 5084 // set and check the step1 overlay hash 5085 self.overlayHash = null; 5086 5087 // stores IBE view model instances for single/multi properties 5088 self.vm = {}; 5089 5090 // true/false if website is multi-property 5091 self.isMultiProperty = IBE.Config.isMultiProperty; 5092 5093 if (self.isMultiProperty === true) { 5094 ko.utils.arrayForEach(self.properties, function (item) { 5095 self.cachePrefix += item.hotelId + '_'; 5096 }); 5097 } else { 5098 self.cachePrefix += IBE.Config.hotelId + '_'; 5099 } 5100 // the cache key used to save to local storage 5101 5102 // Overload IBE Cache 5103 if (typeof Cache !== 'undefined') { 5104 self.cache = Cache; 5105 self.cache.prefix += self.cachePrefix; 5106 } 5107 5108 // used in step1 hotel select box and step2 filtering hotel results 5109 self.selectedHotel = ko.observable(self.cache.read(self.customerPreferencesCacheKey + '_selectedHotel') || parseInt(window.location.hash.replace(/[^\d.]/g, ''))); 5110 self.selectedHotel.subscribe(function (value) { 5111 if (typeof value === 'undefined' || value === false) { 5112 return; 5113 } 5114 self.cache.write(self.customerPreferencesCacheKey + '_selectedHotel', value); 5115 }); 5116 var $sidebarHotel = $('.sidebar__hotel'); 5117 if ($sidebarHotel.length && $sidebarHotel.data('hotelId')) { 5118 self.selectedHotel($sidebarHotel.data('hotelId')); 5119 } 5120 // the current active booking step 5121 self.step = ko.observable(0); 5122 self.step.subscribe(function (value) { 5123 hp.addClass($('body'), 'hp-step-' + value); 5124 if( self.session() ) { 5125 $('body').addClass('hp-top-bar-enabled'); 5126 } 5127 5128 }); 5129 self.setStep = function (step, data) { 5130 self.step(step); 5131 switch (step) { 5132 case 1: 5133 try { 5134 if (self.isMultiProperty === true) { 5135 self.initMultipleStep('step1', data); 5136 } else { 5137 5138 self.vm.step1.ready.subscribe(function(value){ 5139 if( IBEConfig.post.post_type == "cpt_offer" && IBEConfig.offers.length > 0 ) { 5140 currentOfferId = IBEConfig.offers[0].bookwize_liquid_offer_id; 5141 //search all offers to find the one specified in current offer ( wp cpt_offer post ) 5142 ko.utils.arrayForEach(self.vm.step1.hotel().offers, function(offer, index){ 5143 if( currentOfferId == offer.id){ 5144 if( typeof offer.rules.checkInMin !== "undefined" ){ 5145 checkInMinMoment = moment(offer.rules.checkInMin); 5146 self.vm.step1.minCheckInDate(checkInMinMoment.toDate()); 5147 if( checkInMinMoment.diff(self.vm.step1.checkIn(), 'days') > 0 ){ 5148 self.vm.step1.checkIn(checkInMinMoment); 5149 } 5150 } 5151 5152 if( typeof offer.rules.checkInMax !== "undefined" ) 5153 self.vm.step1.maxCheckInDate(moment(offer.rules.checkInMax).toDate()); 5154 5155 if( typeof offer.rules.checkOutMax !== "undefined" ) 5156 self.vm.step1.maxCheckOutDate(moment(offer.rules.checkOutMax).toDate()); 5157 } 5158 }); 5159 } 5160 }); 5161 5162 self.vm.step1.init(data); 5163 5164 } 5165 } catch (e) { 5166 IBE.Utils.consoleLog(e); 5167 } 5168 break; 5169 case 2: 5170 try { 5171 if (self.isMultiProperty === true) { 5172 self.initMultipleStep('step2', data); 5173 } else { 5174 if (self.vm.step2) { 5175 self.vm.step2.init(data); 5176 } 5177 } 5178 } catch (e) { 5179 IBE.Utils.consoleLog(e); 5180 } 5181 break; 5182 case 3: 5183 try { 5184 var params = {}; 5185 if (self.isMultiProperty === true) { 5186 params = hp.getHotelCredentialsFromRoomId(data.bookingInfo.rooms[0].roomId(), self.properties); 5187 // we need to re instantiate the step3 VM because user may select room from different hotel 5188 self.ready(false); 5189 self.vm.step3 = new BookwizeLiquidStep3Vie
5189wModel(self); 5190 5191 } 5192 self.ready(false); 5193 BookwizeLiquid.vm.step3.dispose(); 5194 BookwizeLiquid.vm.step3 = undefined; 5195 self.vm.step3 = new BookwizeLiquidStep3ViewModel(self); 5196 self.vm.step3.init(data, params); 5197 5198 self.ready(true); 5199 } catch (e) { 5200 if (self.isMultiProperty === true) { 5201 5202 } else { 5203 self.vm.step2.message(e); 5204 } 5205 IBE.Utils.consoleLog(e); 5206 } 5207 break; 5208 case 4: 5209 //debugger; 5210 if (typeof data === 'undefined') { 5211 self.ready(true); 5212 break; 5213 } 5214 try { 5215 var params = {}; 5216 if (self.isMultiProperty === true) { 5217 params = hp.getHotelCredentialsFromRoomId(data.rooms[0].roomId(), self.properties); 5218 } 5219 params.trackAdwords = false; 5220 params.appendAdwordsImage = false; 5221 params.trackAdwordsAsync = true; 5222 params.trackEcommerceScripts = false; 5223 self.vm.step4.init(data, params); 5224 } catch (e) { 5225 self.vm.step3.message(e); 5226 IBE.Utils.consoleLog(e); 5227 } 5228 5229 break; 5230 case 'my-reservation': 5231 5232 try { 5233 var user = self.cache.read('ReservationUser'); 5234 if (user) { 5235 self.vm.myReservation.username(user.username); 5236 self.vm.myReservation.password(user.password); 5237 } 5238 self.vm.myReservation.init(data); 5239 } catch (e) { 5240 self.vm.myReservation.message(e); 5241 IBE.Utils.consoleLog(e); 5242 } 5243 5244 break; 5245 } 5246 }; 5247 5248 // Submit Functions for all view models 5249 self.submit = { 5250 step1: function (data) { 5251 // save to session the selected currency and language 5252 data.currency = self.currency; 5253 data.lang = self.lang; 5254 5255 self.cache.write(self.customerPreferencesCacheKey, data); 5256 self.session($.extend({ 5257 nights: moment(data.checkOut).diff(moment(data.checkIn), 'days'), 5258 totalGuests: self.calculateTotalGuests(data) 5259 }, ko.toJS(data))); 5260 self.setStep(2, data); 5261 }, 5262 step2: function (data) { 5263 self.setStep(3, data); 5264 }, 5265 step3: function (data) { 5266 self.setStep(4, data); 5267 } 5268 }; 5269 5270 // when .hp-checkout is opened this will be true 5271 // and self.redirectToCheckRates will do nothing 5272 self.checkoutProcessStart = false;
5273 5274 // When we click on top book now btn is set to TRUE in order to redirect after step1.submits AND step2.ready 5275 self.forceCheckRatesRedirect = false; 5276 5277 // used to toggle elements through data-toggle="{selector}" 5278 self.toggle = null; 5279 5280 // this function is called when we click on the top book now button 5281 self.setCheckRatesRedirect = function () { 5282 // if current page is NOT 5283 // 1. check rates 5284 // 2. room page 5285 // set the redirect flag to TRUE 5286 if (hp.isCheckRatesPage() === false 5287 && hp.isRoomPage(IBE.Config.post.ID) === false 5288 && hp.isOfferPage(IBE.Config.post.ID) === false) { 5289 self.forceCheckRatesRedirect = true; 5290 } 5291 5292 }; 5293 self.redirectToCheckRates = function (force, hash) { 5294 // if user has started the checkout process 5295 if (self.checkoutProcessStart === true) { 5296 return; 5297 } 5298 var checkRatesPage = self.getPostByBookwizeLiquidPageType('checkrates'); 5299 5300 // if there is not set a checkpage page 5301 if (checkRatesPage.hasOwnProperty('bookwize_liquid_page_url') === false) { 5302 console.log('Bookwize Liquid: Please create a check-rates page.') 5303 return false; 5304 } 5305 // if we ARE in check rates page DO NOTHING 5306 if (hp.isCheckRatesPage() && force !== true) { 5307 return true; 5308 } 5309 // if we ARE in a room page DO NOTHING 5310 if (hp.isRoomPage(IBE.Config.post.ID) && force !== true) { 5311 return true; 5312 } 5313 var url = checkRatesPage.bookwize_liquid_page_url; 5314 5315 5316 // eg. in header template we pass force=true 5317 if (force) { 5318 window.location.href = url; 5319 return true; 5320 } 5321 5322 // check the force redirect flag 5323 if (self.forceCheckRatesRedirect == true) { 5324 window.location.href = url; 5325 return true; 5326 } 5327 window.location.href = url; 5328 }; 5329 5330 self.calculateTotalGuests = function (data) { 5331 var total = 0; 5332 ko.utils.arrayForEach(data.rooms[0], function (guest) { 5333 if(!guest.pax){ 5334 guest.pax = 0; 5335 } 5336 total += guest.pax; 5337 }); 5338 return total; 5339 }; 5340 5341 // when we click on the cancel button 5342 self.clearPreferences = function () { 5343 hp.clearCache(); 5344 }; 5345 5346 // loop through all step2 requestedRooms and find associated room based on post Id 5347 self.setCurrentRoom = function () { 5348 var found = false; 5349 5350 if (self.isMultiProperty === false) { 5351 if (typeof self.vm.step2.request === 'undefined') { 5352 return false; 5353 } 5354 ko.utils.arrayForEach(self.vm.step2.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (room) { 5355 if (found) { 5356 return; 5357 } 5358 ko.utils.arrayForEach(IBE.Config.rooms, function (item) { 5359 if (found) { 5360 return; 5361 } 5362 if (room.roomId() == item.bookwize_liquid_room_id && IBE.C
5362onfig.post.ID == item.ID) { 5363 self.currentRoom(room); 5364 found = true; 5365 } 5366 }); 5367 }); 5368 5369 } else { 5370 ko.utils.arrayForEach(self.vm.step2.properties(), function (viewModel) { 5371 if (found) { 5372 return; 5373 } 5374 ko.utils.arrayForEach(viewModel.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (room) { 5375 if (found) { 5376 return; 5377 } 5378 if (typeof IBE.Config.hotels_rooms[viewModel.hotelId()].rooms !== 'undefined' 5379 && IBE.Config.hotels_rooms[viewModel.hotelId()].rooms != null) { 5380 ko.utils.arrayForEach(IBE.Config.hotels_rooms[viewModel.hotelId()].rooms, function (item) { 5381 if (found) { 5382 return; 5383 } 5384 if (room.roomId() == item.bookwize_liquid_room_id && IBE.C
5384onfig.post.ID == item.ID) { 5385 self.currentRoom(room); 5386 self.currentHotel = viewModel; 5387 found = true; 5388 } 5389 }); 5390 } 5391 }); 5392 }); 5393 5394 } 5395 if (!found) { 5396 return false; 5397 } 5398 }; 5399 5400 // loop through all step2 requestedRooms and find associated room based on post Id 5401 self.setCurrentOffer = function () { 5402 var found = false; 5403 ko.utils.arrayForEach(self.vm.step1.hotel().offers, function (offer) { 5404 if (found) { 5405 return; 5406 } 5407 ko.utils.arrayForEach(IBEConfig.offers, function (item) { 5408 if (found) { 5409 return; 5410 } 5411 if (offer.id == item.bookwize_liquid_offer_id && IBEConfig.post.ID == item.ID) { 5412 offer.rooms = []; 5413 self.currentOffer(offer); 5414 found = true; 5415 } 5416 }); 5417 }); 5418 if (!found) { 5419 return false; 5420 } 5421 5422 // offer found, search for rooms that it is applied 5423 ko.utils.arrayForEach(self.vm.step2.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (room) { 5424 if (self.currentOffer().rules.rooms.indexOf(room.roomId()) > -1) { 5425 ko.utils.arrayForEach(room.rateplans(), function(a) { 5426 if(self.currentOffer().id === a.ratePlanId()){ 5427 self.currentOffer().rooms.push(room); 5428 } 5429 5430 }); 5431 5432 } 5433 }); 5434 }; 5435 5436 // used to toggle the popup preferences or redirect to check rates page 5437 self.bookButtons = function (selector) { 5438 if (typeof selector === 'undefined') { 5439 selector = '.btn--check-rates'; 5440 } 5441 var $buttons = $(selector); 5442 if ($buttons.length === 0) { 5443 return; 5444 } 5445 5446 $buttons.removeAttr('target'); 5447 $buttons.on('click', function (e) { 5448 e.preventDefault(); 5449 5450 if (self.session() !== false) { 5451 self.redirectToCheckRates(false, $(this).data('roomType')); 5452 } else { 5453 self.toggle.toggleOverlays($('[data-hp-toggle=".hp-step1"]'), e); 5454 } 5455 return false; 5456 }); 5457 }; 5458 // General HTML / CSS / JS events 5459 self.design = function () { 5460 5461 self.popup = $.magnificPopup.instance; 5462 5463 // used to set / check the overlay hash; 5464 self.overlayHash = hp.setOverlayHash(); 5465 5466 // because step2 might be multi/single property 5467 // we need to bind here the overlayOpened/Closed event 5468 $(document).on('hp/overlayOpened', function (e, data) { 5469 if ($(e.target).is('.hp-checkout')) { 5470 if (window.location.hash.length) { 5471 window.location.hash = ''; 5472 } 5473 self.checkoutProcessStart = true; 5474 hp.scrollTo({duration: 333}); 5475 } 5476 }); 5477 $(document).on('hp/overlayClosed', function (e, data) { 5478 if ($(e.target).is('.hp-checkout')) { 5479 self.checkoutProcessStart = false;
5480 self.step(2); 5481 } 5482 }); 5483 5484 $(document).on('ready',function() { 5485 if (hp.isCheckRatesPage() ) { 5486 setTimeout(function(){ 5487 self.vm.step2.showTriptease(); 5488 }, 2000); 5489 } 5490 }); 5491 5492 // bind ESC key to close open overlays 5493 hp.escapeKeyUp(); 5494 5495 // for currencies dropdown 5496 hp.dropdown(); 5497 5498 // used to toggle elements through data-toggle="{selector}" 5499 self.toggle = hp.toggle(); 5500 5501 self.overlayHash.init(); 5502 5503 self.bookButtons(); 5504 5505 // when overlay opened and click on transparent div, close all overlays 5506 $(document).on('click', '.hp-backdrop', function (e) { 5507 hp.closeOverlays(); 5508 }); 5509 }; 5510 5511 self.createDeepLink = function (roomId, hotelId) { 5512 var room_url = self.getRoomByBookwizeLiquidRoomId(roomId, hotelId).bookwize_liquid_room_url; 5513 5514 if (typeof room_url === 'undefined') { 5515 return '#'; 5516 } 5517 if (IBE.Config.isUnderSameDomain === true) { 5518 return room_url; 5519 } else { 5520 return room_url + '?' + hp.deepLink(self.session()); 5521 } 5522 }; 5523 5524 self.createIntegratedDeepLinking = function (hotelId) { 5525 var url = self.getPostByBookwizeLiquidPageType('integrated').bookwize_liquid_page_url; 5526 if (self.session() === false) { 5527 return url + '?hotel_id=' + hotelId; 5528 } 5529 var session = ko.toJS(self.session()); 5530 session.rooms.push(session.rooms[0]); 5531 var query = $.param( 5532 $.extend({hotel_id: hotelId}, hp.deepLink(session, 'object')) 5533 ); 5534 return url + '?' + decodeURIComponent(query); 5535 }; 5536 5537 self.getRoomByBookwizeLiquidRoomId = function (roomId, hotelId) { 5538 var rooms = []; 5539 5540 if (self.isMultiProperty === true && typeof hotelId !== 'undefined') { 5541 if (typeof IBE.Config.hotels_rooms[hotelId] !== 'undefined' && IBE.Config.hotels_rooms[hotelId] !== null) { 5542 rooms = (typeof IBE.Config.hotels_rooms[hotelId].rooms !== 'undefined') ? IBE.Config.hotels_rooms[hotelId].rooms : []; 5543 } 5544 } else { 5545 rooms = IBE.Config.rooms; 5546 } 5547 5548 var room = ko.utils.arrayFirst(rooms, function (item) { 5549 return item.bookwize_liquid_room_id == roomId; 5550 }) || {}; 5551 5552 if (room.bookwize_liquid_room_image === '' && self.isMultiProperty) { 5553 ko.utils.arrayForEach(self.vm.step1.step1ViewModels, function (viewModel) { 5554 ko.utils.arrayForEach(viewModel.rooms(), function (hpRoom) { 5555 if (hpRoom.id === roomId) { 5556 room.bookwize_liquid_room_image = hpRoom.photos[0].url(); 5557 } 5558 }); 5559 }); 5560 } 5561 5562 return room; 5563 }; 5564 self.getRoomByPostId = function (id) { 5565 if (self.isMultiProperty === false) { 5566 return ko.utils.arrayFirst(IBE.Config.rooms, function (item) { 5567 return item.ID == id; 5568 }) || {}; 5569 } 5570 // multi-property 5571 for (var prop in IBE.Config.hotels_rooms) { 5572 var room = ko.utils.arrayFirst(IBE.Config.hotels_rooms[prop].rooms, function (item) { 5573 return item.ID == id; 5574 }) || {}; 5575 if (room.ID) { 5576 return room; 5577 } 5578 } 5579 return room; 5580 }; 5581 5582 self.getOfferByBookwizeLiquidOfferId = function (id) { 5583 return ko.utils.arrayFirst(IBE.Config.offers, function (item) { 5584 return item.bookwize_liquid_offer_id == id; 5585 }) || {}; 5586 }; 5587 self.getOfferByPostId = function (id) { 5588 return ko.utils.arrayFirst(IBE.Config.offers, function (item) { 5589 return item.ID == id; 5590 }) || {}; 5591 }; 5592 5593 self.getPostByBookwizeLiquidPageType = function (type) { 5594 return ko.utils.arrayFirst(IBE.Config.pages, function (item) { 5595 return item.bookwize_liquid_page_type == type; 5596 }) || {}; 5597 }; 5598 5599 self.getHotelId = function () { 5600 var $sidebarHotel = $('.sidebar__hotel'); 5601 if ($sidebarHotel.length && $sidebarHotel.data('hotelId')) { 5602 return $sidebarHotel.data('hotelId'); 5603 } 5604 return false;
5605 }; 5606 5607 self.getBookwizeLiquidRoomData = function (roomId) { 5608 var room = { 5609 maxGuests: 0 5610 }; 5611 if (self.isMultiProperty && self.properties.length) { 5612 ko.utils.arrayForEach(self.vm.step1.step1ViewModels, function (viewModel) { 5613 ko.utils.arrayForEach(viewModel.rooms(), function (hpRoom) { 5614 if (hpRoom.id === roomId) { 5615 room = hpRoom; 5616 } 5617 }); 5618 }); 5619 } else { 5620 ko.utils.arrayForEach(self.vm.step1.rooms(), function (hpRoom) { 5621 if (hpRoom.id === roomId) { 5622 room = hpRoom; 5623 } 5624 }); 5625 } 5626 5627 return room; 5628 }; 5629 5630 self.promises = { 5631 step1: [], 5632 step2: [] 5633 }; 5634 self.initMultipleStep = function (step, data) { 5635 if (typeof step === 'undefined') { 5636 step = 'step1'; 5637 } 5638 if (self.promises[step].length) { 5639 return false; 5640 } 5641 5642 ko.utils.arrayForEach(self.properties, function (item) { 5643 for (var prop in item.vm) { 5644 if (prop === step) { 5645 // store initmulti promise method of Step[ X ]ViewModel 5646 self.promises[step].push(item.vm[prop].initmulti(data, item)); 5647 } 5648 } 5649 }); 5650 5651 // when all promises are completely initialize VMs 5652 $.when.apply($, self.promises[step]).then(function () { 5653 if (arguments.length !== self.promises[step].length) { 5654 return false; 5655 } 5656 try { 5657 // self.ready(false); 5658 switch (step) { 5659 case 'step1': 5660 self.vm[step] = new BookwizeLiquidMultipleStep1ViewModel(self, arguments); 5661 break; 5662 case 'step2': 5663 if (hp.isCheckRatesPage() || hp.isOfferPage() || hp.isRoomPage()) { 5664 self.ready(false); 5665 } 5666 5667 self.vm[step] = new BookwizeLiquidMultipleStep2ViewModel(self, arguments); 5668 if (self.forceCheckRatesRedirect === true) { 5669 return self.redirectToCheckRates(); 5670 } 5671 break; 5672 } 5673 5674 if (self.vm.step1 && self.vm.step2 && self.vm.step1.ready() && self.vm.step2.ready()) { 5675 // user has submitted step1 and step2 is initialized 5676 5677 self.promises.step1 = []; 5678 self.promises.step2 = []; 5679 5680 // if we are in a room page- 5681 self.setCurrentRoom(); 5682 5683 // if we are in a offer page 5684 self.setCurrentOffer(); 5685 5686 self.ready(true); 5687 } else if (self.session() === false && self.vm.step1.ready()) { 5688 // user's first time :P 5689 self.promises[step] = []; 5690 5691 self.ready(true); 5692 } 5693 } catch (e) { 5694 IBE.Utils.consoleLog(e); 5695 } 5696 }); 5697 }; 5698 5699 self.init = function (options) { 5700 var $hotelProxyApp = $('[data-bookwize-liquid-app]'); 5701 if ($hotelProxyApp.length == 0) { 5702 return; 5703 } 5704 5705 try { 5706 5707 if (self.isMultiProperty && self.properties.length) { 5708 ko.utils.arrayForEach(self.properties, function (item, index) { 5709 item.vm = {}; 5710 item.vm['step1'] = new BookwizeLiquidStep1ViewModel(self, item); 5711 item.vm['step2'] = new BookwizeLiquidStep2ViewModel(self, item); 5712 }); 5713 // assign bindings fro step1 because all other VM use them 5714 self.currency = self.properties[0].vm.step1.currency; 5715 self.lang = self.properties[0].vm.step1.lang; 5716 } else { 5717 self.vm['step1'] = new BookwizeLiquidStep1ViewModel(self); 5718 if (self.vm['step1'].requestedRooms()[0]) { 5719 ko.utils.arrayForEach(self.vm['step1'].requestedRooms()[0].guests, function (item) { 5720 if (item.ageCategory() != IBE.Config.guestType.Adult) { 5721 item.childrenAges = ko.observableArray([]); 5722 // set the childrenAges and selected 5723 } 5724 }); 5725 5726 self.guests = self.vm['step1'].requestedRooms()[0].guests; 5727 } 5728 // assign bindings fro step1 because all other VM use them 5729 self.currency = self.vm.step1.currency; 5730 self.lang = self.vm.step1.lang; 5731 self.vm['step2'] = new BookwizeLiquidStep2ViewModel(self); 5732 } 5733
5734 self.vm['step3'] = new BookwizeLiquidStep3ViewModel(self); 5735 self.vm['step4'] = new BookwizeLiquidStep4ViewModel(self); 5736 self.vm['myReservation'] = new BookwizeLiquidMyReservationViewModel(self); 5737 5738 // if we need to bind to self.lang, or self.currency changes 5739 // here we should add the subscribers 5740 5741 self.lang($('html').attr('lang'));//.substring(0, 2)); 5742 5743 // apply bindings to <html> 5744 ko.applyBindings(self, $hotelProxyApp[0]); 5745 self.setStep(1); 5746 5747 } catch (e) { 5748 IBE.Utils.consoleLog(e); 5749 } 5750 5751 // if we completed a request/reservation 5752 var confirmedPage = self.getPostByBookwizeLiquidPageType('confirmed'); 5753 if (confirmedPage.ID === IBE.Config.post.ID) { 5754 5755 // ready reservation user from cache 5756 var user = self.cache.read('ReservationUser'); 5757 var flagTracking = self.cache.read('flagTracking'); 5758 if (user !== false) { 5759 self.cache.write('flagTracking', true); 5760 self.vm.step4.init(user, { 5761 reservationSubmitted: true, 5762 trackEcommerceScripts: !flagTracking 5763 }); 5764 } 5765 } 5766 5767 // if we are in my reservation page 5768 var myreservationPage = self.getPostByBookwizeLiquidPageType('myreservation'); 5769 if (myreservationPage.ID === IBE.Config.post.ID) { 5770 // ready reservation user from cache 5771 self.setStep('my-reservation'); 5772 } 5773 5774 // finally apply all HTML/JS functions 5775 self.design(); 5776 }; 5777} 5778function BookwizeLiquidMyReservationViewModel(parent) { 5779 var self = new IBE.ViewModels.MyReservation(); 5780 5781 self.lang = parent.lang; 5782 self.currency = parent.currency; 5783 self.statusUpdate = ko.observable(false); 5784 5785 function _setSuccessMessage() { 5786 hp.scrollTo({ 5787 offset: 0 5788 }); 5789 self.message({ 5790 id: 200, 5791 severity: 'success', 5792 text: IBE.Utils.translate('updateReservationSuccess') 5793 }); 5794 } 5795 5796 self.beforeLogin = function ($data, e) { 5797 // in order not to click multiple times the SUBMIT button 5798 hp.disable($(e.currentTarget)); 5799 5800 self.login(); 5801 }; 5802 5803 self.beforeConfirmAction = function ($data, viewModel, e) { 5804 if (typeof e === 'undefined') { 5805 e = viewModel; 5806 } 5807 // in order not to click multiple times the SUBMIT button 5808 hp.disable($(e.currentTarget)); 5809 5810 self.confirmAction($data, e); 5811 }; 5812 5813 self.events.subscribe(function (status) { 5814 5815 self.ready(status); 5816 5817 }, this, 'ready'); 5818 5819 self.events.subscribe(function (data) { 5820 parent.cache.clear('ReservationUser'); 5821 parent.cache.clear('flagTracking'); 5822 self.errors.showAllMessages(false); // FORCE NEW validation 5823 self.ready(true); 5824 }, this, 'logout'); 5825 5826 self.events.subscribe(function (data) { 5827 5828 // save reservation user to automatically login in my reservation page 5829 parent.cache.write('ReservationUser', { 5830 username: data.email, 5831 password: data.code 5832 }); 5833 5834 }, this, 'login'); 5835 5836 self.events.subscribe(function (error) { 5837 self.ready(true); 5838 5839 self.message(error); 5840 5841 // enable all available buttons in My Reservation section 5842 hp.enable($(document).find('.hp-my-reservation .hp-btn')); 5843 5844 }, this, 'error'); 5845 5846 // when updating the reservation 5847 // the below events will trigger based on the 5848 // update action 5849 5850 self.events.subscribe(function (data) { 5851 if (data === true) { 5852 self.statusUpdate(data); 5853 _setSuccessMessage(); 5854 } 5855 }, this, 'CancelledReservation'); 5856 5857 self.events.subscribe(function (data) { 5858 if (data === true) { 5859 self.statusUpdate(data); 5860 _setSuccessMessage(); 5861 } 5862 }, this, 'CancelledRequest'); 5863 5864 self.events.subscribe(function (data) { 5865 if (data === true) { 5866 self.statusUpdate(data); 5867 _setSuccessMessage(); 5868 } 5869 }, this, 'ConfirmedReservation'); 5870 5871 return self; 5872} 5873function BookwizeLiquidStep1ViewModel(parent, params) { 5874 5875 // this is used to set the IBE.Config credentials 5876 // for current hotel 5877 hp.setHotelApiConfig(params); 5878 5879 var self = new IBE.ViewModels.Step1ViewModel(); 5880 5881 self.params = params; 5882 5883 self.dfd = {}; 5884 5885 self.guests = []; 5886 5887 self.maxCheckInDate = ko.observable(); 5888 self.maxCheckOutDate = ko.observable(); 5889 5890 self.events.subscribe(function (value) { 5891 if (value === false) { 5892 return; 5893 } 5894 5895 self.design(); 5896 5897 parent.submitting(false); 5898 5899 if (parent.isMultiProperty) { 5900 self.dfd.resolve({ 5901 viewModel: self, 5902 ready: value 5903 }); 5904 } else { 5905 5906 // Check if user has already set the preferences 5907 if(self.requestedRooms()[0] !== 'undefined') { 5908 self.guests = self.requestedRooms()[0].guests; 5909 } 5910 ko.utils.arrayForEach(self.guests, function (item) { 5911 if (item.ageCategory() != IBE.Config.guestType.Adult) { 5912 item.childrenAges = ko.observableArray([]); 5913 // set the childrenAges and selected 5914 } 5915 }); 5916 _parseSession();
5917 $(document).on('hp/overlayOpened', function (e) { 5918 hp.setOverlayDefaults(self, parent.session()); 5919 var $el = $(e.target); 5920 // add hash and on load trigger it 5921 if ($el.is('.hp-guests-overlay') === false) { 5922 // parent.overlayHash.setHash(); 5923 } else { 5924 $(document).on('click', function (e) { 5925 if($(e.target).parents('.hp-toggle').length !== 0){ 5926 $('.hp-guests-overlay').addClass('hp-toggle--open').fadeIn(100); 5927 } 5928 else if (!$(e.target).is('.hp-toggle') && $(e.target).parents('.hp-guests-overlay').length === 0) { 5929 5930 $el.removeClass('hp-toggle--open'); 5931 $el.stop(true, true).fadeOut(100); 5932 } 5933 5934 }); 5935 } 5936 }); 5937 5938 // set app view model ready 5939 parent.ready(value); 5940 } 5941 5942 //_parseSession(); 5943 }, this, 'ready'); 5944 self.events.subscribe(function (error) { 5945 5946 if (error.severity == 'Forbidden') { 5947 self.ready(false); 5948 } 5949 IBE.Utils.logEvent(error); 5950 }, this, 'error'); 5951 5952 self.events.subscribe(function (result) { 5953 5954 if (result.success) { 5955 parent.setCheckRatesRedirect(); 5956 // when binding the html to vm the popup template data was changed 5957 // this was trigger the afterRender callback 5958 if (parent.isMultiProperty) { 5959 ko.utils.arrayForEach(parent.properties, function (item) { 5960 if (typeof item.vm.step2.popup() !== 'undefined') { 5961 item.vm.step2.popup().data(false); 5962 } 5963 }); 5964 } else if (typeof parent.vm.step2.popup() !== 'undefined') { 5965 parent.vm.step2.popup().data(false); 5966 } 5967 5968 parent.submit.step1(result.success); 5969 } 5970 if (result.failure) { 5971 self.message(result.failure); 5972 parent.submitting(false); 5973 } 5974 }, this, 'submit'); 5975 5976 self.lang.subscribe(function (value) { 5977 if (typeof value === 'undefined' || value === false) {//} || parent.session() === false) { 5978 return;// false; 5979 } 5980 parent.lang(value); 5981 }); 5982 5983 self.currency.subscribe(function (value) { 5984 if (typeof value === 'undefined' || value === false || parent.session() === false) { 5985 return;// false; 5986 } 5987 parent.session().currency = value; 5988 parent.session.valueHasMutated(); 5989 }); 5990 5991 self.showRoomBoardRateWithSurcharge = function (t, i, r) { 5992 if (!r) return false; 5993 return t + self.surchargeTotalCost(i, r); 5994 }; 5995 5996 self.showRoomBoardRateDailyBreakdownWithSurcharge = function (t, i, r) { 5997 if (!r) return false; 5998 return self.request().nights() > 0 ? t + self.surchargeTotalCost(i, r) / self.request().nights() : t; 5999 }; 6000 6001 function _parseSession() { 6002 var result = parent.cache.read(parent.customerPreferencesCacheKey); 6003 var todaysDate = new Date(); 6004 if (result === false) { 6005 if(IBEConfig.post_offer_checkin !== '') { 6006 var checkInOffer = new Date(IBEConfig.post_offer_checkin); 6007 6008 if(todaysDate <= checkInOffer ) { 6009 self.checkIn(checkInOffer); 6010 } 6011 } 6012 if(IBEConfig.post_offer_checkout !== '') { 6013 var checkOutOffer = new Date(IBEConfig.post_offer_checkout); 6014 if(todaysDate <= checkOutOffer || ( checkInOffer !== undefined && checkInOffer <= checkOutOffer)) { 6015 self.checkOut(checkOutOffer); 6016 } 6017 } 6018 return false; 6019 } 6020 6021 parent.session(ko.toJS(result)); 6022 6023 self.currency(parent.session().currency); 6024 self.checkIn(new Date(parent.session().checkIn)); 6025 self.checkOut(new Date(parent.session().checkOut)); 6026 self.couponCode(parent.session().couponCode); 6027 6028 // assign rooms based on session 6029 try { 6030 ko.utils.arrayForEach(self.requestedRooms()[0].guests, function (selfGuestType, idx) { 6031 var guestType = selfGuestType; 6032 ko.utils.arrayForEach(parent.session().rooms[0], function (sessionGuestType) { 6033 if (guestType.ageCategory() == sessionGuestType.ageCategory && guestType.fromAge() == sessionGuestType.fromAge) { 6034 self.requestedRooms()[0].guests[idx].pax(sessionGuestType.pax); 6035 } 6036 }); 6037 }); 6038 6039 ko.utils.arrayForEach(self.guests, function (guest) { 6040 var session_guest = ko.utils.arrayFilter(parent.session().rooms[0], function (item) { 6041 return item.ageCategory === guest.ageCategory() && item.fromAge === guest.fromAge() 6042 }); 6043 if (session_guest.length) { 6044 guest.pax(session_guest[0].pax); 6045 if (session_guest[0].ages.length) { 6046 var options = []; 6047 for (var i = guest.fromAge(); i <= guest.toAge(); i++) { 6048 options.push(i); 6049 } 6050 for (var j = 0; j < session_guest[0].ages.length; j++) { 6051 guest.childrenAges.push({ 6052 selected: ko.observable(session_guest[0].ages[j]), 6053 options: options 6054 }); 6055 } 6056 } 6057 } 6058 }); 6059 parent.submit.step1(parent.session()); 6060 } catch (e) { 6061 IBE.Utils.consoleLog(e); 6062 } 6063 } 6064 6065 self.design = function () { 6066 $(document).on('click', '.hp-close--checkout', function (e) { 6067 hp.closeOverlays(); 6068 }); 6069 $(document).on('click', '.hp-close', function (e) { 6070 hp.closeOverlays(); 6071 6072 }); 6073 }; 6074 6075 self.beforeSubmit = function ($data, e) { 6076 parent.submitting(true); 6077 $('.hp-wait.loader').show(); 6078 self.validate(); 6079 }; 6080 6081 self.initmulti = function (data, params) { 6082 self.dfd = $.Deferred(); 6083 6084 hp.setHotelApiConfig(params); 6085 self.init(params); 6086 6087 return self.dfd.promise(); 6088 }; 6089 6090 self.addGuest = function (parent, data) { 6091 if (data.pax() > data.options().length - 1) { 6092 return false;
6093 } 6094 if (self.hotel()) { 6095 if (data.ageCategory() !== IBE.Config.guestType.Infant) { 6096 if (!parent.canAddGuest(self.hotel().conditions.maxGuests)) { 6097 return false; 6098 } 6099 } 6100 6101 6102 data.pax(data.pax() + 1); 6103 } 6104 }; 6105 6106 self.removeGuest = function (data) { 6107 if (data.pax() === 0) { 6108 return false; 6109 } 6110 if (data.pax() === 1 && data.ageCategory() === 'Adult') { 6111 return false; 6112 } 6113 data.pax(data.pax() - 1); 6114 }; 6115 6116 return self; 6117} 6118function BookwizeLiquidStep2ViewModel(parent, params) { 6119 6120 hp.setHotelApiConfig(params); 6121 6122 var self = new IBE.ViewModels.Step2ViewModel(); 6123 6124 self.params = params; 6125 6126 self.dfd = {}; 6127 self.soldPopup = function (data) { 6128 parent.popup.open({ 6129 items: { 6130 src: '#hp-popup-sold' + self.hotelId() 6131 }, 6132 type: 'inline' 6133 }, 0); 6134 }; 6135 self.lang = parent.lang; 6136 self.currency = parent.currency; 6137 self.group = function () { 6138 var groupedRooms = []; 6139 for (var prop in IBE.Config.room_types) { 6140 if (IBE.Config.room_types.hasOwnProperty(prop)) { 6141 var rooms = ko.utils.arrayFilter(IBE.Config.rooms, function (post) { 6142 return post.bookwize_liquid_room_type === prop; 6143 }); 6144 ko.utils.arrayForEach(rooms, function (room, index) { 6145 var found = ko.utils.arrayFilter(self.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (item) { 6146 return item.roomId() === room.bookwize_liquid_room_id; 6147 }); 6148 if (found.length) { 6149 rooms[index] = found[0]; 6150 } 6151 }); 6152 6153 groupedRooms.push({ 6154 group: prop, 6155 type: IBE.Config.room_types[prop], 6156 rooms: parent.sort(rooms) 6157 }); 6158 } 6159 } 6160 return groupedRooms; 6161 }; 6162 self.design = function () { 6163 hp.closeOverlays(); 6164 6165 $(document).on('click', '#hp-popup-rateplan .hp-btn', function () { 6166 parent.popup.close(); 6167 }); 6168 6169 }; 6170 6171 // self.sortRooms = function () { 6172 // if (typeof self.request() === 'undefined') { 6173 // return false; 6174 // } 6175 // var rooms = self.request().hotelResults()[0].requestedRooms()[0].roomResults(); 6176 6177 // rooms.sort( 6178 // firstBy(function (v) { 6179 // if (typeof v.availability === 'undefined' || v.minPrice() === null) { 6180 // return 1; 6181 // } 6182 // return v.minPrice() > 0 && (v.availability === IBE.Config.roomAvailability.Available) ? -1 : 1; 6183 // }).thenBy(function (v1, v2) { 6184 // if (v1.minPrice() === null || v2.minPrice() === null) { 6185 // return 1; 6186 // } 6187 // return v1.minPrice() < v2.minPrice() ? -1 : 1; 6188 // }).thenBy(function (v) { 6189 // if (typeof v.availability === 'undefined') { 6190 // return 1; 6191 // } 6192 // return v.availability === IBE.Config.roomAvailability.Available ? -1 : 1; 6193 // }) 6194 // ); 6195 // }; 6196 6197 self.isRoomRatesVisible = function (roomResult) { 6198 for(var i=0; i < roomResult.rateplans().length; i++) { 6199 var rateplan = roomResult.rateplans()[i]; 6200 if(rateplan.isVisible() && rateplan.price() !== 0) { 6201 return true; 6202 } 6203 } 6204 return false; 6205 }; 6206 6207 self.sortRooms = function () { 6208 if (typeof self.request() === 'undefined') { 6209 return false; 6210 } 6211 var rooms = self.request().hotelResults()[0].requestedRooms()[0].roomResults(); 6212 rooms.sort(function (v1, v2) { 6213 if (typeof v1.availability === 'undefined' || typeof v2.availability === 'undefined' 6214 || v1.availability === null || v2.availability === null) { 6215 return 0; 6216 } 6217 6218 var toSortPriority = function (availability) { 6219 if (availability === IBE.Config.roomAvailability.Available || availability === 1) { 6220 return 3; 6221 } 6222 if (availability === IBE.Config.roomAvailability.AvailabilityRestriction || availability === -3) { 6223 return 2; 6224 } 6225 if (availability === IBE.Config.roomAvailability.CannotHost || availability === -4) { 6226 return 1; 6227 } 6228 if (availability === IBE.Config.roomAvailability.NoAvailability || availability === 0) { 6229 return 0; 6230 } 6231 return -10 + availability; 6232 }; 6233 6234 var s1 = toSortPriority(v1.availability); 6235 var s2 = toSortPriority(v2.availability); 6236 6237 if (s1 !== s2) { 6238 return s2 >
6238 s1 ? 1 : -1; 6239 } 6240 6241 var roomRatesVisible1 = self.isRoomRatesVisible(v1); 6242 var roomRatesVisible2 = self.isRoomRatesVisible(v2); 6243 if (roomRatesVisible1 && !roomRatesVisible2) { return -1; } 6244 if (!roomRatesVisible1 && roomRatesVisible2) { return 1; } 6245 6246 var p1 = v1.price(); 6247 var p2 = v2.price(); 6248 if (p1 !== null && p2 !== null) { 6249 return p1 < p2 ? -1 : 1; 6250 } 6251 6252 return 0; 6253 }); 6254 6255 self.request().hotelResults()[0].requestedRooms()[0].roomResults.valueHasMutated(); 6256 6257 self.sortRatePlans(); 6258 }; 6259 6260 self.sortRatePlans = function () { 6261 if (typeof self.request() === 'undefined') { 6262 return false; 6263 } 6264 var rooms = self.request().hotelResults()[0].requestedRooms()[0].roomResults(); 6265 for(var i=0; i < rooms.length; i++) { 6266 // console.log("step2 sortRatePlans "+rooms[i].info().name); 6267 rooms[i].rateplans().sort( 6268 function (v1, v2) { 6269 // debugger; 6270 if ( v1.roomBoards().length == 0 || v2.roomBoards().length == 0) { 6271 return 0; 6272 } 6273 6274 var v1MinRoomBoard = null; 6275 for(var i = 0; i < v1.roomBoards().length; i++) { 6276 var v1RoomBoardTmp = v1.roomBoards()[i]; 6277 if(!v1RoomBoardTmp.showPrices() || v1RoomBoardTmp.price() === null) { 6278 continue; 6279 } 6280 if(v1MinRoomBoard == null || v1RoomBoardTmp.price() < v1MinRoomBoard.price()) { 6281 v1MinRoomBoard = v1RoomBoardTmp; 6282 } 6283 } 6284 var v2MinRoomBoard = null; 6285 for(var i = 0; i < v2.roomBoards().length; i++) { 6286 var v2RoomBoardTmp = v2.roomBoards()[i]; 6287 if(!v2RoomBoardTmp.showPrices() || v2RoomBoardTmp.price() === null) { 6288 continue; 6289 } 6290 if(v2MinRoomBoard == null || v2RoomBoardTmp.price() < v2MinRoomBoard.price()) { 6291 v2MinRoomBoard = v2RoomBoardTmp; 6292 } 6293 } 6294 6295 if(v1MinRoomBoard === null || v2MinRoomBoard === null || v1MinRoomBoard.price() === v2MinRoomBoard.price()) { 6296 return -1; 6297 } 6298 var v1MinPrice = self.showRoomBoardRateWithSurcharge(v1MinRoomBoard.price(), v1.ratePlanId(), rooms[i].roomIndex()); 6299 var v2MinPrice = self.showRoomBoardRateWithSurcharge(v2MinRoomBoard.price(), v2.ratePlanId(), rooms[i].roomIndex()); 6300 6301 return v1MinPrice < v2MinPrice ? -1 : 1; 6302 } 6303 ); 6304 } 6305 }; 6306 6307 self.showPopup = function (room, activeMenu, otherData) { 6308 if(activeMenu === 'rateplan' && otherData instanceof IBE.Models.RoomBoard) { 6309 self.selectedRoomBoardForPopup = otherData.boardType(); 6310 self.selectedRatePlanForPopup = otherData.ratePlanId; 6311 } 6312 if (room instanceof BookwizeLiquidMultipleStep2ViewModel && typeof otherData !== 'undefined' && otherData.room) { 6313 room = otherData.room; 6314 } 6315 if (activeMenu !== 'callus') { 6316 self.popup().toggle(room); 6317 } 6318 self.popup().activeMenu(activeMenu); 6319 6320 6321 parent.popup.open({ 6322 items: { 6323 src: '#hp-popup' + self.hotelId() 6324 }, 6325 type: 'inline', 6326 callbacks: { 6327 open: function () { 6328 $('#hp-popup' + self.hotelId()).addClass('hp-popup--' + self.popup().activeMenu()); 6329 }, 6330 close: function () { 6331 $('#hp-popup' + self.hotelId()).removeClass('hp-popup--' + self.popup().activeMenu()); 6332 } 6333 } 6334 }, 0); 6335 }; 6336 6337 self.showCrossSales = function (roomId) { 6338 var room = ko.utils.arrayFilter(self.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (room) { 6339 return room.roomId() == roomId; 6340 }); 6341 if (room.length > 0) { 6342 return (room[0].availability == IBE.Config.roomAvailability['Available']); 6343 } 6344 return false;
6345 }; 6346 self.offerExist = function (offer) { 6347 var found = false; 6348 ko.utils.arrayFilter(self.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (room) { 6349 if (room.ratePlanId() == offer) { 6350 found = true; 6351 } 6352 }); 6353 return found; 6354 }; 6355 self.ready.subscribe(function (value) { 6356 if (value === false) { 6357 return; 6358 } 6359 // sort rooms based on availability, booking status 6360 //self.sortRooms(); 6361 self.sortRatePlans(); 6362 if (parent.isMultiProperty === false) { 6363 if(typeof self.bookingProcess() !== 'undefined') { 6364 self.bookingProcess().boardType = parent.vm.step1.boardType; 6365 self.bookingProcess().totalGuests = parent.vm.step1.totalGuests; 6366 var groupedRooms = self.group(); 6367 self.request().hotelResults()[0].requestedRooms()[0].groupedRooms = ko.observableArray(groupedRooms); 6368 } 6369 6370 } else { 6371 6372 var currentStep2ViewModel = ko.utils.arrayFilter(parent.properties, function (item) { 6373 return self.hotelId() == item.hotelId; 6374 }); 6375 if (currentStep2ViewModel.length && typeof self.bookingProcess() !== 'undefined') { 6376 self.bookingProcess().boardType = currentStep2ViewModel[0].vm.step1.boardType; 6377 self.bookingProcess().totalGuests = currentStep2ViewModel[0].vm.step1.totalGuests; 6378 } 6379 } 6380 6381 if (parent.forceCheckRatesRedirect === true && parent.isMultiProperty === false) { 6382 return parent.redirectToCheckRates(); 6383 } 6384 6385 self.removeLastRoom(); 6386 6387 parent.submitting(false); 6388 6389 if (parent.isMultiProperty === true) { 6390 self.dfd.resolve({ 6391 viewModel: self, 6392 ready: value 6393 }); 6394 } else { 6395 // if we are in a room page- 6396 parent.setCurrentRoom(); 6397 6398 // if we are in a offer page 6399 parent.setCurrentOffer(); 6400 6401 // set app view model ready 6402 parent.ready(value); 6403 } 6404 6405 self.design(); 6406 }); 6407 6408 self.events.subscribe(function (data) { 6409 parent.submit.step2(data); 6410 }, this, 'submit'); 6411 6412 self.events.subscribe(function (error) { 6413 if (error.severity == "Forbidden") { 6414 self.ready(false); 6415 } 6416 IBE.Utils.logEvent(error); 6417 parent.submitting(false); 6418 }, this, 'error'); 6419 6420 self.roomUpgrade = function (roomId) { 6421 var upgrades = []; 6422 6423 // get current room 6424 var room = ko.utils.arrayFirst(self.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (room) { 6425 return room.roomId() == roomId; 6426 }); 6427 6428 if (room === null) { 6429 return upgrades; 6430 } 6431 6432 // get current ADR 6433 var currenetAverageDailyRate = room.averageDailyRate(); 6434 6435 if(room.averageDailyRate() < 0.1) { 6436 for(var i=0; i < room.rateplans().length; i++) { 6437 if(room.rateplans()[i].averageDailyRate() > 0.1) { 6438 room.ratePlanId(room.rateplans()[i].ratePlanId()); 6439 } 6440 6441 } 6442 } 6443 var allPrices = []; 6444 for (var i = 0; i < room.rateplans().length; i++) { 6445 var roomRates = []; 6446 if (room.rateplans()[i].isVisible()) { 6447 for (let x = 0; x < room.rateplans()[i].roomBoards().length; x++) { 6448 if (room.rateplans()[i].roomBoards()[x].showPrices()) { 6449 roomRates.push(room.rateplans()[i].roomBoards()[x].price()); 6450 } 6451 } 6452 6453 } 6454 var roomMinPrice = Math.min(...roomRates); 6455 if (roomRates.length > 0 && roomMinPrice > 0) { 6456 allPrices.push(roomMinPrice ); 6457 } 6458 } 6459 var minRate = Math.min(...allPrices); 6460 6461 var availablesRooms = []; 6462 var roomResults = self.request().hotelResults()[0].requestedRooms()[0].roomResults(); 6463 for (var y = 0; y < roomResults.length; y++) { 6464 var item = roomResults[y]; 6465 var mappedRoom = IBEConfig.rooms.filter(row => row.bookwize_liquid_room_id == item.roomId()); 6466 if (item.roomId() == roomId || mappedRoom.length === 0 || item.availableRooms <= 0 || item.alternativeBoard()) { 6467 continue; 6468 } 6469 availablesRooms.push(item.roomId()); 6470 } 6471 6472 ko.utils.arrayForEach(self.roomsPrices(), function (item, index) { 6473 if (!availablesRooms.includes(item.roomId) || item.averageDailyRate <= minRate || item.availability < 1) { 6474 return; 6475 } 6476 6477 upgrades.push(item); 6478 }); 6479 6480 upgrades.sort(function (a, b) { 6481 return a.price > b.price ? 1 : -1; 6482 }); 6483 return upgrades; 6484 }; 6485 6486 self.roomDowngrade = function (roomId) { 6487 var downgrades = []; 6488 var mostExpensiveRoom = self.roomsPrices().sort(function (a, b) { 6489 return a.price < b.price ? 1 : -1; 6490 })[0]; 6491 // if the current room is not the most expensive one 6492 // then return empty array 6493 if (mostExpensiveRoom) { 6494 if (roomId !== mostExpensiveRoom.roomId) { 6495 6496 return downgrades; 6497 } 6498 } 6499 6500 // get current room 6501 var room = ko.utils.arrayFirst(self.request().hotelResults()[0].requestedRooms()[0].roomResults(), function (room) { 6502 return room.roomId() == roomId; 6503 }); 6504 6505 if (room === null) { 6506 return downgrades; 6507 } 6508 6509 // get current ADR 6510 var currenetAverageDailyRate = room.averageDailyRate(); 6511 6512 ko.utils.arrayForEach(self.roomsPrices(), function (item, index) { 6513 if (item.roomId === roomId) { 6514 return; 6515 } 6516 6517 if (item.averageDailyRate >= currenetAverageDailyRate) { 6518 return; 6519 } 6520 6521 // push rooms with greater ADR 6522 downgrades.push(item); 6523 }); 6524 6525 return downgrades.sort(function (a, b) { 6526 a.price < b.price ? 1 : -1; 6527 }); 6528 }; 6529 /** 6530 * Give hotels/info call response and return the 6531 * correct guests for step2 init method 6532 * 6533 * @param hotelInfo 6534 * @param guests 6535 * @returns {*} 6536 * 6537 */ 6538 self.prepareMultiPropertyGuestTypes = function (hotelInfo, guests) { 6539 var _tmp_guests = ko.toJS(guests); //in order to remove references 6540 6541 // add all hotel's supported guests 6542 $.extend(guests, hotelInfo.info.guestTypes); 6543 6544 // loop through guests and add the selected pax 6545 ko.utils.arrayForEach(guests, function (dataGuest) { 6546 var guest = ko.utils.arrayFilter(_tmp_guests, function (item) { 6547 return dataGuest.ageCategory === item.ageCategory; 6548 }); 6549 if (guest.length) { 6550 dataGuest.pax = guest[0].pax; 6551 } 6552 }); 6553 6554 return guests; 6555 }; 6556 6557 self.initmulti = function (data, params) { 6558 self.dfd = $.Deferred(); 6559 6560 hp.setHotelApiConfig(params); 6561 6562 $.ajaxSetup({ 6563 dataType: 'json', 6564 contentType: 'application/json' 6565 }); 6566 self.init(data, params); 6567 6568 return self.dfd.promise(); 6569 }; 6570 6571 6572 return self; 6573}
6574function BookwizeLiquidStep3ViewModel(parent) { 6575 var self = new IBE.ViewModels.Step3ViewModel(); 6576 6577 self.lang = parent.lang; 6578 self.currency = parent.currency; 6579 6580 self.design = function () { 6581 parent.popup.close(); 6582 $('.hp-supplements').mCustomScrollbar({theme: 'minimal'}); 6583 }; 6584 6585 self.validateExternalPaymentButton = function () { 6586 if (!self.terms.value() && self.terms.id !== -1) { 6587 self.customer().errors().customer.showAllMessages(); 6588 self.terms.value.notifySubscribers(); 6589 return; 6590 } 6591 window.scrollTo(0, 0); 6592 self.externalPaymentGateway().payWithSixPaymentPage(); 6593 }; 6594 6595 self.validateCardPaymentButton = function () { 6596 if (!self.terms.value() && self.terms.id !== -1) { 6597 self.customer().errors().customer.showAllMessages(); 6598 self.terms.value.notifySubscribers(); 6599 return; 6600 } 6601 window.scrollTo(0, 0); 6602 self.externalPaymentGateway().showSixCreditCardForm(); 6603 }; 6604 6605 self.validateCustomer = function () { 6606 var returnValue = true; 6607 6608 // we set by default Terms & Conditions to true 6609 // self.customer().acceptTerms(true); 6610 6611 // and an empty value for arrivalTime 6612 //self.customer().arrivalTime(' - '); 6613 6614 if (self.customer().errors().customer().length > 0 && self.customer().errors().customer()[0] !== null) { 6615 self.customer().errors().customer.showAllMessages(); 6616 returnValue = false; 6617 } 6618 6619 if (returnValue && typeof ga !== 'undefined') { 6620 ga('send', 'event', 'Liquid', 'Booking Flow', 'Payment Details'); 6621 } 6622 6623 return returnValue; 6624 }; 6625 6626 self.beforeSubmit = function () { 6627 $('.hp-wait.loader').show(); 6628 hp.scrollTo({duration: 333}); 6629 var hasErrors = false; 6630 if (self.bookingProcess().isOnline()) { 6631 if (self.requiredCreditCard() && self.customer().errors().creditCard().length > 0 && self.customer().errors().creditCard()[0] !== null) { 6632 self.customer().errors().creditCard.showAllMessages(); 6633 hasErrors = true; 6634 } 6635 } 6636 if (!self.terms.value() && self.terms.id !== -1) { 6637 self.customer().errors().customer.showAllMessages(); 6638 self.terms.value.notifySubscribers(); 6639 6640 hasErrors = true; 6641 } 6642 6643 if (hasErrors == true) { 6644 $('.hp-wait.loader').hide(); 6645 return; 6646 } 6647 6648 // keep only numbers from customer phone 6649 var customerPhone = self.customer().phone().match(/\d+/g); 6650 if (customerPhone !== null && customerPhone[0].length > 0) { 6651 if(parent.phoneCountryCode() !== '' && parent.phoneCountryCode() !== undefined) { 6652 self.customer().phone(parent.phoneCountryCode() + ' ' + customerPhone.join('')); 6653 } else { 6654 self.customer().phone(customerPhone.join('')); 6655 } 6656 } 6657 6658 var country = ko.utils.arrayFirst(self.countries(), function(item){ 6659 return item.code() === $('#CustomerCountry').val(); 6660 } 6661 ); 6662 6663 if (country !== null){ 6664 self.customer().country(ko.toJS(country)); 6665 } 6666 6667 var customerPreferences = parent.cache.read(parent.customerPreferencesCacheKey); 6668 if (customerPreferences.travelAgencyID !== '') { 6669 var notes = self.customer().notes() + '<ul><li>' + IBE.Utils.translate('travelAgencyID') + ': ' + customerPreferences.travelAgencyID + '</li></ul>'; 6670 self.customer().notes(notes); 6671 } 6672 6673 if (self.bookingProcess().paymentMethodType() === 'ExternalPaymentGateway') { 6674 self.externalPaymentGateway().beforeSubmit(); 6675 if (!self.externalPaymentGateway().externalPaymentGatewayErrors()) { 6676 parent.submitting(true); 6677 } 6678 return; 6679 } 6680 6681 parent.submitting(true); 6682 6683 self.makeReservation(); 6684 }; 6685 6686 self.splitSupplements = function() { 6687 var result = { 6688 mandatory: [], 6689 optional: [] 6690 } 6691 ko.utils.arrayForEach(self.supplements(), function (item) { 6692 ko.utils.arrayForEach(item.supplementResults(), function (supplement) { 6693 if (supplement) { 6694 if (supplement.isMandatory) { 6695 result.mandatory.push(supplement); 6696 } else { 6697 result.optional.push(supplement); 6698 } 6699 } 6700 }); 6701 }); 6702 return result; 6703 }; 6704 6705 self.events.subscribe(function (value) { 6706 if (value === false) { 6707 return; 6708 } 6709 6710 // override customer telephone 6711 self.customer().phone = ko.observable('').extend({ 6712 phone: {message: IBE.Utils.translate("validation.required")} 6713 }); 6714 6715 self.design(); 6716 if (IBE.Config.ibeFlightInfo == 'True') { 6717 self.flightInformation(true); 6718 } 6719 6720 self.externalPaymentGateway().init(); 6721 6722 parent.ready(value); 6723 }, this, 'ready'); 6724 6725 self.titleOptions = [ 6726 { key: 'Mr', text: IBE.Utils.translate('title-mr') }, 6727 { key: 'Mrs', text: IBE.Utils.translate('title-mrs') }, 6728 { key: 'Dr', text: IBE.Utils.translate('title-dr') } 6729 ]; 6730 6731 self.events.subscribe(function (data) { 6732 if (self.flightInformation()) { 6733 data.notes += '<ul>'; 6734 data.notes += '<li><b>' + IBE.Utils.translate('flightInfo') + '</b></li>';
6735 if (self.flightInformationDetails.flightNumber()) { 6736 data.notes += '<li>' + IBE.Utils.translate('label_flightNumber') + ': ' + ko.unwrap(self.flightInformationDetails.flightNumber) + "</li>"; 6737 } 6738 if (self.flightInformationDetails.airportOfArrival()) { 6739 data.notes += '<li>' + IBE.Utils.translate('airportOfArrival') + ': ' + ko.unwrap(self.flightInformationDetails.airportOfArrival) + "</li>"; 6740 } 6741 if (self.flightInformationDetails.estimatedTime()) { 6742 data.notes += '<li>' + IBE.Utils.translate('estimatedTime') + ': ' + ko.unwrap(self.flightInformationDetails.estimatedTime().value) + "</li>"; 6743 } 6744 6745 data.notes += '</ul>'; 6746 } 6747 6748 parent.submit.step3(data); 6749 6750 IBE.Utils.deleteAuthenticationCookie("Authorization="); 6751 parent.cache.clear('Reservation'); 6752 parent.cache.clear('ReservationUser'); 6753 parent.cache.clear('flagTracking'); 6754 6755 }, this, 'submit'); 6756 6757 self.events.subscribe(function (error) { 6758 IBE.Utils.logEvent(error); 6759 parent.submitting(false); 6760 }, this, 'error'); 6761 6762 self.moveToTab3 = function() { 6763 // console.log("tab3"); 6764 setTimeout(function () { 6765 $('.slick-slider').slick('slickGoTo', 2); 6766 }, 20); 6767 }; 6768 6769 return self; 6770} 6771function BookwizeLiquidStep4ViewModel(parent) { 6772 var self = new IBE.ViewModels.Step4ViewModel(); 6773 6774 self.lang = parent.lang; 6775 self.currency = parent.currency; 6776 6777 self.events.subscribe(function (value) { 6778 // debugger; 6779 // we came here from redirection 6780 if (self.options.reservationSubmitted === true) { 6781 return; 6782 } 6783 6784 if (value === false) { 6785 return; 6786 } 6787 6788 parent.vm.step2.ready(false); 6789 6790 // clear all cached data 6791 parent.cache.clear(); 6792 6793 // save reservation user to automatically login in my reservation page 6794 parent.cache.write('ReservationUser', { 6795 username: self.reservations()[0].customer.email(), 6796 password: self.reservations()[0].code 6797 }); 6798 6799 // save reservation for thank you page 6800 parent.cache.write('Reservation', { 6801 lang: ko.toJS(self.lang()), 6802 hotel: ko.toJS(self.hotel()), 6803 reservation: ko.toJS(self.reservations()[0]) 6804 }); 6805 6806 if (typeof ga !== 'undefined') { 6807 ga('send', 'event', 'Liquid', 'Booking Flow', 'Complete ' + self.reservations()[0].status()); 6808 } 6809 6810 // redirect user to thank-you page 6811 var redirect = parent.getPostByBookwizeLiquidPageType('confirmed').bookwize_liquid_page_url; 6812 6813 if (typeof redirect === 'undefined' || redirect.indexOf('http') == -1) { 6814 parent.popup.open({ 6815 items: { 6816 src: '#hp-popup-error' 6817 }, 6818 type: 'inline' 6819 }); 6820 return; 6821 } 6822 6823 parent.cache.write('AllowAnalyticsTracking', true); 6824 redirect += '?code=' + self.reservations()[0].code; 6825 if (window.location.href !== redirect) { 6826 window.location.href = redirect; 6827 } 6828 hp.closeOverlays(); 6829 }, this, 'ready'); 6830 6831 self.events.subscribe(function (error) { 6832 6833 parent.ready(true); 6834 parent.vm.step3.ready(true); 6835 parent.vm.step3.clearMessage(); 6836 parent.vm.step3.message(error); 6837 6838 // enable button previously disabled on click event 6839 parent.submitting(false); 6840 6841 if (error.severity == 'critical') { 6842 IBE.Utils.logEvent(error); 6843 } 6844 parent.vm.step3.moveToTab3(); 6845 }, this, 'error'); 6846 6847 return self; 6848} 6849function BookwizeLiquidMultipleStep1ViewModel(parent, multViewModelData) { 6850 if (typeof multViewModelData === 'undefined' || multViewModelData.length === 0) { 6851 return {}; 6852 } 6853 var self = this; 6854 6855 self.design = function () { 6856 $(document).on('hp/overlayOpened', function (e) { 6857 hp.setOverlayDefaults(self, parent.session()); 6858 var $el = $(e.target); 6859 // add hash and on load trigger it 6860 if ($el.is('.hp-guests-overlay') === false) { 6861 parent.overlayHash.setHash(); 6862 } else { 6863 $(document).on('click', function (e) { 6864 if (!$(e.target).is('.hp-toggle') && $(e.target).parents('.hp-guests-overlay').length === 0) { 6865 $el.removeClass('hp-toggle--open'); 6866 $el.stop(true, true).fadeOut(100); 6867 } 6868 }); 6869 } 6870 }); 6871 }; 6872 6873 self.ready = ko.observable(false); 6874 6875 self.events = new ko.subscribable(); 6876
6877 self.currencies = multViewModelData[0].viewModel.currencies; 6878 6879 self.lang = parent.lang; 6880 self.currency = parent.currency; 6881 self.step1ViewModels = []; 6882 self.boardType = ko.observable(''); 6883 self.couponCode = ko.observable(''); 6884 self.couponValid = ko.observable(true); 6885 self.couponExists = ko.observable(false); 6886 self.guests = []; 6887 6888 self.addGuest = function (data) { 6889 if (data.pax() > data.options[data.options.length - 1]) { 6890 return false; 6891 } 6892 data.pax(data.pax() + 1); 6893 6894 if (data.ageCategory() !== IBE.Config.guestType.Adult) { 6895 var options = []; 6896 for (var i = data.fromAge(); i <= data.toAge(); i++) { 6897 options.push(i); 6898 } 6899 data.childrenAges.push({ 6900 selected: ko.observable(options[0]), 6901 options: options 6902 }); 6903 } 6904 }; 6905 self.removeGuest = function (data) { 6906 if (data.pax() === 1 && data.ageCategory() === IBE.Config.guestType.Adult) { 6907 return false; 6908 } 6909 if (data.pax() <= 0) { 6910 return; 6911 } 6912 data.pax(data.pax() - 1); 6913 6914 if (data.ageCategory() !== IBE.Config.guestType.Adult) { 6915 data.childrenAges.pop(); 6916 } 6917 }; 6918 6919 self.minStay = ko.observable(); 6920 self.maxStay = ko.observable(); 6921 self.minCheckInDate = ko.observable(); 6922 self.currentViewModel = ko.observable(); 6923 self._checkIn = ko.observable(moment()); 6924 self.checkIn = ko.computed({ 6925 write: function (date) { 6926 self._checkIn(moment(date)); 6927 }, 6928 read: function () { 6929 return self._checkIn(); 6930 } 6931 }); 6932 self.checkOut = ko.computed({ 6933 write: function (date) { 6934 6935 if (typeof date === 'undefined') { 6936 self._checkOut(self.minCheckOutDate()); 6937 return; 6938 } 6939 var co = moment(date); 6940 if (co > self.minCheckOutDate()) { 6941 self._checkOut(co); 6942 } else { 6943 self._checkOut(self.minCheckOutDate()); 6944 } 6945 }, 6946 read: function () { 6947 return self._checkOut(); 6948 }, 6949 deferEvaluation: true 6950 }); 6951 6952 self.selectViewModel = function (hotelId) { 6953 return ko.utils.arrayFilter(self.step1ViewModels, function (item) { 6954 return hotelId == item.hotel().info.hotelId; 6955 }); 6956 }; 6957 6958 // stores the hotelId -> hotel name for the dropdown 6959 self.hotelOptions = []; 6960 6961 self.beforeSubmit = function () { 6962 parent.submitting(true); 6963 _prepare_multi_view_models_data(); 6964 self.validate(); 6965 }; 6966 6967 self.validate = function () { 6968 var promises = []; 6969 var mutiValid = 0; 6970 if (self.couponExists()) { 6971 ko.utils.arrayForEach(self.step1ViewModels, function (item) { 6972 promises.push(item.isValidCoupon({ 6973 hotelId: item.hotel().info.hotelId, 6974 apiKey: ko.utils.arrayFilter(parent.properties, function (prop) { 6975 return prop.hotelId == item.hotel().info.hotelId; 6976 })[0].apiKey 6977 })); 6978 }); 6979 6980 $.when.apply($, promises).then(function () { 6981 ko.utils.arrayForEach(arguments, function (item) { 6982 if (item) { 6983 mutiValid++; 6984 } else { 6985 mutiValid--; 6986 } 6987 }); 6988 ko.utils.arrayForEach(self.step1ViewModels, function (item) { 6989 if (mutiValid > 0) { 6990 self.couponValid(true); 6991 item.validate(); 6992 } else { 6993 self.couponValid(false); 6994 item.message({ 6995 id: 3001, 6996 severity: 'error', 6997 text: 'invalidPromoCode' 6998 }); 6999 item.events.notifySubscribers({ 7000 failure: item.message() 7001 }, 'submit'); 7002 } 7003 }); 7004 }); 7005 } else { 7006 ko.utils.arrayForEach(self.step1ViewModels, function (item) { 7007 item.validate(); 7008 }); 7009 } 7010 }; 7011 7012 // set in all step1 viewmodels key = value 7013 function _set_property_to_multi_view_models(key, value) { 7014 if (typeof key === 'undefined' || typeof value === 'undefined') { 7015 return false; 7016 } 7017 ko.utils.arrayForEach(self.step1ViewModels, function (item) { 7018 if (ko.isObservable(item[key])) { 7019 item[key](value); 7020 } else { 7021 item[key] = value; 7022 } 7023 }); 7024 } 7025 7026 // prepare data before submit each step1 View Model 7027 function _prepare_multi_view_models_data() { 7028 _set_property_to_multi_view_models('_checkIn', self._checkIn()); 7029 _set_property_to_multi_view_models('_checkOut', self._checkOut()); 7030 _set_property_to_multi_view_models('couponCode', self.couponCode()); 7031 7032 ko.utils.arrayForEach(self.guests, function (guest) { 7033 if (guest.ageCategory() !== IBE.Config.guestType.Adult) { 7034 for (var i = 0; i < guest.pax(); i++) { 7035 guest.ages.push(guest.childrenAges()[i].selected()); 7036 } 7037 } 7038 }); 7039 7040 ko.utils.arrayForEach(self.step1ViewModels, function (vm) { 7041 vm.requestedRooms()[0].guests = self.guests; 7042 }); 7043 } 7044 7045 function _populate_multi_view_models_from_session() { 7046 if (parent.session() === false) { 7047 return false;
7048 } 7049 7050 self.checkIn(parent.session().checkIn); 7051 self.checkOut(parent.session().checkOut); 7052 self.couponCode(parent.session().couponCode); 7053 self.boardType(parent.session().board); 7054 7055 ko.utils.arrayForEach(self.guests, function (guest) { 7056 var session_guest = ko.utils.arrayFilter(parent.session().rooms[0], function (item) { 7057 return item.ageCategory === guest.ageCategory() 7058 }); 7059 if (session_guest.length) { 7060 guest.pax(session_guest[0].pax); 7061 if (session_guest[0].ages.length) { 7062 var options = []; 7063 for (var i = guest.fromAge(); i <= guest.toAge(); i++) { 7064 options.push(i); 7065 } 7066 for (var j = 0; j < session_guest[0].ages.length; j++) { 7067 guest.childrenAges.push({ 7068 selected: ko.observable(session_guest[0].ages[j]), 7069 options: options 7070 }); 7071 } 7072 } 7073 } 7074 }); 7075 } 7076 7077 function _populate_data(multViewModelData) { 7078 var minCheckInDates = []; 7079 var maxStays = []; 7080 var minStays = []; 7081 var checkIns = []; 7082 var checkOuts = []; 7083 var couponExists = []; 7084 7085 ko.utils.arrayForEach(multViewModelData, function (item) { 7086 self.step1ViewModels.push(item.viewModel); 7087 7088 self.hotelOptions.push({ 7089 id: item.viewModel.hotel().info.hotelId, 7090 name: item.viewModel.hotel().info.name 7091 }); 7092 7093 minCheckInDates.push(item.viewModel.minCheckInDate()); 7094 checkIns.push(item.viewModel.checkIn()); 7095 7096 checkOuts.push(item.viewModel.checkOut()); 7097 7098 minStays.push(item.viewModel.minStay()); 7099 maxStays.push(item.viewModel.maxStay()); 7100 couponExists.push(item.viewModel.couponExists()); 7101 }); 7102 7103 // todo: hotels may not have the same default BoardType 7104 self.boardType(self.step1ViewModels[0].boardType()); 7105 self.guests = self.step1ViewModels[0].requestedRooms()[0].guests; 7106 ko.utils.arrayForEach(self.guests, function (item) { 7107 if (item.ageCategory() != IBE.Config.guestType.Adult) { 7108 item.childrenAges = ko.observableArray([]); 7109 // set the childrenAges and selected 7110 } 7111 }); 7112 self.minCheckInDate(moment(minCheckInDates.reduce(function (a, b) { 7113 return a < b ? a : b; 7114 }))); 7115 self.minCheckOutDate = ko.computed(function () { 7116 var co = moment(self.checkIn()); 7117 co.add(self.minStay(), 'days'); 7118 return co; 7119 }); 7120 7121 self._checkOut = ko.observable(self.minCheckOutDate()); 7122 7123 self.checkIn.subscribe(function (newDate) { 7124 var checkOut = moment(newDate).add(self.minStay(), 'days'); 7125
7126 if (self.checkOut() - checkOut <= 0) { 7127 self.checkOut(checkOut); 7128 } 7129 }); 7130 self.checkIn(moment(checkIns.reduce(function (a, b) { 7131 return a < b ? a : b; 7132 }))); 7133 7134 self.minStay(minStays.reduce(function (a, b) { 7135 return a > b ? a : b; 7136 })); 7137 self.maxStay(maxStays.reduce(function (a, b) { 7138 return a > b ? a : b; 7139 })); 7140 7141 self.isValidStay = ko.computed({ 7142 read: function () { 7143 return (self.nights() > 0 && self.nights() <= self.maxStay()); 7144 }, 7145 deferEvaluation: true 7146 }); 7147 7148 self.nights = ko.computed({ 7149 write: function (nights) { 7150 self.checkOut(self.checkIn().add(nights, 'days')); 7151 }, 7152 read: function () { 7153 return self.checkOut().diff(self.checkIn(), 'days'); 7154 }, 7155 deferEvaluation: true 7156 }); 7157 7158 self.couponExists(( couponExists.reduce(function (a, b) { 7159 return a + b; 7160 }, 0) ) === couponExists.length); 7161 7162 self.bookingProcess = ko.observable(new IBE.Models.BookingProcess({ 7163 checkIn: self.checkIn, 7164 checkOut: self.checkOut, 7165 couponCode: self.couponCode, 7166 reservationStatus: "Unknown", 7167 lang: self.lang(), 7168 currency: self.currency() 7169 })); 7170 } 7171 7172 // populate multiple response data 7173 _populate_data(multViewModelData); 7174 7175 // set to multi step1 view models the preferences found on parent.session 7176 _populate_multi_view_models_from_session(); 7177 7178 self.ready(true); 7179 7180 self.design(); 7181 7182 return self; 7183} 7184function BookwizeLiquidMultipleStep2ViewModel(parent, multViewModelData) { 7185 if (typeof multViewModelData === 'undefined' || multViewModelData.length === 0) { 7186 return {}; 7187 } 7188 var self = this; 7189 7190 self.ready = ko.observable(false); 7191 7192 self.events = new ko.subscribable(); 7193 7194 self.lang = parent.lang; 7195 self.currency = parent.currency; 7196 7197 self.properties = ko.observableArray(); 7198 7199 ko.utils.arrayForEach(multViewModelData, function (item) { 7200 item.viewModel.lang = self.lang; 7201 item.viewModel.currency = self.currency; 7202 // set the default boardType for the dropdown select mealplan 7203 item.viewModel.request().preferredBoard(item.viewModel.hotelInfo().defaultBoardType()); 7204 self.properties.push(item.viewModel); 7205 }); 7206 7207 self.currencies = self.properties()[0].currencies; 7208 self.calculateRate = self.properties()[0].calculateRate; 7209 self.popup = self.properties()[0].popup; 7210 7211 self.bookingProcess = ko.observable(new IBE.Models.BookingProcess({ 7212 checkIn: ko.observable(moment(parent.session().checkIn)), 7213 checkOut: ko.observable(moment(parent.session().checkOut)), 7214 rooms: parent.session().rooms, 7215 couponCode: parent.session().couponCode, 7216 reservationStatus: "Unknown", 7217 lang: self.lang, 7218 currency: self.currency 7219 })); 7220 7221 // assign references 7222 self.bookingProcess().boardType = self.properties()[0].bookingProcess().boardType; 7223 self.bookingProcess().totalGuests = ko.observable(parent.session().totalGuests); 7224 self.bookingProcess().boardType(parent.session().board); 7225 7226 // we need to reference the self.currency and self.lang to bookingProcess objects 7227 // for each property 7228 ko.utils.arrayForEach(self.properties(), function (item) { 7229 item.bookingProcess().currency = self.bookingProcess().currency; 7230 item.bookingProcess().lang = self.bookingProcess().lang; 7231 }); 7232 7233 self.scrollToSelectedHotel = function () { 7234 $(document).on('hp/overlayClosed', function (e) { 7235 if (isNaN(parent.selectedHotel())) { 7236 return; 7237 } 7238 hp.scrollTo({ 7239 offset: $('#hp-hotel-' + parent.selectedHotel()).offset().top - $('.site-head ').height(), 7240 callback: function () { 7241 window.location.hash = '#!hotel-' + parent.selectedHotel(); 7242 } 7243 }); 7244 }); 7245 }; 7246 7247 self.design = function () { 7248 hp.anchorLink({ 7249 header: $('.site-head') 7250 }); 7251 }; 7252 7253 self.filterHotel = function (hotelId) { 7254 if (isNaN(parent.selectedHotel())) { 7255 // users didn't select any hotel 7256 return true; 7257 } 7258 if (typeof hotelId !== 'undefined') { 7259 return (parent.selectedHotel() === hotelId); 7260 } 7261 return false; 7262 }; 7263 7264 self.design(); 7265 7266 self.ready(true); 7267 7268 return self; 7269} 7270 7271(function ($) { 7272 'use strict'; 7273 7274 if (typeof IBE === 'undefined') { 7275 console.log('IBE is not loaded'); 7276 return false; 7277 } 7278 7279 var browser = hp.browserVersion(); 7280 if (browser.name.indexOf('MSIE') !== -1 && parseInt(browser.version) < 10) { 7281 // browser is Internet Explorer 9 or older 7282 // Booking engine does not support this browser 7283 return hp.legacy(); 7284 } 7285 7286 if (IBE.Config.validApiKeys === false) { 7287 console.log('IBE cannot initialize because API KEYS are not the same'); 7288 return false;
7289 } 7290 7291 IBE.Config.deviceType = 'Desktop'; 7292 7293 window.BookwizeLiquid = new BookwizeLiquidAppViewModel(); 7294 7295 if (hp.isMobile()) { 7296 IBE.Config.deviceType = 'Mobile'; 7297 if (window.location.hash === '#!booking-preferences') { 7298 window.location.href = window.BookwizeLiquid.getPostByBookwizeLiquidPageType('integrated').bookwize_liquid_page_url; 7299 } 7300 window.BookwizeLiquid.bookButtons(); 7301 return hp.legacy(true); 7302 } 7303 7304 // initialize liquid booking engine 7305 window.BookwizeLiquid.init(); 7306 7307 // if is set the ?clearCache 7308 if (window.location.search.indexOf('clearCache') !== -1) { 7309 return hp.clearCache(); 7310 } 7311})(jQuery);
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.