1/*! 2* MediaElement.js 3* HTML5 <video> and <audio> shim and player 4* http://mediaelementjs.com/ 5* 6* Creates a JavaScript object that mimics HTML5 MediaElement API 7* for browsers that don't understand HTML5 or can't play the provided codec 8* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3 9* 10* Copyright 2010-2014, John Dyer (http://j.hn) 11* License: MIT 12* 13*/var mejs=mejs||{};mejs.version="2.15.1";mejs.meIndex=0; 14mejs.plugins={silverlight:[{version:[3,0],types:["video/mp4","video/m4v","video/mov","video/wmv","audio/wma","audio/m4a","audio/mp3","audio/wav","audio/mpeg"]}],flash:[{version:[9,0,124],types:["video/mp4","video/m4v","video/mov","video/flv","video/rtmp","video/x-flv","audio/flv","audio/x-flv","audio/mp3","audio/m4a","audio/mpeg","video/youtube","video/x-youtube","application/x-mpegURL"]}],youtube:[{version:null,types:["video/youtube","video/x-youtube","audio/youtube","audio/x-youtube"]}],vimeo:[{version:null, 15types:["video/vimeo","video/x-vimeo"]}]}; 16mejs.Utility={encodeUrl:function(a){return encodeURIComponent(a)},escapeHTML:function(a){return a.toString().split("&").join("&").split("<").join("<").split('"').join(""")},absolutizeUrl:function(a){var b=document.createElement("div");b.innerHTML='<a href="'+this.escapeHTML(a)+'">x</a>';return b.firstChild.href},getScriptPath:function(a){for(var b=0,c,d="",e="",g,f,i=document.getElementsByTagName("script"),k=i.length,h=a.length;b<k;b++){g=i[b].src;c=g.lastIndexOf("/");if(c>-1){f=g.substring(c+ 171);g=g.substring(0,c+1)}else{f=g;g=""}for(c=0;c<h;c++){e=a[c];e=f.indexOf(e);if(e>-1){d=g;break}}if(d!=="")break}return d},secondsToTimeCode:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;var e=Math.floor(a/3600)%24,g=Math.floor(a/60)%60,f=Math.floor(a%60);a=Math.floor((a%1*d).toFixed(3));return(b||e>0?(e<10?"0"+e:e)+":":"")+(g<10?"0"+g:g)+":"+(f<10?"0"+f:f)+(c?":"+(a<10?"0"+a:a):"")},timeCodeToSeconds:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d== 18"undefined")d=25;a=a.split(":");b=parseInt(a[0],10);var e=parseInt(a[1],10),g=parseInt(a[2],10),f=0,i=0;if(c)f=parseInt(a[3])/d;return i=b*3600+e*60+g+f},convertSMPTEtoSeconds:function(a){if(typeof a!="string")return false;a=a.replace(",",".");var b=0,c=a.indexOf(".")!=-1?a.split(".")[1].length:0,d=1;a=a.split(":").reverse();for(var e=0;e<a.length;e++){d=1;if(e>0)d=Math.pow(60,e);b+=Number(a[e])*d}return Number(b.toFixed(c))},removeSwf:function(a){var b=document.getElementById(a);if(b&&/object|embed/i.test(b.nodeName))if(mejs.MediaFeatures.isIE){b.style.display= 19"none";(function(){b.readyState==4?mejs.Utility.removeObjectInIE(a):setTimeout(arguments.callee,10)})()}else b.parentNode.removeChild(b)},removeObjectInIE:function(a){if(a=document.getElementById(a)){for(var b in a)if(typeof a[b]=="function")a[b]=null;a.parentNode.removeChild(a)}}}; 20mejs.PluginDetector={hasPluginVersion:function(a,b){var c=this.plugins[a];b[1]=b[1]||0;b[2]=b[2]||0;return c[0]>b[0]||c[0]==b[0]&&c[1]>b[1]||c[0]==b[0]&&c[1]==b[1]&&c[2]>=b[2]?true:false},nav:window.navigator,ua:window.navigator.userAgent.toLowerCase(),plugins:[],addPlugin:function(a,b,c,d,e){this.plugins[a]=this.detectPlugin(b,c,d,e)},detectPlugin:function(a,b,c,d){var e=[0,0,0],g;if(typeof this.nav.plugins!="undefined"&&typeof this.nav.plugins[a]=="object"){if((c=this.nav.plugins[a].description)&& 21!(typeof this.nav.mimeTypes!="undefined"&&this.nav.mimeTypes[b]&&!this.nav.mimeTypes[b].enabledPlugin)){e=c.replace(a,"").replace(/^\s+/,"").replace(/\sr/gi,".").split(".");for(a=0;a<e.length;a++)e[a]=parseInt(e[a].match(/\d+/),10)}}else if(typeof window.ActiveXObject!="undefined")try{if(g=new ActiveXObject(c))e=d(g)}catch(f){}return e}}; 22mejs.PluginDetector.addPlugin("flash","Shockwave Flash","application/x-shockwave-flash","ShockwaveFlash.ShockwaveFlash",function(a){var b=[];if(a=a.GetVariable("$version")){a=a.split(" ")[1].split(",");b=[parseInt(a[0],10),parseInt(a[1],10),parseInt(a[2],10)]}return b}); 23mejs.PluginDetector.addPlugin("silverlight","Silverlight Plug-In","application/x-silverlight-2","AgControl.AgControl",function(a){var b=[0,0,0,0],c=function(d,e,g,f){for(;d.isVersionSupported(e[0]+"."+e[1]+"."+e[2]+"."+e[3]);)e[g]+=f;e[g]-=f};c(a,b,0,1);c(a,b,1,1);c(a,b,2,1E4);c(a,b,2,1E3);c(a,b,2,100);c(a,b,2,10);c(a,b,2,1);c(a,b,3,1);return b}); 24mejs.MediaFeatures={init:function(){var a=this,b=document,c=mejs.PluginDetector.nav,d=mejs.PluginDetector.ua.toLowerCase(),e,g=["source","track","audio","video"];a.isiPad=d.match(/ipad/i)!==null;a.isiPhone=d.match(/iphone/i)!==null;a.isiOS=a.isiPhone||a.isiPad;a.isAndroid=d.match(/android/i)!==null;a.isBustedAndroid=d.match(/android 2\.[12]/)!==null;a.isBustedNativeHTTPS=location.protocol==="https:"&&(d.match(/android [12]\./)!==null||d.match(/macintosh.* version.* safari/)!==null);a.isIE=c.appName.toLowerCase().indexOf("microsoft")!= 25-1||c.appName.toLowerCase().match(/trident/gi)!==null;a.isChrome=d.match(/chrome/gi)!==null;a.isChromium=d.match(/chromium/gi)!==null;a.isFirefox=d.match(/firefox/gi)!==null;a.isWebkit=d.match(/webkit/gi)!==null;a.isGecko=d.match(/gecko/gi)!==null&&!a.isWebkit&&!a.isIE;a.isOpera=d.match(/opera/gi)!==null;a.hasTouch="ontouchstart"in window;a.svg=!!document.createElementNS&&!!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect;for(c=0;c<g.length;c++)e=document.createElement(g[c]); 26a.supportsMediaTag=typeof e.canPlayType!=="undefined"||a.isBustedAndroid;try{e.canPlayType("video/mp4")}catch(f){a.supportsMediaTag=false}a.hasSemiNativeFullScreen=typeof e.webkitEnterFullscreen!=="undefined";a.hasNativeFullscreen=typeof e.requestFullscreen!=="undefined";a.hasWebkitNativeFullScreen=typeof e.webkitRequestFullScreen!=="undefined";a.hasMozNativeFullScreen=typeof e.mozRequestFullScreen!=="undefined";a.hasMsNativeFullScreen=typeof e.msRequestFullscreen!=="undefined";a.hasTrueNativeFullScreen= 27a.hasWebkitNativeFullScreen||a.hasMozNativeFullScreen||a.hasMsNativeFullScreen;a.nativeFullScreenEnabled=a.hasTrueNativeFullScreen;if(a.hasMozNativeFullScreen)a.nativeFullScreenEnabled=document.mozFullScreenEnabled;else if(a.hasMsNativeFullScreen)a.nativeFullScreenEnabled=document.msFullscreenEnabled;if(a.isChrome)a.hasSemiNativeFullScreen=false;if(a.hasTrueNativeFullScreen){a.fullScreenEventName="";if(a.hasWebkitNativeFullScreen)a.fullScreenEventName="webkitfullscreenchange";else if(a.hasMozNativeFullScreen)a.fullScreenEventName= 28"mozfullscreenchange";else if(a.hasMsNativeFullScreen)a.fullScreenEventName="MSFullscreenChange";a.isFullScreen=function(){if(a.hasMozNativeFullScreen)return b.mozFullScreen;else if(a.hasWebkitNativeFullScreen)return b.webkitIsFullScreen;else if(a.hasMsNativeFullScreen)return b.msFullscreenElement!==null};a.requestFullScreen=function(i){if(a.hasWebkitNativeFullScreen)i.webkitRequestFullScreen();else if(a.hasMozNativeFullScreen)i.mozRequestFullScreen();else a.hasMsNativeFullScreen&&i.msRequestFullscreen()}; 29a.cancelFullScreen=function(){if(a.hasWebkitNativeFullScreen)document.webkitCancelFullScreen();else if(a.hasMozNativeFullScreen)document.mozCancelFullScreen();else a.hasMsNativeFullScreen&&document.msExitFullscreen()}}if(a.hasSemiNativeFullScreen&&d.match(/mac os x 10_5/i)){a.hasNativeFullScreen=false;a.hasSemiNativeFullScreen=false}}};mejs.MediaFeatures.init(); 30mejs.HtmlMediaElement={pluginType:"native",isFullScreen:false,setCurrentTime:function(a){this.currentTime=a},setMuted:function(a){this.muted=a},setVolume:function(a){this.volume=a},stop:function(){this.pause()},setSrc:function(a){for(var b=this.getElementsByTagName("source");b.length>0;)this.removeChild(b[0]);
30if(typeof a=="string")this.src=a;else{var c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.src=c.src;break}}}},setVideoSize:function(a,b){this.width=a;this.height=b}}; 31mejs.PluginMediaElement=function(a,b,c){this.id=a;this.pluginType=b;this.src=c;this.events={};this.attributes={}}; 32mejs.PluginMediaElement.prototype={pluginElement:null,pluginType:"",isFullScreen:false,playbackRate:-1,defaultPlaybackRate:-1,seekable:[],played:[],paused:true,ended:false,seeking:false,duration:0,error:null,tagName:"",muted:false,volume:1,currentTime:0,play:function(){if(this.pluginApi!=null){this.pluginType=="youtube"||this.pluginType=="vimeo"?this.pluginApi.playVideo():this.pluginApi.playMedia();this.paused=false}},load:function(){if(this.pluginApi!=null){this.pluginType=="youtube"||this.pluginType== 33"vimeo"||this.pluginApi.loadMedia();this.paused=false}},pause:function(){if(this.pluginApi!=null){this.pluginType=="youtube"||this.pluginType=="vimeo"?this.pluginApi.pauseVideo():this.pluginApi.pauseMedia();this.paused=true}},stop:function(){if(this.pluginApi!=null){this.pluginType=="youtube"||this.pluginType=="vimeo"?this.pluginApi.stopVideo():this.pluginApi.stopMedia();this.paused=true}},canPlayType:function(a){var b,c,d,e=mejs.plugins[this.pluginType];for(b=0;b<e.length;b++){d=e[b];if(mejs.PluginDetector.hasPluginVersion(this.pluginType, 34d.version))for(c=0;c<d.types.length;c++)if(a==d.types[c])return"probably"}return""},positionFullscreenButton:function(a,b,c){this.pluginApi!=null&&this.pluginApi.positionFullscreenButton&&this.pluginApi.positionFullscreenButton(Math.floor(a),Math.floor(b),c)},hideFullscreenButton:function(){this.pluginApi!=null&&this.pluginApi.hideFullscreenButton&&this.pluginApi.hideFullscreenButton()},setSrc:function(a){if(typeof a=="string"){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(a));this.src=mejs.Utility.absolutizeUrl(a)}else{var b, 35c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(c.src));this.src=mejs.Utility.absolutizeUrl(a);break}}}},setCurrentTime:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"||this.pluginType=="vimeo"?this.pluginApi.seekTo(a):this.pluginApi.setCurrentTime(a);this.currentTime=a}},setVolume:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.setVolume(a*100):this.pluginApi.setVolume(a);this.volume=a}}, 36setMuted:function(a){if(this.pluginApi!=null){if(this.pluginType=="youtube"){a?this.pluginApi.mute():this.pluginApi.unMute();this.muted=a;this.dispatchEvent("volumechange")}else this.pluginApi.setMuted(a);this.muted=a}},setVideoSize:function(a,b){if(this.pluginElement&&this.pluginElement.style){this.pluginElement.style.width=a+"px";this.pluginElement.style.height=b+"px"}this.pluginApi!=null&&this.pluginApi.setVideoSize&&this.pluginApi.setVideoSize(a,b)},setFullscreen:function(a){this.pluginApi!=null&& 37this.pluginApi.setFullscreen&&this.pluginApi.setFullscreen(a)},enterFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.setFullscreen(true)},exitFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.setFullscreen(false)},addEventListener:function(a,b){this.events[a]=this.events[a]||[];this.events[a].push(b)},removeEventListener:function(a,b){if(!a){this.events={};return true}var c=this.events[a];if(!c)return true;if(!b){this.events[a]=[];return true}for(var d= 380;d<c.length;d++)if(c[d]===b){this.events[a].splice(d,1);return true}return false},dispatchEvent:function(a){var b,c,d=this.events[a];if(d){c=Array.prototype.slice.call(arguments,1);for(b=0;b<d.length;b++)d[b].apply(null,c)}},hasAttribute:function(a){return a in this.attributes},removeAttribute:function(a){delete this.attributes[a]},getAttribute:function(a){if(this.hasAttribute(a))return this.attributes[a];return""},setAttribute:function(a,b){this.attributes[a]=b},remove:function(){mejs.Utility.removeSwf(this.pluginElement.id); 39mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id)}}; 40mejs.MediaPluginBridge={pluginMediaElements:{},htmlMediaElements:{},registerPluginElement:function(a,b,c){this.pluginMediaElements[a]=b;this.htmlMediaElements[a]=c},unregisterPluginElement:function(a){delete this.pluginMediaElements[a];delete this.htmlMediaElements[a]},initPlugin:function(a){var b=this.pluginMediaElements[a],c=this.htmlMediaElements[a];if(b){switch(b.pluginType){case "flash":b.pluginElement=b.pluginApi=document.getElementById(a);break;case "silverlight":b.pluginElement=document.getElementById(b.id); 41b.pluginApi=b.pluginElement.Content.MediaElementJS}b.pluginApi!=null&&b.success&&b.success(b,c)}},fireEvent:function(a,b,c){var d,e;if(a=this.pluginMediaElements[a]){b={type:b,target:a};for(d in c){a[d]=c[d];b[d]=c[d]}e=c.bufferedTime||0;b.target.buffered=b.buffered={start:function(){return 0},end:function(){return e},length:1};a.dispatchEvent(b.type,b)}}}; 42mejs.MediaElementDefaults={mode:"auto",plugins:["flash","silverlight","youtube","vimeo"],enablePluginDebug:false,httpsBasicAuthSite:false,type:"",pluginPath:mejs.Utility.getScriptPath(["mediaelement.js","mediaelement.min.js","mediaelement-and-player.js","mediaelement-and-player.min.js"]),flashName:"flashmediaelement.swf",flashStreamer:"",enablePluginSmoothing:false,enablePseudoStreaming:false,pseudoStreamingStartQueryParam:"start",silverlightName:"silverlightmediaelement.xap",defaultVideoWidth:480, 43defaultVideoHeight:270,pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:0.8,success:function(){},error:function(){}};mejs.MediaElement=function(a,b){return mejs.HtmlMediaElementShim.create(a,b)}; 44mejs.HtmlMediaElementShim={create:function(a,b){var c=mejs.MediaElementDefaults,d=typeof a=="str
44ing"?document.getElementById(a):a,e=d.tagName.toLowerCase(),g=e==="audio"||e==="video",f=g?d.getAttribute("src"):d.getAttribute("href");e=d.getAttribute("poster");var i=d.getAttribute("autoplay"),k=d.getAttribute("preload"),h=d.getAttribute("controls"),j;for(j in b)c[j]=b[j];f=typeof f=="undefined"||f===null||f==""?null:f;e=typeof e=="undefined"||e===null?"":e;k=typeof k=="undefined"||k===null||k==="false"? 45"none":k;i=!(typeof i=="undefined"||i===null||i==="false");h=!(typeof h=="undefined"||h===null||h==="false");j=this.determinePlayback(d,c,mejs.MediaFeatures.supportsMediaTag,g,f);j.url=j.url!==null?mejs.Utility.absolutizeUrl(j.url):"";if(j.method=="native"){if(mejs.MediaFeatures.isBustedAndroid){d.src=j.url;d.addEventListener("click",function(){d.play()},false)}return this.updateNative(j,c,i,k)}else if(j.method!=="")return this.createPlugin(j,c,e,i,k,h);else{this.createErrorMessage(j,c,e);return this}}, 46determinePlayback:function(a,b,c,d,e){var g=[],f,i,k,h={method:"",url:"",htmlMediaElement:a,isVideo:a.tagName.toLowerCase()!="audio"},j;if(typeof b.type!="undefined"&&b.type!=="")if(typeof b.type=="string")g.push({type:b.type,url:e});else for(f=0;f<b.type.length;f++)g.push({type:b.type[f],url:e});else if(e!==null){k=this.formatType(e,a.getAttribute("type"));g.push({type:k,url:e})}else for(f=0;f<a.childNodes.length;f++){i=a.childNodes[f];if(i.nodeType==1&&i.tagName.toLowerCase()=="source"){e=i.getAttribute("src"); 47k=this.formatType(e,i.getAttribute("type"));i=i.getAttribute("media");if(!i||!window.matchMedia||window.matchMedia&&window.matchMedia(i).matches)g.push({type:k,url:e})}}if(!d&&g.length>0&&g[0].url!==null&&this.getTypeFromFile(g[0].url).indexOf("audio")>-1)h.isVideo=false;if(mejs.MediaFeatures.isBustedAndroid)a.canPlayType=function(m){return m.match(/video\/(mp4|m4v)/gi)!==null?"maybe":""};if(mejs.MediaFeatures.isChromium)a.canPlayType=function(m){return m.match(/video\/(webm|ogv|ogg)/gi)!==null?"maybe": 48""};if(c&&(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="native")&&!(mejs.MediaFeatures.isBustedNativeHTTPS&&b.httpsBasicAuthSite===true)){if(!d){f=document.createElement(h.isVideo?"video":"audio");a.parentNode.insertBefore(f,a);a.style.display="none";h.htmlMediaElement=a=f}for(f=0;f<g.length;f++)if(g[f].type=="video/m3u8"||a.canPlayType(g[f].type).replace(/no/,"")!==""||a.canPlayType(g[f].type.replace(/mp3/,"mpeg")).replace(/no/,"")!==""||a.canPlayType(g[f].type.replace(/m4a/,"mp4")).replace(/no/, 49"")!==""){h.method="native";h.url=g[f].url;break}if(h.method==="native"){if(h.url!==null)a.src=h.url;if(b.mode!=="auto_plugin")return h}}if(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="shim")for(f=0;f<g.length;f++){k=g[f].type;for(a=0;a<b.plugins.length;a++){e=b.plugins[a];i=mejs.plugins[e];for(c=0;c<i.length;c++){j=i[c];if(j.version==null||mejs.PluginDetector.hasPluginVersion(e,j.version))for(d=0;d<j.types.length;d++)if(k==j.types[d]){h.method=e;h.url=g[f].url;return h}}}}if(b.mode==="auto_plugin"&& 50h.method==="native")return h;if(h.method===""&&g.length>0)h.url=g[0].url;return h},formatType:function(a,b){return a&&!b?this.getTypeFromFile(a):b&&~b.indexOf(";")?b.substr(0,b.indexOf(";")):b},getTypeFromFile:function(a){a=a.split("?")[0];a=a.substring(a.lastIndexOf(".")+1).toLowerCase();return(/(mp4|m4v|ogg|ogv|m3u8|webm|webmv|flv|wmv|mpeg|mov)/gi.test(a)?"video":"audio")+"/"+this.getTypeFromExtension(a)},getTypeFromExtension:function(a){switch(a){case "mp4":case "m4v":case "m4a":return"mp4";case "webm":case "webma":case "webmv":return"webm"; 51case "ogg":case "oga":case "ogv":return"ogg";default:return a}},createErrorMessage:function(a,b,c){var d=a.htmlMediaElement,e=document.createElement("div");e.className="me-cannotplay";try{e.style.width=d.width+"px";e.style.height=d.height+"px"}catch(g){}e.innerHTML=b.customError?b.customError:c!==""?'<a href="'+a.url+'"><img src="'+c+'" width="100%" height="100%" /></a>':'<a href="'+a.url+'"><span>'+mejs.i18n.t("Download File")+"</span></a>";d.parentNode.insertBefore(e,d);d.style.display="none";b.error(d)}, 52createPlugin:function(a,b,c,d,e,g){c=a.htmlMediaElement;var f=1,i=1,k="me_"+a.method+"_"+mejs.meIndex++,h=new mejs.PluginMediaElement(k,a.method,a.url),j=document.createElement("div"),m;h.tagName=c.tagName;for(m=0;m<c.attributes.length;m++){var q=c.attributes[m];q.specified==true&&h.setAttribute(q.name,q.value)}for(m=c.parentNode;m!==null&&m.tagName.toLowerCase()!=="body"&&m.parentNode!=null;){if(m.parentNode.tagName.toLowerCase()==="p"){m.parentNode.parentNode.insertBefore(m,m.parentNode);break}m= 53m.parentNode}if(a.isVideo){f=b.pluginWidth>0?b.pluginWidth:b.videoWidth>0?b.videoWidth:c.getAttribute("width")!==null?c.getAttribute("width"):b.defaultVideoWidth;i=b.pluginHeight>0?b.pluginHeight:b.videoHeight>0?b.videoHeight:c.getAttribute("height")!==null?c.getAttribute("height"):b.defaultVideoHeight;f=mejs.Utility.encodeUrl(f);i=mejs.Utility.encodeUrl(i)}else if(b.enablePluginDebug){f=320;i=240}h.success=b.success;mejs.MediaPluginBridge.registerPluginElement(k,h,c);j.className="me-plugin";j.id= 54k+"_container";a.isVideo?c.parentNode.insertBefore(j,c):document.body.insertBefore(j,document.body.childNodes[0]);
54d=["id="+k,"isvideo="+(a.isVideo?"true":"false"),"autoplay="+(d?"true":"false"),"preload="+e,"width="+f,"startvolume="+b.startVolume,"timerrate="+b.timerRate,"flashstreamer="+b.flashStreamer,"height="+i,"pseudostreamstart="+b.pseudoStreamingStartQueryParam];if(a.url!==null)a.method=="flash"?d.push("file="+mejs.Utility.encodeUrl(a.url)):d.push("file="+a.url);b.enablePluginDebug&&d.push("debug=true"); 55b.enablePluginSmoothing&&d.push("smoothing=true");b.enablePseudoStreaming&&d.push("pseudostreaming=true");g&&d.push("controls=true");if(b.pluginVars)d=d.concat(b.pluginVars);switch(a.method){case "silverlight":j.innerHTML='<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="'+k+'" name="'+k+'" width="'+f+'" height="'+i+'" class="mejs-shim"><param name="initParams" value="'+d.join(",")+'" /><param name="windowless" value="true" /><param name="background" value="black" /><param name="minRuntimeVersion" value="3.0.0.0" /><param name="autoUpgrade" value="true" /><param name="source" value="'+ 56b.pluginPath+b.silverlightName+'" /></object>';break;case "flash":if(mejs.MediaFeatures.isIE){a=document.createElement("div");j.appendChild(a);a.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+k+'" width="'+f+'" height="'+i+'" class="mejs-shim"><param name="movie" value="'+b.pluginPath+b.flashName+"?x="+new Date+'" /><param name="flashvars" value="'+d.join("&")+'" /><param name="quality" value="high" /><param name="bgcolor" value="#000000" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><param name="scale" value="default" /></object>'}else j.innerHTML= 57'<embed id="'+k+'" name="'+k+'" play="true" loop="false" quality="high" bgcolor="#000000" wmode="transparent" allowScriptAccess="always" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" src="'+b.pluginPath+b.flashName+'" flashvars="'+d.join("&")+'" width="'+f+'" height="'+i+'" scale="default"class="mejs-shim"></embed>';break;case "youtube":if(a.url.lastIndexOf("youtu.be")!=-1){a=a.url.substr(a.url.lastIndexOf("/")+1);if(a.indexOf("?")!= 58-1)a=a.substr(0,a.indexOf("?"))}else a=a.url.substr(a.url.lastIndexOf("=")+1);youtubeSettings={container:j,containerId:j.id,pluginMediaElement:h,pluginId:k,videoId:a,height:i,width:f};mejs.PluginDetector.hasPluginVersion("flash",[10,0,0])?mejs.YouTubeApi.createFlash(youtubeSettings):mejs.YouTubeApi.enqueueIframe(youtubeSettings);break;case "vimeo":b=k+"_player";h.vimeoid=a.url.substr(a.url.lastIndexOf("/")+1);j.innerHTML='<iframe src="//player.vimeo.com/video/'+h.vimeoid+"?api=1&portrait=0&byline=0&title=0&player_id="+ 59b+'" width="'+f+'" height="'+i+'" frameborder="0" class="mejs-shim" id="'+b+'"></iframe>';if(typeof $f=="function"){var l=$f(j.childNodes[0]);l.addEvent("ready",function(){function o(n,p,r,s){n={type:r,target:p};if(r=="timeupdate"){p.currentTime=n.currentTime=s.seconds;p.duration=n.duration=s.duration}p.dispatchEvent(n.type,n)}$.extend(l,{playVideo:function(){l.api("play")},stopVideo:function(){l.api("unload")},pauseVideo:function(){l.api("pause")},seekTo:function(n){l.api("seekTo",n)},setVolume:function(n){l.api("setVolume", 60n)},setMuted:function(n){if(n){l.lastVolume=l.api("getVolume");l.api("setVolume",0)}else{l.api("setVolume",l.lastVolume);delete l.lastVolume}}});l.addEvent("play",function(){o(l,h,"play");o(l,h,"playing")});l.addEvent("pause",function(){o(l,h,"pause")});l.addEvent("finish",function(){o(l,h,"ended")});l.addEvent("playProgress",function(n){o(l,h,"timeupdate",n)});h.pluginElement=j;h.pluginApi=l;mejs.MediaPluginBridge.initPlugin(k)})}else console.warn("You need to include froogaloop for vimeo to work")}c.style.display= 61"none";c.removeAttribute("autoplay");return h},updateNative:function(a,b){var c=a.htmlMediaElement,d;for(d in mejs.HtmlMediaElement)c[d]=mejs.HtmlMediaElement[d];b.success(c,c);return c}}; 62mejs.YouTubeApi={isIframeStarted:false,isIframeLoaded:false,loadIframeApi:function(){if(!this.isIframeStarted){var a=document.createElement("script");a.src="//www.youtube.com/player_api";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b);this.isIframeStarted=true}}
62,iframeQueue:[],enqueueIframe:function(a){if(this.isLoaded)this.createIframe(a);else{this.loadIframeApi();this.iframeQueue.push(a)}},createIframe:function(a){var b=a.pluginMediaElement,c=new YT.Player(a.containerId, 63{height:a.height,width:a.width,videoId:a.videoId,playerVars:{controls:0},events:{onReady:function(){a.pluginMediaElement.pluginApi=c;mejs.MediaPluginBridge.initPlugin(a.pluginId);setInterval(function(){mejs.YouTubeApi.createEvent(c,b,"timeupdate")},250)},onStateChange:function(d){mejs.YouTubeApi.handleStateChange(d.data,c,b)}}})},createEvent:function(a,b,c){c={type:c,target:b};if(a&&a.getDuration){b.currentTime=c.currentTime=a.getCurrentTime();b.duration=c.duration=a.getDuration();c.paused=b.paused; 64c.ended=b.ended;c.muted=a.isMuted();c.volume=a.getVolume()/100;c.bytesTotal=a.getVideoBytesTotal();c.bufferedBytes=a.getVideoBytesLoaded();var d=c.bufferedBytes/c.bytesTotal*c.duration;c.target.buffered=c.buffered={start:function(){return 0},end:function(){return d},length:1}}b.dispatchEvent(c.type,c)},iFrameReady:function(){for(this.isIframeLoaded=this.isLoaded=true;this.iframeQueue.length>0;)this.createIframe(this.iframeQueue.pop())},flashPlayers:{},createFlash:function(a){this.flashPlayers[a.pluginId]= 65a;var b,c="//www.youtube.com/apiplayer?enablejsapi=1&playerapiid="+a.pluginId+"&version=3&autoplay=0&controls=0&modestbranding=1&loop=0";if(mejs.MediaFeatures.isIE){b=document.createElement("div");a.container.appendChild(b);b.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+a.pluginId+'" width="'+a.width+'" height="'+a.height+'" class="mejs-shim"><param name="movie" value="'+ 66c+'" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else a.container.innerHTML='<object type="application/x-shockwave-flash" id="'+a.pluginId+'" data="'+c+'" width="'+a.width+'" height="'+a.height+'" style="visibility: visible; " class="mejs-shim"><param name="allowScriptAccess" value="always"><param name="wmode" value="transparent"></object>'},flashReady:function(a){var b=this.flashPlayers[a],c= 67document.getElementById(a),d=b.pluginMediaElement;d.pluginApi=d.pluginElement=c;mejs.MediaPluginBridge.initPlugin(a);c.cueVideoById(b.videoId);a=b.containerId+"_callback";window[a]=function(e){mejs.YouTubeApi.handleStateChange(e,c,d)};c.addEventListener("onStateChange",a);setInterval(function(){mejs.YouTubeApi.createEvent(c,d,"timeupdate")},250);mejs.YouTubeApi.createEvent(c,d,"canplay")},handleStateChange:function(a,b,c){switch(a){case -1:c.paused=true;c.ended=true;mejs.YouTubeApi.createEvent(b, 68c,"loadedmetadata");break;case 0:c.paused=false;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"ended");break;case 1:c.paused=false;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"play");mejs.YouTubeApi.createEvent(b,c,"playing");break;case 2:c.paused=true;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"pause");break;case 3:mejs.YouTubeApi.createEvent(b,c,"progress")}}};function onYouTubePlayerAPIReady(){mejs.YouTubeApi.iFrameReady()}function onYouTubePlayerReady(a){mejs.YouTubeApi.flashReady(a)} 69window.mejs=mejs;window.MediaElement=mejs.MediaElement; 70(function(a,b){var c={locale:{language:"",strings:{}},methods:{}};c.getLanguage=function(){return(c.locale.language||window.navigator.userLanguage||window.navigator.language).substr(0,2).toLowerCase()};if(typeof mejsL10n!="undefined")c.locale.language=mejsL10n.language;c.methods.checkPlain=function(d){var e,g,f={"&":"&",'"':""","<":"<",">":">"};d=String(d);for(e in f)if(f.hasOwnProperty(e)){g=RegExp(e,"g");d=d.replace(g,f[e])}return d};c.methods.t=function(d,e){if(c.locale.strings&& 71c.locale.strings[e.context]&&c.locale.strings[e.context][d])d=c.locale.strings[e.context][d];return c.methods.checkPlain(d)};c.t=function(d,e){if(typeof d==="string"&&d.length>0){var g=c.getLanguage();e=e||{context:g};return c.methods.t(d,e)}else throw{name:"InvalidArgumentException",message:"First argument is either not a string or empty."};};b.i18n=c})(document,mejs);
71(function(a){if(typeof mejsL10n!="undefined")a[mejsL10n.language]=mejsL10n.strings})(mejs.i18n.locale.strings); 72(function(a){if(typeof a.de==="undefined")a.de={Fullscreen:"Vollbild","Go Fullscreen":"Vollbild an","Turn off Fullscreen":"Vollbild aus",Close:"Schlie\u00dfen"}})(mejs.i18n.locale.strings);(function(a){if(typeof a.zh==="undefined")a.zh={Fullscreen:"\u5168\u87a2\u5e55","Go Fullscreen":"\u5168\u5c4f\u6a21\u5f0f","Turn off Fullscreen":"\u9000\u51fa\u5168\u5c4f\u6a21\u5f0f",Close:"\u95dc\u9589"}})(mejs.i18n.locale.strings); 73 74/*! 75 * MediaElementPlayer 76 * http://mediaelementjs.com/ 77 * 78 * Creates a controller bar for HTML5 <video> add <audio> tags 79 * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper) 80 * 81 * Copyright 2010-2013, John Dyer (http://j.hn/) 82 * License: MIT 83 * 84 */if(typeof jQuery!="undefined")mejs.$=jQuery;else if(typeof ender!="undefined")mejs.$=ender; 85(function(f){mejs.MepDefaults={poster:"",showPosterWhenEnded:false,defaultVideoWidth:480,defaultVideoHeight:270,videoWidth:-1,videoHeight:-1,defaultAudioWidth:400,defaultAudioHeight:30,defaultSeekBackwardInterval:function(a){return a.duration*0.05},defaultSeekForwardInterval:function(a){return a.duration*0.05},setDimensions:true,audioWidth:-1,audioHeight:-1,startVolume:0.8,loop:false,autoRewind:true,enableAutosize:true,alwaysShowHours:false,showTimecodeFrameCount:false,framesPerSecond:25,autosizeProgress:true, 86alwaysShowControls:false,hideVideoControlsOnLoad:false,clickToPlayPause:true,iPadUseNativeControls:false,iPhoneUseNativeControls:false,AndroidUseNativeControls:false,features:["playpause","current","progress","duration","tracks","volume","fullscreen"],isVideo:true,enableKeyboard:true,pauseOtherPlayers:true,keyActions:[{keys:[32,179],action:function(a,b){b.paused||b.ended?a.play():a.pause()}},{keys:[38],action:function(a,b){a.container.find(".mejs-volume-slider").css("display","block");if(a.isVideo){a.showControls(); 87a.startControlsTimer()}b.setVolume(Math.min(b.volume+0.1,1))}},{keys:[40],action:function(a,b){a.container.find(".mejs-volume-slider").css("display","block");if(a.isVideo){a.showControls();a.startControlsTimer()}
87b.setVolume(Math.max(b.volume-0.1,0))}},{keys:[37,227],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.max(b.currentTime-a.options.defaultSeekBackwardInterval(b),0);b.setCurrentTime(c)}}},{keys:[39,228],action:function(a, 88b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.min(b.currentTime+a.options.defaultSeekForwardInterval(b),b.duration);b.setCurrentTime(c)}}},{keys:[70],action:function(a){if(typeof a.enterFullScreen!="undefined")a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}},{keys:[77],action:function(a){a.container.find(".mejs-volume-slider").css("display","block");if(a.isVideo){a.showControls();a.startControlsTimer()}a.media.muted?a.setMuted(false): 89a.setMuted(true)}}]};mejs.mepIndex=0;mejs.players={};mejs.MediaElementPlayer=function(a,b){if(!(this instanceof mejs.MediaElementPlayer))return new mejs.MediaElementPlayer(a,b);this.$media=this.$node=f(a);this.node=this.media=this.$media[0];if(typeof this.node.player!="undefined")return this.node.player;else this.node.player=this;if(typeof b=="undefined")b=this.$node.data("mejsoptions");this.options=f.extend({},mejs.MepDefaults,b);this.id="mep_"+mejs.mepIndex++;mejs.players[this.id]=this;this.init(); 90return this};mejs.MediaElementPlayer.prototype={hasFocus:false,controlsAreVisible:true,init:function(){var a=this,b=mejs.MediaFeatures,c=f.extend(true,{},a.options,{success:function(d,g){a.meReady(d,g)},error:function(d){a.handleError(d)}}),e=a.media.tagName.toLowerCase();a.isDynamic=e!=="audio"&&e!=="video";a.isVideo=a.isDynamic?a.options.isVideo:e!=="audio"&&a.options.isVideo;if(b.isiPad&&a.options.iPadUseNativeControls||b.isiPhone&&a.options.iPhoneUseNativeControls){a.$media.attr("controls","controls"); 91b.isiPad&&a.media.getAttribute("autoplay")!==null&&a.play()}else if(!(b.isAndroid&&a.options.AndroidUseNativeControls)){a.$media.removeAttr("controls");a.container=f('<div id="'+a.id+'" class="mejs-container '+(mejs.MediaFeatures.svg?"svg":"no-svg")+'"><div class="mejs-inner"><div class="mejs-mediaelement"></div><div class="mejs-layers"></div><div class="mejs-controls"></div><div class="mejs-clear"></div></div></div>').addClass(a.$media[0].className).insertBefore(a.$media);a.container.addClass((b.isAndroid? 92"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=a.isVideo?"video":"audio";e=b.substring(0,1).toUpperCase()+b.substring(1); 93a.width=a.options[b+"Width"]>0||a.options[b+"Width"].toString().indexOf("%")>-1?a.options[b+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+e+"Width"];a.height=a.options[b+"Height"]>0||a.options[b+"Height"].toString().indexOf("%")>-1?a.options[b+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!==null?a.$media.attr("height"): 94a.options["default"+e+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.width;c.pluginHeight=a.height}mejs.MediaElement(a.$media[0],c);typeof a.container!="undefined"&&a.controlsAreVisible&&a.container.trigger("controlsshown")},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true;b.container.trigger("controlsshown")});b.container.find(".mejs-control").css("visibility", 95"visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility","visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true;b.container.trigger("controlsshown")}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!(!b.controlsAreVisible||b.options.alwaysShowControls))if(a){b.controls.stop(true,true).fadeOut(200,function(){f(this).css("visibility", 96"hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")}},controlsTimer:null,startControlsTimer:function(a){var b= 97this;a=typeof a!="undefined"?a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false);this.controlsEnabled=true}, 98meReady:function(a,b){var c=this,e=mejs.MediaFeatures,d=b.getAttribute("autoplay");d=!(typeof d=="undefined"||d===null||d==="false");var g;if(!c.created){c.created=true;c.media=a;
98c.domNode=b;if(!(e.isAndroid&&c.options.AndroidUseNativeControls)&&!(e.isiPad&&c.options.iPadUseNativeControls)&&!(e.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media);c.findTracks();for(g in c.options.features){e= 99c.options.features[g];if(c["build"+e])try{c["build"+e](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);else c.controlsEnabled&&c.showControls(false)});else{c.clickToPlayPauseCallback=function(){if(c.options.clickToPlayPause)c.media.paused?c.play():c.pause()};c.media.addEventListener("click", 100c.clickToPlayPauseCallback,false);c.container.bind("mouseenter mouseover",function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&&c.startControlsTimer(1E3)})}c.options.hideVideoControlsOnLoad&& 101c.hideControls(false);d&&!c.options.alwaysShowControls&&c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(j){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(j.target.videoHeight)){c.setPlayerSize(j.target.videoWidth,j.target.videoHeight);c.setControlsSize();c.media.setVideoSize(j.target.videoWidth,j.target.videoHeight)}},false)}a.addEventListener("play",function(){for(var j in mejs.players){var m=mejs.players[j];m.id!=c.id&& 102c.options.pauseOtherPlayers&&!m.paused&&!m.ended&&m.pause();m.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){if(c.options.autoRewind)try{c.media.setCurrentTime(0)}catch(j){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",function(){c.updateDuration&&c.updateDuration();c.updateCurrent&& 103c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width,c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);c.globalBind("resize",function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.options.autoplay&&c.container.find(".mejs-overlay-play").hide()}d&&a.pluginType=="native"&&c.play();if(c.options.success)typeof c.options.success== 104"string"?window[c.options.success](c.media,c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(!this.options.setDimensions)return false;if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0||this.$node.css("max-width")==="100%"||this.$node[0].currentStyle&&this.$node[0].currentStyle.maxWidth==="100%"){var c=this.isVideo? 105this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.media.getAttribute("width")!==null?this.media.getAttribute("width"):this.options.defaultVideoWidth:this.options.defaultAudioWidth,e=this.isVideo?this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.media.getAttribute("height")!==null?this.media.getAttribute("height"):this.options.defaultVideoHeight:this.options.defaultAudioHeight,d=this.container.parent().closest(":visible").width(),g=this.container.parent().closest(":visible").height(); 106c=this.isVideo||!this.options.autosizeProgress?parseInt(d*e/c,10):e;if(isNaN(c)||g!=0&&c>g)c=g;if(this.container.parent()[0].tagName.toLowerCase()==="body"){d=f(window).width();c=f(window).height()}if(c!=0&&d!=0){this.container.width(d).height(c);this.$media.add(this.container.find(".mejs-shim")).width("100%").height("100%");this.isVideo&&this.media.setVideoSize&&this.media.setVideoSize(d,c);this.layers.children(".mejs-layer").width("100%").height("100%")}}else{this.container.width(this.width).height(this.height); 107this.layers.children(".mejs-layer").width(this.width).height(this.height)}d=this.layers.find(".mejs-overlay-play");g=d.find(".mejs-overlay-button");d.height(this.container.height()-this.controls.height());g.css("margin-top","-"+(g.height()/2-this.controls.height()/2).toString()+"px")},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),e=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var d=c.siblings(), 108g=d.last(),k=null;if(!(!this.container.is(":visible")||!c.length||!c.is(":visible"))){if(this.options&&!this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){d.each(function(){var j=f(this);if(j.css("position")!="absolute"&&j.is(":visible"))a+=f(this).outerWidth(true)});b=this.controls.width()-a-(c.outerWidth(true)-c.width())}do{c.width(b);e.width(b-(e.outerWidth(true)-e.width()));if(g.css("position")!="absolute"){k=g.position();b--}}while(k!=null&&k.top>0&&b>0);this.setProgressRail&& 109this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()}},buildposter:function(a,b,c,e){var d=f('<div class="mejs-poster mejs-layer"></div>').appendTo(c);b=a.$media.attr("poster");if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):d.hide();e.addEventListener("play",function(){d.hide()},false);a.options.showPosterWhenEnded&&a.options.autoRewind&&e.addEventListener("ended",function(){d.show()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"), 110c=b.find("img");if(c.length==0)c=f('<img width="100%" height="100%" />').appendTo(b);c.attr("src",a);b.css({"background-image":"url("+a+")"})},buildoverlays:function(a,b,c,e){var d=this;if(a.isVideo){var g=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-loading"><span></span></div></div>').hide().appendTo(c),k=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-error"></div></div>').hide().appendTo(c),j=f('<div class="mejs-overlay mejs-layer mejs-overlay-play"><div class="mejs-overlay-button"></div></div>').appendTo(c).bind("click", 111function(){d.options.clickToPlayPause&&e.paused&&e.play()});e.addEventListener("play",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);e.addEventListener("playing",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);e.addEventListener("seeking",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("seeked",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone|| 112j.show()},false);e.addEventListener("waiting",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("loadeddata",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("canplay",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("error",function(){g.hide();b.find(".mejs-time-buffering").hide();k.show();k.find("mejs-overlay-error").html("Error loading this resource")},false);e.addEventListener("keydown", 113function(m){d.onkeydown(a,e,m)},false)}},buildkeyboard:function(a,b,c,e){var d=this;d.globalBind("keydown",function(g){return d.onkeydown(a,e,g)});d.globalBind("click",function(g){a.hasFocus=f(g.target).closest(".mejs-container").length!=0})},onkeydown:function(a,b,c){if(a.hasFocus&&a.options.enableKeyboard)for(var e=0,d=a.options.keyActions.length;e<d;e++)for(var g=a.options.keyActions[e],k=0,j=g.keys.length;k<j;k++)if(c.keyCode==g.keys[k]){typeof c.preventDefault=="function"&&c.preventDefault(); 114g.action(a,b,c.keyCode);return false}return true},findTracks:function(){var a=this,b=a.$media.find("track");a.tracks=[];b.each(function(c,e){e=f(e);a.tracks.push({srclang:e.attr("srclang")?e.attr("srclang").toLowerCase():"",src:e.attr("src"),kind:e.attr("kind"),label:e.attr("label")||"",entries:[],isLoaded:false})})},changeSkin:function(a){this.container[0].className="mejs-container "+a;this.setPlayerSize(this.width,this.height);this.setControlsSize()},play:function(){this.load();this.media.play()}, 115pause:function(){try{this.media.pause()}catch(a){}},load:function(){this.isLoaded||this.media.load();this.isLoaded=true},setMuted:function(a){this.media.setMuted(a)},setCurrentTime:function(a){this.media.setCurrentTime(a)},getCurrentTime:function(){return this.media.currentTime},setVolume:function(a){this.media.setVolume(a)},getVolume:function(){return this.media.volume},setSrc:function(a){this.media.setSrc(a)},remove:function(){var a,b;for(a in this.options.features){b=this.options.features[a];if(this["clean"+ 116b])try{this["clean"+b](this)}catch(c){}}if(this.isDynamic)this.$node.insertBefore(this.container);else{this.$media.prop("controls",true);
116this.$node.clone().insertBefore(this.container).show();this.$node.remove()}this.media.pluginType!=="native"&&this.media.remove();delete mejs.players[this.id];typeof this.container=="object"&&this.container.remove();this.globalUnbind();delete this.node.player}};(function(){function a(c,e){var d={d:[],w:[]};f.each((c||"").split(" "),function(g,k){var j=k+"."+e;if(j.indexOf(".")=== 1170){d.d.push(j);d.w.push(j)}else d[b.test(k)?"w":"d"].push(j)});d.d=d.d.join(" ");d.w=d.w.join(" ");return d}var b=/^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/;mejs.MediaElementPlayer.prototype.globalBind=function(c,e,d){c=a(c,this.id);c.d&&f(document).bind(c.d,e,d);c.w&&f(window).bind(c.w,e,d)};mejs.MediaElementPlayer.prototype.globalUnbind=function(c,e){c=a(c,this.id);c.d&&f(document).unbind(c.d,e);c.w&&f(window).unbind(c.w,e)}})(); 118if(typeof f!="undefined"){f.fn.mediaelementplayer=function(a){a===false?this.each(function(){var b=f(this).data("mediaelementplayer");b&&b.remove();f(this).removeData("mediaelementplayer")}):this.each(function(){f(this).data("mediaelementplayer",new mejs.MediaElementPlayer(this,a))});return this};f(document).ready(function(){f(".mejs-player").mediaelementplayer()})}window.MediaElementPlayer=mejs.MediaElementPlayer})(mejs.$); 119(function(f){f.extend(mejs.MepDefaults,{playpauseText:mejs.i18n.t("Play/Pause")});f.extend(MediaElementPlayer.prototype,{buildplaypause:function(a,b,c,e){var d=f('<div class="mejs-button mejs-playpause-button mejs-play" ><button type="button" aria-controls="'+this.id+'" title="'+this.options.playpauseText+'" aria-label="'+this.options.playpauseText+'"></button></div>').appendTo(b).click(function(g){g.preventDefault();e.paused?e.play():e.pause();return false});e.addEventListener("play",function(){d.removeClass("mejs-play").addClass("mejs-pause")}, 120false);e.addEventListener("playing",function(){d.removeClass("mejs-play").addClass("mejs-pause")},false);e.addEventListener("pause",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false);e.addEventListener("paused",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$); 121(function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,e){f('<div class="mejs-button mejs-stop-button mejs-stop"><button type="button" aria-controls="'+this.id+'" title="'+this.options.stopText+'" aria-label="'+this.options.stopText+'"></button></div>').appendTo(b).click(function(){e.paused||e.pause();if(e.currentTime>0){e.setCurrentTime(0);e.pause();b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left", 122"0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$); 123(function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,e){f('<div class="mejs-time-rail"><span class="mejs-time-total"><span class="mejs-time-buffering"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span></span></div>').appendTo(b);b.find(".mejs-time-buffering").hide();var d= 124this,g=b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var k=b.find(".mejs-time-current"),j=b.find(".mejs-time-handle"),m=b.find(".mejs-time-float"),q=b.find(".mejs-time-float-current"),p=function(h){h=h.originalEvent.changedTouches?h.originalEvent.changedTouches[0].pageX:h.pageX;var l=g.offset(),r=g.outerWidth(true),n=0,o=n=0;if(e.duration){if(h<l.left)h=l.left;else if(h>r+l.left)h=r+l.left;o=h-l.left;n=o/r;n=n<=0.02?0:n*e.duration;t&&n!==e.currentTime&&e.setCurrentTime(n);if(!mejs.MediaFeatures.hasTouch){m.css("left", 125o);q.html(mejs.Utility.secondsToTimeCode(n));m.show()}}},t=false;g.bind("mousedown touchstart",function(h){if(h.which===1||h.which===0){t=true;p(h);d.globalBind("mousemove.dur touchmove.dur",function(l){p(l)});d.globalBind("mouseup.dur touchend.dur",function(){t=false;m.hide();d.globalUnbind(".dur")});return false}}).bind("mouseenter",function(){d.globalBind("mousemove.dur",function(h){p(h)});mejs.MediaFeatures.hasTouch||m.show()}).bind("mouseleave",function(){if(!t){d.globalUnbind(".dur");m.hide()}}); 126e.addEventListener("progress",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);e.addEventListener("timeupdate",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);d.loaded=c;d.total=g;d.current=k;d.handle=j},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal; 127else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1,Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=Math.round(this.total.width()*this.media.currentTime/this.media.duration),b=a-Math.round(this.handle.outerWidth(true)/2);this.current.width(a);this.handle.css("left",b)}}})})(mejs.$); 128(function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:"<span> | </span>"});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,e){f('<div class="mejs-time"><span class="mejs-currenttime">
128'+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"</span></div>").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");e.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a,b, 129c,e){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+'<span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span>").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container"); 130f('<div class="mejs-time mejs-duration-container"><span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span></div>").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");e.addEventListener("timeupdate",function(){a.updateDuration()}, 131false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){this.container.toggleClass("mejs-long-video",this.media.duration>3600);if(this.durationD&&(this.options.duration>0||this.media.duration))this.durationD.html(mejs.Utility.secondsToTimeCode(this.options.duration>0?this.options.duration: 132this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$); 133(function(f){f.extend(mejs.MepDefaults,{muteText:mejs.i18n.t("Mute Toggle"),hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,e){if(!((mejs.MediaFeatures.isAndroid||mejs.MediaFeatures.isiOS)&&this.options.hideVolumeOnTouchDevices)){var d=this,g=d.isVideo?d.options.videoVolume:d.options.audioVolume,k=g=="horizontal"?f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+ 134d.id+'" title="'+d.options.muteText+'" aria-label="'+d.options.muteText+'"></button></div><div class="mejs-horizontal-volume-slider"><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current"></div><div class="mejs-horizontal-volume-handle"></div></div>').appendTo(b):f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+d.id+'" title="'+d.options.muteText+'" aria-label="'+d.options.muteText+'"></button><div class="mejs-volume-slider"><div class="mejs-volume-total"></div><div class="mejs-volume-current"></div><div class="mejs-volume-handle"></div></div></div>').appendTo(b), 135j=d.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),m=d.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),q=d.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),p=d.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),t=function(n,o){if(!j.is(":visible")&&typeof o=="undefined"){j.show();t(n,true);j.hide()}else{n=Math.max(0,n);n=Math.min(n,1);n==0?k.removeClass("mejs-mute").addClass("mejs-unmute"):k.removeClass("mejs-unmute").addClass("mejs-mute"); 136if(g=="vertical"){var s=m.height(),u=m.position(),v=s-s*n;p.css("top",Math.round(u.top+v-p.height()/2));q.height(s-v);q.css("top",u.top+v)}else{s=m.width();u=m.position();s=s*n;p.css("left",Math.round(u.left+s-p.width()/2));q.width(Math.round(s))}}},h=function(n){var o=null,s=m.offset();if(g=="vertical"){o=m.height();parseInt(m.css("top").replace(/px/,""),10);o=(o-(n.pageY-s.top))/o;if(s.top==0||s.left==0)return}else{o=m.width();o=(n.pageX-s.left)/o}o=Math.max(0,o);o=Math.min(o,1);t(o);
136o==0?e.setMuted(true): 137e.setMuted(false);e.setVolume(o)},l=false,r=false;k.hover(function(){j.show();r=true},function(){r=false;!l&&g=="vertical"&&j.hide()});j.bind("mouseover",function(){r=true}).bind("mousedown",function(n){h(n);d.globalBind("mousemove.vol",function(o){h(o)});d.globalBind("mouseup.vol",function(){l=false;d.globalUnbind(".vol");!r&&g=="vertical"&&j.hide()});l=true;return false});k.find("button").click(function(){e.setMuted(!e.muted)});e.addEventListener("volumechange",function(){if(!l)if(e.muted){t(0); 138k.removeClass("mejs-mute").addClass("mejs-unmute")}else{t(e.volume);k.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(d.container.is(":visible")){t(a.options.startVolume);a.options.startVolume===0&&e.setMuted(true);e.pluginType==="native"&&e.setVolume(a.options.startVolume)}}}})})(mejs.$); 139(function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:mejs.i18n.t("Fullscreen")});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,isInIframe:false,buildfullscreen:function(a,b,c,e){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;mejs.MediaFeatures.hasTrueNativeFullScreen&&a.globalBind(mejs.MediaFeatures.fullScreenEventName,function(){if(a.isFullScreen)if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen= 140true;a.setControlsSize()}else{a.isNativeFullScreen=false;a.exitFullScreen()}});var d=this,g=f('<div class="mejs-button mejs-fullscreen-button"><button type="button" aria-controls="'+d.id+'" title="'+d.options.fullscreenText+'" aria-label="'+d.options.fullscreenText+'"></button></div>').appendTo(b);if(d.media.pluginType==="native"||!d.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||a.isFullScreen? 141a.exitFullScreen():a.enterFullScreen()});else{var k=null;if(function(){var h=document.createElement("x"),l=document.documentElement,r=window.getComputedStyle;if(!("pointerEvents"in h.style))return false;h.style.pointerEvents="auto";h.style.pointerEvents="x";l.appendChild(h);r=r&&r(h,"").pointerEvents==="auto";l.removeChild(h);return!!r}()&&!mejs.MediaFeatures.isOpera){var j=false,m=function(){if(j){for(var h in q)q[h].hide();g.css("pointer-events","");d.controls.css("pointer-events","");d.media.removeEventListener("click", 142d.clickToPlayPauseCallback);j=false}},q={};b=["top","left","right","bottom"];var p,t=function(){var h=g.offset().left-d.container.offset().left,l=g.offset().top-d.container.offset().top,r=g.outerWidth(true),n=g.outerHeight(true),o=d.container.width(),s=d.container.height();for(p in q)q[p].css({position:"absolute",top:0,left:0});q.top.width(o).height(l);q.left.width(h).height(n).css({top:l});q.right.width(o-h-r).height(n).css({top:l,left:h+r});q.bottom.width(o).height(s-n-l).css({top:l+n})};d.globalBind("resize", 143function(){t()});p=0;for(c=b.length;p<c;p++)q[b[p]]=f('<div class="mejs-fullscreen-hover" />').appendTo(d.container).mouseover(m).hide();g.on("mouseover",function(){if(!d.isFullScreen){var h=g.offset(),l=a.container.offset();e.positionFullscreenButton(h.left-l.left,h.top-l.top,false);g.css("pointer-events","none");d.controls.css("pointer-events","none");d.media.addEventListener("click",d.clickToPlayPauseCallback);for(p in q)q[p].show();t();j=true}});e.addEventListener("fullscreenchange",function(){d.isFullScreen= 144!d.isFullScreen;d.isFullScreen?d.media.removeEventListener("click",d.clickToPlayPauseCallback):d.media.addEventListener("click",d.clickToPlayPauseCallback);m()});d.globalBind("mousemove",function(h){if(j){var l=g.offset();if(h.pageY<l.top||h.pageY>l.top+g.outerHeight(true)||h.pageX<l.left||h.pageX>l.left+g.outerWidth(true)){g.css("pointer-events","");d.controls.css("pointer-events","");j=false}}})}else g.on("mouseover",function(){if(k!==null){clearTimeout(k);delete k}var h=g.offset(),l=a.container.offset(); 145e.positionFullscreenButton(h.left-l.left,h.top-l.top,true)}).on("mouseout",function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){e.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;d.globalBind("keydown",function(h){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||d.isFullScreen)&&h.keyCode==27)a.exitFullScreen()})}},cleanfullscreen:function(a){a.exitFullScreen()},containerSizeTimeout:null,enterFullScreen:function(){var a=this;if(!(a.media.pluginType!== 146"native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){f(document.documentElement).addClass("mejs-fullscreen");normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&setTimeout(function c(){if(a.isNativeFullScreen){var e=(window.devicePixelRatio||1)*f(window).width(),d=screen.width;Math.abs(d-e)>d*0.0020?a.exitFullScreen(): 147setTimeout(c,500)}},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();
147window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},250);else{a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+ 148",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");a.containerSizeTimeout=setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.media.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find(".mejs-shim").width("100%").height("100%");a.media.setVideoSize(f(window).width(),f(window).height())}a.layers.children("div").width("100%").height("100%"); 149a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true;a.container.find(".mejs-captions-text").css("font-size",screen.width/a.width*1*100+"%");a.container.find(".mejs-captions-position").css("bottom","45px")}},exitFullScreen:function(){clearTimeout(this.containerSizeTimeout);if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&& 150(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen();f(document.documentElement).removeClass("mejs-fullscreen");this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.media.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find(".mejs-shim").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight); 151this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen");this.setControlsSize();this.isFullScreen=false;this.container.find(".mejs-captions-text").css("font-size","");this.container.find(".mejs-captions-position").css("bottom","")}}})})(mejs.$); 152(function(f){f.extend(mejs.MepDefaults,{speeds:["1.50","1.25","1.00","0.75"],defaultSpeed:"1.00"});f.extend(MediaElementPlayer.prototype,{buildspeed:function(a,b,c,e){if(this.media.pluginType=="native"){c='<div class="mejs-button mejs-speed-button"><button type="button">'+this.options.defaultSpeed+'x</button><div class="mejs-speed-selector"><ul>';var d;f.inArray(this.options.defaultSpeed,this.options.speeds)===-1&&this.options.speeds.push(this.options.defaultSpeed);this.options.speeds.sort(function(g, 153k){return parseFloat(k)-parseFloat(g)});for(d=0;d<this.options.speeds.length;d++){c+='<li><input type="radio" name="speed" value="'+this.options.speeds[d]+'" id="'+this.options.speeds[d]+'" ';if(this.options.speeds[d]==this.options.defaultSpeed){c+="checked=true ";c+='/><label for="'+this.options.speeds[d]+'" class="mejs-speed-selected">'+this.options.speeds[d]+"x</label></li>"}else c+='/><label for="'+this.options.speeds[d]+'">'+this.options.speeds[d]+"x</label></li>"}c+="</ul></div></div>";a.speedButton= 154f(c).appendTo(b);a.playbackspeed=this.options.defaultSpeed;a.speedButton.on("click","input[type=radio]",function(){a.playbackspeed=f(this).attr("value");e.playbackRate=parseFloat(a.playbackspeed);a.speedButton.find("button").text(a.playbackspeed+"x");a.speedButton.find(".mejs-speed-selected").removeClass("mejs-speed-selected");a.speedButton.find("input[type=radio]:checked").next().addClass("mejs-speed-selected")});b=a.speedButton.find(".mejs-speed-selector");b.height(this.speedButton.find(".mejs-speed-selector ul").outerHeight(true)+ 155a.speedButton.find(".mejs-speed-translations").outerHeight(true));b.css("top",-1*b.height()+"px")}}})})(mejs.$); 156(function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:mejs.i18n.t("Captions/Subtitles"),hideCaptionsButtonWhenEmpty:true,toggleCaptionsButtonWhenOnlyOne:false,slidesSelector:""});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,e){if(a.tracks.length!==0){var d;if(this.domNode.textTracks)for(d=this.domNode.textTracks.length-1;d>=0;d--)this.domNode.textTracks[d].mode="hidden";a.chapters=f('<div class="mejs-chapters mejs-layer"></div>').prependTo(c).hide(); 157a.captions=f('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>').prependTo(c).hide();a.captionsText=a.captions.find(".mejs-captions-text");a.captionsButton=f('<div class="mejs-button mejs-captions-button"><button type="button" aria-controls="'+this.id+'" title="'+this.options.tracksText+'" aria-label="'+this.options.tracksText+'"></button><div class="mejs-captions-selector"><ul><li><input type="radio" name="'+ 158a.id+'_captions" id="'+a.id+'_captions_none" value="none" checked="checked" /><label for="'+a.id+'_captions_none">'+mejs.i18n.t("None")+"</label></li></ul></div></div>").appendTo(b);for(d=b=0;d<a.tracks.length;d++)a.tracks[d].kind=="subtitles"&&b++;if(this.options.toggleCaptionsButtonWhenOnlyOne&&b==1)a.captionsButton.on("click",function(){lang=a.selectedTrack===null?a.tracks[0].srclang:"none";a.setTrack(lang)});else{a.captionsButton.on("mouseenter focusin",function(){f(this).find(".mejs-captions-selector").css("visibility", 159"visible")}).on("click","input[type=radio]",function(){lang=this.value;a.setTrack(lang)});a.captionsButton.on("mouseleave focusout",function(){f(this).find(".mejs-captions-selector").css("visibility","hidden")})}a.options.alwaysShowControls?a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover"):a.container.bind("controlsshown",function(){a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover")}).bind("controlshidden",function(){e.paused||a.container.find(".mejs-captions-position").removeClass("mejs-captions-position-hover")}); 160a.trackToLoad=-1;a.selectedTrack=null;a.isLoadingTrack=false;for(d=0;d<a.tracks.length;d++)a.tracks[d].kind=="subtitles"&&a.addTrackButton(a.tracks[d].srclang,a.tracks[d].label);a.loadNextTrack();e.addEventListener("timeupdate",function(){a.displayCaptions()},false);
160if(a.options.slidesSelector!==""){a.slidesContainer=f(a.options.slidesSelector);e.addEventListener("timeupdate",function(){a.displaySlides()},false)}e.addEventListener("loadedmetadata",function(){a.displayChapters()},false);a.container.hover(function(){if(a.hasChapters){a.chapters.css("visibility", 161"visible");a.chapters.fadeIn(200).height(a.chapters.find(".mejs-chapter").outerHeight())}},function(){a.hasChapters&&!e.paused&&a.chapters.fadeOut(200,function(){f(this).css("visibility","hidden");f(this).css("display","block")})});a.node.getAttribute("autoplay")!==null&&a.chapters.css("visibility","hidden")}},setTrack:function(a){var b;if(a=="none"){this.selectedTrack=null;this.captionsButton.removeClass("mejs-captions-enabled")}else for(b=0;b<this.tracks.length;b++)if(this.tracks[b].srclang==a){this.selectedTrack=== 162null&&this.captionsButton.addClass("mejs-captions-enabled");this.selectedTrack=this.tracks[b];this.captions.attr("lang",this.selectedTrack.srclang);this.displayCaptions();break}},loadNextTrack:function(){this.trackToLoad++;if(this.trackToLoad<this.tracks.length){this.isLoadingTrack=true;this.loadTrack(this.trackToLoad)}else{this.isLoadingTrack=false;this.checkForTracks()}},loadTrack:function(a){var b=this,c=b.tracks[a];f.ajax({url:c.src,dataType:"text",success:function(e){c.entries=typeof e=="string"&& 163/<tt\s+xml/ig.exec(e)?mejs.TrackFormatParser.dfxp.parse(e):mejs.TrackFormatParser.webvtt.parse(e);c.isLoaded=true;b.enableTrackButton(c.srclang,c.label);b.loadNextTrack();c.kind=="chapters"&&b.media.addEventListener("play",function(){b.media.duration>0&&b.displayChapters(c)},false);c.kind=="slides"&&b.setupSlides(c)},error:function(){b.loadNextTrack()}})},enableTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("input[value="+a+"]").prop("disabled",false).siblings("label").html(b); 164this.options.startLanguage==a&&f("#"+this.id+"_captions_"+a).prop("checked",true).trigger("click");this.adjustLanguageBox()},addTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("ul").append(f('<li><input type="radio" name="'+this.id+'_captions" id="'+this.id+"_captions_"+a+'" value="'+a+'" disabled="disabled" /><label for="'+this.id+"_captions_"+a+'">'+b+" (loading)</label></li>"));this.adjustLanguageBox();this.container.find(".mejs-captions-translations option[value="+ 165a+"]").remove()},adjustLanguageBox:function(){this.captionsButton.find(".mejs-captions-selector").height(this.captionsButton.find(".mejs-captions-selector ul").outerHeight(true)+this.captionsButton.find(".mejs-captions-translations").outerHeight(true))},checkForTracks:function(){var a=false;if(this.options.hideCaptionsButtonWhenEmpty){for(i=0;i<this.tracks.length;i++)if(this.tracks[i].kind=="subtitles"){a=true;break}if(!a){this.captionsButton.hide();this.setControlsSize()}}},displayCaptions:function(){if(typeof this.tracks!= 166"undefined"){var a,b=this.selectedTrack;if(b!==null&&b.isLoaded)for(a=0;a<b.entries.times.length;a++)if(this.media.currentTime>=b.entries.times[a].start&&this.media.currentTime<=b.entries.times[a].stop){this.captionsText.html(b.entries.text[a]).attr("class","mejs-captions-text "+(b.entries.times[a].identifier||""));this.captions.show().height(0);return}this.captions.hide()}},setupSlides:function(a){this.slides=a;this.slides.entries.imgs=[this.slides.entries.text.length];this.showSlide(0)},showSlide:function(a){if(!(typeof this.tracks== 167"undefined"||typeof this.slidesContainer=="undefined")){var b=this,c=b.slides.entries.text[a],e=b.slides.entries.imgs[a];if(typeof e=="undefined"||typeof e.fadeIn=="undefined")b.slides.entries.imgs[a]=e=f('<img src="'+c+'">').on("load",function(){e.appendTo(b.slidesContainer).hide().fadeIn().siblings(":visible").fadeOut()});else!e.is(":visible")&&!e.is(":animated")&&e.fadeIn().siblings(":visible").fadeOut()}},displaySlides:function(){if(typeof this.slides!="undefined"){var a=this.slides,b;for(b=0;b< 168a.entries.times.length;b++)if(this.media.currentTime>=a.entries.times[b].start&&this.media.currentTime<=a.entries.times[b].stop){this.showSlide(b);break}}},displayChapters:function(){var a;for(a=0;a<this.tracks.length;a++)if(this.tracks[a].kind=="chapters"&&this.tracks[a].isLoaded){this.drawChapters(this.tracks[a]);this.hasChapters=true;break}},drawChapters:function(a){var b=this,c,e,d=e=0;b.chapters.empty();for(c=0;c<a.entries.times.length;c++){e=a.entries.times[c].stop-a.entries.times[c].start; 169e=Math.floor(e/b.media.duration*100);if(e+d>100||c==a.entries.times.length-1&&e+d<100)e=100-d;b.chapters.append(f('<div class="mejs-chapter" rel="'+a.entries.times[c].start+'" style="left: '+d.toString()+"%;width: "+e.toString()+'%;"><div class="mejs-chapter-block'+(c==a.entries.times.length-1?" mejs-chapter-block-last":"")+'"><span class="ch-title">
169'+a.entries.text[c]+'</span><span class="ch-time">'+mejs.Utility.secondsToTimeCode(a.entries.times[c].start)+"–"+mejs.Utility.secondsToTimeCode(a.entries.times[c].stop)+ 170"</span></div></div>"));d+=e}b.chapters.find("div.mejs-chapter").click(function(){b.media.setCurrentTime(parseFloat(f(this).attr("rel")));b.media.paused&&b.media.play()});b.chapters.show()}});mejs.language={codes:{af:"Afrikaans",sq:"Albanian",ar:"Arabic",be:"Belarusian",bg:"Bulgarian",ca:"Catalan",zh:"Chinese","zh-cn":"Chinese Simplified","zh-tw":"Chinese Traditional",hr:"Croatian",cs:"Czech",da:"Danish",nl:"Dutch",en:"English",et:"Estonian",fl:"Filipino",fi:"Finnish",fr:"French",gl:"Galician",de:"German", 171el:"Greek",ht:"Haitian Creole",iw:"Hebrew",hi:"Hindi",hu:"Hungarian",is:"Icelandic",id:"Indonesian",ga:"Irish",it:"Italian",ja:"Japanese",ko:"Korean",lv:"Latvian",lt:"Lithuanian",mk:"Macedonian",ms:"Malay",mt:"Maltese",no:"Norwegian",fa:"Persian",pl:"Polish",pt:"Portuguese",ro:"Romanian",ru:"Russian",sr:"Serbian",sk:"Slovak",sl:"Slovenian",es:"Spanish",sw:"Swahili",sv:"Swedish",tl:"Tagalog",th:"Thai",tr:"Turkish",uk:"Ukrainian",vi:"Vietnamese",cy:"Welsh",yi:"Yiddish"}};mejs.TrackFormatParser={webvtt:{pattern_timecode:/^((?:[0-9]{1,2}:)?[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ((?:[0-9]{1,2}:)?[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/, 172parse:function(a){var b=0;a=mejs.TrackFormatParser.split2(a,/\r?\n/);for(var c={text:[],times:[]},e,d,g;b<a.length;b++){if((e=this.pattern_timecode.exec(a[b]))&&b<a.length){if(b-1>=0&&a[b-1]!=="")g=a[b-1];b++;d=a[b];for(b++;a[b]!==""&&b<a.length;){d=d+"\n"+a[b];b++}d=f.trim(d).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig,"<a href='$1' target='_blank'>$1</a>");c.text.push(d);c.times.push({identifier:g,start:mejs.Utility.convertSMPTEtoSeconds(e[1])===0?0.2:mejs.Utility.convertSMPTEtoSeconds(e[1]), 173stop:mejs.Utility.convertSMPTEtoSeconds(e[3]),settings:e[5]})}g=""}return c}},dfxp:{parse:function(a){a=f(a).filter("tt");var b=0;b=a.children("div").eq(0);var c=b.find("p");b=a.find("#"+b.attr("style"));var e,d;a={text:[],times:[]};if(b.length){d=b.removeAttr("id").get(0).attributes;if(d.length){e={};for(b=0;b<d.length;b++)e[d[b].name.split(":")[1]]=d[b].value}}for(b=0;b<c.length;b++){var g;d={start:null,stop:null,style:null};if(c.eq(b).attr("begin"))d.start=mejs.Utility.convertSMPTEtoSeconds(c.eq(b).attr("begin")); 174if(!d.start&&c.eq(b-1).attr("end"))d.start=mejs.Utility.convertSMPTEtoSeconds(c.eq(b-1).attr("end"));if(c.eq(b).attr("end"))d.stop=mejs.Utility.convertSMPTEtoSeconds(c.eq(b).attr("end"));if(!d.stop&&c.eq(b+1).attr("begin"))d.stop=mejs.Utility.convertSMPTEtoSeconds(c.eq(b+1).attr("begin"));if(e){g="";for(var k in e)g+=k+":"+e[k]+";"}if(g)d.style=g;if(d.start===0)d.start=0.2;a.times.push(d);d=f.trim(c.eq(b).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, 175"<a href='$1' target='_blank'>$1</a>");a.text.push(d);if(a.times.start===0)a.times.start=2}return a}},split2:function(a,b){return a.split(b)}};if("x\n\ny".split(/\n/gi).length!=3)mejs.TrackFormatParser.split2=function(a,b){var c=[],e="",d;for(d=0;d<a.length;d++){e+=a.substring(d,d+1);if(b.test(e)){c.push(e.replace(b,""));e=""}}c.push(e);return c}})(mejs.$); 176(function(f){f.extend(mejs.MepDefaults,{contextMenuItems:[{render:function(a){if(typeof a.enterFullScreen=="undefined")return null;return a.isFullScreen?mejs.i18n.t("Turn off Fullscreen"):mejs.i18n.t("Go Fullscreen")},click:function(a){a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}},{render:function(a){return a.media.muted?mejs.i18n.t("Unmute"):mejs.i18n.t("Mute")},click:function(a){a.media.muted?a.setMuted(false):a.setMuted(true)}},{isSeparator:true},{render:function(){return mejs.i18n.t("Download Video")}, 177click:function(a){window.location.href=a.media.currentSrc}}]});f.extend(MediaElementPlayer.prototype,{buildcontextmenu:function(a){a.contextMenu=f('<div class="mejs-contextmenu"></div>').appendTo(f("body")).hide();a.container.bind("contextmenu",function(b){if(a.isContextMenuEnabled){b.preventDefault();a.renderContextMenu(b.clientX-1,b.clientY-1);return false}});a.container.bind("click",function(){a.contextMenu.hide()});a.contextMenu.bind("mouseleave",function(){a.startContextMenuTimer()})},cleancontextmenu:function(a){a.contextMenu.remove()}, 178isContextMenuEnabled:true,enableContextMenu:function(){this.isContextMenuEnabled=true},disableContextMenu:function(){this.isContextMenuEnabled=false},contextMenuTimeout:null,startContextMenuTimer:function(){var a=this;a.killContextMenuTimer();a.contextMenuTimer=setTimeout(function(){a.hideContextMenu();a.killContextMenuTimer()},750)},killContextMenuTimer:function(){var a=this.contextMenuTimer;if(a!=null){clearTimeout(a);delete a}},hideContextMenu:function(){this.contextMenu.hide()},renderContextMenu:function(a, 179b){for(var c=this,e="",d=c.options.contextMenuItems,g=0,k=d.length;g<k;g++)if(d[g].isSeparator)e+='<div class="mejs-contextmenu-separator"></div>';else{var j=d[g].render(c);if(j!=null)e+='<div class="mejs-contextmenu-item" data-itemindex="'+g+'" id="element-'+Math.random()*1E6+'">'+j+"</div>"}c.contextMenu.empty().append(f(e)).css({top:b,left:a}).show();c.contextMenu.find(".mejs-contextmenu-item").each(function(){var m=f(this),q=parseInt(m.data("itemindex"),10),p=c.options.contextMenuItems[q];typeof p.show!= 180"undefined"&&p.show(m,c);m.click(function(){typeof p.click!="undefined"&&p.click(c);c.contextMenu.hide()})});
180setTimeout(function(){c.killControlsTimer("rev3")},100)}})})(mejs.$); 181(function(f){f.extend(mejs.MepDefaults,{postrollCloseText:mejs.i18n.t("Close")});f.extend(MediaElementPlayer.prototype,{buildpostroll:function(a,b,c){var e=this.container.find('link[rel="postroll"]').attr("href");if(typeof e!=="undefined"){a.postroll=f('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">'+this.options.postrollCloseText+'</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(c).hide();this.media.addEventListener("ended", 182function(){f.ajax({dataType:"html",url:e,success:function(d){c.find(".mejs-postroll-layer-content").html(d)}});a.postroll.show()},false)}}})})(mejs.$); 183 184 185/*! 186 * Bootstrap v3.3.5 (http://getbootstrap.com) 187 * Copyright 2011-2015 Twitter, Inc. 188 * Licensed under the MIT license 189 */ 190 191if (typeof jQuery === 'undefined') { 192 throw new Error('Bootstrap\'s JavaScript requires jQuery') 193} 194 195+function ($) { 196 'use strict'; 197 var version = $.fn.jquery.split(' ')[0].split('.') 198 if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) { 199 throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher') 200 } 201}(jQuery); 202 203/* ======================================================================== 204 * Bootstrap: transition.js v3.3.5 205 * http://getbootstrap.com/javascript/#transitions 206 * ======================================================================== 207 * Copyright 2011-2015 Twitter, Inc. 208 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 209 * ======================================================================== */ 210 211 212+function ($) { 213 'use strict'; 214 215 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 216 // ============================================================ 217 218 function transitionEnd() { 219 var el = document.createElement('bootstrap') 220 221 var transEndEventNames = { 222 WebkitTransition : 'webkitTransitionEnd', 223 MozTransition : 'transitionend', 224 OTransition : 'oTransitionEnd otransitionend', 225 transition : 'transitionend' 226 } 227 228 for (var name in transEndEventNames) { 229 if (el.style[name] !== undefined) { 230 return { end: transEndEventNames[name] } 231 } 232 } 233 234 return false // explicit for ie8 ( ._.) 235 } 236 237 // http://blog.alexmaccaw.com/css-transitions 238 $.fn.emulateTransitionEnd = function (duration) { 239 var called = false 240 var $el = this 241 $(this).one('bsTransitionEnd', function () { called = true }) 242 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 243 setTimeout(callback, duration) 244 return this 245 } 246 247 $(function () { 248 $.support.transition = transitionEnd() 249 250 if (!$.support.transition) return 251 252 $.event.special.bsTransitionEnd = { 253 bindType: $.support.transition.end, 254 delegateType: $.support.transition.end, 255 handle: function (e) { 256 if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) 257 } 258 } 259 }) 260 261}(jQuery); 262 263/* ======================================================================== 264 * Bootstrap: alert.js v3.3.5 265 * http://getbootstrap.com/javascript/#alerts 266 * ======================================================================== 267 * Copyright 2011-2015 Twitter, Inc. 268 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 269 * ======================================================================== */ 270 271 272+function ($) { 273 'use strict'; 274 275 // ALERT CLASS DEFINITION 276 // ====================== 277 278 var dismiss = '[data-dismiss="alert"]' 279 var Alert = function (el) { 280 $(el).on('click', dismiss, this.close) 281 } 282 283 Alert.VERSION = '3.3.5' 284 285 Alert.TRANSITION_DURATION = 150 286 287 Alert.prototype.close = function (e) { 288 var $this = $(this) 289 var selector = $this.attr('data-target') 290 291 if (!selector) { 292 selector = $this.attr('href') 293 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 294 } 295 296 var $parent = $(selector) 297 298 if (e) e.preventDefault() 299 300 if (!$parent.length) { 301 $parent = $this.closest('.alert') 302 } 303 304 $parent.trigger(e = $.Event('close.bs.alert')) 305 306 if (e.isDefaultPrevented()) return 307 308 $parent.removeClass('in') 309 310 function removeElement() { 311 // detach from parent, fire event then clean up data 312 $parent.detach().trigger('closed.bs.alert').remove() 313 } 314 315 $.support.transition && $parent.hasClass('fade') ? 316 $parent 317 .one('bsTransitionEnd', removeElement) 318 .emulateTransitionEnd(Alert.TRANSITION_DURATION) : 319 removeElement() 320 } 321 322 323 // ALERT PLUGIN DEFINITION 324 // ======================= 325 326 function Plugin(option) { 327 return this.each(function () { 328 var $this = $(this) 329 var data = $this.data('bs.alert') 330
vendor: 69,034 bytes, lines 331-2619
331 if (!data) $this.data('bs.alert', (data = new Alert(this))) 332 if (typeof option == 'string') data[option].call($this) 333 }) 334 } 335 336 var old = $.fn.alert 337 338 $.fn.alert = Plugin 339 $.fn.alert.Constructor = Alert 340 341 342 // ALERT NO CONFLICT 343 // ================= 344 345 $.fn.alert.noConflict = function () { 346 $.fn.alert = old 347 return this 348 } 349 350 351 // ALERT DATA-API 352 // ============== 353 354 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) 355 356}(jQuery); 357 358/* ======================================================================== 359 * Bootstrap: button.js v3.3.5 360 * http://getbootstrap.com/javascript/#buttons 361 * ======================================================================== 362 * Copyright 2011-2015 Twitter, Inc. 363 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 364 * ======================================================================== */ 365 366 367+function ($) { 368 'use strict'; 369 370 // BUTTON PUBLIC CLASS DEFINITION 371 // ============================== 372 373 var Button = function (element, options) { 374 this.$element = $(element) 375 this.options = $.extend({}, Button.DEFAULTS, options) 376 this.isLoading = false 377 } 378 379 Button.VERSION = '3.3.5' 380 381 Button.DEFAULTS = { 382 loadingText: 'loading...' 383 } 384 385 Button.prototype.setState = function (state) { 386 var d = 'disabled' 387 var $el = this.$element 388 var val = $el.is('input') ? 'val' : 'html' 389 var data = $el.data() 390 391 state += 'Text' 392 393 if (data.resetText == null) $el.data('resetText', $el[val]()) 394 395 // push to event loop to allow forms to submit 396 setTimeout($.proxy(function () { 397 $el[val](data[state] == null ? this.options[state] : data[state]) 398 399 if (state == 'loadingText') { 400 this.isLoading = true 401 $el.addClass(d).attr(d, d) 402 } else if (this.isLoading) { 403 this.isLoading = false 404 $el.removeClass(d).removeAttr(d) 405 } 406 }, this), 0) 407 } 408 409 Button.prototype.toggle = function () { 410 var changed = true 411 var $parent = this.$element.closest('[data-toggle="buttons"]') 412 413 if ($parent.length) { 414 var $input = this.$element.find('input') 415 if ($input.prop('type') == 'radio') { 416 if ($input.prop('checked')) changed = false 417 $parent.find('.active').removeClass('active') 418 this.$element.addClass('active') 419 } else if ($input.prop('type') == 'checkbox') { 420 if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false 421 this.$element.toggleClass('active') 422 } 423 $input.prop('checked', this.$element.hasClass('active')) 424 if (changed) $input.trigger('change') 425 } else { 426 this.$element.attr('aria-pressed', !this.$element.hasClass('active')) 427 this.$element.toggleClass('active') 428 } 429 } 430 431 432 // BUTTON PLUGIN DEFINITION 433 // ======================== 434 435 function Plugin(option) { 436 return this.each(function () { 437 var $this = $(this) 438 var data = $this.data('bs.button') 439 var options = typeof option == 'object' && option 440 441 if (!data) $this.data('bs.button', (data = new Button(this, options))) 442 443 if (option == 'toggle') data.toggle() 444 else if (option) data.setState(option) 445 }) 446 } 447 448 var old = $.fn.button 449 450 $.fn.button = Plugin 451 $.fn.button.Constructor = Button 452 453 454 // BUTTON NO CONFLICT 455 // ================== 456 457 $.fn.button.noConflict = function () { 458 $.fn.button = old 459 return this 460 } 461 462 463 // BUTTON DATA-API 464 // =============== 465 466 $(document) 467 .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { 468 var $btn = $(e.target) 469 if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 470 Plugin.call($btn, 'toggle') 471 if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() 472 }) 473 .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { 474 $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) 475 }) 476 477}(jQuery); 478 479/* ======================================================================== 480 * Bootstrap: carousel.js v3.3.5 481 * http://getbootstrap.com/javascript/#carousel 482 * ======================================================================== 483 * Copyright 2011-2015 Twitter, Inc. 484 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 485 * ======================================================================== */ 486 487 488+function ($) { 489 'use strict'; 490 491 // CAROUSEL CLASS DEFINITION 492 // ========================= 493 494 var Carousel = function (element, options) { 495 this.$element = $(element) 496 this.$indicators = this.$element.find('.carousel-indicators') 497 this.options = options 498 this.paused = null 499 this.sliding = null 500 this.interval = null 501 this.$active = null 502 this.$items = null 503 504 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) 505 506 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element 507 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) 508 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) 509 } 510 511 Carousel.VERSION = '3.3.5' 512 513 Carousel.TRANSITION_DURATION = 600 514 515 Carousel.DEFAULTS = { 516 interval: 5000, 517 pause: 'hover', 518 wrap: true, 519 keyboard: true 520 } 521 522 Carousel.prototype.keydown = function (e) { 523 if (/input|textarea/i.test(e.target.tagName)) return 524 switch (e.which) { 525 case 37: this.prev(); break 526 case 39: this.next(); break 527 default: return 528 } 529 530 e.preventDefault() 531 } 532 533 Carousel.prototype.cycle = function (e) { 534 e || (this.paused = false) 535 536 this.interval && clearInterval(this.interval) 537 538 this.options.interval 539 && !this.paused 540 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 541 542 return this 543 } 544 545 Carousel.prototype.getItemIndex = function (item) { 546 this.$items = item.parent().children('.item') 547 return this.$items.index(item || this.$active) 548 } 549 550 Carousel.prototype.getItemForDirection = function (direction, active) { 551 var activeIndex = this.getItemIndex(active) 552 var willWrap = (direction == 'prev' && activeIndex === 0) 553 || (direction == 'next' && activeIndex == (this.$items.length - 1)) 554 if (willWrap && !this.options.wrap) return active 555 var delta = direction == 'prev' ? -1 : 1 556 var itemIndex = (activeIndex + delta) % this.$items.length 557 return this.$items.eq(itemIndex) 558 } 559 560 Carousel.prototype.to = function (pos) { 561 var that = this 562 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) 563 564 if (pos > (this.$items.length - 1) || pos < 0) return 565 566 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 567 if (activeIndex == pos) return this.pause().cycle() 568 569 return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) 570 } 571 572 Carousel.prototype.pause = function (e) { 573 e || (this.paused = true) 574 575 if (this.$element.find('.next, .prev').length && $.support.transition) { 576 this.$element.trigger($.support.transition.end) 577 this.cycle(true) 578 } 579 580 this.interval = clearInterval(this.interval) 581 582 return this 583 } 584 585 Carousel.prototype.next = function () { 586 if (this.sliding) return 587 return this.slide('next') 588 } 589 590 Carousel.prototype.prev = function () { 591 if (this.sliding) return 592 return this.slide('prev') 593 } 594 595 Carousel.prototype.slide = function (type, next) { 596 var $active = this.$element.find('.item.active') 597 var $next = next || this.getItemForDirection(type, $active) 598 var isCycling = this.interval 599 var direction = type == 'next' ? 'left' : 'right' 600 var that = this 601 602 if ($next.hasClass('active')) return (this.sliding = false) 603 604 var relatedTarget = $next[0] 605 var slideEvent = $.Event('slide.bs.carousel', { 606 relatedTarget: relatedTarget, 607 direction: direction 608 }) 609 this.$element.trigger(slideEvent) 610 if (slideEvent.isDefaultPrevented()) return 611 612 this.sliding = true 613 614 isCycling && this.pause() 615 616 if (this.$indicators.length) { 617 this.$indicators.find('.active').removeClass('active') 618 var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) 619 $nextIndicator && $nextIndicator.addClass('active') 620 } 621 622 var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" 623 if ($.support.transition && this.$element.hasClass('slide')) { 624 $next.addClass(type) 625 $next[0].offsetWidth // force reflow 626 $active.addClass(direction) 627 $next.addClass(direction) 628 $active 629 .one('bsTransitionEnd', function () { 630 $next.removeClass([type, direction].join(' ')).addClass('active') 631 $active.removeClass(['active', direction].join(' ')) 632 that.sliding = false 633 setTimeout(function () { 634 that.$element.trigger(slidEvent) 635 }, 0) 636 }) 637 .emulateTransitionEnd(Carousel.TRANSITION_DURATION) 638 } else { 639 $active.removeClass('active') 640 $next.addClass('active') 641 this.sliding = false 642 this.$element.trigger(slidEvent) 643 } 644 645 isCycling && this.cycle() 646 647 return this 648 } 649 650 651 // CAROUSEL PLUGIN DEFINITION 652 // ========================== 653 654 function Plugin(option) { 655 return this.each(function () { 656 var $this = $(this) 657 var data = $this.data('bs.carousel') 658 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 659 var action = typeof option == 'string' ? option : options.slide 660 661 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 662 if (typeof option == 'number') data.to(option) 663 else if (action) data[action]() 664 else if (options.interval) data.pause().cycle() 665 }) 666 } 667 668 var old = $.fn.carousel 669 670 $.fn.carousel = Plugin 671 $.fn.carousel.Constructor = Carousel 672 673 674 // CAROUSEL NO CONFLICT 675 // ==================== 676 677 $.fn.carousel.noConflict = function () { 678 $.fn.carousel = old 679 return this 680 } 681 682 683 // CAROUSEL DATA-API 684 // ================= 685 686 var clickHandler = function (e) { 687 var href 688 var $this = $(this) 689 var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 690 if (!$target.hasClass('carousel')) return 691 var options = $.extend({}, $target.data(), $this.data()) 692 var slideIndex = $this.attr('data-slide-to') 693 if (slideIndex) options.interval = false 694 695 Plugin.call($target, options) 696 697 if (slideIndex) { 698 $target.data('bs.carousel').to(slideIndex) 699 } 700 701 e.preventDefault() 702 } 703 704 $(document) 705 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) 706 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) 707 708 $(window).on('load', function () { 709 $('[data-ride="carousel"]').each(function () { 710 var $carousel = $(this) 711 Plugin.call($carousel, $carousel.data()) 712 }) 713 }) 714 715}(jQuery); 716 717/* ======================================================================== 718 * Bootstrap: collapse.js v3.3.5 719 * http://getbootstrap.com/javascript/#collapse 720 * ======================================================================== 721 * Copyright 2011-2015 Twitter, Inc. 722 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 723 * ======================================================================== */ 724 725 726+function ($) { 727 'use strict'; 728 729 // COLLAPSE PUBLIC CLASS DEFINITION 730 // ================================ 731 732 var Collapse = function (element, options) { 733 this.$element = $(element) 734 this.options = $.extend({}, Collapse.DEFAULTS, options) 735 this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + 736 '[data-toggle="collapse"][data-target="#' + element.id + '"]') 737 this.transitioning = null 738 739 if (this.options.parent) { 740 this.$parent = this.getParent() 741 } else { 742 this.addAriaAndCollapsedClass(this.$element, this.$trigger) 743 } 744 745 if (this.options.toggle) this.toggle() 746 } 747 748 Collapse.VERSION = '3.3.5' 749 750 Collapse.TRANSITION_DURATION = 350 751 752 Collapse.DEFAULTS = { 753 toggle: true 754 } 755 756 Collapse.prototype.dimension = function () { 757 var hasWidth = this.$element.hasClass('width') 758 return hasWidth ? 'width' : 'height' 759 } 760 761 Collapse.prototype.show = function () { 762 if (this.transitioning || this.$element.hasClass('in')) return 763 764 var activesData 765 var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') 766 767 if (actives && actives.length) { 768 activesData = actives.data('bs.collapse') 769 if (activesData && activesData.transitioning) return 770 } 771 772 var startEvent = $.Event('show.bs.collapse') 773 this.$element.trigger(startEvent) 774 if (startEvent.isDefaultPrevented()) return 775 776 if (actives && actives.length) { 777 Plugin.call(actives, 'hide') 778 activesData || actives.data('bs.collapse', null) 779 } 780 781 var dimension = this.dimension() 782 783 this.$element 784 .removeClass('collapse') 785 .addClass('collapsing')[dimension](0) 786 .attr('aria-expanded', true) 787 788 this.$trigger 789 .removeClass('collapsed') 790 .attr('aria-expanded', true) 791 792 this.transitioning = 1 793 794 var complete = function () { 795 this.$element 796 .removeClass('collapsing') 797 .addClass('collapse in')[dimension]('') 798 this.transitioning = 0 799 this.$element 800 .trigger('shown.bs.collapse') 801 } 802 803 if (!$.support.transition) return complete.call(this) 804 805 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 806 807 this.$element 808 .one('bsTransitionEnd', $.proxy(complete, this)) 809 .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 810 } 811 812 Collapse.prototype.hide = function () { 813 if (this.transitioning || !this.$element.hasClass('in')) return 814 815 var startEvent = $.Event('hide.bs.collapse') 816 this.$element.trigger(startEvent) 817 if (startEvent.isDefaultPrevented()) return 818 819 var dimension = this.dimension() 820 821 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 822 823 this.$element 824 .addClass('collapsing') 825 .removeClass('collapse in') 826 .attr('aria-expanded', false) 827 828 this.$trigger 829 .addClass('collapsed') 830 .attr('aria-expanded', false) 831 832 this.transitioning = 1 833 834 var complete = function () { 835 this.transitioning = 0 836 this.$element 837 .removeClass('collapsing') 838 .addClass('collapse') 839 .trigger('hidden.bs.collapse') 840 } 841 842 if (!$.support.transition) return complete.call(this) 843 844 this.$element 845 [dimension](0) 846 .one('bsTransitionEnd', $.proxy(complete, this)) 847 .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 848 } 849 850 Collapse.prototype.toggle = function () { 851 this[this.$element.hasClass('in') ? 'hide' : 'show']() 852 } 853 854 Collapse.prototype.getParent = function () { 855 return $(this.options.parent) 856 .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 857 .each($.proxy(function (i, element) { 858 var $element = $(element) 859 this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 860 }, this)) 861 .end() 862 } 863 864 Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 865 var isOpen = $element.hasClass('in') 866 867 $element.attr('aria-expanded', isOpen) 868 $trigger 869 .toggleClass('collapsed', !isOpen) 870 .attr('aria-expanded', isOpen) 871 } 872 873 function getTargetFromTrigger($trigger) { 874 var href 875 var target = $trigger.attr('data-target') 876 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 877 878 return $(target) 879 } 880 881 882 // COLLAPSE PLUGIN DEFINITION 883 // ========================== 884 885 function Plugin(option) { 886 return this.each(function () { 887 var $this = $(this) 888 var data = $this.data('bs.collapse') 889 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 890 891 if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false 892 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 893 if (typeof option == 'string') data[option]() 894 }) 895 } 896 897 var old = $.fn.collapse 898 899 $.fn.collapse = Plugin 900 $.fn.collapse.Constructor = Collapse 901 902 903 // COLLAPSE NO CONFLICT 904 // ==================== 905 906 $.fn.collapse.noConflict = function () { 907 $.fn.collapse = old 908 return this 909 } 910 911 912 // COLLAPSE DATA-API 913 // ================= 914 915 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 916 var $this = $(this) 917 918 if (!$this.attr('data-target')) e.preventDefault() 919 920 var $target = getTargetFromTrigger($this) 921 var data = $target.data('bs.collapse') 922 var option = data ? 'toggle' : $this.data() 923 924 Plugin.call($target, option) 925 }) 926 927}(jQuery); 928 929/* ======================================================================== 930 * Bootstrap: dropdown.js v3.3.5 931 * http://getbootstrap.com/javascript/#dropdowns 932 * ======================================================================== 933 * Copyright 2011-2015 Twitter, Inc. 934 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 935 * ======================================================================== */ 936 937 938+function ($) { 939 'use strict'; 940 941 // DROPDOWN CLASS DEFINITION 942 // ========================= 943 944 var backdrop = '.dropdown-backdrop' 945 var toggle = '[data-toggle="dropdown"]' 946 var Dropdown = function (element) { 947 $(element).on('click.bs.dropdown', this.toggle) 948 } 949 950 Dropdown.VERSION = '3.3.5' 951 952 function getParent($this) { 953 var selector = $this.attr('data-target') 954 955 if (!selector) { 956 selector = $this.attr('href') 957 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 958 } 959 960 var $parent = selector && $(selector) 961 962 return $parent && $parent.length ? $parent : $this.parent() 963 } 964 965 function clearMenus(e) { 966 if (e && e.which === 3) return 967 $(backdrop).remove() 968 $(toggle).each(function () { 969 var $this = $(this) 970 var $parent = getParent($this) 971 var relatedTarget = { relatedTarget: this } 972 973 if (!$parent.hasClass('open')) return 974 975 if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return 976 977 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) 978 979 if (e.isDefaultPrevented()) return 980 981 $this.attr('aria-expanded', 'false') 982 $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) 983 }) 984 } 985 986 Dropdown.prototype.toggle = function (e) { 987 var $this = $(this) 988 989 if ($this.is('.disabled, :disabled')) return 990 991 var $parent = getParent($this) 992 var isActive = $parent.hasClass('open') 993 994 clearMenus() 995 996 if (!isActive) { 997 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 998 // if mobile we use a backdrop because click events don't delegate 999 $(document.createElement('div')) 1000 .addClass('dropdown-backdrop') 1001 .insertAfter($(this)) 1002 .on('click', clearMenus) 1003 } 1004 1005 var relatedTarget = { relatedTarget: this } 1006 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) 1007 1008 if (e.isDefaultPrevented()) return 1009 1010 $this 1011 .trigger('focus') 1012 .attr('aria-expanded', 'true') 1013 1014 $parent 1015 .toggleClass('open') 1016 .trigger('shown.bs.dropdown', relatedTarget) 1017 } 1018 1019 return false 1020 } 1021 1022 Dropdown.prototype.keydown = function (e) { 1023 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return 1024 1025 var $this = $(this) 1026 1027 e.preventDefault() 1028 e.stopPropagation() 1029 1030 if ($this.is('.disabled, :disabled')) return 1031 1032 var $parent = getParent($this) 1033 var isActive = $parent.hasClass('open') 1034 1035 if (!isActive && e.which != 27 || isActive && e.which == 27) { 1036 if (e.which == 27) $parent.find(toggle).trigger('focus') 1037 return $this.trigger('click') 1038 } 1039 1040 var desc = ' li:not(.disabled):visible a' 1041 var $items = $parent.find('.dropdown-menu' + desc) 1042 1043 if (!$items.length) return 1044 1045 var index = $items.index(e.target) 1046 1047 if (e.which == 38 && index > 0) index-- // up 1048 if (e.which == 40 && index < $items.length - 1) index++ // down 1049 if (!~index) index = 0 1050 1051 $items.eq(index).trigger('focus') 1052 } 1053 1054 1055 // DROPDOWN PLUGIN DEFINITION 1056 // ========================== 1057 1058 function Plugin(option) { 1059 return this.each(function () { 1060 var $this = $(this) 1061 var data = $this.data('bs.dropdown') 1062 1063 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) 1064 if (typeof option == 'string') data[option].call($this) 1065 }) 1066 } 1067 1068 var old = $.fn.dropdown 1069 1070 $.fn.dropdown = Plugin 1071 $.fn.dropdown.Constructor = Dropdown 1072 1073 1074 // DROPDOWN NO CONFLICT 1075 // ==================== 1076 1077 $.fn.dropdown.noConflict = function () { 1078 $.fn.dropdown = old 1079 return this 1080 } 1081 1082 1083 // APPLY TO STANDARD DROPDOWN ELEMENTS 1084 // =================================== 1085 1086 $(document) 1087 .on('click.bs.dropdown.data-api', clearMenus) 1088 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 1089 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 1090 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) 1091 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) 1092 1093}(jQuery); 1094 1095/* ======================================================================== 1096 * Bootstrap: modal.js v3.3.5 1097 * http://getbootstrap.com/javascript/#modals 1098 * ======================================================================== 1099 * Copyright 2011-2015 Twitter, Inc. 1100 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1101 * ======================================================================== */ 1102 1103 1104+function ($) { 1105 'use strict'; 1106 1107 // MODAL CLASS DEFINITION 1108 // ====================== 1109 1110 var Modal = function (element, options) { 1111 this.options = options 1112 this.$body = $(document.body) 1113 this.$element = $(element) 1114 this.$dialog = this.$element.find('.modal-dialog') 1115 this.$backdrop = null 1116 this.isShown = null 1117 this.originalBodyPad = null 1118 this.scrollbarWidth = 0 1119 this.ignoreBackdropClick = false 1120 1121 if (this.options.remote) { 1122 this.$element 1123 .find('.modal-content') 1124 .load(this.options.remote, $.proxy(function () { 1125 this.$element.trigger('loaded.bs.modal') 1126 }, this)) 1127 } 1128 } 1129 1130 Modal.VERSION = '3.3.5' 1131 1132 Modal.TRANSITION_DURATION = 300 1133 Modal.BACKDROP_TRANSITION_DURATION = 150 1134 1135 Modal.DEFAULTS = { 1136 backdrop: true, 1137 keyboard: true, 1138 show: true 1139 } 1140 1141 Modal.prototype.toggle = function (_relatedTarget) { 1142 return this.isShown ? this.hide() : this.show(_relatedTarget) 1143 } 1144 1145 Modal.prototype.show = function (_relatedTarget) { 1146 var that = this 1147 var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) 1148 1149 this.$element.trigger(e) 1150 1151 if (this.isShown || e.isDefaultPrevented()) return 1152 1153 this.isShown = true 1154 1155 this.checkScrollbar() 1156 this.setScrollbar() 1157 this.$body.addClass('modal-open') 1158 1159 this.escape() 1160 this.resize() 1161 1162 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 1163 1164 this.$dialog.on('mousedown.dismiss.bs.modal', function () { 1165 that.$element.one('mouseup.dismiss.bs.modal', function (e) { 1166 if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true 1167 }) 1168 }) 1169 1170 this.backdrop(function () { 1171 var transition = $.support.transition && that.$element.hasClass('fade') 1172 1173 if (!that.$element.parent().length) { 1174 that.$element.appendTo(that.$body) // don't move modals dom position 1175 } 1176 1177 that.$element 1178 .show() 1179 .scrollTop(0) 1180 1181 that.adjustDialog() 1182 1183 if (transition) { 1184 that.$element[0].offsetWidth // force reflow 1185 } 1186 1187 that.$element.addClass('in') 1188 1189 that.enforceFocus() 1190 1191 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 1192 1193 transition ? 1194 that.$dialog // wait for modal to slide in 1195 .one('bsTransitionEnd', function () { 1196 that.$element.trigger('focus').trigger(e) 1197 }) 1198 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 1199 that.$element.trigger('focus').trigger(e) 1200 }) 1201 } 1202 1203 Modal.prototype.hide = function (e) { 1204 if (e) e.preventDefault() 1205 1206 e = $.Event('hide.bs.modal') 1207 1208 this.$element.trigger(e) 1209 1210 if (!this.isShown || e.isDefaultPrevented()) return 1211 1212 this.isShown = false 1213 1214 this.escape() 1215 this.resize() 1216 1217 $(document).off('focusin.bs.modal') 1218 1219 this.$element 1220 .removeClass('in') 1221 .off('click.dismiss.bs.modal') 1222 .off('mouseup.dismiss.bs.modal') 1223 1224 this.$dialog.off('mousedown.dismiss.bs.modal') 1225 1226 $.support.transition && this.$element.hasClass('fade') ? 1227 this.$element 1228 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 1229 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 1230 this.hideModal() 1231 } 1232 1233 Modal.prototype.enforceFocus = function () { 1234 $(document) 1235 .off('focusin.bs.modal') // guard against infinite focus loop 1236 .on('focusin.bs.modal', $.proxy(function (e) { 1237 if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { 1238 this.$element.trigger('focus') 1239 } 1240 }, this)) 1241 } 1242 1243 Modal.prototype.escape = function () { 1244 if (this.isShown && this.options.keyboard) { 1245 this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { 1246 e.which == 27 && this.hide() 1247 }, this)) 1248 } else if (!this.isShown) { 1249 this.$element.off('keydown.dismiss.bs.modal') 1250 } 1251 } 1252 1253 Modal.prototype.resize = function () { 1254 if (this.isShown) { 1255 $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) 1256 } else { 1257 $(window).off('resize.bs.modal') 1258 } 1259 } 1260 1261 Modal.prototype.hideModal = function () { 1262 var that = this 1263 this.$element.hide() 1264 this.backdrop(function () { 1265 that.$body.removeClass('modal-open') 1266 that.resetAdjustments() 1267 that.resetScrollbar() 1268 that.$element.trigger('hidden.bs.modal') 1269 }) 1270 } 1271 1272 Modal.prototype.removeBackdrop = function () { 1273 this.$backdrop && this.$backdrop.remove() 1274 this.$backdrop = null 1275 } 1276 1277 Modal.prototype.backdrop = function (callback) { 1278 var that = this 1279 var animate = this.$element.hasClass('fade') ? 'fade' : '' 1280 1281 if (this.isShown && this.options.backdrop) { 1282 var doAnimate = $.support.transition && animate 1283 1284 this.$backdrop = $(document.createElement('div')) 1285 .addClass('modal-backdrop ' + animate) 1286 .appendTo(this.$body) 1287 1288 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { 1289 if (this.ignoreBackdropClick) { 1290 this.ignoreBackdropClick = false 1291 return 1292 } 1293 if (e.target !== e.currentTarget) return 1294 this.options.backdrop == 'static' 1295 ? this.$element[0].focus() 1296 : this.hide() 1297 }, this)) 1298 1299 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 1300 1301 this.$backdrop.addClass('in') 1302 1303 if (!callback) return 1304 1305 doAnimate ? 1306 this.$backdrop 1307 .one('bsTransitionEnd', callback) 1308 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 1309 callback() 1310 1311 } else if (!this.isShown && this.$backdrop) { 1312 this.$backdrop.removeClass('in') 1313 1314 var callbackRemove = function () { 1315 that.removeBackdrop() 1316 callback && callback() 1317 } 1318 $.support.transition && this.$element.hasClass('fade') ? 1319 this.$backdrop 1320 .one('bsTransitionEnd', callbackRemove) 1321 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 1322 callbackRemove() 1323 1324 } else if (callback) { 1325 callback() 1326 } 1327 } 1328 1329 // these following methods are used to handle overflowing modals 1330 1331 Modal.prototype.handleUpdate = function () { 1332 this.adjustDialog() 1333 } 1334 1335 Modal.prototype.adjustDialog = function () { 1336 var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight 1337 1338 this.$element.css({ 1339 paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', 1340 paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' 1341 }) 1342 } 1343 1344 Modal.prototype.resetAdjustments = function () { 1345 this.$element.css({ 1346 paddingLeft: '', 1347 paddingRight: '' 1348 }) 1349 } 1350 1351 Modal.prototype.checkScrollbar = function () { 1352 var fullWindowWidth = window.innerWidth 1353 if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 1354 var documentElementRect = document.documentElement.getBoundingClientRect() 1355 fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) 1356 } 1357 this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth 1358 this.scrollbarWidth = this.measureScrollbar() 1359 } 1360 1361 Modal.prototype.setScrollbar = function () { 1362 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 1363 this.originalBodyPad = document.body.style.paddingRight || '' 1364 if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) 1365 } 1366 1367 Modal.prototype.resetScrollbar = function () { 1368 this.$body.css('padding-right', this.originalBodyPad) 1369 } 1370 1371 Modal.prototype.measureScrollbar = function () { // thx walsh 1372 var scrollDiv = document.createElement('div') 1373 scrollDiv.className = 'modal-scrollbar-measure' 1374 this.$body.append(scrollDiv) 1375 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 1376 this.$body[0].removeChild(scrollDiv) 1377 return scrollbarWidth 1378 } 1379 1380 1381 // MODAL PLUGIN DEFINITION 1382 // ======================= 1383 1384 function Plugin(option, _relatedTarget) { 1385 return this.each(function () { 1386 var $this = $(this) 1387 var data = $this.data('bs.modal') 1388 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 1389 1390 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 1391 if (typeof option == 'string') data[option](_relatedTarget) 1392 else if (options.show) data.show(_relatedTarget) 1393 }) 1394 } 1395 1396 var old = $.fn.modal 1397 1398 $.fn.modal = Plugin 1399 $.fn.modal.Constructor = Modal 1400 1401 1402 // MODAL NO CONFLICT 1403 // ================= 1404 1405 $.fn.modal.noConflict = function () { 1406 $.fn.modal = old 1407 return this 1408 } 1409 1410 1411 // MODAL DATA-API 1412 // ============== 1413 1414 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 1415 var $this = $(this) 1416 var href = $this.attr('href') 1417 var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 1418 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 1419 1420 if ($this.is('a')) e.preventDefault() 1421 1422 $target.one('show.bs.modal', function (showEvent) { 1423 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown 1424 $target.one('hidden.bs.modal', function () { 1425 $this.is(':visible') && $this.trigger('focus') 1426 }) 1427 }) 1428 Plugin.call($target, option, this) 1429 }) 1430 1431}(jQuery); 1432 1433/* ======================================================================== 1434 * Bootstrap: tooltip.js v3.3.5 1435 * http://getbootstrap.com/javascript/#tooltip 1436 * Inspired by the original jQuery.tipsy by Jason Frame 1437 * ======================================================================== 1438 * Copyright 2011-2015 Twitter, Inc. 1439 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1440 * ======================================================================== */ 1441 1442 1443+function ($) { 1444 'use strict'; 1445 1446 // TOOLTIP PUBLIC CLASS DEFINITION 1447 // =============================== 1448 1449 var Tooltip = function (element, options) { 1450 this.type = null 1451 this.options = null 1452 this.enabled = null 1453 this.timeout = null 1454 this.hoverState = null 1455 this.$element = null 1456 this.inState = null 1457 1458 this.init('tooltip', element, options) 1459 } 1460 1461 Tooltip.VERSION = '3.3.5' 1462 1463 Tooltip.TRANSITION_DURATION = 150 1464 1465 Tooltip.DEFAULTS = { 1466 animation: true, 1467 placement: 'top', 1468 selector: false, 1469 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 1470 trigger: 'hover focus', 1471 title: '', 1472 delay: 0, 1473 html: false, 1474 container: false, 1475 viewport: { 1476 selector: 'body', 1477 padding: 0 1478 } 1479 } 1480 1481 Tooltip.prototype.init = function (type, element, options) { 1482 this.enabled = true 1483 this.type = type 1484 this.$element = $(element) 1485 this.options = this.getOptions(options) 1486 this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) 1487 this.inState = { click: false, hover: false, focus: false } 1488 1489 if (this.$element[0] instanceof document.constructor && !this.options.selector) { 1490 throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') 1491 } 1492 1493 var triggers = this.options.trigger.split(' ') 1494 1495 for (var i = triggers.length; i--;) { 1496 var trigger = triggers[i] 1497 1498 if (trigger == 'click') { 1499 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 1500 } else if (trigger != 'manual') { 1501 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 1502 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 1503 1504 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 1505 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 1506 } 1507 } 1508 1509 this.options.selector ? 1510 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 1511 this.fixTitle() 1512 } 1513 1514 Tooltip.prototype.getDefaults = function () { 1515 return Tooltip.DEFAULTS 1516 } 1517 1518 Tooltip.prototype.getOptions = function (options) { 1519 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 1520 1521 if (options.delay && typeof options.delay == 'number') { 1522 options.delay = { 1523 show: options.delay, 1524 hide: options.delay 1525 } 1526 } 1527 1528 return options 1529 } 1530 1531 Tooltip.prototype.getDelegateOptions = function () { 1532 var options = {} 1533 var defaults = this.getDefaults() 1534 1535 this._options && $.each(this._options, function (key, value) { 1536 if (defaults[key] != value) options[key] = value 1537 }) 1538 1539 return options 1540 } 1541 1542 Tooltip.prototype.enter = function (obj) { 1543 var self = obj instanceof this.constructor ? 1544 obj : $(obj.currentTarget).data('bs.' + this.type) 1545 1546 if (!self) { 1547 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 1548 $(obj.currentTarget).data('bs.' + this.type, self) 1549 } 1550 1551 if (obj instanceof $.Event) { 1552 self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true 1553 } 1554 1555 if (self.tip().hasClass('in') || self.hoverState == 'in') { 1556 self.hoverState = 'in' 1557 return 1558 } 1559 1560 clearTimeout(self.timeout) 1561 1562 self.hoverState = 'in' 1563 1564 if (!self.options.delay || !self.options.delay.show) return self.show() 1565 1566 self.timeout = setTimeout(function () { 1567 if (self.hoverState == 'in') self.show() 1568 }, self.options.delay.show) 1569 } 1570 1571 Tooltip.prototype.isInStateTrue = function () { 1572 for (var key in this.inState) { 1573 if (this.inState[key]) return true 1574 } 1575 1576 return false 1577 } 1578 1579 Tooltip.prototype.leave = function (obj) { 1580 var self = obj instanceof this.constructor ? 1581 obj : $(obj.currentTarget).data('bs.' + this.type) 1582 1583 if (!self) { 1584 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 1585 $(obj.currentTarget).data('bs.' + this.type, self) 1586 } 1587 1588 if (obj instanceof $.Event) { 1589 self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false 1590 } 1591 1592 if (self.isInStateTrue()) return 1593 1594 clearTimeout(self.timeout) 1595 1596 self.hoverState = 'out' 1597 1598 if (!self.options.delay || !self.options.delay.hide) return self.hide() 1599 1600 self.timeout = setTimeout(function () { 1601 if (self.hoverState == 'out') self.hide() 1602 }, self.options.delay.hide) 1603 } 1604 1605 Tooltip.prototype.show = function () { 1606 var e = $.Event('show.bs.' + this.type) 1607 1608 if (this.hasContent() && this.enabled) { 1609 this.$element.trigger(e) 1610 1611 var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) 1612 if (e.isDefaultPrevented() || !inDom) return 1613 var that = this 1614 1615 var $tip = this.tip() 1616 1617 var tipId = this.getUID(this.type) 1618 1619 this.setContent() 1620 $tip.attr('id', tipId) 1621 this.$element.attr('aria-describedby', tipId) 1622 1623 if (this.options.animation) $tip.addClass('fade') 1624 1625 var placement = typeof this.options.placement == 'function' ? 1626 this.options.placement.call(this, $tip[0], this.$element[0]) : 1627 this.options.placement 1628 1629 var autoToken = /\s?auto?\s?/i 1630 var autoPlace = autoToken.test(placement) 1631 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 1632 1633 $tip 1634 .detach() 1635 .css({ top: 0, left: 0, display: 'block' }) 1636 .addClass(placement) 1637 .data('bs.' + this.type, this) 1638 1639 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 1640 this.$element.trigger('inserted.bs.' + this.type) 1641 1642 var pos = this.getPosition() 1643 var actualWidth = $tip[0].offsetWidth 1644 var actualHeight = $tip[0].offsetHeight 1645 1646 if (autoPlace) { 1647 var orgPlacement = placement 1648 var viewportDim = this.getPosition(this.$viewport) 1649 1650 placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : 1651 placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : 1652 placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : 1653 placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : 1654 placement 1655 1656 $tip 1657 .removeClass(orgPlacement) 1658 .addClass(placement) 1659 } 1660 1661 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 1662 1663 this.applyPlacement(calculatedOffset, placement) 1664 1665 var complete = function () { 1666 var prevHoverState = that.hoverState 1667 that.$element.trigger('shown.bs.' + that.type) 1668 that.hoverState = null 1669 1670 if (prevHoverState == 'out') that.leave(that) 1671 } 1672 1673 $.support.transition && this.$tip.hasClass('fade') ? 1674 $tip 1675 .one('bsTransitionEnd', complete) 1676 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 1677 complete() 1678 } 1679 } 1680 1681 Tooltip.prototype.applyPlacement = function (offset, placement) { 1682 var $tip = this.tip() 1683 var width = $tip[0].offsetWidth 1684 var height = $tip[0].offsetHeight 1685 1686 // manually read margins because getBoundingClientRect includes difference 1687 var marginTop = parseInt($tip.css('margin-top'), 10) 1688 var marginLeft = parseInt($tip.css('margin-left'), 10) 1689 1690 // we must check for NaN for ie 8/9 1691 if (isNaN(marginTop)) marginTop = 0 1692 if (isNaN(marginLeft)) marginLeft = 0 1693 1694 offset.top += marginTop 1695 offset.left += marginLeft 1696 1697 // $.fn.offset doesn't round pixel values 1698 // so we use setOffset directly with our own function B-0 1699 $.offset.setOffset($tip[0], $.extend({ 1700 using: function (props) { 1701 $tip.css({ 1702 top: Math.round(props.top), 1703 left: Math.round(props.left) 1704 }) 1705 } 1706 }, offset), 0) 1707 1708 $tip.addClass('in') 1709 1710 // check to see if placing tip in new offset caused the tip to resize itself 1711 var actualWidth = $tip[0].offsetWidth 1712 var actualHeight = $tip[0].offsetHeight 1713 1714 if (placement == 'top' && actualHeight != height) { 1715 offset.top = offset.top + height - actualHeight 1716 } 1717 1718 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 1719 1720 if (delta.left) offset.left += delta.left 1721 else offset.top += delta.top 1722 1723 var isVertical = /top|bottom/.test(placement) 1724 var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 1725 var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' 1726 1727 $tip.offset(offset) 1728 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) 1729 } 1730 1731 Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { 1732 this.arrow() 1733 .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') 1734 .css(isVertical ? 'top' : 'left', '') 1735 } 1736 1737 Tooltip.prototype.setContent = function () { 1738 var $tip = this.tip() 1739 var title = this.getTitle() 1740 1741 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 1742 $tip.removeClass('fade in top bottom left right') 1743 } 1744 1745 Tooltip.prototype.hide = function (callback) { 1746 var that = this 1747 var $tip = $(this.$tip) 1748 var e = $.Event('hide.bs.' + this.type) 1749 1750 function complete() { 1751 if (that.hoverState != 'in') $tip.detach() 1752 that.$element 1753 .removeAttr('aria-describedby') 1754 .trigger('hidden.bs.' + that.type) 1755 callback && callback() 1756 } 1757 1758 this.$element.trigger(e) 1759 1760 if (e.isDefaultPrevented()) return 1761 1762 $tip.removeClass('in') 1763 1764 $.support.transition && $tip.hasClass('fade') ? 1765 $tip 1766 .one('bsTransitionEnd', complete) 1767 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 1768 complete() 1769 1770 this.hoverState = null 1771 1772 return this 1773 } 1774 1775 Tooltip.prototype.fixTitle = function () { 1776 var $e = this.$element 1777 if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { 1778 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 1779 } 1780 } 1781 1782 Tooltip.prototype.hasContent = function () { 1783 return this.getTitle() 1784 } 1785 1786 Tooltip.prototype.getPosition = function ($element) { 1787 $element = $element || this.$element 1788 1789 var el = $element[0] 1790 var isBody = el.tagName == 'BODY' 1791 1792 var elRect = el.getBoundingClientRect() 1793 if (elRect.width == null) { 1794 // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 1795 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) 1796 } 1797 var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() 1798 var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } 1799 var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null 1800 1801 return $.extend({}, elRect, scroll, outerDims, elOffset) 1802 } 1803 1804 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 1805 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 1806 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 1807 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 1808 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 1809 1810 } 1811 1812 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 1813 var delta = { top: 0, left: 0 } 1814 if (!this.$viewport) return delta 1815 1816 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 1817 var viewportDimensions = this.getPosition(this.$viewport) 1818 1819 if (/right|left/.test(placement)) { 1820 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 1821 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 1822 if (topEdgeOffset < viewportDimensions.top) { // top overflow 1823 delta.top = viewportDimensions.top - topEdgeOffset 1824 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 1825 delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset 1826 } 1827 } else { 1828 var leftEdgeOffset = pos.left - viewportPadding 1829 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 1830 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 1831 delta.left = viewportDimensions.left - leftEdgeOffset 1832 } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow 1833 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 1834 } 1835 } 1836 1837 return delta 1838 } 1839 1840 Tooltip.prototype.getTitle = function () { 1841 var title 1842 var $e = this.$element 1843 var o = this.options 1844 1845 title = $e.attr('data-original-title') 1846 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 1847 1848 return title 1849 } 1850 1851 Tooltip.prototype.getUID = function (prefix) { 1852 do prefix += ~~(Math.random() * 1000000) 1853 while (document.getElementById(prefix)) 1854 return prefix 1855 } 1856 1857 Tooltip.prototype.tip = function () { 1858 if (!this.$tip) { 1859 this.$tip = $(this.options.template) 1860 if (this.$tip.length != 1) { 1861 throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') 1862 } 1863 } 1864 return this.$tip 1865 } 1866 1867 Tooltip.prototype.arrow = function () { 1868 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) 1869 } 1870 1871 Tooltip.prototype.enable = function () { 1872 this.enabled = true 1873 } 1874 1875 Tooltip.prototype.disable = function () { 1876 this.enabled = false 1877 } 1878 1879 Tooltip.prototype.toggleEnabled = function () { 1880 this.enabled = !this.enabled 1881 } 1882 1883 Tooltip.prototype.toggle = function (e) { 1884 var self = this 1885 if (e) { 1886 self = $(e.currentTarget).data('bs.' + this.type) 1887 if (!self) { 1888 self = new this.constructor(e.currentTarget, this.getDelegateOptions()) 1889 $(e.currentTarget).data('bs.' + this.type, self) 1890 } 1891 } 1892 1893 if (e) { 1894 self.inState.click = !self.inState.click 1895 if (self.isInStateTrue()) self.enter(self) 1896 else self.leave(self) 1897 } else { 1898 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 1899 } 1900 } 1901 1902 Tooltip.prototype.destroy = function () { 1903 var that = this 1904 clearTimeout(this.timeout) 1905 this.hide(function () { 1906 that.$element.off('.' + that.type).removeData('bs.' + that.type) 1907 if (that.$tip) { 1908 that.$tip.detach() 1909 } 1910 that.$tip = null 1911 that.$arrow = null 1912 that.$viewport = null 1913 }) 1914 } 1915 1916 1917 // TOOLTIP PLUGIN DEFINITION 1918 // ========================= 1919 1920 function Plugin(option) { 1921 return this.each(function () { 1922 var $this = $(this) 1923 var data = $this.data('bs.tooltip') 1924 var options = typeof option == 'object' && option 1925 1926 if (!data && /destroy|hide/.test(option)) return 1927 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 1928 if (typeof option == 'string') data[option]() 1929 }) 1930 } 1931 1932 var old = $.fn.tooltip 1933 1934 $.fn.tooltip = Plugin 1935 $.fn.tooltip.Constructor = Tooltip 1936 1937 1938 // TOOLTIP NO CONFLICT 1939 // =================== 1940 1941 $.fn.tooltip.noConflict = function () { 1942 $.fn.tooltip = old 1943 return this 1944 } 1945 1946}(jQuery); 1947 1948/* ======================================================================== 1949 * Bootstrap: popover.js v3.3.5 1950 * http://getbootstrap.com/javascript/#popovers 1951 * ======================================================================== 1952 * Copyright 2011-2015 Twitter, Inc. 1953 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1954 * ======================================================================== */ 1955 1956 1957+function ($) { 1958 'use strict'; 1959 1960 // POPOVER PUBLIC CLASS DEFINITION 1961 // =============================== 1962 1963 var Popover = function (element, options) { 1964 this.init('popover', element, options) 1965 } 1966 1967 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 1968 1969 Popover.VERSION = '3.3.5' 1970 1971 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { 1972 placement: 'right', 1973 trigger: 'click', 1974 content: '', 1975 template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' 1976 }) 1977 1978 1979 // NOTE: POPOVER EXTENDS tooltip.js 1980 // ================================ 1981 1982 Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) 1983 1984 Popover.prototype.constructor = Popover 1985 1986 Popover.prototype.getDefaults = function () { 1987 return Popover.DEFAULTS 1988 } 1989 1990 Popover.prototype.setContent = function () { 1991 var $tip = this.tip() 1992 var title = this.getTitle() 1993 var content = this.getContent() 1994 1995 $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) 1996 $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events 1997 this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' 1998 ](content) 1999 2000 $tip.removeClass('fade top bottom left right in') 2001 2002 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do 2003 // this manually by checking the contents. 2004 if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() 2005 } 2006 2007 Popover.prototype.hasContent = function () { 2008 return this.getTitle() || this.getContent() 2009 } 2010 2011 Popover.prototype.getContent = function () { 2012 var $e = this.$element 2013 var o = this.options 2014 2015 return $e.attr('data-content') 2016 || (typeof o.content == 'function' ? 2017 o.content.call($e[0]) : 2018 o.content) 2019 } 2020 2021 Popover.prototype.arrow = function () { 2022 return (this.$arrow = this.$arrow || this.tip().find('.arrow')) 2023 } 2024 2025 2026 // POPOVER PLUGIN DEFINITION 2027 // ========================= 2028 2029 function Plugin(option) { 2030 return this.each(function () { 2031 var $this = $(this) 2032 var data = $this.data('bs.popover') 2033 var options = typeof option == 'object' && option 2034 2035 if (!data && /destroy|hide/.test(option)) return 2036 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 2037 if (typeof option == 'string') data[option]() 2038 }) 2039 } 2040 2041 var old = $.fn.popover 2042 2043 $.fn.popover = Plugin 2044 $.fn.popover.Constructor = Popover 2045 2046 2047 // POPOVER NO CONFLICT 2048 // =================== 2049 2050 $.fn.popover.noConflict = function () { 2051 $.fn.popover = old 2052 return this 2053 } 2054 2055}(jQuery); 2056 2057/* ======================================================================== 2058 * Bootstrap: scrollspy.js v3.3.5 2059 * http://getbootstrap.com/javascript/#scrollspy 2060 * ======================================================================== 2061 * Copyright 2011-2015 Twitter, Inc. 2062 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 2063 * ======================================================================== */ 2064 2065 2066+function ($) { 2067 'use strict'; 2068 2069 // SCROLLSPY CLASS DEFINITION 2070 // ========================== 2071 2072 function ScrollSpy(element, options) { 2073 this.$body = $(document.body) 2074 this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) 2075 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 2076 this.selector = (this.options.target || '') + ' .nav li > a' 2077 this.offsets = [] 2078 this.targets = [] 2079 this.activeTarget = null 2080 this.scrollHeight = 0 2081 2082 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) 2083 this.refresh() 2084 this.process() 2085 } 2086 2087 ScrollSpy.VERSION = '3.3.5' 2088 2089 ScrollSpy.DEFAULTS = { 2090 offset: 10 2091 } 2092 2093 ScrollSpy.prototype.getScrollHeight = function () { 2094 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) 2095 } 2096 2097 ScrollSpy.prototype.refresh = function () { 2098 var that = this 2099 var offsetMethod = 'offset' 2100 var offsetBase = 0 2101 2102 this.offsets = [] 2103 this.targets = [] 2104 this.scrollHeight = this.getScrollHeight() 2105 2106 if (!$.isWindow(this.$scrollElement[0])) { 2107 offsetMethod = 'position' 2108 offsetBase = this.$scrollElement.scrollTop() 2109 } 2110 2111 this.$body 2112 .find(this.selector) 2113 .map(function () { 2114 var $el = $(this) 2115 var href = $el.data('target') || $el.attr('href') 2116 var $href = /^#./.test(href) && $(href) 2117 2118 return ($href 2119 && $href.length 2120 && $href.is(':visible') 2121 && [[$href[offsetMethod]().top + offsetBase, href]]) || null 2122 }) 2123 .sort(function (a, b) { return a[0] - b[0] }) 2124 .each(function () { 2125 that.offsets.push(this[0]) 2126 that.targets.push(this[1]) 2127 }) 2128 } 2129 2130 ScrollSpy.prototype.process = function () { 2131 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 2132 var scrollHeight = this.getScrollHeight() 2133 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() 2134 var offsets = this.offsets 2135 var targets = this.targets 2136 var activeTarget = this.activeTarget 2137 var i 2138 2139 if (this.scrollHeight != scrollHeight) { 2140 this.refresh() 2141 } 2142 2143 if (scrollTop >= maxScroll) { 2144 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) 2145 } 2146 2147 if (activeTarget && scrollTop < offsets[0]) { 2148 this.activeTarget = null 2149 return this.clear() 2150 } 2151 2152 for (i = offsets.length; i--;) { 2153 activeTarget != targets[i] 2154 && scrollTop >= offsets[i] 2155 && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) 2156 && this.activate(targets[i]) 2157 } 2158 } 2159 2160 ScrollSpy.prototype.activate = function (target) { 2161 this.activeTarget = target 2162 2163 this.clear() 2164 2165 var selector = this.selector + 2166 '[data-target="' + target + '"],' + 2167 this.selector + '[href="' + target + '"]' 2168 2169 var active = $(selector) 2170 .parents('li') 2171 .addClass('active') 2172 2173 if (active.parent('.dropdown-menu').length) { 2174 active = active 2175 .closest('li.dropdown') 2176 .addClass('active') 2177 } 2178 2179 active.trigger('activate.bs.scrollspy') 2180 } 2181 2182 ScrollSpy.prototype.clear = function () { 2183 $(this.selector) 2184 .parentsUntil(this.options.target, '.active') 2185 .removeClass('active') 2186 } 2187 2188 2189 // SCROLLSPY PLUGIN DEFINITION 2190 // =========================== 2191 2192 function Plugin(option) { 2193 return this.each(function () { 2194 var $this = $(this) 2195 var data = $this.data('bs.scrollspy') 2196 var options = typeof option == 'object' && option 2197 2198 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) 2199 if (typeof option == 'string') data[option]() 2200 }) 2201 } 2202 2203 var old = $.fn.scrollspy 2204 2205 $.fn.scrollspy = Plugin 2206 $.fn.scrollspy.Constructor = ScrollSpy 2207 2208 2209 // SCROLLSPY NO CONFLICT 2210 // ===================== 2211 2212 $.fn.scrollspy.noConflict = function () { 2213 $.fn.scrollspy = old 2214 return this 2215 } 2216 2217 2218 // SCROLLSPY DATA-API 2219 // ================== 2220 2221 $(window).on('load.bs.scrollspy.data-api', function () { 2222 $('[data-spy="scroll"]').each(function () { 2223 var $spy = $(this) 2224 Plugin.call($spy, $spy.data()) 2225 }) 2226 }) 2227 2228}(jQuery); 2229 2230/* ======================================================================== 2231 * Bootstrap: tab.js v3.3.5 2232 * http://getbootstrap.com/javascript/#tabs 2233 * ======================================================================== 2234 * Copyright 2011-2015 Twitter, Inc. 2235 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 2236 * ======================================================================== */ 2237 2238 2239+function ($) { 2240 'use strict'; 2241 2242 // TAB CLASS DEFINITION 2243 // ==================== 2244 2245 var Tab = function (element) { 2246 // jscs:disable requireDollarBeforejQueryAssignment 2247 this.element = $(element) 2248 // jscs:enable requireDollarBeforejQueryAssignment 2249 } 2250 2251 Tab.VERSION = '3.3.5' 2252 2253 Tab.TRANSITION_DURATION = 150 2254 2255 Tab.prototype.show = function () { 2256 var $this = this.element 2257 var $ul = $this.closest('ul:not(.dropdown-menu)') 2258 var selector = $this.data('target') 2259 2260 if (!selector) { 2261 selector = $this.attr('href') 2262 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 2263 } 2264 2265 if ($this.parent('li').hasClass('active')) return 2266 2267 var $previous = $ul.find('.active:last a') 2268 var hideEvent = $.Event('hide.bs.tab', { 2269 relatedTarget: $this[0] 2270 }) 2271 var showEvent = $.Event('show.bs.tab', { 2272 relatedTarget: $previous[0] 2273 }) 2274 2275 $previous.trigger(hideEvent) 2276 $this.trigger(showEvent) 2277 2278 if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return 2279 2280 var $target = $(selector) 2281 2282 this.activate($this.closest('li'), $ul) 2283 this.activate($target, $target.parent(), function () { 2284 $previous.trigger({ 2285 type: 'hidden.bs.tab', 2286 relatedTarget: $this[0] 2287 }) 2288 $this.trigger({ 2289 type: 'shown.bs.tab', 2290 relatedTarget: $previous[0] 2291 }) 2292 }) 2293 } 2294 2295 Tab.prototype.activate = function (element, container, callback) { 2296 var $active = container.find('> .active') 2297 var transition = callback 2298 && $.support.transition 2299 && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) 2300 2301 function next() { 2302 $active 2303 .removeClass('active') 2304 .find('> .dropdown-menu > .active') 2305 .removeClass('active') 2306 .end() 2307 .find('[data-toggle="tab"]') 2308 .attr('aria-expanded', false) 2309 2310 element 2311 .addClass('active') 2312 .find('[data-toggle="tab"]') 2313 .attr('aria-expanded', true) 2314 2315 if (transition) { 2316 element[0].offsetWidth // reflow for transition 2317 element.addClass('in') 2318 } else { 2319 element.removeClass('fade') 2320 } 2321 2322 if (element.parent('.dropdown-menu').length) { 2323 element 2324 .closest('li.dropdown') 2325 .addClass('active') 2326 .end() 2327 .find('[data-toggle="tab"]') 2328 .attr('aria-expanded', true) 2329 } 2330 2331 callback && callback() 2332 } 2333 2334 $active.length && transition ? 2335 $active 2336 .one('bsTransitionEnd', next) 2337 .emulateTransitionEnd(Tab.TRANSITION_DURATION) : 2338 next() 2339 2340 $active.removeClass('in') 2341 } 2342 2343 2344 // TAB PLUGIN DEFINITION 2345 // ===================== 2346 2347 function Plugin(option) { 2348 return this.each(function () { 2349 var $this = $(this) 2350 var data = $this.data('bs.tab') 2351 2352 if (!data) $this.data('bs.tab', (data = new Tab(this))) 2353 if (typeof option == 'string') data[option]() 2354 }) 2355 } 2356 2357 var old = $.fn.tab 2358 2359 $.fn.tab = Plugin 2360 $.fn.tab.Constructor = Tab 2361 2362 2363 // TAB NO CONFLICT 2364 // =============== 2365 2366 $.fn.tab.noConflict = function () { 2367 $.fn.tab = old 2368 return this 2369 } 2370 2371 2372 // TAB DATA-API 2373 // ============ 2374 2375 var clickHandler = function (e) { 2376 e.preventDefault() 2377 Plugin.call($(this), 'show') 2378 } 2379 2380 $(document) 2381 .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) 2382 .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) 2383 2384}(jQuery); 2385 2386/* ======================================================================== 2387 * Bootstrap: affix.js v3.3.5 2388 * http://getbootstrap.com/javascript/#affix 2389 * ======================================================================== 2390 * Copyright 2011-2015 Twitter, Inc. 2391 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 2392 * ======================================================================== */ 2393 2394 2395+function ($) { 2396 'use strict'; 2397 2398 // AFFIX CLASS DEFINITION 2399 // ====================== 2400 2401 var Affix = function (element, options) { 2402 this.options = $.extend({}, Affix.DEFAULTS, options) 2403 2404 this.$target = $(this.options.target) 2405 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) 2406 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 2407 2408 this.$element = $(element) 2409 this.affixed = null 2410 this.unpin = null 2411 this.pinnedOffset = null 2412 2413 this.checkPosition() 2414 } 2415 2416 Affix.VERSION = '3.3.5' 2417 2418 Affix.RESET = 'affix affix-top affix-bottom' 2419 2420 Affix.DEFAULTS = { 2421 offset: 0, 2422 target: window 2423 } 2424 2425 Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { 2426 var scrollTop = this.$target.scrollTop() 2427 var position = this.$element.offset() 2428 var targetHeight = this.$target.height() 2429 2430 if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false 2431 2432 if (this.affixed == 'bottom') { 2433 if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' 2434 return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' 2435 } 2436 2437 var initializing = this.affixed == null 2438 var colliderTop = initializing ? scrollTop : position.top 2439 var colliderHeight = initializing ? targetHeight : height 2440 2441 if (offsetTop != null && scrollTop <= offsetTop) return 'top' 2442 if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' 2443 2444 return false 2445 } 2446 2447 Affix.prototype.getPinnedOffset = function () { 2448 if (this.pinnedOffset) return this.pinnedOffset 2449 this.$element.removeClass(Affix.RESET).addClass('affix') 2450 var scrollTop = this.$target.scrollTop() 2451 var position = this.$element.offset() 2452 return (this.pinnedOffset = position.top - scrollTop) 2453 } 2454 2455 Affix.prototype.checkPositionWithEventLoop = function () { 2456 setTimeout($.proxy(this.checkPosition, this), 1) 2457 } 2458 2459 Affix.prototype.checkPosition = function () { 2460 if (!this.$element.is(':visible')) return 2461 2462 var height = this.$element.height() 2463 var offset = this.options.offset 2464 var offsetTop = offset.top 2465 var offsetBottom = offset.bottom 2466 var scrollHeight = Math.max($(document).height(), $(document.body).height()) 2467 2468 if (typeof offset != 'object') offsetBottom = offsetTop = offset 2469 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 2470 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 2471 2472 var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) 2473 2474 if (this.affixed != affix) { 2475 if (this.unpin != null) this.$element.css('top', '') 2476 2477 var affixType = 'affix' + (affix ? '-' + affix : '') 2478 var e = $.Event(affixType + '.bs.affix') 2479 2480 this.$element.trigger(e) 2481 2482 if (e.isDefaultPrevented()) return 2483 2484 this.affixed = affix 2485 this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 2486 2487 this.$element 2488 .removeClass(Affix.RESET) 2489 .addClass(affixType) 2490 .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') 2491 } 2492 2493 if (affix == 'bottom') { 2494 this.$element.offset({ 2495 top: scrollHeight - height - offsetBottom 2496 }) 2497 } 2498 } 2499 2500 2501 // AFFIX PLUGIN DEFINITION 2502 // ======================= 2503 2504 function Plugin(option) { 2505 return this.each(function () { 2506 var $this = $(this) 2507 var data = $this.data('bs.affix') 2508 var options = typeof option == 'object' && option 2509 2510 if (!data) $this.data('bs.affix', (data = new Affix(this, options))) 2511 if (typeof option == 'string') data[option]() 2512 }) 2513 } 2514 2515 var old = $.fn.affix 2516 2517 $.fn.affix = Plugin 2518 $.fn.affix.Constructor = Affix 2519 2520 2521 // AFFIX NO CONFLICT 2522 // ================= 2523 2524 $.fn.affix.noConflict = function () { 2525 $.fn.affix = old 2526 return this 2527 } 2528 2529 2530 // AFFIX DATA-API 2531 // ============== 2532 2533 $(window).on('load', function () { 2534 $('[data-spy="affix"]').each(function () { 2535 var $spy = $(this) 2536 var data = $spy.data() 2537 2538 data.offset = data.offset || {} 2539 2540 if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom 2541 if (data.offsetTop != null) data.offset.top = data.offsetTop 2542 2543 Plugin.call($spy, data) 2544 }) 2545 }) 2546 2547}(jQuery); 2548 2549/** 2550 * Isotope v1.5.26 2551 * An exquisite jQuery plugin for magical layouts 2552 * http://isotope.metafizzy.co 2553 * 2554 * Commercial use requires one-time purchase of a commercial license 2555 * http://isotope.metafizzy.co/docs/license.html 2556 * 2557 * Non-commercial use is licensed under the MIT License 2558 * 2559 * Copyright 2014 Metafizzy 2560 */ 2561 2562/*jshint asi: true, browser: true, curly: true, eqeqeq: true, forin: false, immed: false, newcap: true, noempty: true, strict: true, undef: true */ 2563/*global jQuery: false */ 2564 2565(function( window, $, undefined ){ 2566 2567 'use strict'; 2568 2569 // get global vars 2570 var document = window.document; 2571 var docElem = document.documentElement; 2572 var Modernizr = window.Modernizr; 2573 2574 // helper function 2575 var capitalize = function( str ) { 2576 return str.charAt(0).toUpperCase() + str.slice(1); 2577 }; 2578 2579 // ========================= getStyleProperty by kangax =============================== 2580 // http://perfectionkills.com/feature-testing-css-properties/ 2581 2582 var prefixes = 'Moz Webkit O Ms'.split(' '); 2583 2584 var getStyleProperty = function( propName ) { 2585 var style = docElem.style, 2586 prefixed; 2587 2588 // test standard property first 2589 if ( typeof style[propName] === 'string' ) { 2590 return propName; 2591 } 2592 2593 // capitalize 2594 propName = capitalize( propName ); 2595 2596 // test vendor specific properties 2597 for ( var i=0, len = prefixes.length; i < len; i++ ) { 2598 prefixed = prefixes[i] + propName; 2599 if ( typeof style[ prefixed ] === 'string' ) { 2600 return prefixed; 2601 } 2602 } 2603 }; 2604 2605 var transformProp = getStyleProperty('transform'), 2606 transitionProp = getStyleProperty('transitionProperty'); 2607 2608 2609 // ========================= miniModernizr =============================== 2610 // <3<3<3 and thanks to Faruk and Paul for doing the heavy lifting 2611 2612 /*! 2613 * Modernizr v1.6ish: miniModernizr for Isotope 2614 * http://www.modernizr.com 2615 * 2616 * Developed by: 2617 * - Faruk Ates http://farukat.es/ 2618 * - Paul Irish http://paulirish.com/ 2619 *
2620 * Copyright (c) 2009-2010 2621 * Dual-licensed under the BSD or MIT licenses. 2622 * http://www.modernizr.com/license/ 2623 */ 2624 2625 /* 2626 * This version whittles down the script just to check support for 2627 * CSS transitions, transforms, and 3D transforms. 2628 */ 2629 2630 var tests = { 2631 csstransforms: function() { 2632 return !!transformProp; 2633 }, 2634 2635 csstransforms3d: function() { 2636 var test = !!getStyleProperty('perspective'); 2637 // double check for Chrome's false positive 2638 if ( test && 'webkitPerspective' in docElem.style ) { 2639 var $style = $('<style>@media (transform-3d),(-webkit-transform-3d)' + 2640 '{#modernizr{height:3px}}</style>').appendTo('head'), 2641 $div = $('<div id="modernizr" />').appendTo('html'); 2642 2643 test = $div.height() === 3; 2644 2645 $div.remove(); 2646 $style.remove(); 2647 } 2648 return test; 2649 }, 2650 2651 csstransitions: function() { 2652 return !!transitionProp; 2653 } 2654 }; 2655 2656 var testName; 2657 2658 if ( Modernizr ) { 2659 // if there's a previous Modernzir, check if there are necessary tests 2660 for ( testName in tests) { 2661 if ( !Modernizr.hasOwnProperty( testName ) ) { 2662 // if test hasn't been run, use addTest to run it 2663 Modernizr.addTest( testName, tests[ testName ] ); 2664 } 2665 } 2666 } else { 2667 // or create new mini Modernizr that just has the 3 tests 2668 Modernizr = window.Modernizr = { 2669 _version : '1.6ish: miniModernizr for Isotope' 2670 }; 2671 2672 var classes = ' '; 2673 var result; 2674 2675 // Run through tests 2676 for ( testName in tests) { 2677 result = tests[ testName ](); 2678 Modernizr[ testName ] = result; 2679 classes += ' ' + ( result ? '' : 'no-' ) + testName; 2680 } 2681 2682 // Add the new classes to the <html> element. 2683 $('html').addClass( classes ); 2684 } 2685 2686 2687 // ========================= isoTransform =============================== 2688 2689 /** 2690 * provides hooks for .css({ scale: value, translate: [x, y] }) 2691 * Progressively enhanced CSS transforms 2692 * Uses hardware accelerated 3D transforms for Safari 2693 * or falls back to 2D transforms. 2694 */ 2695 2696 if ( Modernizr.csstransforms ) { 2697 2698 // i.e. transformFnNotations.scale(0.5) >> 'scale3d( 0.5, 0.5, 1)' 2699 var transformFnNotations = Modernizr.csstransforms3d ? 2700 { // 3D transform functions 2701 translate : function ( position ) { 2702 return 'translate3d(' + position[0] + 'px, ' + position[1] + 'px, 0) '; 2703 }, 2704 scale : function ( scale ) { 2705 return 'scale3d(' + scale + ', ' + scale + ', 1) '; 2706 } 2707 } : 2708 { // 2D transform functions 2709 translate : function ( position ) { 2710 return 'translate(' + position[0] + 'px, ' + position[1] + 'px) '; 2711 }, 2712 scale : function ( scale ) { 2713 return 'scale(' + scale + ') '; 2714 } 2715 } 2716 ; 2717 2718 var setIsoTransform = function ( elem, name, value ) { 2719 // unpack current transform data 2720 var data = $.data( elem, 'isoTransform' ) || {}, 2721 newData = {}, 2722 fnName, 2723 transformObj = {}, 2724 transformValue; 2725 2726 // i.e. newData.scale = 0.5 2727 newData[ name ] = value; 2728 // extend new value over current data 2729 $.extend( data, newData ); 2730 2731 for ( fnName in data ) { 2732 transformValue = data[ fnName ]; 2733 transformObj[ fnName ] = transformFnNotations[ fnName ]( transformValue ); 2734 } 2735 2736 // get proper order 2737 // ideally, we could loop through this give an array, but since we only have 2738 // a couple transforms we're keeping track of, we'll do it like so 2739 var translateFn = transformObj.translate || '', 2740 scaleFn = transformObj.scale || '', 2741 // sorting so translate always comes first 2742 valueFns = translateFn + scaleFn; 2743 2744 // set data back in elem 2745 $.data( elem, 'isoTransform', data ); 2746 2747 // set name to vendor specific property 2748 elem.style[ transformProp ] = valueFns; 2749 }; 2750 2751 // ==================== scale =================== 2752 2753 $.cssNumber.scale = true; 2754 2755 $.cssHooks.scale = { 2756 set: function( elem, value ) { 2757 // uncomment this bit if you want to properly parse strings 2758 // if ( typeof value === 'string' ) { 2759 // value = parseFloat( value ); 2760 // } 2761 setIsoTransform( elem, 'scale', value ); 2762 }, 2763 get: function( elem, computed ) { 2764 var transform = $.data( elem, 'isoTransform' ); 2765 return transform && transform.scale ? transform.scale : 1; 2766 } 2767 }; 2768 2769 $.fx.step.scale = function( fx ) { 2770 $.cssHooks.scale.set( fx.elem, fx.now+fx.unit ); 2771 }; 2772 2773 2774 // ==================== translate =================== 2775 2776 $.cssNumber.translate = true; 2777 2778 $.cssHooks.translate = { 2779 set: function( elem, value ) { 2780 2781 // uncomment this bit if you want to properly parse strings 2782 // if ( typeof value === 'string' ) { 2783 // value = value.split(' '); 2784 // } 2785 // 2786 // var i, val; 2787 // for ( i = 0; i < 2; i++ ) { 2788 // val = value[i]; 2789 // if ( typeof val === 'string' ) { 2790 // val = parseInt( val ); 2791 // } 2792 // } 2793 2794 setIsoTransform( elem, 'translate', value ); 2795 }, 2796 2797 get: function( elem, computed ) { 2798 var transform = $.data( elem, 'isoTransform' ); 2799 return transform && transform.translate ? transform.translate : [ 0, 0 ]; 2800 } 2801 }; 2802 2803 } 2804 2805 // ========================= get transition-end event =============================== 2806 var transitionEndEvent, transitionDurProp; 2807 2808 if ( Modernizr.csstransitions ) { 2809 transitionEndEvent = { 2810 WebkitTransitionProperty: 'webkitTransitionEnd', // webkit 2811 MozTransitionProperty: 'transitionend', 2812 OTransitionProperty: 'oTransitionEnd otransitionend', 2813 transitionProperty: 'transitionend' 2814 }[ transitionProp ]; 2815 2816 transitionDurProp = getStyleProperty('transitionDuration'); 2817 } 2818 2819 // ========================= smartresize =============================== 2820 2821 /* 2822 * smartresize: debounced resize event for jQuery 2823 * 2824 * latest version and complete README available on Github: 2825 * https://github.com/louisremi/jquery.smartresize.js 2826 * 2827 * Copyright 2011 @louis_remi 2828 * Licensed under the MIT license. 2829 */ 2830 2831 var $event = $.event, 2832 dispatchMethod = $.event.handle ? 'handle' : 'dispatch', 2833 resizeTimeout; 2834 2835 $event.special.smartresize = { 2836 setup: function() { 2837 $(this).bind( "resize", $event.special.smartresize.handler ); 2838 }, 2839 teardown: function() { 2840 $(this).unbind( "resize", $event.special.smartresize.handler ); 2841 }, 2842 handler: function( event, execAsap ) { 2843 // Save the context 2844 var context = this, 2845 args = arguments; 2846 2847 // set correct event type 2848 event.type = "smartresize"; 2849 2850 if ( resizeTimeout ) { clearTimeout( resizeTimeout ); } 2851 resizeTimeout = setTimeout(function() { 2852 $event[ dispatchMethod ].apply( context, args ); 2853 }, execAsap === "execAsap"? 0 : 100 ); 2854 } 2855 }; 2856 2857 $.fn.smartresize = function( fn ) { 2858 return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] ); 2859 }; 2860 2861 2862 2863// ========================= Isotope =============================== 2864 2865
2866 // our "Widget" object constructor 2867 $.Isotope = function( options, element, callback ){ 2868 this.element = $( element ); 2869 2870 this._create( options ); 2871 this._init( callback ); 2872 }; 2873 2874 // styles of container element we want to keep track of 2875 var isoContainerStyles = [ 'width', 'height' ]; 2876 2877 var $window = $(window); 2878 2879 $.Isotope.settings = { 2880 resizable: true, 2881 layoutMode : 'masonry', 2882 containerClass : 'isotope', 2883 itemClass : 'isotope-item', 2884 hiddenClass : 'isotope-hidden', 2885 hiddenStyle: { opacity: 0, scale: 0.001 }, 2886 visibleStyle: { opacity: 1, scale: 1 }, 2887 containerStyle: { 2888 position: 'relative', 2889 overflow: 'hidden' 2890 }, 2891 animationEngine: 'best-available', 2892 animationOptions: { 2893 queue: false, 2894 duration: 800 2895 }, 2896 sortBy : 'original-order', 2897 sortAscending : true, 2898 resizesContainer : true, 2899 transformsEnabled: true, 2900 itemPositionDataEnabled: false 2901 }; 2902 2903 $.Isotope.prototype = { 2904 2905 // sets up widget 2906 _create : function( options ) { 2907 2908 this.options = $.extend( {}, $.Isotope.settings, options ); 2909 2910 this.styleQueue = []; 2911 this.elemCount = 0; 2912 2913 // get original styles in case we re-apply them in .destroy() 2914 var elemStyle = this.element[0].style; 2915 this.originalStyle = {}; 2916 // keep track of container styles 2917 var containerStyles = isoContainerStyles.slice(0); 2918 for ( var prop in this.options.containerStyle ) { 2919 containerStyles.push( prop ); 2920 } 2921 for ( var i=0, len = containerStyles.length; i < len; i++ ) { 2922 prop = containerStyles[i]; 2923 this.originalStyle[ prop ] = elemStyle[ prop ] || ''; 2924 } 2925 // apply container style from options 2926 this.element.css( this.options.containerStyle ); 2927 2928 this._updateAnimationEngine(); 2929 this._updateUsingTransforms(); 2930 2931 // sorting 2932 var originalOrderSorter = { 2933 'original-order' : function( $elem, instance ) { 2934 instance.elemCount ++; 2935 return instance.elemCount; 2936 }, 2937 random : function() { 2938 return Math.random(); 2939 } 2940 }; 2941 2942 this.options.getSortData = $.extend( this.options.getSortData, originalOrderSorter ); 2943 2944 // need to get atoms 2945 this.reloadItems(); 2946 2947 // get top left position of where the bricks should be 2948 this.offset = { 2949 left: parseInt( ( this.element.css('padding-left') || 0 ), 10 ), 2950 top: parseInt( ( this.element.css('padding-top') || 0 ), 10 ) 2951 }; 2952 2953 // add isotope class first time around 2954 var instance = this; 2955 setTimeout( function() { 2956 instance.element.addClass( instance.options.containerClass ); 2957 }, 0 ); 2958 2959 // bind resize method 2960 if ( this.options.resizable ) { 2961 $window.bind( 'smartresize.isotope', function() { 2962 instance.resize(); 2963 }); 2964 } 2965 2966 // dismiss all click events from hidden events 2967 this.element.delegate( '.' + this.options.hiddenClass, 'click', function(){ 2968 return false; 2969 }); 2970 2971 }, 2972 2973 _getAtoms : function( $elems ) { 2974 var selector = this.options.itemSelector, 2975 // filter & find 2976 $atoms = selector ? $elems.filter( selector ).add( $elems.find( selector ) ) : $elems, 2977 // base style for atoms 2978 atomStyle = { position: 'absolute' }; 2979 2980 // filter out text nodes 2981 $atoms = $atoms.filter( function( i, atom ) { 2982 return atom.nodeType === 1; 2983 }); 2984 2985 if ( this.usingTransforms ) { 2986 atomStyle.left = 0; 2987 atomStyle.top = 0; 2988 } 2989 2990 $atoms.css( atomStyle ).addClass( this.options.itemClass ); 2991 2992 this.updateSortData( $atoms, true ); 2993 2994 return $atoms; 2995 }, 2996 2997 // _init fires when your instance is first created 2998 // (from the constructor above), and when you 2999 // attempt to initialize the widget again (by the bridge) 3000 // after it has already been initialized. 3001 _init : function( callback ) { 3002 3003 this.$filteredAtoms = this._filter( this.$allAtoms ); 3004 this._sort(); 3005 this.reLayout( callback ); 3006 3007 }, 3008 3009 option : function( opts ){ 3010 // change options AFTER initialization: 3011 // signature: $('#foo').bar({ cool:false }); 3012 if ( $.isPlainObject( opts ) ){ 3013 this.options = $.extend( true, this.options, opts ); 3014 3015 // trigger _updateOptionName if it exists 3016 var updateOptionFn; 3017 for ( var optionName in opts ) { 3018 updateOptionFn = '_update' + capitalize( optionName ); 3019 if ( this[ updateOptionFn ] ) { 3020 this[ updateOptionFn ](); 3021 } 3022 } 3023 } 3024 }, 3025 3026 // ====================== updaters ====================== // 3027 // kind of like setters 3028 3029 _updateAnimationEngine : function() { 3030 var animationEngine = this.options.animationEngine.toLowerCase().replace( /[ _\-]/g, ''); 3031 var isUsingJQueryAnimation; 3032 // set applyStyleFnName 3033 switch ( animationEngine ) { 3034 case 'css' : 3035 case 'none' : 3036 isUsingJQueryAnimation = false; 3037 break; 3038 case 'jquery' : 3039 isUsingJQueryAnimation = true; 3040 break; 3041 default : // best available 3042 isUsingJQueryAnimation = !Modernizr.csstransitions; 3043 } 3044 this.isUsingJQueryAnimation = isUsingJQueryAnimation; 3045 this._updateUsingTransforms(); 3046 }, 3047 3048 _updateTransformsEnabled : function() { 3049 this._updateUsingTransforms(); 3050 }, 3051 3052 _updateUsingTransforms : function() { 3053 var usingTransforms = this.usingTransforms = this.options.transformsEnabled && 3054 Modernizr.csstransforms && Modernizr.csstransitions && !this.isUsingJQueryAnimation; 3055 3056 // prevent scales when transforms are disabled 3057 if ( !usingTransforms ) { 3058 delete this.options.hiddenStyle.scale; 3059 delete this.options.visibleStyle.scale; 3060 } 3061 3062 this.getPositionStyles = usingTransforms ? this._translate : this._positionAbs; 3063 }, 3064 3065 3066 // ====================== Filtering ====================== 3067 3068 _filter : function( $atoms ) { 3069 var filter = this.options.filter === '' ? '*' : this.options.filter; 3070 3071 if ( !filter ) { 3072 return $atoms; 3073 } 3074 3075 var hiddenClass = this.options.hiddenClass, 3076 hiddenSelector = '.' + hiddenClass, 3077 $hiddenAtoms = $atoms.filter( hiddenSelector ), 3078 $atomsToShow = $hiddenAtoms; 3079 3080 if ( filter !== '*' ) { 3081 $atomsToShow = $hiddenAtoms.filter( filter );
3082 var $atomsToHide = $atoms.not( hiddenSelector ).not( filter ).addClass( hiddenClass ); 3083 this.styleQueue.push({ $el: $atomsToHide, style: this.options.hiddenStyle }); 3084 } 3085 3086 this.styleQueue.push({ $el: $atomsToShow, style: this.options.visibleStyle }); 3087 $atomsToShow.removeClass( hiddenClass ); 3088 3089 return $atoms.filter( filter ); 3090 }, 3091 3092 // ====================== Sorting ====================== 3093 3094 updateSortData : function( $atoms, isIncrementingElemCount ) { 3095 var instance = this, 3096 getSortData = this.options.getSortData, 3097 $this, sortData; 3098 $atoms.each(function(){ 3099 $this = $(this); 3100 sortData = {}; 3101 // get value for sort data based on fn( $elem ) passed in 3102 for ( var key in getSortData ) { 3103 if ( !isIncrementingElemCount && key === 'original-order' ) { 3104 // keep original order original 3105 sortData[ key ] = $.data( this, 'isotope-sort-data' )[ key ]; 3106 } else { 3107 sortData[ key ] = getSortData[ key ]( $this, instance ); 3108 } 3109 } 3110 // apply sort data to element 3111 $.data( this, 'isotope-sort-data', sortData ); 3112 }); 3113 }, 3114 3115 // used on all the filtered atoms 3116 _sort : function() { 3117 3118 var sortBy = this.options.sortBy, 3119 getSorter = this._getSorter, 3120 sortDir = this.options.sortAscending ? 1 : -1, 3121 sortFn = function( alpha, beta ) { 3122 var a = getSorter( alpha, sortBy ), 3123 b = getSorter( beta, sortBy ); 3124 // fall back to original order if data matches 3125 if ( a === b && sortBy !== 'original-order') { 3126 a = getSorter( alpha, 'original-order' ); 3127 b = getSorter( beta, 'original-order' ); 3128 } 3129 return ( ( a > b ) ? 1 : ( a < b ) ? -1 : 0 ) * sortDir; 3130 }; 3131 3132 this.$filteredAtoms.sort( sortFn ); 3133 }, 3134 3135 _getSorter : function( elem, sortBy ) { 3136 return $.data( elem, 'isotope-sort-data' )[ sortBy ]; 3137 }, 3138 3139 // ====================== Layout Helpers ====================== 3140 3141 _translate : function( x, y ) { 3142 return { translate : [ x, y ] }; 3143 }, 3144 3145 _positionAbs : function( x, y ) { 3146 return { left: x, top: y }; 3147 }, 3148 3149 _pushPosition : function( $elem, x, y ) { 3150 x = Math.round( x + this.offset.left ); 3151 y = Math.round( y + this.offset.top ); 3152 var position = this.getPositionStyles( x, y ); 3153 this.styleQueue.push({ $el: $elem, style: position }); 3154 if ( this.options.itemPositionDataEnabled ) { 3155 $elem.data('isotope-item-position', {x: x, y: y} ); 3156 } 3157 }, 3158 3159 3160 // ====================== General Layout ====================== 3161 3162 // used on collection of atoms (should be filtered, and sorted before ) 3163 // accepts atoms-to-be-laid-out to start with 3164 layout : function( $elems, callback ) { 3165 3166 var layoutMode = this.options.layoutMode; 3167 3168 // layout logic 3169 this[ '_' + layoutMode + 'Layout' ]( $elems ); 3170 3171 // set the size of the container 3172 if ( this.options.resizesContainer ) { 3173 var containerStyle = this[ '_' + layoutMode + 'GetContainerSize' ](); 3174 this.styleQueue.push({ $el: this.element, style: containerStyle }); 3175 } 3176 3177 this._processStyleQueue( $elems, callback ); 3178 3179 this.isLaidOut = true; 3180 }, 3181 3182 _processStyleQueue : function( $elems, callback ) { 3183 // are we animating the layout arrangement? 3184 // use plugin-ish syntax for css or animate 3185 var styleFn = !this.isLaidOut ? 'css' : ( 3186 this.isUsingJQueryAnimation ? 'animate' : 'css' 3187 ), 3188 animOpts = this.options.animationOptions, 3189 onLayout = this.options.onLayout, 3190 objStyleFn, processor, 3191 triggerCallbackNow, callbackFn; 3192 3193 // default styleQueue processor, may be overwritten down below 3194 processor = function( i, obj ) { 3195 obj.$el[ styleFn ]( obj.style, animOpts ); 3196 }; 3197 3198 if ( this._isInserting && this.isUsingJQueryAnimation ) { 3199 // if using styleQueue to insert items 3200 processor = function( i, obj ) { 3201 // only animate if it not being inserted 3202 objStyleFn = obj.$el.hasClass('no-transition') ? 'css' : styleFn; 3203 obj.$el[ objStyleFn ]( obj.style, animOpts ); 3204 }; 3205 3206 } else if ( callback || onLayout || animOpts.complete ) { 3207 // has callback 3208 var isCallbackTriggered = false, 3209 // array of possible callbacks to trigger 3210 callbacks = [ callback, onLayout, animOpts.complete ], 3211 instance = this; 3212 triggerCallbackNow = true; 3213 // trigger callback only once 3214 callbackFn = function() { 3215 if ( isCallbackTriggered ) { 3216 return; 3217 } 3218 var hollaback; 3219 for (var i=0, len = callbacks.length; i < len; i++) { 3220 hollaback = callbacks[i]; 3221 if ( typeof hollaback === 'function' ) { 3222 hollaback.call( instance.element, $elems, instance ); 3223 } 3224 } 3225 isCallbackTriggered = true; 3226 }; 3227 3228 if ( this.isUsingJQueryAnimation && styleFn === 'animate' ) { 3229 // add callback to animation options 3230 animOpts.complete = callbackFn; 3231 triggerCallbackNow = false; 3232 3233 } else if ( Modernizr.csstransitions ) { 3234 // detect if first item has transition 3235 var i = 0, 3236 firstItem = this.styleQueue[0], 3237 testElem = firstItem && firstItem.$el, 3238 styleObj; 3239 // get first non-empty jQ object 3240 while ( !testElem || !testElem.length ) { 3241 styleObj = this.styleQueue[ i++ ]; 3242 // HACK: sometimes styleQueue[i] is undefined 3243 if ( !styleObj ) { 3244 return; 3245 } 3246 testElem = styleObj.$el; 3247 } 3248 // get transition duration of the first element in that object 3249 // yeah, this is inexact 3250 var duration = parseFloat( getComputedStyle( testElem[0] )[ transitionDurProp ] ); 3251 if ( duration > 0 ) { 3252 processor = function( i, obj ) { 3253 obj.$el[ styleFn ]( obj.style, animOpts ) 3254 // trigger callback at transition end 3255 .one( transitionEndEvent, callbackFn ); 3256 }; 3257 triggerCallbackNow = false; 3258 } 3259 } 3260 } 3261 3262 // process styleQueue 3263 $.each( this.styleQueue, processor ); 3264 3265 if ( triggerCallbackNow ) { 3266 callbackFn(); 3267 } 3268 3269 // clear out queue for next time 3270 this.styleQueue = []; 3271 }, 3272 3273 3274 resize : function() { 3275 if ( this[ '_' + this.options.layoutMode + 'ResizeChanged' ]() ) { 3276 this.reLayout(); 3277 } 3278 }, 3279 3280 3281 reLayout : function( callback ) { 3282 3283 this[ '_' + this.options.layoutMode + 'Reset' ](); 3284 this.layout( this.$filteredAtoms, callback ); 3285 3286 }, 3287 3288 // ====================== Convenience methods ====================== 3289 3290 // ====================== Adding items ====================== 3291 3292 // adds a jQuery object of items to a isotope container 3293 addItems : function( $content, callback ) { 3294 var $newAtoms = this._getAtoms( $content ); 3295 // add new atoms to atoms pools 3296 this.$allAtoms = this.$allAtoms.add( $newAtoms ); 3297 3298 if ( callback ) { 3299 callback( $newAtoms ); 3300 } 3301 }, 3302 3303 // convienence method for adding elements properly to any layout 3304 // positions items, hides them, then animates them back in <--- very sezzy 3305 insert : function( $content, callback ) { 3306 // position items 3307 this.element.append( $content ); 3308 3309 var instance = this; 3310 this.addItems( $content, function( $newAtoms ) { 3311 var $newFilteredAtoms = instance._filter( $newAtoms ); 3312 instance._addHideAppended( $newFilteredAtoms ); 3313 instance._sort(); 3314 instance.reLayout(); 3315 instance._revealAppended( $newFilteredAtoms, callback ); 3316 }); 3317 3318 }, 3319 3320 // convienence method for working with Infinite Scroll 3321 appended : function( $content, callback ) { 3322 var instance = this; 3323 this.addItems( $content, function( $newAtoms ) { 3324 instance._addHideAppended( $newAtoms ); 3325 instance.layout( $newAtoms ); 3326 instance._revealAppended( $newAtoms, callback ); 3327 }); 3328 }, 3329 3330 // adds new atoms, then hides them before positioning 3331 _addHideAppended : function( $newAtoms ) { 3332 this.$filteredAtoms = this.$filteredAtoms.add( $newAtoms ); 3333 $newAtoms.addClass('no-transition'); 3334 3335 this._isInserting = true; 3336 3337 // apply hidden styles 3338 this.styleQueue.push({ $el: $newAtoms, style: this.options.hiddenStyle }); 3339 }, 3340 3341 // sets visible style on new atoms 3342 _revealAppended : function( $newAtoms, callback ) { 3343 var instance = this; 3344 // apply visible style after a sec 3345 setTimeout( function() { 3346 // enable animation 3347 $newAtoms.removeClass('no-transition'); 3348 // reveal newly inserted filtered elements 3349 instance.styleQueue.push({ $el: $newAtoms, style: instance.options.visibleStyle }); 3350 instance._isInserting = false; 3351 instance._processStyleQueue( $newAtoms, callback ); 3352 }, 10 ); 3353 }, 3354 3355 // gathers all atoms 3356 reloadItems : function() { 3357 this.$allAtoms = this._getAtoms( this.element.children() ); 3358 }, 3359 3360 // removes elements from Isotope widget 3361 remove: function( $content, callback ) { 3362 // remove elements immediately from Isotope instance 3363 this.$allAtoms = this.$allAtoms.not( $content ); 3364 this.$filteredAtoms = this.$filteredAtoms.not( $content ); 3365 // remove() as a callback, for after transition / animation 3366 var instance = this; 3367 var removeContent = function() { 3368 $content.remove(); 3369 if ( callback ) { 3370 callback.call( instance.element ); 3371 } 3372 }; 3373 3374 if ( $content.filter( ':not(.' + this.options.hiddenClass + ')' ).length ) { 3375 // if any non-hidden content needs to be removed 3376 this.styleQueue.push({ $el: $content, style: this.options.hiddenStyle }); 3377 this._sort(); 3378 this.reLayout( removeContent ); 3379 } else { 3380 // remove it now 3381 removeContent(); 3382 } 3383 3384 }, 3385 3386 shuffle : function( callback ) { 3387 this.updateSortData( this.$allAtoms ); 3388 this.options.sortBy = 'random'; 3389 this._sort(); 3390 this.reLayout( callback ); 3391 }, 3392 3393 // destroys widget, returns elements and container back (close) to original style 3394 destroy : function() { 3395 3396 var usingTransforms = this.usingTransforms;
3397 var options = this.options; 3398 3399 this.$allAtoms 3400 .removeClass( options.hiddenClass + ' ' + options.itemClass ) 3401 .each(function(){ 3402 var style = this.style; 3403 style.position = ''; 3404 style.top = ''; 3405 style.left = ''; 3406 style.opacity = ''; 3407 if ( usingTransforms ) { 3408 style[ transformProp ] = ''; 3409 } 3410 }); 3411 3412 // re-apply saved container styles 3413 var elemStyle = this.element[0].style; 3414 for ( var prop in this.originalStyle ) { 3415 elemStyle[ prop ] = this.originalStyle[ prop ]; 3416 } 3417 3418 this.element 3419 .unbind('.isotope') 3420 .undelegate( '.' + options.hiddenClass, 'click' ) 3421 .removeClass( options.containerClass ) 3422 .removeData('isotope'); 3423 3424 $window.unbind('.isotope'); 3425 3426 }, 3427 3428 3429 // ====================== LAYOUTS ====================== 3430 3431 // calculates number of rows or columns 3432 // requires columnWidth or rowHeight to be set on namespaced object 3433 // i.e. this.masonry.columnWidth = 200 3434 _getSegments : function( isRows ) { 3435 var namespace = this.options.layoutMode, 3436 measure = isRows ? 'rowHeight' : 'columnWidth', 3437 size = isRows ? 'height' : 'width', 3438 segmentsName = isRows ? 'rows' : 'cols', 3439 containerSize = this.element[ size ](), 3440 segments, 3441 // i.e. options.masonry && options.masonry.columnWidth 3442 segmentSize = this.options[ namespace ] && this.options[ namespace ][ measure ] || 3443 // or use the size of the first item, i.e. outerWidth 3444 this.$filteredAtoms[ 'outer' + capitalize(size) ](true) || 3445 // if there's no items, use size of container 3446 containerSize; 3447 3448 segments = Math.floor( containerSize / segmentSize ); 3449 segments = Math.max( segments, 1 ); 3450 3451 // i.e. this.masonry.cols = .... 3452 this[ namespace ][ segmentsName ] = segments; 3453 // i.e. this.masonry.columnWidth = ... 3454 this[ namespace ][ measure ] = segmentSize; 3455 3456 }, 3457 3458 _checkIfSegmentsChanged : function( isRows ) { 3459 var namespace = this.options.layoutMode, 3460 segmentsName = isRows ? 'rows' : 'cols', 3461 prevSegments = this[ namespace ][ segmentsName ]; 3462 // update cols/rows 3463 this._getSegments( isRows ); 3464 // return if updated cols/rows is not equal to previous 3465 return ( this[ namespace ][ segmentsName ] !== prevSegments ); 3466 }, 3467 3468 // ====================== Masonry ====================== 3469 3470 _masonryReset : function() { 3471 // layout-specific props 3472 this.masonry = {}; 3473 // FIXME shouldn't have to call this again 3474 this._getSegments(); 3475 var i = this.masonry.cols; 3476 this.masonry.colYs = []; 3477 while (i--) { 3478 this.masonry.colYs.push( 0 ); 3479 } 3480 }, 3481 3482 _masonryLayout : function( $elems ) { 3483 var instance = this, 3484 props = instance.masonry; 3485 $elems.each(function(){ 3486 var $this = $(this), 3487 //how many columns does this brick span 3488 colSpan = Math.ceil( $this.outerWidth(true) / props.columnWidth ); 3489 colSpan = Math.min( colSpan, props.cols ); 3490 3491 if ( colSpan === 1 ) { 3492 // if brick spans only one column, just like singleMode 3493 instance._masonryPlaceBrick( $this, props.colYs ); 3494 } else { 3495 // brick spans more than one column 3496 // how many different places could this brick fit horizontally 3497 var groupCount = props.cols + 1 - colSpan, 3498 groupY = [], 3499 groupColY, 3500 i; 3501 3502 // for each group potential horizontal position 3503 for ( i=0; i < groupCount; i++ ) { 3504 // make an array of colY values for that one group 3505 groupColY = props.colYs.slice( i, i+colSpan ); 3506 // and get the max value of the array 3507 groupY[i] = Math.max.apply( Math, groupColY ); 3508 } 3509 3510 instance._masonryPlaceBrick( $this, groupY ); 3511 } 3512 }); 3513 }, 3514 3515 // worker method that places brick in the columnSet 3516 // with the the minY 3517 _masonryPlaceBrick : function( $brick, setY ) { 3518 // get the minimum Y value from the columns 3519 var minimumY = Math.min.apply( Math, setY ), 3520 shortCol = 0; 3521 3522 // Find index of short column, the first from the left 3523 for (var i=0, len = setY.length; i < len; i++) { 3524 if ( setY[i] === minimumY ) { 3525 shortCol = i; 3526 break; 3527 } 3528 } 3529 3530 // position the brick 3531 var x = this.masonry.columnWidth * shortCol,
3532 y = minimumY; 3533 this._pushPosition( $brick, x, y ); 3534 3535 // apply setHeight to necessary columns 3536 var setHeight = minimumY + $brick.outerHeight(true), 3537 setSpan = this.masonry.cols + 1 - len; 3538 for ( i=0; i < setSpan; i++ ) { 3539 this.masonry.colYs[ shortCol + i ] = setHeight; 3540 } 3541 3542 }, 3543 3544 _masonryGetContainerSize : function() { 3545 var containerHeight = Math.max.apply( Math, this.masonry.colYs ); 3546 return { height: containerHeight }; 3547 }, 3548 3549 _masonryResizeChanged : function() { 3550 return this._checkIfSegmentsChanged(); 3551 }, 3552 3553 // ====================== fitRows ====================== 3554 3555 _fitRowsReset : function() { 3556 this.fitRows = { 3557 x : 0, 3558 y : 0, 3559 height : 0 3560 }; 3561 }, 3562 3563 _fitRowsLayout : function( $elems ) { 3564 var instance = this, 3565 containerWidth = this.element.width(), 3566 props = this.fitRows; 3567 3568 $elems.each( function() { 3569 var $this = $(this), 3570 atomW = $this.outerWidth(true), 3571 atomH = $this.outerHeight(true); 3572 3573 if ( props.x !== 0 && atomW + props.x > containerWidth ) { 3574 // if this element cannot fit in the current row 3575 props.x = 0; 3576 props.y = props.height; 3577 } 3578 3579 // position the atom 3580 instance._pushPosition( $this, props.x, props.y ); 3581 3582 props.height = Math.max( props.y + atomH, props.height ); 3583 props.x += atomW; 3584 3585 }); 3586 }, 3587 3588 _fitRowsGetContainerSize : function () { 3589 return { height : this.fitRows.height }; 3590 }, 3591 3592 _fitRowsResizeChanged : function() { 3593 return true; 3594 }, 3595 3596 3597 // ====================== cellsByRow ====================== 3598 3599 _cellsByRowReset : function() { 3600 this.cellsByRow = { 3601 index : 0 3602 }; 3603 // get this.cellsByRow.columnWidth 3604 this._getSegments(); 3605 // get this.cellsByRow.rowHeight 3606 this._getSegments(true); 3607 }, 3608 3609 _cellsByRowLayout : function( $elems ) { 3610 var instance = this, 3611 props = this.cellsByRow; 3612 $elems.each( function(){ 3613 var $this = $(this), 3614 col = props.index % props.cols, 3615 row = Math.floor( props.index / props.cols ), 3616 x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2, 3617 y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2; 3618 instance._pushPosition( $this, x, y ); 3619 props.index ++; 3620 }); 3621 }, 3622 3623 _cellsByRowGetContainerSize : function() { 3624 return { height : Math.ceil( this.$filteredAtoms.length / this.cellsByRow.cols ) * this.cellsByRow.rowHeight + this.offset.top }; 3625 }, 3626 3627 _cellsByRowResizeChanged : function() { 3628 return this._checkIfSegmentsChanged(); 3629 }, 3630 3631 3632 // ====================== straightDown ====================== 3633 3634 _straightDownReset : function() { 3635 this.straightDown = { 3636 y : 0 3637 }; 3638 }, 3639 3640 _straightDownLayout : function( $elems ) { 3641 var instance = this; 3642 $elems.each( function( i ){ 3643 var $this = $(this); 3644 instance._pushPosition( $this, 0, instance.straightDown.y ); 3645 instance.straightDown.y += $this.outerHeight(true); 3646 }); 3647 }, 3648 3649 _straightDownGetContainerSize : function() { 3650 return { height : this.straightDown.y }; 3651 }, 3652 3653 _straightDownResizeChanged : function() { 3654 return true; 3655 }, 3656 3657 3658 // ====================== masonryHorizontal ====================== 3659 3660 _masonryHorizontalReset : function() { 3661 // layout-specific props 3662 this.masonryHorizontal = {}; 3663 // FIXME shouldn't have to call this again 3664 this._getSegments( true ); 3665 var i = this.masonryHorizontal.rows; 3666 this.masonryHorizontal.rowXs = []; 3667 while (i--) { 3668 this.masonryHorizontal.rowXs.push( 0 ); 3669 } 3670 }, 3671 3672 _masonryHorizontalLayout : function( $elems ) { 3673 var instance = this, 3674 props = instance.masonryHorizontal; 3675 $elems.each(function(){ 3676 var $this = $(this), 3677 //how many rows does this brick span 3678 rowSpan = Math.ceil( $this.outerHeight(true) / props.rowHeight ); 3679 rowSpan = Math.min( rowSpan, props.rows ); 3680 3681 if ( rowSpan === 1 ) { 3682 // if brick spans only one column, just like singleMode 3683 instance._masonryHorizontalPlaceBrick( $this, props.rowXs ); 3684 } else { 3685 // brick spans more than one row 3686 // how many different places could this brick fit horizontally 3687 var groupCount = props.rows + 1 - rowSpan, 3688 groupX = [], 3689 groupRowX, i; 3690 3691 // for each group potential horizontal position 3692 for ( i=0; i < groupCount; i++ ) { 3693 // make an array of colY values for that one group 3694 groupRowX = props.rowXs.slice( i, i+rowSpan ); 3695 // and get the max value of the array 3696 groupX[i] = Math.max.apply( Math, groupRowX ); 3697 } 3698 3699 instance._masonryHorizontalPlaceBrick( $this, groupX ); 3700 } 3701 }); 3702 }, 3703 3704 _masonryHorizontalPlaceBrick : function( $brick, setX ) { 3705 // get the minimum Y value from the columns 3706 var minimumX = Math.min.apply( Math, setX ), 3707 smallRow = 0; 3708 // Find index of smallest row, the first from the top 3709 for (var i=0, len = setX.length; i < len; i++) { 3710 if ( setX[i] === minimumX ) { 3711 smallRow = i; 3712 break; 3713 } 3714 } 3715 3716 // position the brick 3717 var x = minimumX, 3718 y = this.masonryHorizontal.rowHeight * smallRow; 3719 this._pushPosition( $brick, x, y ); 3720 3721 // apply setHeight to necessary columns
3722 var setWidth = minimumX + $brick.outerWidth(true), 3723 setSpan = this.masonryHorizontal.rows + 1 - len; 3724 for ( i=0; i < setSpan; i++ ) { 3725 this.masonryHorizontal.rowXs[ smallRow + i ] = setWidth; 3726 } 3727 }, 3728 3729 _masonryHorizontalGetContainerSize : function() { 3730 var containerWidth = Math.max.apply( Math, this.masonryHorizontal.rowXs ); 3731 return { width: containerWidth }; 3732 }, 3733 3734 _masonryHorizontalResizeChanged : function() { 3735 return this._checkIfSegmentsChanged(true); 3736 }, 3737 3738 3739 // ====================== fitColumns ====================== 3740 3741 _fitColumnsReset : function() { 3742 this.fitColumns = { 3743 x : 0, 3744 y : 0, 3745 width : 0 3746 }; 3747 }, 3748 3749 _fitColumnsLayout : function( $elems ) { 3750 var instance = this, 3751 containerHeight = this.element.height(), 3752 props = this.fitColumns; 3753 $elems.each( function() { 3754 var $this = $(this), 3755 atomW = $this.outerWidth(true), 3756 atomH = $this.outerHeight(true); 3757 3758 if ( props.y !== 0 && atomH + props.y > containerHeight ) { 3759 // if this element cannot fit in the current column 3760 props.x = props.width; 3761 props.y = 0; 3762 } 3763 3764 // position the atom 3765 instance._pushPosition( $this, props.x, props.y ); 3766 3767 props.width = Math.max( props.x + atomW, props.width ); 3768 props.y += atomH; 3769 3770 }); 3771 }, 3772 3773 _fitColumnsGetContainerSize : function () { 3774 return { width : this.fitColumns.width }; 3775 }, 3776 3777 _fitColumnsResizeChanged : function() { 3778 return true; 3779 }, 3780 3781 3782 3783 // ====================== cellsByColumn ====================== 3784 3785 _cellsByColumnReset : function() { 3786 this.cellsByColumn = { 3787 index : 0 3788 }; 3789 // get this.cellsByColumn.columnWidth 3790 this._getSegments(); 3791 // get this.cellsByColumn.rowHeight 3792 this._getSegments(true); 3793 }, 3794 3795 _cellsByColumnLayout : function( $elems ) { 3796 var instance = this, 3797 props = this.cellsByColumn; 3798 $elems.each( function(){ 3799 var $this = $(this), 3800 col = Math.floor( props.index / props.rows ), 3801 row = props.index % props.rows, 3802 x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2, 3803 y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2; 3804 instance._pushPosition( $this, x, y ); 3805 props.index ++; 3806 }); 3807 }, 3808 3809 _cellsByColumnGetContainerSize : function() { 3810 return { width : Math.ceil( this.$filteredAtoms.length / this.cellsByColumn.rows ) * this.cellsByColumn.columnWidth }; 3811 }, 3812 3813 _cellsByColumnResizeChanged : function() { 3814 return this._checkIfSegmentsChanged(true); 3815 }, 3816 3817 // ====================== straightAcross ====================== 3818 3819 _straightAcrossReset : function() { 3820 this.straightAcross = { 3821 x : 0 3822 }; 3823 }, 3824 3825 _straightAcrossLayout : function( $elems ) { 3826 var instance = this; 3827 $elems.each( function( i ){ 3828 var $this = $(this); 3829 instance._pushPosition( $this, instance.straightAcross.x, 0 ); 3830 instance.straightAcross.x += $this.outerWidth(true); 3831 }); 3832 }, 3833 3834 _straightAcrossGetContainerSize : function() { 3835 return { width : this.straightAcross.x }; 3836 }, 3837 3838 _straightAcrossResizeChanged : function() { 3839 return true; 3840 } 3841 3842 }; 3843 3844 3845 // ======================= imagesLoaded Plugin =============================== 3846 /*! 3847 * jQuery imagesLoaded plugin v1.1.0 3848 * http://github.com/desandro/imagesloaded 3849 * 3850 * MIT License. by Paul Irish et al. 3851 */ 3852 3853 3854 // $('#my-container').imagesLoaded(myFunction) 3855 // or 3856 // $('img').imagesLoaded(myFunction) 3857 3858 // execute a callback when all images have loaded. 3859 // needed because .load() doesn't work on cached images 3860 3861 // callback function gets image collection as argument 3862 // `this` is the container 3863 3864 $.fn.imagesLoaded = function( callback ) { 3865 var $this = this, 3866 $images = $this.find('img').add( $this.filter('img') ), 3867 len = $images.length, 3868 blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', 3869 loaded = []; 3870 3871 function triggerCallback() { 3872 callback.call( $this, $images ); 3873 } 3874 3875 function imgLoaded( event ) { 3876 var img = event.target; 3877 if ( img.src !== blank && $.inArray( img, loaded ) === -1 ){ 3878 loaded.push( img ); 3879 if ( --len <= 0 ){ 3880 setTimeout( triggerCallback ); 3881 $images.unbind( '.imagesLoaded', imgLoaded ); 3882 } 3883 } 3884 } 3885 3886 // if no images, trigger immediately 3887 if ( !len ) { 3888 triggerCallback(); 3889 } 3890 3891 $images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoaded ).each( function() { 3892 // cached images don't fire load sometimes, so we reset src. 3893 var src = this.src; 3894 // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f 3895 // data uri bypasses webkit log warning (thx doug jones) 3896 this.src = blank; 3897 this.src = src; 3898 });
vendor: 30,270 bytes, lines 3899-5203
3899 3900 return $this; 3901 }; 3902 3903 3904 // helper function for logging errors 3905 // $.error breaks jQuery chaining 3906 var logError = function( message ) { 3907 if ( window.console ) { 3908 window.console.error( message ); 3909 } 3910 }; 3911 3912 // ======================= Plugin bridge =============================== 3913 // leverages data method to either create or return $.Isotope constructor 3914 // A bit from jQuery UI 3915 // https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js 3916 // A bit from jcarousel 3917 // https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js 3918 3919 $.fn.isotope = function( options, callback ) { 3920 if ( typeof options === 'string' ) { 3921 // call method 3922 var args = Array.prototype.slice.call( arguments, 1 ); 3923 3924 this.each(function(){ 3925 var instance = $.data( this, 'isotope' ); 3926 if ( !instance ) { 3927 logError( "cannot call methods on isotope prior to initialization; " + 3928 "attempted to call method '" + options + "'" ); 3929 return; 3930 } 3931 if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) { 3932 logError( "no such method '" + options + "' for isotope instance" ); 3933 return; 3934 } 3935 // apply method 3936 instance[ options ].apply( instance, args ); 3937 }); 3938 } else { 3939 this.each(function() { 3940 var instance = $.data( this, 'isotope' ); 3941 if ( instance ) { 3942 // apply options & init 3943 instance.option( options ); 3944 instance._init( callback ); 3945 } else { 3946 // initialize new instance 3947 $.data( this, 'isotope', new $.Isotope( options, this, callback ) ); 3948 } 3949 }); 3950 } 3951 // return jQuery object 3952 // so plugin methods do not have to 3953 return this; 3954 }; 3955 3956})( window, jQuery ); 3957/*! Magnific Popup - v0.9.9 - 2013-11-15 3958* http://dimsemenov.com/plugins/magnific-popup/ 3959* Copyright (c) 2013 Dmitry Semenov; */ 3960;(function($) { 3961 3962/*>>core*/ 3963/** 3964 * 3965 * Magnific Popup Core JS file 3966 * 3967 */ 3968 3969 3970/** 3971 * Private static constants 3972 */ 3973var CLOSE_EVENT = 'Close', 3974 BEFORE_CLOSE_EVENT = 'BeforeClose', 3975 AFTER_CLOSE_EVENT = 'AfterClose', 3976 BEFORE_APPEND_EVENT = 'BeforeAppend', 3977 MARKUP_PARSE_EVENT = 'MarkupParse', 3978 OPEN_EVENT = 'Open', 3979 CHANGE_EVENT = 'Change', 3980 NS = 'mfp', 3981 EVENT_NS = '.' + NS, 3982 READY_CLASS = 'mfp-ready', 3983 REMOVING_CLASS = 'mfp-removing', 3984 PREVENT_CLOSE_CLASS = 'mfp-prevent-close'; 3985 3986 3987/** 3988 * Private vars 3989 */ 3990var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this' 3991 MagnificPopup = function(){}, 3992 _isJQ = !!(window.jQuery), 3993 _prevStatus, 3994 _window = $(window), 3995 _body, 3996 _document, 3997 _prevContentType, 3998 _wrapClasses, 3999 _currPopupType; 4000 4001 4002/** 4003 * Private functions 4004 */ 4005var _mfpOn = function(name, f) { 4006 mfp.ev.on(NS + name + EVENT_NS, f); 4007 }, 4008 _getEl = function(className, appendTo, html, raw) { 4009 var el = document.createElement('div'); 4010 el.className = 'mfp-'+className; 4011 if(html) { 4012 el.innerHTML = html; 4013 } 4014 if(!raw) { 4015 el = $(el); 4016 if(appendTo) { 4017 el.appendTo(appendTo); 4018 } 4019 } else if(appendTo) { 4020 appendTo.appendChild(el); 4021 } 4022 return el; 4023 }, 4024 _mfpTrigger = function(e, data) { 4025 mfp.ev.triggerHandler(NS + e, data); 4026 4027 if(mfp.st.callbacks) { 4028 // converts "mfpEventName" to "eventName" callback and triggers it if it's present 4029 e = e.charAt(0).toLowerCase() + e.slice(1); 4030 if(mfp.st.callbacks[e]) { 4031 mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]); 4032 } 4033 } 4034 }, 4035 _getCloseBtn = function(type) { 4036 if(type !== _currPopupType || !mfp.currTemplate.closeBtn) { 4037 mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) ); 4038 _currPopupType = type; 4039 } 4040 return mfp.currTemplate.closeBtn; 4041 }, 4042 // Initialize Magnific Popup only when called at least once 4043 _checkInstance = function() { 4044 if(!$.magnificPopup.instance) { 4045 mfp = new MagnificPopup(); 4046 mfp.init(); 4047 $.magnificPopup.instance = mfp; 4048 } 4049 }, 4050 // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr 4051 supportsTransitions = function() { 4052 var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist 4053 v = ['ms','O','Moz','Webkit']; // 'v' for vendor 4054 4055 if( s['transition'] !== undefined ) { 4056 return true; 4057 } 4058 4059 while( v.length ) { 4060 if( v.pop() + 'Transition' in s ) { 4061 return true; 4062 } 4063 } 4064 4065 return false; 4066 }; 4067 4068 4069 4070/** 4071 * Public functions 4072 */ 4073MagnificPopup.prototype = { 4074 4075 constructor: MagnificPopup, 4076 4077 /** 4078 * Initializes Magnific Popup plugin. 4079 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed 4080 */ 4081 init: function() { 4082 var appVersion = navigator.appVersion; 4083 mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1; 4084 mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1; 4085 mfp.isLowIE = mfp.isIE7 || mfp.isIE8; 4086 mfp.isAndroid = (/android/gi).test(appVersion); 4087 mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion); 4088 mfp.supportsTransition = supportsTransitions(); 4089 4090 // We disable fixed positioned lightbox on devices that don't handle it nicely. 4091 // If you know a better way of detecting this - let me know. 4092 mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) ); 4093 _body = $(document.body); 4094 _document = $(document); 4095 4096 mfp.popupsCache = {}; 4097 }, 4098 4099 /** 4100 * Opens popup 4101 * @param data [description] 4102 */ 4103 open: function(data) { 4104 4105 var i; 4106 4107 if(data.isObj === false) { 4108 // convert jQuery collection to array to avoid conflicts later 4109 mfp.items = data.items.toArray(); 4110 4111 mfp.index = 0; 4112 var items = data.items, 4113 item; 4114 for(i = 0; i < items.length; i++) { 4115 item = items[i]; 4116 if(item.parsed) { 4117 item = item.el[0]; 4118 } 4119 if(item === data.el[0]) { 4120 mfp.index = i; 4121 break; 4122 } 4123 } 4124 } else { 4125 mfp.items = $.isArray(data.items) ? data.items : [data.items]; 4126 mfp.index = data.index || 0; 4127 } 4128 4129 // if popup is already opened - we just update the content 4130 if(mfp.isOpen) { 4131 mfp.updateItemHTML(); 4132 return; 4133 } 4134 4135 mfp.types = []; 4136 _wrapClasses = ''; 4137 if(data.mainEl && data.mainEl.length) { 4138 mfp.ev = data.mainEl.eq(0); 4139 } else { 4140 mfp.ev = _document; 4141 } 4142 4143 if(data.key) { 4144 if(!mfp.popupsCache[data.key]) { 4145 mfp.popupsCache[data.key] = {}; 4146 } 4147 mfp.currTemplate = mfp.popupsCache[data.key]; 4148 } else { 4149 mfp.currTemplate = {}; 4150 } 4151 4152 4153 4154 mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 4155 mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos; 4156 4157 if(mfp.st.modal) { 4158 mfp.st.closeOnContentClick = false; 4159 mfp.st.closeOnBgClick = false; 4160 mfp.st.showCloseBtn = false; 4161 mfp.st.enableEscapeKey = false; 4162 } 4163 4164 4165 // Building markup 4166 // main containers are created only once 4167 if(!mfp.bgOverlay) { 4168 4169 // Dark overlay 4170 mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() { 4171 mfp.close(); 4172 }); 4173 4174 mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) { 4175 if(mfp._checkIfClose(e.target)) { 4176 mfp.close(); 4177 } 4178 }); 4179 4180 mfp.container = _getEl('container', mfp.wrap); 4181 } 4182 4183 mfp.contentContainer = _getEl('content'); 4184 if(mfp.st.preloader) { 4185 mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading); 4186 } 4187 4188 4189 // Initializing modules 4190 var modules = $.magnificPopup.modules; 4191 for(i = 0; i < modules.length; i++) { 4192 var n = modules[i]; 4193 n = n.charAt(0).toUpperCase() + n.slice(1); 4194 mfp['init'+n].call(mfp); 4195 } 4196 _mfpTrigger('BeforeOpen'); 4197 4198 4199 if(mfp.st.showCloseBtn) { 4200 // Close button 4201 if(!mfp.st.closeBtnInside) { 4202 mfp.wrap.append( _getCloseBtn() ); 4203 } else { 4204 _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) { 4205 values.close_replaceWith = _getCloseBtn(item.type); 4206 }); 4207 _wrapClasses += ' mfp-close-btn-in'; 4208 } 4209 } 4210 4211 if(mfp.st.alignTop) { 4212 _wrapClasses += ' mfp-align-top'; 4213 } 4214 4215 4216 4217 if(mfp.fixedContentPos) { 4218 mfp.wrap.css({ 4219 overflow: mfp.st.overflowY, 4220 overflowX: 'hidden', 4221 overflowY: mfp.st.overflowY 4222 }); 4223 } else { 4224 mfp.wrap.css({ 4225 top: _window.scrollTop(), 4226 position: 'absolute' 4227 }); 4228 } 4229 if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) { 4230 mfp.bgOverlay.css({ 4231 height: _document.height(), 4232 position: 'absolute' 4233 }); 4234 } 4235 4236 4237 4238 if(mfp.st.enableEscapeKey) { 4239 // Close on ESC key 4240 _document.on('keyup' + EVENT_NS, function(e) { 4241 if(e.keyCode === 27) { 4242 mfp.close(); 4243 } 4244 }); 4245 } 4246 4247 _window.on('resize' + EVENT_NS, function() { 4248 mfp.updateSize(); 4249 }); 4250 4251 4252 if(!mfp.st.closeOnContentClick) { 4253 _wrapClasses += ' mfp-auto-cursor'; 4254 } 4255 4256 if(_wrapClasses) 4257 mfp.wrap.addClass(_wrapClasses); 4258 4259 4260 // this triggers recalculation of layout, so we get it once to not to trigger twice 4261 var windowHeight = mfp.wH = _window.height(); 4262 4263 4264 var windowStyles = {}; 4265 4266 if( mfp.fixedContentPos ) { 4267 if(mfp._hasScrollBar(windowHeight)){ 4268 var s = mfp._getScrollbarSize(); 4269 if(s) { 4270 windowStyles.marginRight = s; 4271 } 4272 } 4273 } 4274 4275 if(mfp.fixedContentPos) { 4276 if(!mfp.isIE7) { 4277 windowStyles.overflow = 'hidden'; 4278 } else { 4279 // ie7 double-scroll bug 4280 $('body, html').css('overflow', 'hidden'); 4281 } 4282 } 4283 4284 4285 4286 var classesToadd = mfp.st.mainClass; 4287 if(mfp.isIE7) { 4288 classesToadd += ' mfp-ie7'; 4289 } 4290 if(classesToadd) { 4291 mfp._addClassToMFP( classesToadd ); 4292 } 4293 4294 // add content 4295 mfp.updateItemHTML(); 4296 4297 _mfpTrigger('BuildControls'); 4298 4299 4300 // remove scrollbar, add margin e.t.c 4301 $('html').css(windowStyles); 4302 4303 // add everything to DOM 4304 mfp.bgOverlay.add(mfp.wrap).prependTo( document.body ); 4305 4306 4307 4308 // Save last focused element 4309 mfp._lastFocusedEl = document.activeElement; 4310 4311 // Wait for next cycle to allow CSS transition 4312 setTimeout(function() { 4313 4314 if(mfp.content) { 4315 mfp._addClassToMFP(READY_CLASS); 4316 mfp._setFocus(); 4317 } else { 4318 // if content is not defined (not loaded e.t.c) we add class only for BG 4319 mfp.bgOverlay.addClass(READY_CLASS); 4320 } 4321 4322 // Trap the focus in popup 4323 _document.on('focusin' + EVENT_NS, mfp._onFocusIn); 4324 4325 }, 16); 4326 4327 mfp.isOpen = true; 4328 mfp.updateSize(windowHeight); 4329 _mfpTrigger(OPEN_EVENT); 4330 4331 return data; 4332 }, 4333 4334 /** 4335 * Closes the popup 4336 */ 4337 close: function() { 4338 if(!mfp.isOpen) return; 4339 _mfpTrigger(BEFORE_CLOSE_EVENT); 4340 4341 mfp.isOpen = false; 4342 // for CSS3 animation 4343 if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition ) { 4344 mfp._addClassToMFP(REMOVING_CLASS); 4345 setTimeout(function() { 4346 mfp._close(); 4347 }, mfp.st.removalDelay); 4348 } else { 4349 mfp._close(); 4350 } 4351 }, 4352 4353 /** 4354 * Helper for close() function 4355 */ 4356 _close: function() { 4357 _mfpTrigger(CLOSE_EVENT); 4358 4359 var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' '; 4360 4361 mfp.bgOverlay.detach(); 4362 mfp.wrap.detach(); 4363 mfp.container.empty(); 4364 4365 if(mfp.st.mainClass) { 4366 classesToRemove += mfp.st.mainClass + ' '; 4367 } 4368 4369 mfp._removeClassFromMFP(classesToRemove); 4370 4371 if(mfp.fixedContentPos) { 4372 var windowStyles = {marginRight: ''}; 4373 if(mfp.isIE7) { 4374 $('body, html').css('overflow', ''); 4375 } else { 4376 windowStyles.overflow = ''; 4377 } 4378 $('html').css(windowStyles); 4379 } 4380 4381 _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS); 4382 mfp.ev.off(EVENT_NS); 4383 4384 // clean up DOM elements that aren't removed 4385 mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style'); 4386 mfp.bgOverlay.attr('class', 'mfp-bg'); 4387 mfp.container.attr('class', 'mfp-container'); 4388 4389 // remove close button from target element 4390 if(mfp.st.showCloseBtn && 4391 (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) { 4392 if(mfp.currTemplate.closeBtn) 4393 mfp.currTemplate.closeBtn.detach(); 4394 } 4395 4396 4397 if(mfp._lastFocusedEl) { 4398 $(mfp._lastFocusedEl).focus(); // put tab focus back 4399 } 4400 mfp.currItem = null; 4401 mfp.content = null; 4402 mfp.currTemplate = null; 4403 mfp.prevHeight = 0; 4404 4405 _mfpTrigger(AFTER_CLOSE_EVENT); 4406 }, 4407 4408 updateSize: function(winHeight) { 4409 4410 if(mfp.isIOS) { 4411 // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2 4412 var zoomLevel = document.documentElement.clientWidth / window.innerWidth; 4413 var height = window.innerHeight * zoomLevel; 4414 mfp.wrap.css('height', height); 4415 mfp.wH = height; 4416 } else { 4417 mfp.wH = winHeight || _window.height(); 4418 } 4419 // Fixes #84: popup incorrectly positioned with position:relative on body 4420 if(!mfp.fixedContentPos) { 4421 mfp.wrap.css('height', mfp.wH); 4422 } 4423 4424 _mfpTrigger('Resize'); 4425 4426 }, 4427 4428 /** 4429 * Set content of popup based on current index 4430 */ 4431 updateItemHTML: function() { 4432 var item = mfp.items[mfp.index]; 4433 4434 // Detach and perform modifications 4435 mfp.contentContainer.detach(); 4436 4437 if(mfp.content) 4438 mfp.content.detach(); 4439 4440 if(!item.parsed) { 4441 item = mfp.parseEl( mfp.index ); 4442 } 4443 4444 var type = item.type; 4445 4446 _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]); 4447 // BeforeChange event works like so: 4448 // _mfpOn('BeforeChange', function(e, prevType, newType) { }); 4449 4450 mfp.currItem = item; 4451 4452 4453 4454 4455 4456 if(!mfp.currTemplate[type]) { 4457 var markup = mfp.st[type] ? mfp.st[type].markup : false; 4458 4459 // allows to modify markup 4460 _mfpTrigger('FirstMarkupParse', markup); 4461 4462 if(markup) { 4463 mfp.currTemplate[type] = $(markup); 4464 } else { 4465 // if there is no markup found we just define that template is parsed 4466 mfp.currTemplate[type] = true; 4467 } 4468 } 4469 4470 if(_prevContentType && _prevContentType !== item.type) { 4471 mfp.container.removeClass('mfp-'+_prevContentType+'-holder'); 4472 } 4473 4474 var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]); 4475 mfp.appendContent(newContent, type); 4476 4477 item.preloaded = true; 4478 4479 _mfpTrigger(CHANGE_EVENT, item); 4480 _prevContentType = item.type; 4481 4482 // Append container back after its content changed 4483 mfp.container.prepend(mfp.contentContainer); 4484 4485 _mfpTrigger('AfterChange'); 4486 }, 4487 4488 4489 /** 4490 * Set HTML content of popup 4491 */ 4492 appendContent: function(newContent, type) { 4493 mfp.content = newContent; 4494 4495 if(newContent) { 4496 if(mfp.st.showCloseBtn && mfp.st.closeBtnInside && 4497 mfp.currTemplate[type] === true) { 4498 // if there is no markup, we just append close button element inside 4499 if(!mfp.content.find('.mfp-close').length) { 4500 mfp.content.append(_getCloseBtn()); 4501 } 4502 } else { 4503 mfp.content = newContent; 4504 } 4505 } else { 4506 mfp.content = ''; 4507 } 4508 4509 _mfpTrigger(BEFORE_APPEND_EVENT); 4510 mfp.container.addClass('mfp-'+type+'-holder'); 4511 4512 mfp.contentContainer.append(mfp.content); 4513 }, 4514 4515 4516 4517 4518 /** 4519 * Creates Magnific Popup data object based on given data 4520 * @param {int} index Index of item to parse 4521 */ 4522 parseEl: function(index) { 4523 var item = mfp.items[index], 4524 type = item.type; 4525 4526 if(item.tagName) { 4527 item = { el: $(item) }; 4528 } else { 4529 item = { data: item, src: item.src }; 4530 } 4531 4532 if(item.el) { 4533 var types = mfp.types; 4534 4535 // check for 'mfp-TYPE' class 4536 for(var i = 0; i < types.length; i++) { 4537 if( item.el.hasClass('mfp-'+types[i]) ) { 4538 type = types[i]; 4539 break; 4540 } 4541 } 4542 4543 item.src = item.el.attr('data-mfp-src'); 4544 if(!item.src) { 4545 item.src = item.el.attr('href'); 4546 } 4547 } 4548 4549 item.type = type || mfp.st.type || 'inline'; 4550 item.index = index; 4551 item.parsed = true; 4552 mfp.items[index] = item; 4553 _mfpTrigger('ElementParse', item); 4554 4555 return mfp.items[index]; 4556 }, 4557 4558 4559 /** 4560 * Initializes single popup or a group of popups 4561 */ 4562 addGroup: function(el, options) { 4563 var eHandler = function(e) { 4564 e.mfpEl = this; 4565 mfp._openClick(e, el, options); 4566 }; 4567 4568 if(!options) { 4569 options = {}; 4570 } 4571 4572 var eName = 'click.magnificPopup'; 4573 options.mainEl = el; 4574 4575 if(options.items) { 4576 options.isObj = true; 4577 el.off(eName).on(eName, eHandler); 4578 } else { 4579 options.isObj = false; 4580 if(options.delegate) { 4581 el.off(eName).on(eName, options.delegate , eHandler); 4582 } else { 4583 options.items = el; 4584 el.off(eName).on(eName, eHandler); 4585 } 4586 } 4587 }, 4588 _openClick: function(e, el, options) { 4589 var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick; 4590 4591 4592 if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) { 4593 return; 4594 } 4595 4596 var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn; 4597 4598 if(disableOn) { 4599 if($.isFunction(disableOn)) { 4600 if( !disableOn.call(mfp) ) { 4601 return true; 4602 } 4603 } else { // else it's number 4604 if( _window.width() < disableOn ) { 4605 return true; 4606 } 4607 } 4608 } 4609 4610 if(e.type) { 4611 e.preventDefault(); 4612 4613 // This will prevent popup from closing if element is inside and popup is already opened 4614 if(mfp.isOpen) { 4615 e.stopPropagation(); 4616 } 4617 } 4618 4619 4620 options.el = $(e.mfpEl); 4621 if(options.delegate) { 4622 options.items = el.find(options.delegate); 4623 } 4624 mfp.open(options); 4625 }, 4626 4627 4628 /** 4629 * Updates text on preloader 4630 */ 4631 updateStatus: function(status, text) { 4632 4633 if(mfp.preloader) { 4634 if(_prevStatus !== status) { 4635 mfp.container.removeClass('mfp-s-'+_prevStatus); 4636 } 4637 4638 if(!text && status === 'loading') { 4639 text = mfp.st.tLoading; 4640 } 4641 4642 var data = { 4643 status: status, 4644 text: text 4645 }; 4646 // allows to modify status 4647 _mfpTrigger('UpdateStatus', data); 4648 4649 status = data.status; 4650 text = data.text; 4651 4652 mfp.preloader.html(text); 4653 4654 mfp.preloader.find('a').on('click', function(e) { 4655 e.stopImmediatePropagation(); 4656 }); 4657 4658 mfp.container.addClass('mfp-s-'+status); 4659 _prevStatus = status; 4660 } 4661 }, 4662 4663 4664 /* 4665 "Private" helpers that aren't private at all 4666 */ 4667 // Check to close popup or not 4668 // "target" is an element that was clicked 4669 _checkIfClose: function(target) { 4670 4671 if($(target).hasClass(PREVENT_CLOSE_CLASS)) { 4672 return; 4673 } 4674 4675 var closeOnContent = mfp.st.closeOnContentClick; 4676 var closeOnBg = mfp.st.closeOnBgClick; 4677 4678 if(closeOnContent && closeOnBg) { 4679 return true; 4680 } else { 4681 4682 // We close the popup if click is on close button or on preloader. Or if there is no content. 4683 if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) { 4684 return true; 4685 } 4686 4687 // if click is outside the content 4688 if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { 4689 if(closeOnBg) { 4690 // last check, if the clicked element is in DOM, (in case it's removed onclick) 4691 if( $.contains(document, target) ) { 4692 return true; 4693 } 4694 } 4695 } else if(closeOnContent) { 4696 return true; 4697 } 4698 4699 } 4700 return false; 4701 }, 4702 _addClassToMFP: function(cName) { 4703 mfp.bgOverlay.addClass(cName); 4704 mfp.wrap.addClass(cName); 4705 }, 4706 _removeClassFromMFP: function(cName) { 4707 this.bgOverlay.removeClass(cName); 4708 mfp.wrap.removeClass(cName); 4709 }, 4710 _hasScrollBar: function(winHeight) { 4711 return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) ); 4712 }, 4713 _setFocus: function() { 4714 (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus(); 4715 }, 4716 _onFocusIn: function(e) { 4717 if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { 4718 mfp._setFocus(); 4719 return false; 4720 } 4721 }, 4722 _parseMarkup: function(template, values, item) { 4723 var arr; 4724 if(item.data) { 4725 values = $.extend(item.data, values); 4726 } 4727 _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] ); 4728 4729 $.each(values, function(key, value) { 4730 if(value === undefined || value === false) { 4731 return true; 4732 } 4733 arr = key.split('_'); 4734 if(arr.length > 1) { 4735 var el = template.find(EVENT_NS + '-'+arr[0]); 4736 4737 if(el.length > 0) { 4738 var attr = arr[1]; 4739 if(attr === 'replaceWith') { 4740 if(el[0] !== value[0]) { 4741 el.replaceWith(value); 4742 } 4743 } else if(attr === 'img') { 4744 if(el.is('img')) { 4745 el.attr('src', value); 4746 } else { 4747 el.replaceWith( '<img src="'+value+'" class="' + el.attr('class') + '" />' ); 4748 } 4749 } else { 4750 el.attr(arr[1], value); 4751 } 4752 } 4753 4754 } else { 4755 template.find(EVENT_NS + '-'+key).html(value); 4756 } 4757 }); 4758 }, 4759 4760 _getScrollbarSize: function() { 4761 // thx David 4762 if(mfp.scrollbarSize === undefined) { 4763 var scrollDiv = document.createElement("div"); 4764 scrollDiv.id = "mfp-sbm"; 4765 scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; 4766 document.body.appendChild(scrollDiv); 4767 mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth; 4768 document.body.removeChild(scrollDiv); 4769 } 4770 return mfp.scrollbarSize; 4771 } 4772 4773}; /* MagnificPopup core prototype end */ 4774 4775 4776 4777 4778/** 4779 * Public static functions 4780 */ 4781$.magnificPopup = { 4782 instance: null, 4783 proto: MagnificPopup.prototype, 4784 modules: [], 4785 4786 open: function(options, index) { 4787 _checkInstance(); 4788 4789 if(!options) { 4790 options = {}; 4791 } else { 4792 options = $.extend(true, {}, options); 4793 } 4794 4795 4796 options.isObj = true; 4797 options.index = index || 0; 4798 return this.instance.open(options); 4799 }, 4800 4801 close: function() { 4802 return $.magnificPopup.instance && $.magnificPopup.instance.close(); 4803 }, 4804 4805 registerModule: function(name, module) { 4806 if(module.options) { 4807 $.magnificPopup.defaults[name] = module.options; 4808 } 4809 $.extend(this.proto, module.proto); 4810 this.modules.push(name); 4811 }, 4812 4813 defaults: { 4814 4815 // Info about options is in docs: 4816 // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options 4817 4818 disableOn: 0, 4819 4820 key: null, 4821 4822 midClick: false, 4823 4824 mainClass: '', 4825 4826 preloader: true, 4827 4828 focus: '', // CSS selector of input to focus after popup is opened 4829 4830 closeOnContentClick: false, 4831 4832 closeOnBgClick: true, 4833 4834 closeBtnInside: true, 4835 4836 showCloseBtn: true, 4837 4838 enableEscapeKey: true, 4839 4840 modal: false, 4841 4842 alignTop: false, 4843 4844 removalDelay: 0, 4845 4846 fixedContentPos: 'auto', 4847 4848 fixedBgPos: 'auto', 4849 4850 overflowY: 'auto', 4851 4852 closeMarkup: '<button title="%title%" type="button" class="mfp-close">×</button>', 4853 4854 tClose: 'Close (Esc)', 4855 4856 tLoading: 'Loading...' 4857 4858 } 4859}; 4860 4861 4862 4863$.fn.magnificPopup = function(options) { 4864 _checkInstance(); 4865 4866 var jqEl = $(this); 4867 4868 // We call some API method of first param is a string 4869 if (typeof options === "string" ) { 4870 4871 if(options === 'open') { 4872 var items, 4873 itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup, 4874 index = parseInt(arguments[1], 10) || 0; 4875 4876 if(itemOpts.items) { 4877 items = itemOpts.items[index]; 4878 } else { 4879 items = jqEl; 4880 if(itemOpts.delegate) { 4881 items = items.find(itemOpts.delegate); 4882 } 4883 items = items.eq( index ); 4884 } 4885 mfp._openClick({mfpEl:items}, jqEl, itemOpts); 4886 } else { 4887 if(mfp.isOpen) 4888 mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1)); 4889 } 4890 4891 } else { 4892 // clone options obj 4893 options = $.extend(true, {}, options); 4894 4895 /* 4896 * As Zepto doesn't support .data() method for objects 4897 * and it works only in normal browsers 4898 * we assign "options" object directly to the DOM element. FTW! 4899 */ 4900 if(_isJQ) { 4901 jqEl.data('magnificPopup', options); 4902 } else { 4903 jqEl[0].magnificPopup = options; 4904 } 4905 4906 mfp.addGroup(jqEl, options); 4907 4908 } 4909 return jqEl; 4910}; 4911 4912 4913//Quick benchmark 4914/* 4915var start = performance.now(), 4916 i, 4917 rounds = 1000; 4918 4919for(i = 0; i < rounds; i++) { 4920 4921} 4922console.log('Test #1:', performance.now() - start); 4923 4924start = performance.now(); 4925for(i = 0; i < rounds; i++) { 4926 4927} 4928console.log('Test #2:', performance.now() - start); 4929*/ 4930 4931 4932/*>>core*/ 4933 4934/*>>inline*/ 4935 4936var INLINE_NS = 'inline', 4937 _hiddenClass, 4938 _inlinePlaceholder, 4939 _lastInlineElement, 4940 _putInlineElementsBack = function() { 4941 if(_lastInlineElement) { 4942 _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach(); 4943 _lastInlineElement = null; 4944 } 4945 }; 4946 4947$.magnificPopup.registerModule(INLINE_NS, { 4948 options: { 4949 hiddenClass: 'hide', // will be appended with `mfp-` prefix 4950 markup: '', 4951 tNotFound: 'Content not found' 4952 }, 4953 proto: { 4954 4955 initInline: function() { 4956 mfp.types.push(INLINE_NS); 4957 4958 _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() { 4959 _putInlineElementsBack(); 4960 }); 4961 }, 4962 4963 getInline: function(item, template) { 4964 4965 _putInlineElementsBack(); 4966 4967 if(item.src) { 4968 var inlineSt = mfp.st.inline, 4969 el = $(item.src); 4970 4971 if(el.length) { 4972 4973 // If target element has parent - we replace it with placeholder and put it back after popup is closed 4974 var parent = el[0].parentNode; 4975 if(parent && parent.tagName) { 4976 if(!_inlinePlaceholder) { 4977 _hiddenClass = inlineSt.hiddenClass; 4978 _inlinePlaceholder = _getEl(_hiddenClass); 4979 _hiddenClass = 'mfp-'+_hiddenClass; 4980 } 4981 // replace target inline element with placeholder 4982 _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass); 4983 } 4984 4985 mfp.updateStatus('ready'); 4986 } else { 4987 mfp.updateStatus('error', inlineSt.tNotFound); 4988 el = $('<div>'); 4989 } 4990 4991 item.inlineElement = el; 4992 return el; 4993 } 4994 4995 mfp.updateStatus('ready'); 4996 mfp._parseMarkup(template, {}, item); 4997 return template; 4998 } 4999 } 5000}); 5001 5002/*>>inline*/ 5003 5004/*>>ajax*/ 5005var AJAX_NS = 'ajax', 5006 _ajaxCur, 5007 _removeAjaxCursor = function() { 5008 if(_ajaxCur) { 5009 _body.removeClass(_ajaxCur); 5010 } 5011 }, 5012 _destroyAjaxRequest = function() { 5013 _removeAjaxCursor(); 5014 if(mfp.req) { 5015 mfp.req.abort(); 5016 } 5017 }; 5018 5019$.magnificPopup.registerModule(AJAX_NS, { 5020 5021 options: { 5022 settings: null, 5023 cursor: 'mfp-ajax-cur', 5024 tError: '<a href="%url%">The content</a> could not be loaded.' 5025 }, 5026 5027 proto: { 5028 initAjax: function() { 5029 mfp.types.push(AJAX_NS); 5030 _ajaxCur = mfp.st.ajax.cursor; 5031 5032 _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest); 5033 _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest); 5034 }, 5035 getAjax: function(item) { 5036 5037 if(_ajaxCur) 5038 _body.addClass(_ajaxCur); 5039 5040 mfp.updateStatus('loading'); 5041 5042 var opts = $.extend({ 5043 url: item.src, 5044 success: function(data, textStatus, jqXHR) { 5045 var temp = { 5046 data:data, 5047 xhr:jqXHR 5048 }; 5049 5050 _mfpTrigger('ParseAjax', temp); 5051 5052 mfp.appendContent( $(temp.data), AJAX_NS ); 5053 5054 item.finished = true; 5055 5056 _removeAjaxCursor(); 5057 5058 mfp._setFocus(); 5059 5060 setTimeout(function() { 5061 mfp.wrap.addClass(READY_CLASS); 5062 }, 16); 5063 5064 mfp.updateStatus('ready'); 5065 5066 _mfpTrigger('AjaxContentAdded'); 5067 }, 5068 error: function() { 5069 _removeAjaxCursor(); 5070 item.finished = item.loadError = true; 5071 mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src)); 5072 } 5073 }, mfp.st.ajax.settings); 5074 5075 mfp.req = $.ajax(opts); 5076 5077 return ''; 5078 } 5079 } 5080}); 5081 5082 5083 5084 5085 5086 5087 5088/*>>ajax*/ 5089 5090/*>>image*/ 5091var _imgInterval, 5092 _getTitle = function(item) { 5093 if(item.data && item.data.title !== undefined) 5094 return item.data.title; 5095 5096 var src = mfp.st.image.titleSrc; 5097 5098 if(src) { 5099 if($.isFunction(src)) { 5100 return src.call(mfp, item); 5101 } else if(item.el) { 5102 return item.el.attr(src) || ''; 5103 } 5104 } 5105 return ''; 5106 }; 5107 5108$.magnificPopup.registerModule('image', { 5109 5110 options: { 5111 markup: '<div class="mfp-figure">'+ 5112 '<div class="mfp-close"></div>'+ 5113 '<figure>'+ 5114 '<div class="mfp-img"></div>'+ 5115 '<figcaption>'+ 5116 '<div class="mfp-bottom-bar">'+ 5117 '<div class="mfp-title"></div>'+ 5118 '<div class="mfp-counter"></div>'+ 5119 '</div>'+ 5120 '</figcaption>'+ 5121 '</figure>'+ 5122 '</div>', 5123 cursor: 'mfp-zoom-out-cur', 5124 titleSrc: 'title', 5125 verticalFit: true, 5126 tError: '<a href="%url%">The image</a> could not be loaded.' 5127 }, 5128 5129 proto: { 5130 initImage: function() { 5131 var imgSt = mfp.st.image, 5132 ns = '.image'; 5133 5134 mfp.types.push('image'); 5135 5136 _mfpOn(OPEN_EVENT+ns, function() { 5137 if(mfp.currItem.type === 'image' && imgSt.cursor) { 5138 _body.addClass(imgSt.cursor); 5139 } 5140 }); 5141 5142 _mfpOn(CLOSE_EVENT+ns, function() { 5143 if(imgSt.cursor) { 5144 _body.removeClass(imgSt.cursor); 5145 } 5146 _window.off('resize' + EVENT_NS); 5147 }); 5148 5149 _mfpOn('Resize'+ns, mfp.resizeImage); 5150 if(mfp.isLowIE) { 5151 _mfpOn('AfterChange', mfp.resizeImage); 5152 } 5153 }, 5154 resizeImage: function() { 5155 var item = mfp.currItem; 5156 if(!item || !item.img) return; 5157 5158 if(mfp.st.image.verticalFit) { 5159 var decr = 0; 5160 // fix box-sizing in ie7/8 5161 if(mfp.isLowIE) { 5162 decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10); 5163 } 5164 item.img.css('max-height', mfp.wH-decr); 5165 } 5166 }, 5167 _onImageHasSize: function(item) { 5168 if(item.img) { 5169 5170 item.hasSize = true; 5171 5172 if(_imgInterval) { 5173 clearInterval(_imgInterval); 5174 } 5175 5176 item.isCheckingImgSize = false; 5177 5178 _mfpTrigger('ImageHasSize', item); 5179 5180 if(item.imgHidden) { 5181 if(mfp.content) 5182 mfp.content.removeClass('mfp-loading'); 5183 5184 item.imgHidden = false; 5185 } 5186 5187 } 5188 }, 5189 5190 /** 5191 * Function that loops until the image has size to display elements that rely on it asap 5192 */ 5193 findImageSize: function(item) { 5194 5195 var counter = 0, 5196 img = item.img[0], 5197 mfpSetInterval = function(delay) { 5198 5199 if(_imgInterval) { 5200 clearInterval(_imgInterval); 5201 } 5202 // decelerating interval that checks for size of an image 5203 _imgInterval = setInterval(function() {
5204 if(img.naturalWidth > 0) { 5205 mfp._onImageHasSize(item); 5206 return; 5207 } 5208 5209 if(counter > 200) { 5210 clearInterval(_imgInterval); 5211 } 5212 5213 counter++; 5214 if(counter === 3) { 5215 mfpSetInterval(10); 5216 } else if(counter === 40) { 5217 mfpSetInterval(50); 5218 } else if(counter === 100) { 5219 mfpSetInterval(500); 5220 } 5221 }, delay); 5222 }; 5223 5224 mfpSetInterval(1); 5225 }, 5226 5227 getImage: function(item, template) { 5228 5229 var guard = 0, 5230 5231 // image load complete handler 5232 onLoadComplete = function() { 5233 if(item) { 5234 if (item.img[0].complete) { 5235 item.img.off('.mfploader'); 5236 5237 if(item === mfp.currItem){ 5238 mfp._onImageHasSize(item); 5239 5240 mfp.updateStatus('ready'); 5241 } 5242 5243 item.hasSize = true; 5244 item.loaded = true; 5245 5246 _mfpTrigger('ImageLoadComplete'); 5247 5248 } 5249 else { 5250 // if image complete check fails 200 times (20 sec), we assume that there was an error. 5251 guard++; 5252 if(guard < 200) { 5253 setTimeout(onLoadComplete,100); 5254 } else { 5255 onLoadError(); 5256 } 5257 } 5258 } 5259 }, 5260 5261 // image error handler 5262 onLoadError = function() { 5263 if(item) { 5264 item.img.off('.mfploader'); 5265 if(item === mfp.currItem){ 5266 mfp._onImageHasSize(item); 5267 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); 5268 } 5269 5270 item.hasSize = true; 5271 item.loaded = true; 5272 item.loadError = true; 5273 } 5274 }, 5275 imgSt = mfp.st.image; 5276 5277 5278 var el = template.find('.mfp-img'); 5279 if(el.length) { 5280 var img = document.createElement('img'); 5281 img.className = 'mfp-img'; 5282 item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError); 5283 img.src = item.src; 5284 5285 // without clone() "error" event is not firing when IMG is replaced by new IMG
vendor: 9,086 bytes, lines 5286-5674
5286 // TODO: find a way to avoid such cloning 5287 if(el.is('img')) { 5288 item.img = item.img.clone(); 5289 } 5290 if(item.img[0].naturalWidth > 0) { 5291 item.hasSize = true; 5292 } 5293 } 5294 5295 mfp._parseMarkup(template, { 5296 title: _getTitle(item), 5297 img_replaceWith: item.img 5298 }, item); 5299 5300 mfp.resizeImage(); 5301 5302 if(item.hasSize) { 5303 if(_imgInterval) clearInterval(_imgInterval); 5304 5305 if(item.loadError) { 5306 template.addClass('mfp-loading'); 5307 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); 5308 } else { 5309 template.removeClass('mfp-loading'); 5310 mfp.updateStatus('ready'); 5311 } 5312 return template; 5313 } 5314 5315 mfp.updateStatus('loading'); 5316 item.loading = true; 5317 5318 if(!item.hasSize) { 5319 item.imgHidden = true; 5320 template.addClass('mfp-loading'); 5321 mfp.findImageSize(item); 5322 } 5323 5324 return template; 5325 } 5326 } 5327}); 5328 5329 5330 5331/*>>image*/ 5332 5333/*>>zoom*/ 5334var hasMozTransform, 5335 getHasMozTransform = function() { 5336 if(hasMozTransform === undefined) { 5337 hasMozTransform = document.createElement('p').style.MozTransform !== undefined; 5338 } 5339 return hasMozTransform; 5340 }; 5341 5342$.magnificPopup.registerModule('zoom', { 5343 5344 options: { 5345 enabled: false, 5346 easing: 'ease-in-out', 5347 duration: 300, 5348 opener: function(element) { 5349 return element.is('img') ? element : element.find('img'); 5350 } 5351 }, 5352 5353 proto: { 5354 5355 initZoom: function() { 5356 var zoomSt = mfp.st.zoom, 5357 ns = '.zoom', 5358 image; 5359 5360 if(!zoomSt.enabled || !mfp.supportsTransition) { 5361 return; 5362 } 5363 5364 var duration = zoomSt.duration, 5365 getElToAnimate = function(image) { 5366 var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'), 5367 transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing, 5368 cssObj = { 5369 position: 'fixed', 5370 zIndex: 9999, 5371 left: 0, 5372 top: 0, 5373 '-webkit-backface-visibility': 'hidden' 5374 }, 5375 t = 'transition'; 5376 5377 cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition; 5378 5379 newImg.css(cssObj); 5380 return newImg; 5381 }, 5382 showMainContent = function() { 5383 mfp.content.css('visibility', 'visible'); 5384 }, 5385 openTimeout, 5386 animatedImg; 5387 5388 _mfpOn('BuildControls'+ns, function() { 5389 if(mfp._allowZoom()) { 5390 5391 clearTimeout(openTimeout); 5392 mfp.content.css('visibility', 'hidden'); 5393 5394 // Basically, all code below does is clones existing image, puts in on top of the current one and animated it 5395 5396 image = mfp._getItemToZoom(); 5397 5398 if(!image) { 5399 showMainContent(); 5400 return; 5401 } 5402 5403 animatedImg = getElToAnimate(image); 5404 5405 animatedImg.css( mfp._getOffset() ); 5406 5407 mfp.wrap.append(animatedImg); 5408 5409 openTimeout = setTimeout(function() { 5410 animatedImg.css( mfp._getOffset( true ) ); 5411 openTimeout = setTimeout(function() { 5412 5413 showMainContent(); 5414 5415 setTimeout(function() { 5416 animatedImg.remove(); 5417 image = animatedImg = null; 5418 _mfpTrigger('ZoomAnimationEnded'); 5419 }, 16); // avoid blink when switching images 5420 5421 }, duration); // this timeout equals animation duration 5422 5423 }, 16); // by adding this timeout we avoid short glitch at the beginning of animation 5424 5425 5426 // Lots of timeouts... 5427 } 5428 }); 5429 _mfpOn(BEFORE_CLOSE_EVENT+ns, function() { 5430 if(mfp._allowZoom()) { 5431 5432 clearTimeout(openTimeout); 5433 5434 mfp.st.removalDelay = duration; 5435 5436 if(!image) { 5437 image = mfp._getItemToZoom(); 5438 if(!image) { 5439 return; 5440 } 5441 animatedImg = getElToAnimate(image); 5442 } 5443 5444 5445 animatedImg.css( mfp._getOffset(true) ); 5446 mfp.wrap.append(animatedImg); 5447 mfp.content.css('visibility', 'hidden'); 5448 5449 setTimeout(function() { 5450 animatedImg.css( mfp._getOffset() ); 5451 }, 16); 5452 } 5453 5454 }); 5455 5456 _mfpOn(CLOSE_EVENT+ns, function() { 5457 if(mfp._allowZoom()) { 5458 showMainContent(); 5459 if(animatedImg) { 5460 animatedImg.remove(); 5461 } 5462 image = null; 5463 } 5464 }); 5465 }, 5466 5467 _allowZoom: function() { 5468 return mfp.currItem.type === 'image'; 5469 }, 5470 5471 _getItemToZoom: function() { 5472 if(mfp.currItem.hasSize) { 5473 return mfp.currItem.img; 5474 } else { 5475 return false; 5476 } 5477 }, 5478 5479 // Get element postion relative to viewport 5480 _getOffset: function(isLarge) { 5481 var el; 5482 if(isLarge) { 5483 el = mfp.currItem.img; 5484 } else { 5485 el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem); 5486 } 5487 5488 var offset = el.offset(); 5489 var paddingTop = parseInt(el.css('padding-top'),10); 5490 var paddingBottom = parseInt(el.css('padding-bottom'),10); 5491 offset.top -= ( $(window).scrollTop() - paddingTop ); 5492 5493 5494 /* 5495 5496 Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa. 5497 5498 */ 5499 var obj = { 5500 width: el.width(), 5501 // fix Zepto height+padding issue 5502 height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop 5503 }; 5504 5505 // I hate to do this, but there is no another option 5506 if( getHasMozTransform() ) { 5507 obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)'; 5508 } else { 5509 obj.left = offset.left; 5510 obj.top = offset.top; 5511 } 5512 return obj; 5513 } 5514 5515 } 5516}); 5517 5518 5519 5520/*>>zoom*/ 5521 5522/*>>iframe*/ 5523 5524var IFRAME_NS = 'iframe', 5525 _emptyPage = '//about:blank', 5526 5527 _fixIframeBugs = function(isShowing) { 5528 if(mfp.currTemplate[IFRAME_NS]) { 5529 var el = mfp.currTemplate[IFRAME_NS].find('iframe'); 5530 if(el.length) { 5531 // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug 5532 if(!isShowing) { 5533 el[0].src = _emptyPage; 5534 } 5535 5536 // IE8 black screen bug fix 5537 if(mfp.isIE8) { 5538 el.css('display', isShowing ? 'block' : 'none'); 5539 } 5540 } 5541 } 5542 }; 5543 5544$.magnificPopup.registerModule(IFRAME_NS, { 5545 5546 options: { 5547 markup: '<div class="mfp-iframe-scaler">'+ 5548 '<div class="mfp-close"></div>'+ 5549 '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+ 5550 '</div>', 5551 5552 srcAction: 'iframe_src', 5553 5554 // we don't care and support only one default type of URL by default 5555 patterns: { 5556 youtube: { 5557 index: 'youtube.com', 5558 id: 'v=', 5559 src: '//www.youtube.com/embed/%id%?autoplay=1' 5560 }, 5561 vimeo: { 5562 index: 'vimeo.com/', 5563 id: '/', 5564 src: '//player.vimeo.com/video/%id%?autoplay=1' 5565 }, 5566 gmaps: { 5567 index: '//maps.google.', 5568 src: '%id%&output=embed' 5569 } 5570 } 5571 }, 5572 5573 proto: { 5574 initIframe: function() { 5575 mfp.types.push(IFRAME_NS); 5576 5577 _mfpOn('BeforeChange', function(e, prevType, newType) { 5578 if(prevType !== newType) { 5579 if(prevType === IFRAME_NS) { 5580 _fixIframeBugs(); // iframe if removed 5581 } else if(newType === IFRAME_NS) { 5582 _fixIframeBugs(true); // iframe is showing 5583 } 5584 }// else { 5585 // iframe source is switched, don't do anything 5586 //} 5587 }); 5588 5589 _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { 5590 _fixIframeBugs(); 5591 }); 5592 }, 5593 5594 getIframe: function(item, template) { 5595 var embedSrc = item.src; 5596 var iframeSt = mfp.st.iframe; 5597 5598 $.each(iframeSt.patterns, function() { 5599 if(embedSrc.indexOf( this.index ) > -1) { 5600 if(this.id) { 5601 if(typeof this.id === 'string') { 5602 embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); 5603 } else { 5604 embedSrc = this.id.call( this, embedSrc ); 5605 } 5606 } 5607 embedSrc = this.src.replace('%id%', embedSrc ); 5608 return false; // break; 5609 } 5610 }); 5611 5612 var dataObj = {}; 5613 if(iframeSt.srcAction) { 5614 dataObj[iframeSt.srcAction] = embedSrc; 5615 } 5616 mfp._parseMarkup(template, dataObj, item); 5617 5618 mfp.updateStatus('ready'); 5619 5620 return template; 5621 } 5622 } 5623}); 5624 5625 5626 5627/*>>iframe*/ 5628 5629/*>>gallery*/ 5630/** 5631 * Get looped index depending on number of slides 5632 */ 5633var _getLoopedId = function(index) { 5634 var numSlides = mfp.items.length; 5635 if(index > numSlides - 1) { 5636 return index - numSlides; 5637 } else if(index < 0) { 5638 return numSlides + index; 5639 } 5640 return index; 5641 }, 5642 _replaceCurrTotal = function(text, curr, total) { 5643 return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total); 5644 }; 5645 5646$.magnificPopup.registerModule('gallery', { 5647 5648 options: { 5649 enabled: false, 5650 arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>', 5651 preload: [0,2], 5652 navigateByImgClick: true, 5653 arrows: true, 5654 5655 tPrev: 'Previous (Left arrow key)', 5656 tNext: 'Next (Right arrow key)', 5657 tCounter: '%curr% of %total%' 5658 }, 5659 5660 proto: { 5661 initGallery: function() { 5662 5663 var gSt = mfp.st.gallery, 5664 ns = '.mfp-gallery', 5665 supportsFastClick = Boolean($.fn.mfpFastClick); 5666 5667 mfp.direction = true; // true - next, false - prev 5668 5669 if(!gSt || !gSt.enabled ) return false; 5670 5671 _wrapClasses += ' mfp-gallery'; 5672 5673 _mfpOn(OPEN_EVENT+ns, function() { 5674
5675 if(gSt.navigateByImgClick) { 5676 mfp.wrap.on('click'+ns, '.mfp-img', function() { 5677 if(mfp.items.length > 1) { 5678 mfp.next(); 5679 return false; 5680 } 5681 }); 5682 } 5683 5684 _document.on('keydown'+ns, function(e) { 5685 if (e.keyCode === 37) { 5686 mfp.prev(); 5687 } else if (e.keyCode === 39) { 5688 mfp.next(); 5689 } 5690 }); 5691 }); 5692 5693 _mfpOn('UpdateStatus'+ns, function(e, data) { 5694 if(data.text) { 5695 data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); 5696 } 5697 }); 5698 5699 _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { 5700 var l = mfp.items.length; 5701 values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; 5702 }); 5703 5704 _mfpOn('BuildControls' + ns, function() { 5705 if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { 5706 var markup = gSt.arrowMarkup, 5707 arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS), 5708 arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS); 5709 5710 var eName = supportsFastClick ? 'mfpFastClick' : 'click'; 5711 arrowLeft[eName](function() { 5712 mfp.prev(); 5713 }); 5714 arrowRight[eName](function() { 5715 mfp.next(); 5716 }); 5717 5718 // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b) 5719 if(mfp.isIE7) { 5720 _getEl('b', arrowLeft[0], false, true); 5721 _getEl('a', arrowLeft[0], false, true); 5722 _getEl('b', arrowRight[0], false, true); 5723 _getEl('a', arrowRight[0], false, true); 5724 } 5725 5726 mfp.container.append(arrowLeft.add(arrowRight)); 5727 } 5728 }); 5729 5730 _mfpOn(CHANGE_EVENT+ns, function() { 5731 if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); 5732 5733 mfp._preloadTimeout = setTimeout(function() { 5734 mfp.preloadNearbyImages(); 5735 mfp._preloadTimeout = null; 5736 }, 16); 5737 }); 5738 5739 5740 _mfpOn(CLOSE_EVENT+ns, function() { 5741 _document.off(ns); 5742 mfp.wrap.off('click'+ns); 5743 5744 if(mfp.arrowLeft && supportsFastClick) { 5745 mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick(); 5746 } 5747 mfp.arrowRight = mfp.arrowLeft = null; 5748 }); 5749 5750 }, 5751 next: function() { 5752 mfp.direction = true; 5753 mfp.index = _getLoopedId(mfp.index + 1); 5754 mfp.updateItemHTML(); 5755 }, 5756 prev: function() { 5757 mfp.direction = false; 5758 mfp.index = _getLoopedId(mfp.index - 1); 5759 mfp.updateItemHTML(); 5760 }, 5761 goTo: function(newIndex) { 5762 mfp.direction = (newIndex >= mfp.index); 5763 mfp.index = newIndex; 5764 mfp.updateItemHTML(); 5765 }, 5766 preloadNearbyImages: function() { 5767 var p = mfp.st.gallery.preload, 5768 preloadBefore = Math.min(p[0], mfp.items.length), 5769 preloadAfter = Math.min(p[1], mfp.items.length), 5770 i; 5771 5772 for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { 5773 mfp._preloadItem(mfp.index+i); 5774 } 5775 for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { 5776 mfp._preloadItem(mfp.index-i); 5777 } 5778 }, 5779 _preloadItem: function(index) { 5780 index = _getLoopedId(index); 5781 5782 if(mfp.items[index].preloaded) { 5783 return; 5784 } 5785 5786 var item = mfp.items[index]; 5787 if(!item.parsed) { 5788 item = mfp.parseEl( index ); 5789 } 5790 5791 _mfpTrigger('LazyLoad', item); 5792 5793 if(item.type === 'image') { 5794 item.img = $('<img class="mfp-img" />').on('load.mfploader', function() { 5795 item.hasSize = true; 5796 }).on('error.mfploader', function() { 5797 item.hasSize = true; 5798 item.loadError = true; 5799 _mfpTrigger('LazyLoadError', item); 5800 }).attr('src', item.src); 5801 } 5802 5803 5804 item.preloaded = true; 5805 } 5806 } 5807}); 5808 5809/* 5810Touch Support that might be implemented some day 5811 5812addSwipeGesture: function() { 5813 var startX, 5814 moved, 5815 multipleTouches; 5816 5817 return; 5818 5819 var namespace = '.mfp', 5820 addEventNames = function(pref, down, move, up, cancel) { 5821 mfp._tStart = pref + down + namespace; 5822 mfp._tMove = pref + move + namespace; 5823 mfp._tEnd = pref + up + namespace; 5824 mfp._tCancel = pref + cancel + namespace; 5825 }; 5826 5827 if(window.navigator.msPointerEnabled) { 5828 addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel'); 5829 } else if('ontouchstart' in window) { 5830 addEventNames('touch', 'start', 'move', 'end', 'cancel'); 5831 } else { 5832 return; 5833 } 5834 _window.on(mfp._tStart, function(e) { 5835 var oE = e.originalEvent; 5836 multipleTouches = moved = false;
5837 startX = oE.pageX || oE.changedTouches[0].pageX; 5838 }).on(mfp._tMove, function(e) { 5839 if(e.originalEvent.touches.length > 1) { 5840 multipleTouches = e.originalEvent.touches.length; 5841 } else { 5842 //e.preventDefault(); 5843 moved = true; 5844 } 5845 }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) { 5846 if(moved && !multipleTouches) { 5847 var oE = e.originalEvent, 5848 diff = startX - (oE.pageX || oE.changedTouches[0].pageX); 5849 5850 if(diff > 20) { 5851 mfp.next(); 5852 } else if(diff < -20) { 5853 mfp.prev(); 5854 } 5855 } 5856 }); 5857}, 5858*/ 5859 5860 5861/*>>gallery*/ 5862 5863/*>>retina*/ 5864 5865var RETINA_NS = 'retina'; 5866 5867$.magnificPopup.registerModule(RETINA_NS, { 5868 options: { 5869 replaceSrc: function(item) { 5870 return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); 5871 }, 5872 ratio: 1 // Function or number. Set to 1 to disable. 5873 }, 5874 proto: { 5875 initRetina: function() { 5876 if(window.devicePixelRatio > 1) { 5877 5878 var st = mfp.st.retina, 5879 ratio = st.ratio; 5880 5881 ratio = !isNaN(ratio) ? ratio : ratio(); 5882 5883 if(ratio > 1) { 5884 _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { 5885 item.img.css({ 5886 'max-width': item.img[0].naturalWidth / ratio, 5887 'width': '100%' 5888 }); 5889 }); 5890 _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { 5891 item.src = st.replaceSrc(item, ratio); 5892 }); 5893 } 5894 } 5895 5896 } 5897 } 5898}); 5899 5900/*>>retina*/ 5901 5902/*>>fastclick*/ 5903/** 5904 * FastClick event implementation. (removes 300ms delay on touch devices) 5905 * Based on https://developers.google.com/mobile/articles/fast_buttons 5906 * 5907 * You may use it outside the Magnific Popup by calling just: 5908 * 5909 * $('.your-el').mfpFastClick(function() { 5910 * console.log('Clicked!'); 5911 * }); 5912 * 5913 * To unbind: 5914 * $('.your-el').destroyMfpFastClick(); 5915 * 5916 * 5917 * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound. 5918 * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick 5919 * 5920 */ 5921 5922(function() { 5923 var ghostClickDelay = 1000, 5924 supportsTouch = 'ontouchstart' in window, 5925 unbindTouchMove = function() { 5926 _window.off('touchmove'+ns+' touchend'+ns); 5927 }, 5928 eName = 'mfpFastClick', 5929 ns = '.'+eName; 5930 5931 5932 // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way 5933 $.fn.mfpFastClick = function(callback) { 5934 5935 return $(this).each(function() { 5936 5937 var elem = $(this), 5938 lock; 5939 5940 if( supportsTouch ) { 5941 5942 var timeout, 5943 startX, 5944 startY, 5945 pointerMoved, 5946 point, 5947 numPointers; 5948 5949 elem.on('touchstart' + ns, function(e) { 5950 pointerMoved = false; 5951 numPointers = 1; 5952 5953 point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0]; 5954 startX = point.clientX; 5955 startY = point.clientY; 5956 5957 _window.on('touchmove'+ns, function(e) { 5958 point = e.originalEvent ? e.originalEvent.touches : e.touches; 5959 numPointers = point.length; 5960 point = point[0]; 5961 if (Math.abs(point.clientX - startX) > 10 || 5962 Math.abs(point.clientY - startY) > 10) { 5963 pointerMoved = true; 5964 unbindTouchMove(); 5965 } 5966 }).on('touchend'+ns, function(e) { 5967 unbindTouchMove(); 5968 if(pointerMoved || numPointers > 1) { 5969 return; 5970 } 5971 lock = true; 5972 e.preventDefault(); 5973 clearTimeout(timeout); 5974 timeout = setTimeout(function() { 5975 lock = false; 5976 }, ghostClickDelay); 5977 callback(); 5978 }); 5979 }); 5980 5981 } 5982 5983 elem.on('click' + ns, function() { 5984 if(!lock) { 5985 callback(); 5986 } 5987 }); 5988 }); 5989 }; 5990 5991 $.fn.destroyMfpFastClick = function() { 5992 $(this).off('touchstart' + ns + ' click' + ns); 5993 if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns); 5994 }; 5995})(); 5996 5997/*>>fastclick*/ 5998 _checkInstance(); })(window.jQuery || window.Zepto); 5999/**! 6000 * easyPieChart 6001 * Lightweight plugin to render simple, animated and retina optimized pie charts 6002 * 6003 * @license 6004 * @author Robert Fleischmann <[email protected]> (http://robert-fleischmann.de) 6005 * @version 2.1.6 6006 **/ 6007 6008(function(root, factory) { 6009 if(typeof exports === 'object') { 6010 module.exports = factory(require('jquery')); 6011 } 6012 else if(typeof define === 'function' && define.amd) { 6013 define(['jquery'], factory); 6014 } 6015 else { 6016 factory(root.jQuery); 6017 } 6018}(this, function($) { 6019 6020/** 6021 * Renderer to render the chart on a canvas object 6022 * @param {DOMElement} el DOM element to host the canvas (root of the plugin) 6023 * @param {object} options options object of the plugin 6024 */ 6025var CanvasRenderer = function(el, options) {
6026 var cachedBackground; 6027 var canvas = document.createElement('canvas'); 6028 6029 el.appendChild(canvas); 6030 6031 if (typeof(G_vmlCanvasManager) !== 'undefined') { 6032 G_vmlCanvasManager.initElement(canvas); 6033 } 6034 6035 var ctx = canvas.getContext('2d'); 6036 6037 canvas.width = canvas.height = options.size; 6038 6039 // canvas on retina devices 6040 var scaleBy = 1; 6041 if (window.devicePixelRatio > 1) { 6042 scaleBy = window.devicePixelRatio; 6043 canvas.style.width = canvas.style.height = [options.size, 'px'].join(''); 6044 canvas.width = canvas.height = options.size * scaleBy; 6045 ctx.scale(scaleBy, scaleBy); 6046 } 6047 6048 // move 0,0 coordinates to the center 6049 ctx.translate(options.size / 2, options.size / 2); 6050 6051 // rotate canvas -90deg 6052 ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); 6053 6054 var radius = (options.size - options.lineWidth) / 2; 6055 if (options.scaleColor && options.scaleLength) { 6056 radius -= options.scaleLength + 2; // 2 is the distance between scale and bar 6057 } 6058 6059 // IE polyfill for Date 6060 Date.now = Date.now || function() { 6061 return +(new Date()); 6062 }; 6063 6064 /** 6065 * Draw a circle around the center of the canvas 6066 * @param {strong} color Valid CSS color string 6067 * @param {number} lineWidth Width of the line in px 6068 * @param {number} percent Percentage to draw (float between -1 and 1) 6069 */ 6070 var drawCircle = function(color, lineWidth, percent) { 6071 percent = Math.min(Math.max(-1, percent || 0), 1); 6072 var isNegative = percent <= 0 ? true : false; 6073 6074 ctx.beginPath(); 6075 ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative); 6076 6077 ctx.strokeStyle = color; 6078 ctx.lineWidth = lineWidth; 6079 6080 ctx.stroke(); 6081 }; 6082 6083 /** 6084 * Draw the scale of the chart 6085 */ 6086 var drawScale = function() { 6087 var offset; 6088 var length; 6089 6090 ctx.lineWidth = 1; 6091 ctx.fillStyle = options.scaleColor; 6092 6093 ctx.save(); 6094 for (var i = 24; i > 0; --i) { 6095 if (i % 6 === 0) { 6096 length = options.scaleLength; 6097 offset = 0; 6098 } else { 6099 length = options.scaleLength * 0.6; 6100 offset = options.scaleLength - length; 6101 } 6102 ctx.fillRect(-options.size/2 + offset, 0, length, 1); 6103 ctx.rotate(Math.PI / 12); 6104 } 6105 ctx.restore(); 6106 }; 6107 6108 /** 6109 * Request animation frame wrapper with polyfill 6110 * @return {function} Request animation frame method or timeout fallback 6111 */ 6112 var reqAnimationFrame = (function() { 6113 return window.requestAnimationFrame || 6114 window.webkitRequestAnimationFrame || 6115 window.mozRequestAnimationFrame || 6116 function(callback) { 6117 window.setTimeout(callback, 1000 / 60); 6118 }; 6119 }()); 6120 6121 /** 6122 * Draw the background of the plugin including the scale and the track 6123 */ 6124 var drawBackground = function() { 6125 if(options.scaleColor) drawScale(); 6126 if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); 6127 }; 6128 6129 /** 6130 * Canvas accessor 6131 */ 6132 this.getCanvas = function() { 6133 return canvas; 6134 }; 6135 6136 /** 6137 * Canvas 2D context 'ctx' accessor 6138 */ 6139 this.getCtx = function() { 6140 return ctx; 6141 }; 6142 6143 /** 6144 * Clear the complete canvas 6145 */ 6146 this.clear = function() { 6147 ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size); 6148 }; 6149 6150 /** 6151 * Draw the complete chart 6152 * @param {number} percent Percent shown by the chart between -100 and 100 6153 */ 6154 this.draw = function(percent) { 6155 // do we need to render a background 6156 if (!!options.scaleColor || !!options.trackColor) { 6157 // getImageData and putImageData are supported 6158 if (ctx.getImageData && ctx.putImageData) { 6159 if (!cachedBackground) { 6160 drawBackground(); 6161 cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy); 6162 } else { 6163 ctx.putImageData(cachedBackground, 0, 0); 6164 } 6165 } else { 6166 this.clear(); 6167 drawBackground(); 6168 } 6169 } else { 6170 this.clear(); 6171 } 6172 6173 ctx.lineCap = options.lineCap; 6174 6175 // if barcolor is a function execute it and pass the percent as a value 6176 var color; 6177 if (typeof(options.barColor) === 'function') { 6178 color = options.barColor(percent); 6179 } else { 6180 color = options.barColor; 6181 } 6182 6183 // draw bar 6184 drawCircle(color, options.lineWidth, percent / 100); 6185 }.bind(this); 6186 6187 /** 6188 * Animate from some percent to some other percentage 6189 * @param {number} from Starting percentage 6190 * @param {number} to Final percentage 6191 */ 6192 this.animate = function(from, to) { 6193 var startTime = Date.now(); 6194 options.onStart(from, to); 6195 var animation = function() { 6196 var process = Math.min(Date.now() - startTime, options.animate.duration); 6197 var currentValue = options.easing(this, process, from, to - from, options.animate.duration); 6198 this.draw(currentValue); 6199 options.onStep(from, to, currentValue); 6200 if (process >= options.animate.duration) { 6201 options.onStop(from, to); 6202 } else { 6203 reqAnimationFrame(animation); 6204 } 6205 }.bind(this); 6206 6207 reqAnimationFrame(animation); 6208 }.bind(this); 6209}; 6210 6211var EasyPieChart = function(el, opts) { 6212 var defaultOptions = { 6213 barColor: '#ef1e25', 6214 trackColor: '#f9f9f9', 6215 scaleColor: '#dfe0e0', 6216 scaleLength: 5, 6217 lineCap: 'round', 6218 lineWidth: 3, 6219 trackWidth: undefined, 6220 size: 110, 6221 rotate: 0, 6222 animate: { 6223 duration: 1000, 6224 enabled: true 6225 }, 6226 easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/ 6227 t = t / (d/2); 6228 if (t < 1) { 6229 return c / 2 * t * t + b; 6230 } 6231 return -c/2 * ((--t)*(t-2) - 1) + b; 6232 }, 6233 onStart: function(from, to) { 6234 return; 6235 }, 6236 onStep: function(from, to, currentValue) { 6237 return; 6238 }, 6239 onStop: function(from, to) { 6240 return; 6241 } 6242 }; 6243 6244 // detect present renderer 6245 if (typeof(CanvasRenderer) !== 'undefined') { 6246 defaultOptions.renderer = CanvasRenderer; 6247 } else if (typeof(SVGRenderer) !== 'undefined') { 6248 defaultOptions.renderer = SVGRenderer; 6249 } else { 6250 throw new Error('Please load either the SVG- or the CanvasRenderer'); 6251 } 6252 6253 var options = {}; 6254 var currentValue = 0; 6255 6256 /** 6257 * Initialize the plugin by creating the options object and initialize rendering 6258 */ 6259 var init = function() { 6260 this.el = el; 6261 this.options = options; 6262 6263 // merge user options into default options 6264 for (var i in defaultOptions) { 6265 if (defaultOptions.hasOwnProperty(i)) { 6266 options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i]; 6267 if (typeof(options[i]) === 'function') { 6268 options[i] = options[i].bind(this); 6269 } 6270 } 6271 } 6272 6273 // check for jQuery easing 6274 if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) { 6275 options.easing = jQuery.easing[options.easing]; 6276 } else { 6277 options.easing = defaultOptions.easing; 6278 } 6279 6280 // process earlier animate option to avoid bc breaks 6281 if (typeof(options.animate) === 'number') { 6282 options.animate = { 6283 duration: options.animate, 6284 enabled: true 6285 }; 6286 } 6287 6288 if (typeof(options.animate) === 'boolean' && !options.animate) { 6289 options.animate = { 6290 duration: 1000, 6291 enabled: options.animate 6292 }; 6293 } 6294 6295 // create renderer 6296 this.renderer = new options.renderer(el, options); 6297 6298 // initial draw 6299 this.renderer.draw(currentValue); 6300 6301 // initial update 6302 if (el.dataset && el.dataset.percent) { 6303 this.update(parseFloat(el.dataset.percent)); 6304 } else if (el.getAttribute && el.getAttribute('data-percent')) { 6305 this.update(parseFloat(el.getAttribute('data-percent'))); 6306 } 6307 }.bind(this); 6308 6309 /** 6310 * Update the value of the chart 6311 * @param {number} newValue Number between 0 and 100 6312 * @return {object} Instance of the plugin for method chaining 6313 */ 6314 this.update = function(newValue) { 6315 newValue = parseFloat(newValue); 6316 if (options.animate.enabled) { 6317 this.renderer.animate(currentValue, newValue); 6318 } else { 6319 this.renderer.draw(newValue); 6320 } 6321 currentValue = newValue; 6322 return this; 6323 }.bind(this); 6324 6325 /** 6326 * Disable animation 6327 * @return {object} Instance of the plugin for method chaining 6328 */ 6329 this.disableAnimation = function() { 6330 options.animate.enabled = false; 6331 return this; 6332 }; 6333 6334 /** 6335 * Enable animation 6336 * @return {object} Instance of the plugin for method chaining 6337 */ 6338 this.enableAnimation = function() { 6339 options.animate.enabled = true; 6340 return this; 6341 }; 6342 6343 init(); 6344}; 6345 6346$.fn.easyPieChart = function(options) { 6347 return this.each(function() { 6348 var instanceOptions; 6349 6350 if (!$.data(this, 'easyPieChart')) { 6351 instanceOptions = $.extend({}, options, $(this).data()); 6352 $.data(this, 'easyPieChart', new EasyPieChart(this, instanceOptions)); 6353 } 6354 }); 6355}; 6356 6357 6358})); 6359 6360/*! 6361Waypoints - 3.1.1 6362Copyright © 2011-2015 Caleb Troughton 6363Licensed under the MIT license. 6364https://github.com/imakewebthings/waypoints/blog/master/licenses.txt 6365*/ 6366(function() { 6367 'use strict' 6368 6369 var keyCounter = 0 6370 var allWaypoints = {} 6371 6372 /* http://imakewebthings.com/waypoints/api/waypoint */ 6373 function Waypoint(options) { 6374 if (!options) { 6375 throw new Error('No options passed to Waypoint constructor') 6376 } 6377 if (!options.element) { 6378 throw new Error('No element option passed to Waypoint constructor') 6379 } 6380 if (!options.handler) { 6381 throw new Error('No handler option passed to Waypoint constructor') 6382 } 6383 6384 this.key = 'waypoint-' + keyCounter 6385 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 6386 this.element = this.options.element 6387 this.adapter = new Waypoint.Adapter(this.element) 6388 this.callback = options.handler 6389 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 6390 this.enabled = this.options.enabled 6391 this.triggerPoint = null 6392 this.group = Waypoint.Group.findOrCreate({ 6393 name: this.options.group, 6394 axis: this.axis 6395 }) 6396 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 6397 6398 if (Waypoint.offsetAliases[this.options.offset]) { 6399 this.options.offset = Waypoint.offsetAliases[this.options.offset] 6400 } 6401 this.group.add(this) 6402 this.context.add(this) 6403 allWaypoints[this.key] = this 6404 keyCounter += 1 6405 } 6406 6407 /* Private */ 6408 Waypoint.prototype.queueTrigger = function(direction) { 6409 this.group.queueTrigger(this, direction) 6410 } 6411 6412 /* Private */ 6413 Waypoint.prototype.trigger = function(args) { 6414 if (!this.enabled) { 6415 return 6416 } 6417 if (this.callback) { 6418 this.callback.apply(this, args) 6419 } 6420 } 6421 6422 /* Public */ 6423 /* http://imakewebthings.com/waypoints/api/destroy */ 6424 Waypoint.prototype.destroy = function() { 6425 this.context.remove(this) 6426 this.group.remove(this) 6427 delete allWaypoints[this.key] 6428 } 6429 6430 /* Public */ 6431 /* http://imakewebthings.com/waypoints/api/disable */ 6432 Waypoint.prototype.disable = function() { 6433 this.enabled = false 6434 return this 6435 } 6436 6437 /* Public */ 6438 /* http://imakewebthings.com/waypoints/api/enable */ 6439 Waypoint.prototype.enable = function() { 6440 this.context.refresh() 6441 this.enabled = true 6442 return this 6443 } 6444 6445 /* Public */ 6446 /* http://imakewebthings.com/waypoints/api/next */ 6447 Waypoint.prototype.next = function() { 6448 return this.group.next(this) 6449 } 6450 6451 /* Public */ 6452 /* http://imakewebthings.com/waypoints/api/previous */ 6453 Waypoint.prototype.previous = function() { 6454 return this.group.previous(this) 6455 } 6456 6457 /* Private */ 6458 Waypoint.invokeAll = function(method) { 6459 var allWaypointsArray = []
6460 for (var waypointKey in allWaypoints) { 6461 allWaypointsArray.push(allWaypoints[waypointKey]) 6462 } 6463 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 6464 allWaypointsArray[i][method]() 6465 } 6466 } 6467 6468 /* Public */ 6469 /* http://imakewebthings.com/waypoints/api/destroy-all */ 6470 Waypoint.destroyAll = function() { 6471 Waypoint.invokeAll('destroy') 6472 } 6473 6474 /* Public */ 6475 /* http://imakewebthings.com/waypoints/api/disable-all */ 6476 Waypoint.disableAll = function() { 6477 Waypoint.invokeAll('disable') 6478 } 6479 6480 /* Public */ 6481 /* http://imakewebthings.com/waypoints/api/enable-all */ 6482 Waypoint.enableAll = function() { 6483 Waypoint.invokeAll('enable') 6484 } 6485 6486 /* Public */ 6487 /* http://imakewebthings.com/waypoints/api/refresh-all */ 6488 Waypoint.refreshAll = function() { 6489 Waypoint.Context.refreshAll() 6490 } 6491 6492 /* Public */ 6493 /* http://imakewebthings.com/waypoints/api/viewport-height */ 6494 Waypoint.viewportHeight = function() { 6495 return window.innerHeight || document.documentElement.clientHeight 6496 } 6497 6498 /* Public */ 6499 /* http://imakewebthings.com/waypoints/api/viewport-width */ 6500 Waypoint.viewportWidth = function() { 6501 return document.documentElement.clientWidth 6502 } 6503 6504 Waypoint.adapters = [] 6505 6506 Waypoint.defaults = { 6507 context: window, 6508 continuous: true, 6509 enabled: true, 6510 group: 'default', 6511 horizontal: false, 6512 offset: 0 6513 } 6514 6515 Waypoint.offsetAliases = { 6516 'bottom-in-view': function() { 6517 return this.context.innerHeight() - this.adapter.outerHeight() 6518 }, 6519 'right-in-view': function() { 6520 return this.context.innerWidth() - this.adapter.outerWidth() 6521 } 6522 } 6523 6524 window.Waypoint = Waypoint 6525}()) 6526;(function() { 6527 'use strict' 6528 6529 function requestAnimationFrameShim(callback) { 6530 window.setTimeout(callback, 1000 / 60) 6531 } 6532 6533 var keyCounter = 0 6534 var contexts = {} 6535 var Waypoint = window.Waypoint 6536 var oldWindowLoad = window.onload 6537 6538 /* http://imakewebthings.com/waypoints/api/context */ 6539 function Context(element) { 6540 this.element = element 6541 this.Adapter = Waypoint.Adapter 6542 this.adapter = new this.Adapter(element) 6543 this.key = 'waypoint-context-' + keyCounter 6544 this.didScroll = false 6545 this.didResize = false 6546 this.oldScroll = { 6547 x: this.adapter.scrollLeft(), 6548 y: this.adapter.scrollTop() 6549 } 6550 this.waypoints = { 6551 vertical: {}, 6552 horizontal: {} 6553 } 6554 6555 element.waypointContextKey = this.key 6556 contexts[element.waypointContextKey] = this 6557 keyCounter += 1 6558 6559 this.createThrottledScrollHandler() 6560 this.createThrottledResizeHandler() 6561 } 6562 6563 /* Private */ 6564 Context.prototype.add = function(waypoint) { 6565 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 6566 this.waypoints[axis][waypoint.key] = waypoint 6567 this.refresh() 6568 } 6569 6570 /* Private */ 6571 Context.prototype.checkEmpty = function() { 6572 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 6573 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 6574 if (horizontalEmpty && verticalEmpty) { 6575 this.adapter.off('.waypoints') 6576 delete contexts[this.key] 6577 } 6578 } 6579 6580 /* Private */ 6581 Context.prototype.createThrottledResizeHandler = function() { 6582 var self = this 6583 6584 function resizeHandler() { 6585 self.handleResize() 6586 self.didResize = false 6587 } 6588 6589 this.adapter.on('resize.waypoints', function() { 6590 if (!self.didResize) { 6591 self.didResize = true 6592 Waypoint.requestAnimationFrame(resizeHandler) 6593 } 6594 }) 6595 } 6596 6597 /* Private */ 6598 Context.prototype.createThrottledScrollHandler = function() { 6599 var self = this 6600 function scrollHandler() { 6601 self.handleScroll() 6602 self.didScroll = false 6603 } 6604 6605 this.adapter.on('scroll.waypoints', function() { 6606 if (!self.didScroll || Waypoint.isTouch) { 6607 self.didScroll = true 6608 Waypoint.requestAnimationFrame(scrollHandler) 6609 } 6610 }) 6611 } 6612 6613 /* Private */ 6614 Context.prototype.handleResize = function() { 6615 Waypoint.Context.refreshAll() 6616 } 6617 6618 /* Private */ 6619 Context.prototype.handleScroll = function() { 6620 var triggeredGroups = {} 6621 var axes = { 6622 horizontal: { 6623 newScroll: this.adapter.scrollLeft(), 6624 oldScroll: this.oldScroll.x, 6625 forward: 'right', 6626 backward: 'left' 6627 }, 6628 vertical: { 6629 newScroll: this.adapter.scrollTop(), 6630 oldScroll: this.oldScroll.y, 6631 forward: 'down', 6632 backward: 'up' 6633 } 6634 } 6635 6636 for (var axisKey in axes) { 6637 var axis = axes[axisKey] 6638 var isForward = axis.newScroll > axis.oldScroll 6639 var direction = isForward ? axis.forward : axis.backward 6640
6641 for (var waypointKey in this.waypoints[axisKey]) { 6642 var waypoint = this.waypoints[axisKey][waypointKey] 6643 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 6644 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 6645 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 6646 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 6647 if (crossedForward || crossedBackward) { 6648 waypoint.queueTrigger(direction) 6649 triggeredGroups[waypoint.group.id] = waypoint.group 6650 } 6651 } 6652 } 6653 6654 for (var groupKey in triggeredGroups) { 6655 triggeredGroups[groupKey].flushTriggers() 6656 } 6657 6658 this.oldScroll = { 6659 x: axes.horizontal.newScroll, 6660 y: axes.vertical.newScroll 6661 } 6662 } 6663 6664 /* Private */ 6665 Context.prototype.innerHeight = function() { 6666 /*eslint-disable eqeqeq */ 6667 if (this.element == this.element.window) { 6668 return Waypoint.viewportHeight() 6669 } 6670 /*eslint-enable eqeqeq */ 6671 return this.adapter.innerHeight() 6672 } 6673 6674 /* Private */ 6675 Context.prototype.remove = function(waypoint) { 6676 delete this.waypoints[waypoint.axis][waypoint.key] 6677 this.checkEmpty() 6678 } 6679 6680 /* Private */ 6681 Context.prototype.innerWidth = function() { 6682 /*eslint-disable eqeqeq */ 6683 if (this.element == this.element.window) { 6684 return Waypoint.viewportWidth() 6685 } 6686 /*eslint-enable eqeqeq */ 6687 return this.adapter.innerWidth() 6688 } 6689 6690 /* Public */ 6691 /* http://imakewebthings.com/waypoints/api/context-destroy */ 6692 Context.prototype.destroy = function() { 6693 var allWaypoints = [] 6694 for (var axis in this.waypoints) {
6695 for (var waypointKey in this.waypoints[axis]) { 6696 allWaypoints.push(this.waypoints[axis][waypointKey]) 6697 } 6698 } 6699 for (var i = 0, end = allWaypoints.length; i < end; i++) { 6700 allWaypoints[i].destroy() 6701 } 6702 } 6703 6704 /* Public */ 6705 /* http://imakewebthings.com/waypoints/api/context-refresh */ 6706 Context.prototype.refresh = function() { 6707 /*eslint-disable eqeqeq */ 6708 var isWindow = this.element == this.element.window 6709 /*eslint-enable eqeqeq */ 6710 var contextOffset = this.adapter.offset() 6711 var triggeredGroups = {} 6712 var axes 6713 6714 this.handleScroll() 6715 axes = { 6716 horizontal: { 6717 contextOffset: isWindow ? 0 : contextOffset.left, 6718 contextScroll: isWindow ? 0 : this.oldScroll.x, 6719 contextDimension: this.innerWidth(), 6720 oldScroll: this.oldScroll.x, 6721 forward: 'right', 6722 backward: 'left', 6723 offsetProp: 'left' 6724 }, 6725 vertical: { 6726 contextOffset: isWindow ? 0 : contextOffset.top, 6727 contextScroll: isWindow ? 0 : this.oldScroll.y, 6728 contextDimension: this.innerHeight(), 6729 oldScroll: this.oldScroll.y, 6730 forward: 'down', 6731 backward: 'up', 6732 offsetProp: 'top' 6733 } 6734 } 6735 6736 for (var axisKey in axes) { 6737 var axis = axes[axisKey]
6738 for (var waypointKey in this.waypoints[axisKey]) { 6739 var waypoint = this.waypoints[axisKey][waypointKey] 6740 var adjustment = waypoint.options.offset 6741 var oldTriggerPoint = waypoint.triggerPoint 6742 var elementOffset = 0 6743 var freshWaypoint = oldTriggerPoint == null 6744 var contextModifier, wasBeforeScroll, nowAfterScroll 6745 var triggeredBackward, triggeredForward 6746 6747 if (waypoint.element !== waypoint.element.window) { 6748 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 6749 } 6750 6751 if (typeof adjustment === 'function') { 6752 adjustment = adjustment.apply(waypoint) 6753 } 6754 else if (typeof adjustment === 'string') { 6755 adjustment = parseFloat(adjustment) 6756 if (waypoint.options.offset.indexOf('%') > - 1) { 6757 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 6758 } 6759 } 6760 6761 contextModifier = axis.contextScroll - axis.contextOffset 6762 waypoint.triggerPoint = elementOffset + contextModifier - adjustment 6763 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 6764 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 6765 triggeredBackward = wasBeforeScroll && nowAfterScroll 6766 triggeredForward = !wasBeforeScroll && !nowAfterScroll 6767 6768 if (!freshWaypoint && triggeredBackward) { 6769 waypoint.queueTrigger(axis.backward) 6770 triggeredGroups[waypoint.group.id] = waypoint.group 6771 } 6772 else if (!freshWaypoint && triggeredForward) { 6773 waypoint.queueTrigger(axis.forward) 6774 triggeredGroups[waypoint.group.id] = waypoint.group 6775 } 6776 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 6777 waypoint.queueTrigger(axis.forward) 6778 triggeredGroups[waypoint.group.id] = waypoint.group 6779 } 6780 } 6781 } 6782 6783 for (var groupKey in triggeredGroups) { 6784 triggeredGroups[groupKey].flushTriggers() 6785 } 6786 6787 return this 6788 } 6789 6790 /* Private */ 6791 Context.findOrCreateByElement = function(element) { 6792 return Context.findByElement(element) || new Context(element) 6793 } 6794 6795 /* Private */ 6796 Context.refreshAll = function() { 6797 for (var contextId in contexts) { 6798 contexts[contextId].refresh() 6799 } 6800 } 6801 6802 /* Public */ 6803 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 6804 Context.findByElement = function(element) { 6805 return contexts[element.waypointContextKey] 6806 } 6807 6808 window.onload = function() { 6809 if (oldWindowLoad) { 6810 oldWindowLoad() 6811 } 6812 Context.refreshAll() 6813 } 6814 6815 Waypoint.requestAnimationFrame = function(callback) { 6816 var requestFn = window.requestAnimationFrame || 6817 window.mozRequestAnimationFrame || 6818 window.webkitRequestAnimationFrame || 6819 requestAnimationFrameShim 6820 requestFn.call(window, callback) 6821 } 6822 Waypoint.Context = Context 6823}()) 6824;(function() { 6825 'use strict' 6826 6827 function byTriggerPoint(a, b) { 6828 return a.triggerPoint - b.triggerPoint 6829 } 6830 6831 function byReverseTriggerPoint(a, b) { 6832 return b.triggerPoint - a.triggerPoint 6833 } 6834 6835 var groups = { 6836 vertical: {}, 6837 horizontal: {} 6838 } 6839 var Waypoint = window.Waypoint 6840 6841 /* http://imakewebthings.com/waypoints/api/group */ 6842 function Group(options) { 6843 this.name = options.name 6844 this.axis = options.axis 6845 this.id = this.name + '-' + this.axis 6846 this.waypoints = [] 6847 this.clearTriggerQueues() 6848 groups[this.axis][this.name] = this 6849 } 6850 6851 /* Private */ 6852 Group.prototype.add = function(waypoint) { 6853 this.waypoints.push(waypoint) 6854 } 6855 6856 /* Private */ 6857 Group.prototype.clearTriggerQueues = function() { 6858 this.triggerQueues = { 6859 up: [], 6860 down: [], 6861 left: [], 6862 right: [] 6863 } 6864 } 6865 6866 /* Private */ 6867 Group.prototype.flushTriggers = function() { 6868 for (var direction in this.triggerQueues) { 6869 var waypoints = this.triggerQueues[direction] 6870 var reverse = direction === 'up' || direction === 'left' 6871 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 6872 for (var i = 0, end = waypoints.length; i < end; i += 1) { 6873 var waypoint = waypoints[i] 6874 if (waypoint.options.continuous || i === waypoints.length - 1) { 6875 waypoint.trigger([direction]) 6876 } 6877 } 6878 } 6879 this.clearTriggerQueues() 6880 } 6881 6882 /* Private */ 6883 Group.prototype.next = function(waypoint) { 6884 this.waypoints.sort(byTriggerPoint) 6885 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 6886 var isLast = index === this.waypoints.length - 1 6887 return isLast ? null : this.waypoints[index + 1] 6888 } 6889 6890 /* Private */ 6891 Group.prototype.previous = function(waypoint) { 6892 this.waypoints.sort(byTriggerPoint) 6893 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 6894 return index ? this.waypoints[index - 1] : null 6895 } 6896 6897 /* Private */ 6898 Group.prototype.queueTrigger = function(waypoint, direction) { 6899 this.triggerQueues[direction].push(waypoint) 6900 } 6901 6902 /* Private */ 6903 Group.prototype.remove = function(waypoint) { 6904 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 6905 if (index > -1) { 6906 this.waypoints.splice(index, 1) 6907 } 6908 } 6909 6910 /* Public */ 6911 /* http://imakewebthings.com/waypoints/api/first */ 6912 Group.prototype.first = function() { 6913 return this.waypoints[0] 6914 } 6915 6916 /* Public */ 6917 /* http://imakewebthings.com/waypoints/api/last */ 6918 Group.prototype.last = function() { 6919 return this.waypoints[this.waypoints.length - 1] 6920 } 6921 6922 /* Private */ 6923 Group.findOrCreate = function(options) { 6924 return groups[options.axis][options.name] || new Group(options) 6925 } 6926 6927 Waypoint.Group = Group 6928}()) 6929;(function() { 6930 'use strict' 6931 6932 var $ = window.jQuery 6933 var Waypoint = window.Waypoint 6934 6935 function JQueryAdapter(element) { 6936 this.$element = $(element) 6937 } 6938 6939 $.each([
6940 'innerHeight', 6941 'innerWidth', 6942 'off', 6943 'offset', 6944 'on', 6945 'outerHeight', 6946 'outerWidth', 6947 'scrollLeft', 6948 'scrollTop' 6949 ], function(i, method) { 6950 JQueryAdapter.prototype[method] = function() { 6951 var args = Array.prototype.slice.call(arguments) 6952 return this.$element[method].apply(this.$element, args) 6953 } 6954 }) 6955 6956 $.each([ 6957 'extend', 6958 'inArray', 6959 'isEmptyObject' 6960 ], function(i, method) { 6961 JQueryAdapter[method] = $[method] 6962 }) 6963 6964 Waypoint.adapters.push({ 6965 name: 'jquery', 6966 Adapter: JQueryAdapter 6967 }) 6968 Waypoint.Adapter = JQueryAdapter 6969}()) 6970;(function() { 6971 'use strict' 6972 6973 var Waypoint = window.Waypoint 6974 6975 function createExtension(framework) { 6976 return function() { 6977 var waypoints = [] 6978 var overrides = arguments[0] 6979 6980 if (framework.isFunction(arguments[0])) { 6981 overrides = framework.extend({}, arguments[1]) 6982 overrides.handler = arguments[0] 6983 } 6984 6985 this.each(function() { 6986 var options = framework.extend({}, overrides, { 6987 element: this 6988 }) 6989 if (typeof options.context === 'string') { 6990 options.context = framework(this).closest(options.context)[0] 6991 } 6992 waypoints.push(new Waypoint(options)) 6993 }) 6994 6995 return waypoints 6996 } 6997 } 6998 6999 if (window.jQuery) { 7000 window.jQuery.fn.waypoint = createExtension(window.jQuery) 7001 } 7002 if (window.Zepto) { 7003 window.Zepto.fn.waypoint = createExtension(window.Zepto) 7004 } 7005}()) 7006; 7007/*! 7008Waypoints Sticky Element Shortcut - 3.1.1 7009Copyright © 2011-2015 Caleb Troughton 7010Licensed under the MIT license. 7011https://github.com/imakewebthings/waypoints/blog/master/licenses.txt 7012*/ 7013(function() { 7014 'use strict' 7015 7016 var $ = window.jQuery 7017 var Waypoint = window.Waypoint 7018 7019 /* http://imakewebthings.com/waypoints/shortcuts/sticky-elements */ 7020 function Sticky(options) { 7021 this.options = $.extend({}, Waypoint.defaults, Sticky.defaults, options) 7022 this.element = this.options.element 7023 this.$element = $(this.element) 7024 this.createWrapper() 7025 this.createWaypoint() 7026 } 7027 7028 /* Private */ 7029 Sticky.prototype.createWaypoint = function() { 7030 var originalHandler = this.options.handler 7031 7032 this.waypoint = new Waypoint($.extend({}, this.options, { 7033 element: this.wrapper, 7034 handler: $.proxy(function(direction) { 7035 var shouldBeStuck = this.options.direction.indexOf(direction) > -1 7036 var wrapperHeight = shouldBeStuck ? this.$element.outerHeight(true) : '' 7037 7038 this.$wrapper.height(wrapperHeight) 7039 this.$element.toggleClass(this.options.stuckClass, shouldBeStuck) 7040 7041 if (originalHandler) { 7042 originalHandler.call(this, direction) 7043 } 7044 }, this) 7045 })) 7046 } 7047 7048 /* Private */ 7049 Sticky.prototype.createWrapper = function() { 7050 this.$element.wrap(this.options.wrapper) 7051 this.$wrapper = this.$element.parent() 7052 this.wrapper = this.$wrapper[0] 7053 } 7054 7055 /* Public */ 7056 Sticky.prototype.destroy = function() { 7057 if (this.$element.parent()[0] === this.wrapper) { 7058 this.waypoint.destroy() 7059 this.$element.removeClass(this.options.stuckClass).unwrap() 7060 } 7061 } 7062 7063 Sticky.defaults = { 7064 wrapper: '<div class="sticky-wrapper" />', 7065 stuckClass: 'stuck', 7066 direction: 'down right' 7067 } 7068
7069 Waypoint.Sticky = Sticky 7070}()) 7071; 7072/*! 7073 * imagesLoaded PACKAGED v3.0.4 7074 * JavaScript is all like "You images are done yet or what?" 7075 */ 7076 7077/*! 7078 * EventEmitter v4.2.0 - git.io/ee 7079 * Oliver Caldwell 7080 * MIT license 7081 * @preserve 7082 */ 7083 7084(function () { 7085 // Place the script in strict mode 7086 'use strict'; 7087 7088 /** 7089 * Class for managing events. 7090 * Can be extended to provide event functionality in other classes. 7091 * 7092 * @class EventEmitter Manages event registering and emitting. 7093 */ 7094 function EventEmitter() {} 7095 7096 // Shortcuts to improve speed and size 7097 7098 // Easy access to the prototype 7099 var proto = EventEmitter.prototype; 7100 7101 /** 7102 * Finds the index of the listener for the event in it's storage array. 7103 * 7104 * @param {Function[]} listeners Array of listeners to search through. 7105 * @param {Function} listener Method to look for. 7106 * @return {Number} Index of the specified listener, -1 if not found 7107 * @api private 7108 */ 7109 function indexOfListener(listeners, listener) { 7110 var i = listeners.length; 7111 while (i--) { 7112 if (listeners[i].listener === listener) { 7113 return i; 7114 } 7115 } 7116 7117 return -1; 7118 } 7119 7120 /** 7121 * Returns the listener array for the specified event. 7122 * Will initialise the event object and listener arrays if required. 7123 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object c
7123ontaining bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. 7124 * Each property in the object response is an array of listener functions. 7125 * 7126 * @param {String|RegExp} evt Name of the event to return the listeners from. 7127 * @return {Function[]|Object} All listener functions for the event. 7128 */ 7129 proto.getListeners = function getListeners(evt) { 7130 var events = this._getEvents(); 7131 var response; 7132 var key; 7133 7134 // Return a concatenated array of all matching events if 7135 // the selector is a regular expression. 7136 if (typeof evt === 'object') { 7137 response = {}; 7138 for (key in events) { 7139 if (events.hasOwnProperty(key) && evt.test(key)) { 7140 response[key] = events[key]; 7141 } 7142 } 7143 } 7144 else { 7145 response = events[evt] || (events[evt] = []); 7146 } 7147 7148 return response; 7149 }; 7150 7151 /** 7152 * Takes a list of listener objects and flattens it into a list of listener functions. 7153 * 7154 * @param {Object[]} listeners Raw listener objects. 7155 * @return {Function[]} Just the listener functions. 7156 */ 7157 proto.flattenListeners = function flattenListeners(listeners) { 7158 var flatListeners = []; 7159 var i; 7160 7161 for (i = 0; i < listeners.length; i += 1) { 7162 flatListeners.push(listeners[i].listener); 7163 } 7164 7165 return flatListeners; 7166 }; 7167 7168 /** 7169 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. 7170 * 7171 * @param {String|RegExp} evt Name of the event to return the listeners from. 7172 * @return {Object} All listener functions for an event in an object. 7173 */ 7174 proto.getListenersAsObject = function getListenersAsObject(evt) { 7175 var listeners = this.getListeners(evt); 7176 var response; 7177 7178 if (listeners instanceof Array) { 7179 response = {}; 7180 response[evt] = listeners; 7181 } 7182 7183 return response || listeners; 7184 }; 7185 7186 /** 7187 * Adds a listener function to the specified event. 7188 * The listener will not be added if it is a duplicate. 7189 * If the listener returns true then it will be removed after it is called. 7190 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 7191 * 7192 * @param {String|RegExp} evt Name of the event to attach the listener to. 7193 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 7194 * @return {Object} Current instance of EventEmitter for chaining. 7195 */ 7196 proto.addListener = function addListener(evt, listener) { 7197 var listeners = this.getListenersAsObject(evt); 7198 var listenerIsWrapped = typeof listener === 'object'; 7199 var key; 7200 7201 for (key in listeners) { 7202 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 7203 listeners[key].push(listenerIsWrapped ? listener : { 7204 listener: listener, 7205 once: false 7206 }); 7207 } 7208 } 7209 7210 return this; 7211 }; 7212 7213 /** 7214 * Alias of addListener 7215 */ 7216 proto.on = proto.addListener; 7217 7218 /** 7219 * Semi-alias of addListener. It will add a listener that will be 7220 * automatically removed after it's first execution. 7221 * 7222 * @param {String|RegExp} evt Name of the event to attach the listener to. 7223 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 7224 * @return {Object} Current instance of EventEmitter for chaining. 7225 */ 7226 proto.addOnceListener = function addOnceListener(evt, listener) { 7227 return this.addListener(evt, { 7228 listener: listener, 7229 once: true 7230 }); 7231 }; 7232 7233 /** 7234 * Alias of addOnceListener. 7235 */ 7236 proto.once = proto.addOnceListener; 7237 7238 /** 7239 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. 7240 * You need to tell it what event names should be matched by a regex. 7241 * 7242 * @param {String} evt Name of the event to create. 7243 * @return {Object} Current instance of EventEmitter for chaining. 7244 */ 7245 proto.defineEvent = function defineEvent(evt) { 7246 this.getListeners(evt); 7247 return this; 7248 }; 7249 7250 /** 7251 * Uses defineEvent to define multiple events. 7252 * 7253 * @param {String[]} evts An array of event names to define. 7254 * @return {Object} Current instance of EventEmitter for chaining. 7255 */ 7256 proto.defineEvents = function defineEvents(evts) { 7257 for (var i = 0; i < evts.length; i += 1) { 7258 this.defineEvent(evts[i]); 7259 } 7260 return this; 7261 }; 7262 7263 /** 7264 * Removes a listener function from the specified event. 7265 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 7266 * 7267 * @param {String|RegExp} evt Name of the event to remove the listener from. 7268 * @param {Function} listener Method to remove from the event. 7269 * @return {Object} Current instance of EventEmitter for chaining. 7270 */ 7271 proto.removeListener = function removeListener(evt, listener) { 7272 var listeners = this.getListenersAsObject(evt); 7273 var index; 7274 var key; 7275 7276 for (key in listeners) { 7277 if (listeners.hasOwnProperty(key)) { 7278 index = indexOfListener(listeners[key], listener); 7279 7280 if (index !== -1) { 7281 listeners[key].splice(index, 1); 7282 } 7283 } 7284 } 7285 7286 return this; 7287 }; 7288 7289 /** 7290 * Alias of removeListener 7291 */ 7292 proto.off = proto.removeListener; 7293 7294 /** 7295 * Adds listeners in bulk using the manipulateListeners method. 7296 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. 7297 * You can also pass it a regular expression to add the array of listeners to all events that match it. 7298 * Yeah, this function does quite a bit. That's probably a bad thing. 7299 * 7300 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. 7301 * @param {Function[]} [listeners] An optional array of listener functions to add. 7302 * @return {Object} Current instance of EventEmitter for chaining. 7303 */ 7304 proto.addListeners = function addListeners(evt, listeners) { 7305 // Pass through to manipulateListeners 7306 return this.manipulateListeners(false, evt, listeners); 7307 }; 7308 7309 /** 7310 * Removes listeners in bulk using the manipulateListeners method. 7311 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 7312 * You can also pass it an event name and an array of listeners to be removed. 7313 * You can also pass it a regular expression to remove the listeners from all events that match it. 7314 * 7315 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. 7316 * @param {Function[]} [listeners] An optional array of listener functions to remove. 7317 * @return {Object} Current instance of EventEmitter for chaining. 7318 */ 7319 proto.removeListeners = function removeListeners(evt, listeners) { 7320 // Pass through to manipulateListeners 7321 return this.manipulateListeners(true, evt, listeners); 7322 }; 7323 7324 /** 7325 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. 7326 * The first argument will determine if the listeners are removed (true) or added (false). 7327 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 7328 * You can also pass it an event name and an array of listeners to be added/removed. 7329 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 7330 * 7331 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 7332 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. 7333 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 7334 * @return {Object} Current instance of EventEmitter for chaining. 7335 */ 7336 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 7337 var i; 7338 var value; 7339 var single = remove ? this.removeListener : this.addListener; 7340 var multiple = remove ? this.removeListeners : this.addListeners; 7341 7342 // If evt is an object then pass each of it's properties to this method 7343 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 7344 for (i in evt) { 7345 if (evt.hasOwnProperty(i) && (value = evt[i])) { 7346 // Pass the single listener straight through to the singular method 7347 if (typeof value === 'function') { 7348 single.call(this, i, value); 7349 } 7350 else { 7351 // Otherwise pass back to the multiple function 7352 multiple.call(this, i, value); 7353 } 7354 } 7355 } 7356 } 7357 else { 7358 // So evt must be a string 7359 // And listeners must be an array of listeners 7360 // Loop over it and pass each one to the multiple method 7361 i = listeners.length; 7362 while (i--) { 7363 single.call(this, evt, listeners[i]); 7364 } 7365 } 7366 7367 return this; 7368 }; 7369 7370 /** 7371 * Removes all listeners from a specified event. 7372 * If you do not specify an event then all listeners will be removed. 7373 * That means every event will be emptied. 7374 * You can also pass a regex to remove all events that match it. 7375 * 7376 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 7377 * @return {Object} Current instance of EventEmitter for chaining. 7378 */ 7379 proto.removeEvent = function removeEvent(evt) { 7380 var type = typeof evt; 7381 var events = this._getEvents(); 7382 var key; 7383 7384 // Remove different things depending on the state of evt 7385 if (type === 'string') { 7386 // Remove all listeners for the specified event 7387 delete events[evt]; 7388 } 7389 else if (type === 'object') { 7390 // Remove all events matching the regex. 7391 for (key in events) { 7392 if (events.hasOwnProperty(key) && evt.test(key)) { 7393 delete events[key]; 7394 } 7395 } 7396 } 7397 else { 7398 // Remove all listeners in all events 7399 delete this._events; 7400 } 7401 7402 return this; 7403 }; 7404 7405 /** 7406 * Emits an event of your choice. 7407 * When emitted, every listener attached to that event will be executed. 7408 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 7409 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
7410 * So they will not arrive within the array on the other side, they will be separate. 7411 * You can also pass a regular expression to emit to all events that match it. 7412 * 7413 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 7414 * @param {Array} [args] Optional array of arguments to be passed to each listener. 7415 * @return {Object} Current instance of EventEmitter for chaining. 7416 */ 7417 proto.emitEvent = function emitEvent(evt, args) { 7418 var listeners = this.getListenersAsObject(evt); 7419 var listener; 7420 var i; 7421 var key; 7422 var response; 7423 7424 for (key in listeners) { 7425 if (listeners.hasOwnProperty(key)) { 7426 i = listeners[key].length; 7427 7428 while (i--) { 7429 // If the listener returns true then it shall be removed from the event 7430 // The function is executed either with a basic call or an apply if there is an args array 7431 listener = listeners[key][i]; 7432 response = listener.listener.apply(this, args || []); 7433 if (response === this._getOnceReturnValue() || listener.once === true) { 7434 this.removeListener(evt, listeners[key][i].listener); 7435 } 7436 } 7437 } 7438 } 7439 7440 return this; 7441 }; 7442 7443 /** 7444 * Alias of emitEvent 7445 */ 7446 proto.trigger = proto.emitEvent; 7447 7448 /** 7449 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. 7450 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 7451 * 7452 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 7453 * @param {...*} Optional additional arguments to be passed to each listener. 7454 * @return {Object} Current instance of EventEmitter for chaining. 7455 */ 7456 proto.emit = function emit(evt) { 7457 var args = Array.prototype.slice.call(arguments, 1); 7458 return this.emitEvent(evt, args); 7459 }; 7460 7461 /** 7462 * Sets the current value to check against when executing listeners. If a 7463 * listeners return value matches the one set here then it will be removed 7464 * after execution. This value defaults to true. 7465 * 7466 * @param {*} value The new value to check for when executing listeners. 7467 * @return {Object} Current instance of EventEmitter for chaining. 7468 */ 7469 proto.setOnceReturnValue = function setOnceReturnValue(value) { 7470 this._onceReturnValue = value; 7471 return this; 7472 }; 7473 7474 /** 7475 * Fetches the current value to check against when executing listeners. If 7476 * the listeners return value matches this one then it should be removed 7477 * automatically. It will return true by default. 7478 * 7479 * @return {*|Boolean} The current value to check for or the default, true. 7480 * @api private 7481 */ 7482 proto._getOnceReturnValue = function _getOnceReturnValue() { 7483 if (this.hasOwnProperty('_onceReturnValue')) { 7484 return this._onceReturnValue; 7485 } 7486 else { 7487 return true; 7488 } 7489 }; 7490 7491 /** 7492 * Fetches the events object and creates one if required. 7493 * 7494 * @return {Object} The events storage object. 7495 * @api private 7496 */ 7497 proto._getEvents = function _getEvents() { 7498 return this._events || (this._events = {}); 7499 }; 7500 7501 // Expose the class either via AMD, CommonJS or the global object 7502 if (typeof define === 'function' && define.amd) { 7503 define(function () { 7504 return EventEmitter; 7505 }); 7506 } 7507 else if (typeof module !== 'undefined' && module.exports){ 7508 module.exports = EventEmitter; 7509 } 7510 else { 7511 this.EventEmitter = EventEmitter; 7512 } 7513}.call(this)); 7514 7515/*! 7516 * eventie v1.0.3 7517 * event binding helper 7518 * eventie.bind( elem, 'click', myFn ) 7519 * eventie.unbind( elem, 'click', myFn ) 7520 */ 7521 7522/*jshint browser: true, undef: true, unused: true */ 7523/*global define: false */ 7524 7525( function( window ) { 7526 7527'use strict'; 7528 7529var docElem = document.documentElement; 7530 7531var bind = function() {}; 7532 7533if ( docElem.addEventListener ) { 7534 bind = function( obj, type, fn ) { 7535 obj.addEventListener( type, fn, false ); 7536 }; 7537} else if ( docElem.attachEvent ) { 7538 bind = function( obj, type, fn ) { 7539 obj[ type + fn ] = fn.handleEvent ? 7540 function() { 7541 var event = window.event; 7542 // add event.target 7543 event.target = event.target || event.srcElement; 7544 fn.handleEvent.call( fn, event ); 7545 } : 7546 function() { 7547 var event = window.event; 7548 // add event.target 7549 event.target = event.target || event.srcElement; 7550 fn.call( obj, event ); 7551 }; 7552 obj.attachEvent( "on" + type, obj[ type + fn ] ); 7553 }; 7554} 7555 7556var unbind = function() {}; 7557 7558if ( docElem.removeEventListener ) { 7559 unbind = function( obj, type, fn ) { 7560 obj.removeEventListener( type, fn, false ); 7561 }; 7562} else if ( docElem.detachEvent ) { 7563 unbind = function( obj, type, fn ) { 7564 obj.detachEvent( "on" + type, obj[ type + fn ] ); 7565 try { 7566 delete obj[ type + fn ]; 7567 } catch ( err ) { 7568 // can't delete window object properties 7569 obj[ type + fn ] = undefined; 7570 } 7571 }; 7572} 7573 7574var eventie = { 7575 bind: bind, 7576 unbind: unbind 7577}; 7578 7579// transport 7580if ( typeof define === 'function' && define.amd ) { 7581 // AMD 7582 define( eventie ); 7583} else { 7584 // browser global 7585 window.eventie = eventie; 7586} 7587 7588})( this ); 7589 7590/*! 7591 * imagesLoaded v3.0.4 7592 * JavaScript is all like "You images are done yet or what?" 7593 */ 7594 7595( function( window ) { 7596 7597'use strict'; 7598 7599var $ = window.jQuery; 7600var console = window.console; 7601var hasConsole = typeof console !== 'undefined'; 7602 7603// -------------------------- helpers -------------------------- // 7604 7605// extend objects 7606function extend( a, b ) { 7607 for ( var prop in b ) { 7608 a[ prop ] = b[ prop ]; 7609 } 7610 return a; 7611} 7612 7613var objToString = Object.prototype.toString; 7614function isArray( obj ) { 7615 return objToString.call( obj ) === '[object Array]'; 7616} 7617 7618// turn element or nodeList into an array 7619function makeArray( obj ) { 7620 var ary = []; 7621 if ( isArray( obj ) ) { 7622 // use object if already an array 7623 ary = obj;
7624 } else if ( typeof obj.length === 'number' ) { 7625 // convert nodeList to array 7626 for ( var i=0, len = obj.length; i < len; i++ ) { 7627 ary.push( obj[i] ); 7628 } 7629 } else { 7630 // array of single index 7631 ary.push( obj ); 7632 } 7633 return ary; 7634} 7635 7636// -------------------------- -------------------------- // 7637 7638function defineImagesLoaded( EventEmitter, eventie ) { 7639 7640 /** 7641 * @param {Array, Element, NodeList, String} elem 7642 * @param {Object or Function} options - if function, use as callback 7643 * @param {Function} onAlways - callback function 7644 */ 7645 function ImagesLoaded( elem, options, onAlways ) { 7646 // coerce ImagesLoaded() without new, to be new ImagesLoaded() 7647 if ( !( this instanceof ImagesLoaded ) ) { 7648 return new ImagesLoaded( elem, options ); 7649 } 7650 // use elem as selector string 7651 if ( typeof elem === 'string' ) { 7652 elem = document.querySelectorAll( elem ); 7653 } 7654 7655 this.elements = makeArray( elem ); 7656 this.options = extend( {}, this.options ); 7657 7658 if ( typeof options === 'function' ) { 7659 onAlways = options; 7660 } else { 7661 extend( this.options, options ); 7662 } 7663 7664 if ( onAlways ) { 7665 this.on( 'always', onAlways ); 7666 } 7667 7668 this.getImages(); 7669 7670 if ( $ ) { 7671 // add jQuery Deferred object 7672 this.jqDeferred = new $.Deferred(); 7673 } 7674 7675 // HACK check async to allow time to bind listeners 7676 var _this = this; 7677 setTimeout( function() { 7678 _this.check(); 7679 }); 7680 } 7681 7682 ImagesLoaded.prototype = new EventEmitter(); 7683 7684 ImagesLoaded.prototype.options = {}; 7685 7686 ImagesLoaded.prototype.getImages = function() { 7687 this.images = []; 7688 7689 // filter & find items if we have an item selector 7690 for ( var i=0, len = this.elements.length; i < len; i++ ) { 7691 var elem = this.elements[i]; 7692 // filter siblings 7693 if ( elem.nodeName === 'IMG' ) { 7694 this.addImage( elem ); 7695 } 7696 // find children 7697 var childElems = elem.querySelectorAll('img'); 7698 // concat childElems to filterFound array 7699 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 7700 var img = childElems[j]; 7701 this.addImage( img ); 7702 } 7703 } 7704 }; 7705 7706 /** 7707 * @param {Image} img 7708 */ 7709 ImagesLoaded.prototype.addImage = function( img ) { 7710 var loadingImage = new LoadingImage( img ); 7711 this.images.push( loadingImage ); 7712 }; 7713 7714 ImagesLoaded.prototype.check = function() { 7715 var _this = this; 7716 var checkedCount = 0; 7717 var length = this.images.length; 7718 this.hasAnyBroken = false; 7719 // complete if no images 7720 if ( !length ) { 7721 this.complete(); 7722 return; 7723 } 7724 7725 function onConfirm( image, message ) { 7726 if ( _this.options.debug && hasConsole ) { 7727 console.log( 'confirm', image, message ); 7728 } 7729 7730 _this.progress( image ); 7731 checkedCount++; 7732 if ( checkedCount === length ) { 7733 _this.complete(); 7734 } 7735 return true; // bind once 7736 } 7737 7738 for ( var i=0; i < length; i++ ) { 7739 var loadingImage = this.images[i]; 7740 loadingImage.on( 'confirm', onConfirm ); 7741 loadingImage.check(); 7742 } 7743 }; 7744 7745 ImagesLoaded.prototype.progress = function( image ) { 7746 this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; 7747 // HACK - Chrome triggers event before object properties have changed. #83 7748 var _this = this; 7749 setTimeout( function() { 7750 _this.emit( 'progress', _this, image ); 7751 if ( _this.jqDeferred ) { 7752 _this.jqDeferred.notify( _this, image ); 7753 } 7754 }); 7755 }; 7756 7757 ImagesLoaded.prototype.complete = function() { 7758 var eventName = this.hasAnyBroken ? 'fail' : 'done'; 7759 this.isComplete = true; 7760 var _this = this; 7761 // HACK - another setTimeout so that confirm happens after progress 7762 setTimeout( function() { 7763 _this.emit( eventName, _this ); 7764 _this.emit( 'always', _this ); 7765 if ( _this.jqDeferred ) { 7766 var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve'; 7767 _this.jqDeferred[ jqMethod ]( _this ); 7768 } 7769 });
7770 }; 7771 7772 // -------------------------- jquery -------------------------- // 7773 7774 if ( $ ) { 7775 $.fn.imagesLoaded = function( options, callback ) { 7776 var instance = new ImagesLoaded( this, options, callback ); 7777 return instance.jqDeferred.promise( $(this) ); 7778 }; 7779 } 7780 7781 7782 // -------------------------- -------------------------- // 7783 7784 var cache = {}; 7785 7786 function LoadingImage( img ) { 7787 this.img = img; 7788 } 7789 7790 LoadingImage.prototype = new EventEmitter(); 7791 7792 LoadingImage.prototype.check = function() { 7793 // first check cached any previous images that have same src 7794 var cached = cache[ this.img.src ]; 7795 if ( cached ) { 7796 this.useCached( cached ); 7797 return; 7798 } 7799 // add this to cache 7800 cache[ this.img.src ] = this; 7801 7802 // If complete is true and browser supports natural sizes, 7803 // try to check for image status manually. 7804 if ( this.img.complete && this.img.naturalWidth !== undefined ) { 7805 // report based on naturalWidth 7806 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 7807 return; 7808 } 7809 7810 // If none of the checks above matched, simulate loading on detached element. 7811 var proxyImage = this.proxyImage = new Image(); 7812 eventie.bind( proxyImage, 'load', this ); 7813 eventie.bind( proxyImage, 'error', this ); 7814 proxyImage.src = this.img.src; 7815 }; 7816 7817 LoadingImage.prototype.useCached = function( cached ) { 7818 if ( cached.isConfirmed ) { 7819 this.confirm( cached.isLoaded, 'cached was confirmed' ); 7820 } else { 7821 var _this = this; 7822 cached.on( 'confirm', function( image ) { 7823 _this.confirm( image.isLoaded, 'cache emitted confirmed' ); 7824 return true; // bind once 7825 }); 7826 } 7827 }; 7828 7829 LoadingImage.prototype.confirm = function( isLoaded, message ) { 7830 this.isConfirmed = true; 7831 this.isLoaded = isLoaded; 7832 this.emit( 'confirm', this, message ); 7833 }; 7834 7835 // trigger specified handler for event type 7836 LoadingImage.prototype.handleEvent = function( event ) { 7837 var method = 'on' + event.type; 7838 if ( this[ method ] ) { 7839 this[ method ]( event ); 7840 } 7841 }; 7842 7843 LoadingImage.prototype.onload = function() { 7844 this.confirm( true, 'onload' ); 7845 this.unbindProxyEvents(); 7846 }; 7847 7848 LoadingImage.prototype.onerror = function() { 7849 this.confirm( false, 'onerror' ); 7850 this.unbindProxyEvents(); 7851 }; 7852 7853 LoadingImage.prototype.unbindProxyEvents = function() { 7854 eventie.unbind( this.proxyImage, 'load', this ); 7855 eventie.unbind( this.proxyImage, 'error', this ); 7856 }; 7857 7858 // ----- ----- // 7859 7860 return ImagesLoaded; 7861} 7862 7863// -------------------------- transport -------------------------- // 7864 7865if ( typeof define === 'function' && define.amd ) { 7866 // AMD 7867 define( [ 7868 'eventEmitter/EventEmitter', 7869 'eventie/eventie' 7870 ], 7871 defineImagesLoaded ); 7872} else { 7873 // browser global 7874 window.imagesLoaded = defineImagesLoaded( 7875 window.EventEmitter, 7876 window.eventie 7877 ); 7878} 7879 7880})( window ); 7881 7882/*global jQuery */ 7883/*jshint multistr:true browser:true */ 7884/*! 7885* FitVids 1.0 7886* 7887* Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com 7888* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/ 7889* Released under the WTFPL license - http://sam.zoy.org/wtfpl/ 7890* 7891* Date: Thu Sept 01 18:00:00 2011 -0500 7892*/ 7893 7894(function( $ ){ 7895 7896 "use strict"; 7897 7898 $.fn.fitVids = function( options ) { 7899 var settings = { 7900 customSelector: null 7901 }; 7902 7903 if(!document.getElementById('fit-vids-style')) { 7904 7905 var div = document.createElement('div'), 7906 ref = document.getElementsByTagName('base')[0] || document.getElementsByTagName('script')[0], 7907 cssStyles = '­<style>.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}</style>'; 7908 7909 div.className = 'fit-vids-style'; 7910 div.id = 'fit-vids-style'; 7911 div.style.display = 'none'; 7912 div.innerHTML = cssStyles; 7913 7914 ref.parentNode.insertBefore(div,ref); 7915 7916 } 7917 7918 if ( options ) { 7919 $.extend( settings, options ); 7920 } 7921 7922 return this.each(function(){ 7923 var selectors = [ 7924 "iframe[src*='player.vimeo.com']", 7925 "iframe[src*='youtube.com']", 7926 "iframe[src*='youtube-nocookie.com']", 7927 "iframe[src*='kickstarter.com'][src*='video.html']", 7928 "object", 7929 "embed" 7930 ]; 7931 7932 if (settings.customSelector) { 7933 selectors.push(settings.customSelector); 7934 } 7935 7936 var $allVideos = $(this).find(selectors.join(',')); 7937 $allVideos = $allVideos.not("object object"); // SwfObj conflict patch 7938 7939 $allVideos.each(function(){ 7940 var $this = $(this); 7941 if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; } 7942 var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(), 7943 width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(), 7944 aspectRatio = height / width; 7945 if(!$this.attr('id')){ 7946 var videoID = 'fitvid' + Math.floor(Math.random()*999999); 7947 $this.attr('id', videoID); 7948 } 7949 $this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+"%"); 7950 $this.removeAttr('height').removeAttr('width'); 7951 }); 7952 });
7953 }; 7954// Works with either jQuery or Zepto 7955})( window.jQuery || window.Zepto ); 7956 7957/*! http://mths.be/placeholder v2.0.9 by @mathias */ 7958(function(factory) { 7959 if (typeof define === 'function' && define.amd) { 7960 // AMD 7961 define(['jquery'], factory); 7962 } else { 7963 // Browser globals 7964 factory(jQuery); 7965 } 7966}(function($) { 7967 7968 // Opera Mini v7 doesn’t support placeholder although its DOM seems to indicate so 7969 var isOperaMini = Object.prototype.toString.call(window.operamini) == '[object OperaMini]'; 7970 var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini; 7971 var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini; 7972 var valHooks = $.valHooks; 7973 var propHooks = $.propHooks; 7974 var hooks; 7975 var placeholder; 7976 7977 if (isInputSupported && isTextareaSupported) { 7978 7979 placeholder = $.fn.placeholder = function() { 7980 return this; 7981 }; 7982 7983 placeholder.input = placeholder.textarea = true; 7984 7985 } else { 7986 7987 placeholder = $.fn.placeholder = function() { 7988 var $this = this; 7989 $this 7990 .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]') 7991 .not('.placeholder') 7992 .bind({ 7993 'focus.placeholder': clearPlaceholder, 7994 'blur.placeholder': setPlaceholder 7995 }) 7996 .data('placeholder-enabled', true) 7997 .trigger('blur.placeholder'); 7998 return $this; 7999 }; 8000 8001 placeholder.input = isInputSupported; 8002 placeholder.textarea = isTextareaSupported; 8003 8004 hooks = { 8005 'get': function(element) { 8006 var $element = $(element); 8007 8008 var $passwordInput = $element.data('placeholder-password'); 8009 if ($passwordInput) { 8010 return $passwordInput[0].value; 8011 } 8012 8013 return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value; 8014 }, 8015 'set': function(element, value) { 8016 var $element = $(element); 8017 8018 var $passwordInput = $element.data('placeholder-password'); 8019 if ($passwordInput) { 8020 return $passwordInput[0].value = value; 8021 } 8022 8023 if (!$element.data('placeholder-enabled')) { 8024 return element.value = value; 8025 } 8026 if (value === '') { 8027 element.value = value; 8028 // Issue #56: Setting the placeholder causes problems if the element continues to have focus. 8029 if (element != safeActiveElement()) { 8030 // We can't use `triggerHandler` here because of dummy text/password inputs :( 8031 setPlaceholder.call(element); 8032 } 8033 } else if ($element.hasClass('placeholder')) { 8034 clearPlaceholder.call(element, true, value) || (element.value = value); 8035 } else { 8036 element.value = value; 8037 } 8038 // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363 8039 return $element; 8040 } 8041 }; 8042 8043 if (!isInputSupported) { 8044 valHooks.input = hooks; 8045 propHooks.value = hooks; 8046 } 8047 if (!isTextareaSupported) { 8048 valHooks.textarea = hooks; 8049 propHooks.value = hooks; 8050 } 8051 8052 $(function() { 8053 // Look for forms 8054 $(document).delegate('form', 'submit.placeholder', function() { 8055 // Clear the placeholder values so they don't get submitted 8056 var $inputs = $('.placeholder', this).each(clearPlaceholder); 8057 setTimeout(function() { 8058 $inputs.each(setPlaceholder); 8059 }, 10); 8060 }); 8061 }); 8062 8063 // Clear placeholder values upon page reload 8064 $(window).bind('beforeunload.placeholder', function() { 8065 $('.placeholder').each(function() { 8066 this.value = ''; 8067 }); 8068 }); 8069 8070 } 8071 8072 function args(elem) { 8073 // Return an object of element attributes 8074 var newAttrs = {}; 8075 var rinlinejQuery = /^jQuery\d+$/; 8076 $.each(elem.attributes, function(i, attr) { 8077 if (attr.specified && !rinlinejQuery.test(attr.name)) { 8078 newAttrs[attr.name] = attr.value; 8079 } 8080 }); 8081 return newAttrs; 8082 } 8083 8084 function clearPlaceholder(event, value) { 8085 var input = this; 8086 var $input = $(input); 8087 if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) { 8088 if ($input.data('placeholder-password')) { 8089 $input = $input.hide().nextAll('input[type="password"]:first').show().attr('id', $input.removeAttr('id').data('placeholder-id')); 8090 // If `clearPlaceholder` was called from `$.valHooks.input.set` 8091 if (event === true) { 8092 return $input[0].value = value; 8093 } 8094 $input.focus(); 8095 } else { 8096 input.value = ''; 8097 $input.removeClass('placeholder'); 8098 input == safeActiveElement() && input.select(); 8099 } 8100 } 8101 } 8102 8103 function setPlaceholder() { 8104 var $replacement; 8105 var input = this; 8106 var $input = $(input); 8107 var id = this.id; 8108 if (input.value === '') { 8109 if (input.type === 'password') { 8110 if (!$input.data('placeholder-textinput')) { 8111 try { 8112 $replacement = $input.clone().attr({ 'type': 'text' }); 8113 } catch(e) { 8114 $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' })); 8115 } 8116 $replacement 8117 .removeAttr('name') 8118 .data({ 8119 'placeholder-password': $input, 8120 'placeholder-id': id 8121 }) 8122 .bind('focus.placeholder', clearPlaceholder); 8123 $input 8124 .data({ 8125 'placeholder-textinput': $replacement, 8126 'placeholder-id': id 8127 }) 8128 .before($replacement); 8129 } 8130 $input = $input.removeAttr('id').hide().prevAll('input[type="text"]:first').attr('id', id).show(); 8131 // Note: `$input[0] != input` now! 8132 } 8133 $input.addClass('placeholder'); 8134 $input[0].value = $input.attr('placeholder'); 8135 } else { 8136 $input.removeClass('placeholder'); 8137 } 8138 } 8139 8140 function safeActiveElement() { 8141 // Avoid IE9 `document.activeElement` of death 8142 // https://github.com/mathiasbynens/jquery-placeholder/pull/99 8143 try { 8144 return document.activeElement; 8145 } catch (exception) {} 8146 } 8147 8148})); 8149 8150/*! 8151 * jQuery.scrollTo 8152 * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com 8153 * Licensed under MIT 8154 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
8155 * @projectDescription Easy element scrolling using jQuery. 8156 * @author Ariel Flesler 8157 * @version 1.4.14 8158 */ 8159;(function (define) { 8160 'use strict'; 8161 8162 define(['jquery'], function ($) { 8163 8164 var $scrollTo = $.scrollTo = function( target, duration, settings ) { 8165 return $(window).scrollTo( target, duration, settings ); 8166 }; 8167 8168 $scrollTo.defaults = { 8169 axis:'xy', 8170 duration: 0, 8171 limit:true 8172 }; 8173 8174 // Returns the element that needs to be animated to scroll the window. 8175 // Kept for backwards compatibility (specially for localScroll & serialScroll) 8176 $scrollTo.window = function( scope ) { 8177 return $(window)._scrollable(); 8178 }; 8179 8180 // Hack, hack, hack :) 8181 // Returns the real elements to scroll (supports window/iframes, documents and regular nodes) 8182 $.fn._scrollable = function() { 8183 return this.map(function() { 8184 var elem = this, 8185 isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1; 8186 8187 if (!isWin) 8188 return elem; 8189 8190 var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem; 8191 8192 return /webkit/i.test(navigator.userAgent) || doc.compatMode == 'BackCompat' ? 8193 doc.body : 8194 doc.documentElement; 8195 }); 8196 }; 8197 8198 $.fn.scrollTo = function( target, duration, settings ) { 8199 if (typeof duration == 'object') { 8200 settings = duration; 8201 duration = 0; 8202 } 8203 if (typeof settings == 'function') 8204 settings = { onAfter:settings }; 8205 8206 if (target == 'max') 8207 target = 9e9; 8208 8209 settings = $.extend( {}, $scrollTo.defaults, settings ); 8210 // Speed is still recognized for backwards compatibility 8211 duration = duration || settings.duration; 8212 // Make sure the settings are given right 8213 settings.queue = settings.queue && settings.axis.length > 1; 8214 8215 if (settings.queue) 8216 // Let's keep the overall duration 8217 duration /= 2; 8218 settings.offset = both( settings.offset ); 8219 settings.over = both( settings.over ); 8220 8221 return this._scrollable().each(function() { 8222 // Null target yields nothing, just like jQuery does 8223 if (target == null) return; 8224 8225 var elem = this, 8226 $elem = $(elem), 8227 targ = target, toff, attr = {}, 8228 win = $elem.is('html,body'); 8229 8230 switch (typeof targ) { 8231 // A number will pass the regex 8232 case 'number': 8233 case 'string': 8234 if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) { 8235 targ = both( targ ); 8236 // We are done 8237 break; 8238 } 8239 // Relative/Absolute selector, no break! 8240 targ = win ? $(targ) : $(targ, this); 8241 if (!targ.length) return; 8242 case 'object': 8243 // DOMElement / jQuery 8244 if (targ.is || targ.style) 8245 // Get the real position of the target 8246 toff = (targ = $(targ)).offset(); 8247 } 8248 8249 var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset; 8250 8251 $.each( settings.axis.split(''), function( i, axis ) { 8252 var Pos = axis == 'x' ? 'Left' : 'Top', 8253 pos = Pos.toLowerCase(), 8254 key = 'scroll' + Pos, 8255 old = elem[key], 8256 max = $scrollTo.max(elem, axis); 8257 8258 if (toff) {// jQuery / DOMElement 8259 attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] ); 8260 8261 // If it's a dom element, reduce the margin 8262 if (settings.margin) { 8263 attr[key] -= parseInt(targ.css('margin'+Pos)) || 0; 8264 attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0; 8265 } 8266 8267 attr[key] += offset[pos] || 0; 8268 8269 if(settings.over[pos]) 8270 // Scroll to a fraction of its width/height 8271 attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos]; 8272 } else { 8273 var val = targ[pos]; 8274 // Handle percentage values 8275 attr[key] = val.slice && val.slice(-1) == '%' ? 8276 parseFloat(val) / 100 * max 8277 : val; 8278 } 8279 8280 // Number or 'number' 8281 if (settings.limit && /^\d+$/.test(attr[key])) 8282 // Check the limits 8283 attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max ); 8284 8285 // Queueing axes 8286 if (!i && settings.queue) { 8287 // Don't waste time animating, if there's no need. 8288 if (old != attr[key]) 8289 // Intermediate animation 8290 animate( settings.onAfterFirst ); 8291 // Don't animate this axis again in the next iteration. 8292 delete attr[key]; 8293 } 8294 }); 8295 8296 animate( settings.onAfter ); 8297 8298 function animate( callback ) { 8299 $elem.animate( attr, duration, settings.easing, callback && function() { 8300 callback.call(this, targ, settings); 8301 });
8302 } 8303 }).end(); 8304 }; 8305 8306 // Max scrolling position, works on quirks mode 8307 // It only fails (not too badly) on IE, quirks mode. 8308 $scrollTo.max = function( elem, axis ) { 8309 var Dim = axis == 'x' ? 'Width' : 'Height', 8310 scroll = 'scroll'+Dim; 8311 8312 if (!$(elem).is('html,body')) 8313 return elem[scroll] - $(elem)[Dim.toLowerCase()](); 8314 8315 var size = 'client' + Dim, 8316 html = elem.ownerDocument.documentElement, 8317 body = elem.ownerDocument.body; 8318 8319 return Math.max( html[scroll], body[scroll] ) - Math.min( html[size] , body[size] ); 8320 }; 8321 8322 function both( val ) { 8323 return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val }; 8324 } 8325 8326 // AMD requirement 8327 return $scrollTo; 8328 }) 8329}(typeof define === 'function' && define.amd ? define : function (deps, factory) { 8330 if (typeof module !== 'undefined' && module.exports) { 8331 // Node 8332 module.exports = factory(require('jquery')); 8333 } else { 8334 factory(jQuery); 8335 } 8336})); 8337 8338/*global jQuery: true */ 8339 8340/*! 8341 -------------------------------- 8342 Infinite Scroll 8343 -------------------------------- 8344 + https://github.com/paulirish/infinite-scroll 8345 + version 2.1.0 8346 + Copyright 2011/12 Paul Irish & Luke Shumard 8347 + Licensed under the MIT license 8348 8349 + Documentation: http://infinite-scroll.com/ 8350*/ 8351 8352// Uses AMD or browser globals to create a jQuery plugin. 8353(function (factory) { 8354 if (typeof define === 'function' && define.amd) { 8355 // AMD. Register as an anonymous module. 8356 define(['jquery'], factory); 8357 } else { 8358 // Browser globals 8359 factory(jQuery); 8360 } 8361}(function ($, undefined) { 8362 'use strict'; 8363 8364 $.infinitescroll = function infscr(options, callback, element) { 8365 this.element = $(element); 8366 8367 // Flag the object in the event of a failed creation 8368 if (!this._create(options, callback)) { 8369 this.failed = true; 8370 } 8371 }; 8372 8373 $.infinitescroll.defaults = { 8374 loading: { 8375 finished: undefined, 8376 finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>", 8377 img: 'data:image/gif;base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oX
8377HlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSHMzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2G
8377iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7', 8378 msg: null, 8379 msgText: '<em>Loading the next set of posts...</em>', 8380 selector: null, 8381 speed: 'fast', 8382 start: undefined 8383 }, 8384 state: { 8385 isDuringAjax: false, 8386 isInvalidPage: false,
8387 isDestroyed: false, 8388 isDone: false, // For when it goes all the way through the archive. 8389 isPaused: false, 8390 isBeyondMaxPage: false, 8391 currPage: 1 8392 }, 8393 debug: false, 8394 behavior: undefined, 8395 binder: $(window), // used to cache the selector 8396 nextSelector: 'div.navigation a:first', 8397 navSelector: 'div.navigation', 8398 contentSelector: null, // rename to pageFragment 8399 extraScrollPx: 150, 8400 itemSelector: 'div.post', 8401 animate: false, 8402 pathParse: undefined, 8403 dataType: 'html', 8404 appendCallback: true, 8405 bufferPx: 40, 8406 errorCallback: function () { }, 8407 infid: 0, //Instance ID 8408 pixelsFromNavToBottom: undefined, 8409 path: undefined, // Either parts of a URL as an array (e.g. ["/page/", "/"] or a function that takes in the page number and returns a URL 8410 prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted 8411 maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work) 8412 }; 8413 8414 $.infinitescroll.prototype = { 8415 8416 /* 8417 ---------------------------- 8418 Private methods 8419 ---------------------------- 8420 */ 8421 8422 // Bind or unbind from scroll 8423 _binding: function infscr_binding(binding) { 8424 8425 var instance = this, 8426 opts = instance.options; 8427 8428 opts.v = '2.0b2.120520'; 8429 8430 // if behavior is defined and this function is extended, call that instead of default 8431 if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) { 8432 this['_binding_'+opts.behavior].call(this); 8433 return; 8434 } 8435 8436 if (binding !== 'bind' && binding !== 'unbind') { 8437 this._debug('Binding value ' + binding + ' not valid'); 8438 return false; 8439 } 8440 8441 if (binding === 'unbind') { 8442 (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid); 8443 } else { 8444 (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () { 8445 instance.scroll(); 8446 }); 8447 } 8448 8449 this._debug('Binding', binding); 8450 }, 8451 8452 // Fundamental aspects of the plugin are initialized 8453 _create: function infscr_create(options, callback) { 8454 8455 // Add custom options to defaults 8456 var opts = $.extend(true, {}, $.infinitescroll.defaults, options); 8457 this.options = opts; 8458 var $window = $(window); 8459 var instance = this; 8460 8461 // Validate selectors 8462 if (!instance._validate(options)) { 8463 return false; 8464 } 8465 8466 // Validate page fragment path 8467 var path = $(opts.nextSelector).attr('href'); 8468 if (!path) { 8469 this._debug('Navigation selector not found'); 8470 return false; 8471 } 8472 8473 // Set the path to be a relative URL from root. 8474 opts.path = opts.path || this._determinepath(path); 8475 8476 // contentSelector is 'page fragment' option for .load() / .ajax() calls 8477 opts.contentSelector = opts.contentSelector || this.element; 8478 8479 // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector 8480 opts.loading.selector = opts.loading.selector || opts.contentSelector; 8481 8482 // Define loading.msg 8483 opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>'); 8484 8485 // Preload loading.img 8486 (new Image()).src = opts.loading.img; 8487 8488 // distance from nav links to bottom 8489 // computed as: height of the document + top offset of container - top offset of nav link 8490 if(opts.pixelsFromNavToBottom === undefined) { 8491 opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top; 8492 this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom); 8493 } 8494 8495 var self = this; 8496 8497 // determine loading.start actions 8498 opts.loading.start = opts.loading.start || function() { 8499 $(opts.navSelector).hide(); 8500 opts.loading.msg 8501 .appendTo(opts.loading.selector) 8502 .show(opts.loading.speed, $.proxy(function() { 8503 this.beginAjax(opts); 8504 }, self));
8505 }; 8506 8507 // determine loading.finished actions 8508 opts.loading.finished = opts.loading.finished || function() { 8509 if (!opts.state.isBeyondMaxPage) 8510 opts.loading.msg.fadeOut(opts.loading.speed); 8511 }; 8512 8513 // callback loading 8514 opts.callback = function(instance, data, url) { 8515 if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) { 8516 instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url); 8517 } 8518 8519 if (callback) { 8520 callback.call($(opts.contentSelector)[0], data, opts, url); 8521 } 8522 8523 if (opts.prefill) { 8524 $window.bind('resize.infinite-scroll', instance._prefill); 8525 } 8526 }; 8527 8528 if (options.debug) { 8529 // Tell IE9 to use its built-in console 8530 if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') { 8531 ['log','info','warn','error','assert','dir','clear','profile','profileEnd'] 8532 .forEach(function (method) { 8533 console[method] = this.call(console[method], console); 8534 }, Function.prototype.bind); 8535 } 8536 } 8537 8538 this._setup(); 8539 8540 // Setups the prefill method for use 8541 if (opts.prefill) { 8542 this._prefill(); 8543 } 8544 8545 // Return true to indicate successful creation 8546 return true; 8547 }, 8548 8549 _prefill: function infscr_prefill() { 8550 var instance = this; 8551 var $window = $(window); 8552 8553 function needsPrefill() { 8554 return ( $(instance.options.contentSelector).height() <= $window.height() ); 8555 } 8556 8557 this._prefill = function() { 8558 if (needsPrefill()) { 8559 instance.scroll(); 8560 } 8561 8562 $window.bind('resize.infinite-scroll', function() { 8563 if (needsPrefill()) { 8564 $window.unbind('resize.infinite-scroll'); 8565 instance.scroll(); 8566 } 8567 }); 8568 }; 8569 8570 // Call self after setting up the new function 8571 this._prefill(); 8572 }, 8573 8574 // Console log wrapper 8575 _debug: function infscr_debug() { 8576 if (true !== this.options.debug) { 8577 return; 8578 } 8579 8580 if (typeof console !== 'undefined' && typeof console.log === 'function') { 8581 // Modern browsers 8582 // Single argument, which is a string 8583 if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') { 8584 console.log( (Array.prototype.slice.call(arguments)).toString() ); 8585 } else { 8586 console.log( Array.prototype.slice.call(arguments) ); 8587 } 8588 } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') { 8589 // IE8 8590 Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments)); 8591 } 8592 }, 8593 8594 // find the number to increment in the path. 8595 _determinepath: function infscr_determinepath(path) { 8596 8597 var opts = this.options; 8598 8599 // if behavior is defined and this function is extended, call that instead of default 8600 if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) { 8601 return this['_determinepath_'+opts.behavior].call(this,path); 8602 } 8603 8604 if (!!opts.pathParse) { 8605 8606 this._debug('pathParse manual'); 8607 return opts.pathParse(path, this.options.state.currPage+1); 8608 8609 } else if (path.match(/^(.*?)\b2\b(.*?$)/)) { 8610 path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 8611 8612 // if there is any 2 in the url at all. 8613 } else if (path.match(/^(.*?)2(.*?$)/)) { 8614 8615 // page= is used in django: 8616 // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127 8617 if (path.match(/^(.*?page=)2(\/.*|$)/)) { 8618 path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 8619 return path; 8620 } 8621 8622 path = path.match(/^(.*?)2(.*?$)/).slice(1); 8623 8624 } else { 8625 8626 // page= is used in drupal too but second page is page=1 not page=2: 8627 // thx Jerod Fritz, vladikoff 8628 if (path.match(/^(.*?page=)1(\/.*|$)/)) { 8629 path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 8630 return path; 8631 } else { 8632 this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com."); 8633 // Get rid of isInvalidPage to allow permalink to state 8634 opts.state.isInvalidPage = true; //prevent it from running on this page. 8635 } 8636 } 8637 this._debug('determinePath', path); 8638 return path; 8639 8640 }, 8641 8642 // Custom error 8643 _error: function infscr_error(xhr) { 8644 8645 var opts = this.options; 8646 8647 // if behavior is defined and this function is extended, call that instead of default 8648 if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) { 8649 this['_error_'+opts.behavior].call(this,xhr); 8650 return; 8651 } 8652 8653 if (xhr !== 'destroy' && xhr !== 'end') { 8654 xhr = 'unknown'; 8655 } 8656 8657 this._debug('Error', xhr); 8658 8659 if (xhr === 'end' || opts.state.isBeyondMaxPage) { 8660 this._showdonemsg(); 8661 } 8662 8663 opts.state.isDone = true; 8664 opts.state.currPage = 1; // if you need to go back to this instance
8665 opts.state.isPaused = false; 8666 opts.state.isBeyondMaxPage = false; 8667 this._binding('unbind'); 8668 8669 }, 8670 8671 // Load Callback 8672 _loadcallback: function infscr_loadcallback(box, data, url) { 8673 var opts = this.options, 8674 callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK 8675 result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append', 8676 frag; 8677 8678 // if behavior is defined and this function is extended, call that instead of default 8679 if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) { 8680 this['_loadcallback_'+opts.behavior].call(this,box,data); 8681 return; 8682 } 8683 8684 switch (result) { 8685 case 'done': 8686 this._showdonemsg(); 8687 return false; 8688 8689 case 'no-append': 8690 if (opts.dataType === 'html') { 8691 data = '<div>' + data + '</div>'; 8692 data = $(data).find(opts.itemSelector); 8693 } 8694 8695 // if it didn't return anything 8696 if (data.length === 0) { 8697 return this._error('end'); 8698 } 8699 8700 break; 8701 8702 case 'append': 8703 var children = box.children(); 8704 // if it didn't return anything 8705 if (children.length === 0) { 8706 return this._error('end'); 8707 } 8708 8709 // use a documentFragment because it works when content is going into a table or UL 8710 frag = document.createDocumentFragment(); 8711 while (box[0].firstChild) { 8712 frag.appendChild(box[0].firstChild); 8713 } 8714 8715 this._debug('contentSelector', $(opts.contentSelector)[0]); 8716 $(opts.contentSelector)[0].appendChild(frag); 8717 // previously, we would pass in the new DOM element as context for the callback 8718 // however we're now using a documentfragment, which doesn't have parents or children, 8719 // so the context is the contentContainer guy, and we pass in an array 8720 // of the elements collected as the first argument. 8721 8722 data = children.get(); 8723 break; 8724 } 8725 8726 // loadingEnd function 8727 opts.loading.finished.call($(opts.contentSelector)[0],opts); 8728 8729 // smooth scroll to ease in the new content 8730 if (opts.animate) { 8731 var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px'; 8732 $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; }); 8733 } 8734 8735 if (!opts.animate) { 8736 // once the call is done, we can allow it again. 8737 opts.state.isDuringAjax = false; 8738 } 8739 8740 callback(this, data, url); 8741 8742 if (opts.prefill) { 8743 this._prefill(); 8744 } 8745 }, 8746 8747 _nearbottom: function infscr_nearbottom() { 8748 8749 var opts = this.options, 8750 pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height(); 8751 8752 // if behavior is defined and this function is extended, call that instead of default 8753 if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) { 8754 return this['_nearbottom_'+opts.behavior].call(this); 8755 } 8756 8757 this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom); 8758 8759 // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom.... 8760 return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom); 8761 8762 }, 8763 8764 // Pause / temporarily disable plugin from firing 8765 _pausing: function infscr_pausing(pause) { 8766 8767 var opts = this.options; 8768 8769 // if behavior is defined and this function is extended, call that instead of default 8770 if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) { 8771 this['_pausing_'+opts.behavior].call(this,pause); 8772 return; 8773 } 8774 8775 // If pause is not 'pause' or 'resume', toggle it's value 8776 if (pause !== 'pause' && pause !== 'resume' && pause !== null) { 8777 this._debug('Invalid argument. Toggling pause value instead'); 8778 } 8779 8780 pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle'; 8781 8782 switch (pause) { 8783 case 'pause':
8784 opts.state.isPaused = true; 8785 break; 8786 8787 case 'resume': 8788 opts.state.isPaused = false; 8789 break; 8790 8791 case 'toggle': 8792 opts.state.isPaused = !opts.state.isPaused; 8793 break; 8794 } 8795 8796 this._debug('Paused', opts.state.isPaused); 8797 return false; 8798 8799 }, 8800 8801 // Behavior is determined 8802 // If the behavior option is undefined, it will set to default and bind to scroll 8803 _setup: function infscr_setup() { 8804 8805 var opts = this.options; 8806 8807 // if behavior is defined and this function is extended, call that instead of default 8808 if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) { 8809 this['_setup_'+opts.behavior].call(this); 8810 return; 8811 } 8812 8813 this._binding('bind'); 8814 8815 return false; 8816 8817 }, 8818 8819 // Show done message 8820 _showdonemsg: function infscr_showdonemsg() { 8821 8822 var opts = this.options; 8823 8824 // if behavior is defined and this function is extended, call that instead of default 8825 if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) { 8826 this['_showdonemsg_'+opts.behavior].call(this); 8827 return; 8828 } 8829 8830 opts.loading.msg 8831 .find('img') 8832 .hide() 8833 .parent() 8834 .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () { 8835 $(this).parent().fadeOut(opts.loading.speed); 8836 }); 8837 8838 // user provided callback when done 8839 opts.errorCallback.call($(opts.contentSelector)[0],'done'); 8840 }, 8841 8842 // grab each selector option and see if any fail 8843 _validate: function infscr_validate(opts) { 8844 for (var key in opts) { 8845 if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) { 8846 this._debug('Your ' + key + ' found no elements.'); 8847 return false; 8848 } 8849 } 8850 8851 return true; 8852 }, 8853 8854 /* 8855 ---------------------------- 8856 Public methods 8857 ---------------------------- 8858 */ 8859 8860 // Bind to scroll 8861 bind: function infscr_bind() { 8862 this._binding('bind'); 8863 }, 8864 8865 // Destroy current instance of plugin 8866 destroy: function infscr_destroy() { 8867 this.options.state.isDestroyed = true; 8868 this.options.loading.finished(); 8869 return this._error('destroy'); 8870 }, 8871 8872 // Set pause value to false 8873 pause: function infscr_pause() { 8874 this._pausing('pause'); 8875 }, 8876 8877 // Set pause value to false 8878 resume: function infscr_resume() { 8879 this._pausing('resume'); 8880 }, 8881 8882 beginAjax: function infscr_ajax(opts) { 8883 var instance = this, 8884 path = opts.path, 8885 box, desturl, method, condition; 8886 8887 // increment the URL bit. e.g. /page/3/ 8888 opts.state.currPage++; 8889 8890 // Manually control maximum page 8891 if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){ 8892 opts.state.isBeyondMaxPage = true; 8893 this.destroy(); 8894 return; 8895 } 8896 8897 // if we're dealing with a table we can't use DIVs 8898 box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>'); 8899 8900 desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage); 8901 instance._debug('heading into ajax', desturl); 8902 8903 method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback'; 8904 if (opts.appendCallback && opts.dataType === 'html') { 8905 method += '+callback'; 8906 } 8907 8908 switch (method) { 8909 case 'html+callback': 8910 instance._debug('Using HTML via .load() method'); 8911 box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) { 8912 instance._loadcallback(box, responseText, desturl); 8913 }); 8914 8915 break; 8916 8917 case 'html': 8918 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 8919 $.ajax({
8920 // params 8921 url: desturl, 8922 dataType: opts.dataType, 8923 complete: function infscr_ajax_callback(jqXHR, textStatus) { 8924 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 8925 if (condition) { 8926 instance._loadcallback(box, jqXHR.responseText, desturl); 8927 } else { 8928 instance._error('end'); 8929 } 8930 } 8931 }); 8932 8933 break; 8934 case 'json': 8935 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 8936 $.ajax({ 8937 dataType: 'json', 8938 type: 'GET', 8939 url: desturl, 8940 success: function (data, textStatus, jqXHR) { 8941 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 8942 if (opts.appendCallback) { 8943 // if appendCallback is true, you must defined template in options. 8944 // note that data passed into _loadcallback is already an html (after processed in opts.template(data)). 8945 if (opts.template !== undefined) { 8946 var theData = opts.template(data); 8947 box.append(theData); 8948 if (condition) { 8949 instance._loadcallback(box, theData); 8950 } else { 8951 instance._error('end'); 8952 } 8953 } else { 8954 instance._debug('template must be defined.'); 8955 instance._error('end'); 8956 } 8957 } else { 8958 // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback. 8959 if (condition) { 8960 instance._loadcallback(box, data, desturl); 8961 } else { 8962 instance._error('end'); 8963 } 8964 } 8965 }, 8966 error: function() { 8967 instance._debug('JSON ajax request failed.'); 8968 instance._error('end'); 8969 } 8970 }); 8971 8972 break; 8973 } 8974 }, 8975 8976 // Retrieve next set of content items 8977 retrieve: function infscr_retrieve(pageNum) { 8978 pageNum = pageNum || null; 8979 8980 var instance = this, 8981 opts = instance.options; 8982 8983 // if behavior is defined and this function is extended, call that instead of default 8984 if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) { 8985 this['retrieve_'+opts.behavior].call(this,pageNum); 8986 return; 8987 } 8988 8989 // for manual triggers, if destroyed, get out of here 8990 if (opts.state.isDestroyed) { 8991 this._debug('Instance is destroyed'); 8992 return false; 8993 } 8994 8995 // we dont want to fire the ajax multiple times 8996 opts.state.isDuringAjax = true; 8997 8998 opts.loading.start.call($(opts.contentSelector)[0],opts); 8999 }, 9000 9001 // Check to see next page is needed 9002 scroll: function infscr_scroll() { 9003 9004 var opts = this.options, 9005 state = opts.state; 9006 9007 // if behavior is defined and this function is extended, call that instead of default 9008 if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) { 9009 this['scroll_'+opts.behavior].call(this); 9010 return; 9011 } 9012 9013 if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPau
9013sed) { 9014 return; 9015 } 9016 9017 if (!this._nearbottom()) { 9018 return; 9019 } 9020 9021 this.retrieve(); 9022 9023 }, 9024 9025 // Toggle pause value 9026 toggle: function infscr_toggle() { 9027 this._pausing(); 9028 }, 9029 9030 // Unbind from scroll 9031 unbind: function infscr_unbind() { 9032 this._binding('unbind'); 9033 }, 9034 9035 // update options 9036 update: function infscr_options(key) { 9037 if ($.isPlainObject(key)) { 9038 this.options = $.extend(true,this.options,key); 9039 } 9040 } 9041 }; 9042 9043 9044 /* 9045 ---------------------------- 9046 Infinite Scroll function 9047 ---------------------------- 9048 9049 Borrowed logic from the following... 9050 9051 jQuery UI 9052 - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js 9053 9054 jCarousel 9055 - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js 9056 9057 Masonry 9058 - https://github.com/desandro/masonry/blob/master/jquery.masonry.js 9059 9060*/ 9061 9062 $.fn.infinitescroll = function infscr_init(options, callback) { 9063 9064 9065 var thisCall = typeof options; 9066 9067 switch (thisCall) { 9068 9069 // method 9070 case 'string': 9071 var args = Array.prototype.slice.call(arguments, 1); 9072 9073 this.each(function () { 9074 var instance = $.data(this, 'infinitescroll'); 9075 9076 if (!instance) { 9077 // not setup yet 9078 // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup'); 9079 return false; 9080 } 9081 9082 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') { 9083 // return $.error('No such method ' + options + ' for Infinite Scroll'); 9084 return false; 9085 } 9086 9087 // no errors! 9088 instance[options].apply(instance, args); 9089 }); 9090 9091 break; 9092 9093 // creation 9094 case 'object': 9095 9096 this.each(function () { 9097 9098 var instance = $.data(this, 'infinitescroll'); 9099 9100 if (instance) { 9101 9102 // update options of current instance 9103 instance.update(options); 9104 9105 } else { 9106 9107 // initialize new instance 9108 instance = new $.infinitescroll(options, callback, this); 9109 9110 // don't attach if instantiation failed 9111 if (!instance.failed) { 9112 $.data(this, 'infinitescroll', instance); 9113 } 9114 9115 } 9116 9117 }); 9118 9119 break; 9120 9121 } 9122 9123 return this; 9124 }; 9125 9126 9127 9128 /* 9129 * smartscroll: debounced scroll event for jQuery * 9130 * https://github.com/lukeshumard/smartscroll 9131 * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js * 9132 * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. * 9133 */ 9134 9135 var event = $.event, 9136 scrollTimeout; 9137 9138 event.special.smartscroll = { 9139 setup: function () { 9140 $(this).bind('scroll', event.special.smartscroll.handler); 9141 }, 9142 teardown: function () { 9143 $(this).unbind('scroll', event.special.smartscroll.handler); 9144 }, 9145 handler: function (event, execAsap) { 9146 // Save the context 9147 var context = this, 9148 args = arguments; 9149 9150 // set correct event type 9151 event.type = 'smartscroll'; 9152 9153 if (scrollTimeout) { clearTimeout(scrollTimeout); } 9154 scrollTimeout = setTimeout(function () { 9155 $(context).trigger('smartscroll', args); 9156 }, execAsap === 'execAsap' ? 0 : 100); 9157 } 9158 }; 9159 9160 $.fn.smartscroll = function (fn) {
vendor: 4,950 bytes, lines 9161-9282
9161 return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']); 9162 }; 9163 9164})); 9165 9166/*! 9167 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/) 9168 * Copyright (c) 2014 Edson Hilios 9169 * 9170 * Permission is hereby granted, free of charge, to any person obtaining a copy of 9171 * this software and associated documentation files (the "Software"), to deal in 9172 * the Software without restriction, including without limitation the rights to 9173 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9174 * the Software, and to permit persons to whom the Software is furnished to do so, 9175 * subject to the following conditions: 9176 * 9177 * The above copyright notice and this permission notice shall be included in all 9178 * copies or substantial portions of the Software. 9179 * 9180 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 9181 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 9182 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 9183 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 9184 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 9185 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9186 */ 9187(function(factory) { 9188 "use strict"; 9189 if (typeof define === "function" && define.amd) { 9190 define([ "jquery" ], factory); 9191 } else { 9192 factory(jQuery); 9193 } 9194})(function($) { 9195 "use strict"; 9196 var PRECISION = 100; 9197 var instances = [], matchers = []; 9198 matchers.push(/^[0-9]*$/.source); 9199 matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 9200 matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 9201 matchers = new RegExp(matchers.join("|")); 9202 function parseDateString(dateString) { 9203 if (dateString instanceof Date) { 9204 return dateString; 9205 } 9206 if (String(dateString).match(matchers)) { 9207 if (String(dateString).match(/^[0-9]*$/)) { 9208 dateString = Number(dateString); 9209 } 9210 if (String(dateString).match(/\-/)) { 9211 dateString = String(dateString).replace(/\-/g, "/"); 9212 } 9213 return new Date(dateString); 9214 } else { 9215 throw new Error("Couldn't cast `" + dateString + "` to a date object."); 9216 } 9217 } 9218 var DIRECTIVE_KEY_MAP = { 9219 Y: "years", 9220 m: "months", 9221 w: "weeks", 9222 d: "days", 9223 D: "totalDays", 9224 H: "hours", 9225 M: "minutes", 9226 S: "seconds" 9227 }; 9228 function strftime(offsetObject) { 9229 return function(format) { 9230 var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi); 9231 if (directives) { 9232 for (var i = 0, len = directives.length; i < len; ++i) { 9233 var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = new RegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null; 9234 directive = directive[2]; 9235 if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) { 9236 value = DIRECTIVE_KEY_MAP[directive]; 9237 value = Number(offsetObject[value]); 9238 } 9239 if (value !== null) { 9240 if (modifier === "!") { 9241 value = pluralize(plural, value); 9242 } 9243 if (modifier === "") { 9244 if (value < 10) { 9245 value = "0" + value.toString(); 9246 } 9247 } 9248 format = format.replace(regexp, value.toString()); 9249 } 9250 } 9251 } 9252 format = format.replace(/%%/, "%"); 9253 return format; 9254 }; 9255 } 9256 function pluralize(format, count) { 9257 var plural = "s", singular = ""; 9258 if (format) { 9259 format = format.replace(/(:|;|\s)/gi, "").split(/\,/); 9260 if (format.length === 1) { 9261 plural = format[0]; 9262 } else { 9263 singular = format[0]; 9264 plural = format[1]; 9265 } 9266 } 9267 if (Math.abs(count) === 1) { 9268 return singular; 9269 } else { 9270 return plural; 9271 } 9272 } 9273 var Countdown = function(el, finalDate, callback) { 9274 this.el = el; 9275 this.$el = $(el); 9276 this.interval = null; 9277 this.offset = {}; 9278 this.instanceNumber = instances.length; 9279 instances.push(this); 9280 this.$el.data("countdown-instance", this.instanceNumber); 9281 if (callback) { 9282 this.$el.on("update.countdown", callback);
9283 this.$el.on("stoped.countdown", callback); 9284 this.$el.on("finish.countdown", callback); 9285 } 9286 this.setFinalDate(finalDate); 9287 this.start(); 9288 }; 9289 $.extend(Countdown.prototype, { 9290 start: function() { 9291 if (this.interval !== null) { 9292 clearInterval(this.interval); 9293 } 9294 var self = this; 9295 this.update(); 9296 this.interval = setInterval(function() { 9297 self.update.call(self); 9298 }, PRECISION); 9299 }, 9300 stop: function() { 9301 clearInterval(this.interval); 9302 this.interval = null; 9303 this.dispatchEvent("stoped"); 9304 }, 9305 pause: function() { 9306 this.stop.call(this); 9307 }, 9308 resume: function() { 9309 this.start.call(this); 9310 }, 9311 remove: function() { 9312 this.stop(); 9313 instances[this.instanceNumber] = null; 9314 delete this.$el.data().countdownInstance; 9315 }, 9316 setFinalDate: function(value) { 9317 this.finalDate = parseDateString(value); 9318 }, 9319 update: function() { 9320 if (this.$el.closest("html").length === 0) { 9321 this.remove(); 9322 return; 9323 } 9324 this.totalSecsLeft = this.finalDate.getTime() - new Date().getTime(); 9325 this.totalSecsLeft = Math.ceil(this.totalSecsLeft / 1e3); 9326 this.totalSecsLeft = this.totalSecsLeft < 0 ? 0 : this.totalSecsLeft; 9327 this.offset = { 9328 seconds: this.totalSecsLeft % 60, 9329 minutes: Math.floor(this.totalSecsLeft / 60) % 60, 9330 hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24, 9331 days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 9332 totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24), 9333 weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7), 9334 months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30), 9335 years: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 365) 9336 }; 9337 if (this.totalSecsLeft === 0) { 9338 this.stop(); 9339 this.dispatchEvent("finish"); 9340 } else { 9341 this.dispatchEvent("update"); 9342 } 9343 }, 9344 dispatchEvent: function(eventName) { 9345 var event = $.Event(eventName + ".countdown"); 9346 event.finalDate = this.finalDate; 9347 event.offset = $.extend({}, this.offset); 9348 event.strftime = strftime(this.offset); 9349 this.$el.trigger(event); 9350 } 9351 }); 9352 $.fn.countdown = function() { 9353 var argumentsArray = Array.prototype.slice.call(arguments, 0); 9354 return this.each(function() { 9355 var instanceNumber = $(this).data("countdown-instance"); 9356 if (instanceNumber !== undefined) { 9357 var instance = instances[instanceNumber], method = argumentsArray[0]; 9358 if (Countdown.prototype.hasOwnProperty(method)) { 9359 instance[method].apply(instance, argumentsArray.slice(1)); 9360 } else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) { 9361 instance.setFinalDate.call(instance, method); 9362 instance.start(); 9363 } else { 9364 $.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method)); 9365 } 9366 } else { 9367 new Countdown(this, argumentsArray[0], argumentsArray[1]); 9368 } 9369 }); 9370 }; 9371}); 9372/* 9373 * jQuery FlexSlider v2.5.0 9374 * Copyright 2012 WooThemes 9375 * Contributing Author: Tyler Smith 9376 */ 9377; 9378(function ($) { 9379 9380 //FlexSlider: Object Instance 9381 $.flexslider = function(el, options) { 9382 var slider = $(el); 9383 9384 // making variables public 9385 slider.vars = $.extend({}, $.flexslider.defaults, options); 9386 9387 var namespace = slider.vars.namespace, 9388 msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture, 9389 touch = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch, 9390 // depricating this idea, as devices are being released with both of these events 9391 //eventType = (touch) ? "touchend" : "click", 9392 eventType = "click touchend MSPointerUp keyup", 9393 watchedEvent = "", 9394 watchedEventClearTimer, 9395 vertical = slider.vars.direction === "vertical", 9396 reverse = slider.vars.reverse, 9397 carousel = (slider.vars.itemWidth > 0), 9398 fade = slider.vars.animation === "fade", 9399 asNav = slider.vars.asNavFor !== "", 9400 methods = {}, 9401 focused = true; 9402 9403 // Store a reference to the slider object 9404 $.data(el, "flexslider", slider); 9405 9406 // Private slider methods 9407 methods = { 9408 init: function() { 9409 slider.animating = false; 9410 // Get current slide and make sure it is a number 9411 slider.currentSlide = parseInt( ( slider.vars.startAt ? slider.vars.startAt : 0), 10 ); 9412 if ( isNaN( slider.currentSlide ) ) { slider.currentSlide = 0; } 9413 slider.animatingTo = slider.currentSlide; 9414 slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last); 9415 slider.containerSelector = slider.vars.selector.substr(0,slider.vars.selector.search(' '));
vendor: 49,968 bytes, lines 9416-10501
9416 slider.slides = $(slider.vars.selector, slider); 9417 slider.container = $(slider.containerSelector, slider); 9418 slider.count = slider.slides.length; 9419 // SYNC: 9420 slider.syncExists = $(slider.vars.sync).length > 0; 9421 // SLIDE: 9422 if (slider.vars.animation === "slide") { slider.vars.animation = "swing"; } 9423 slider.prop = (vertical) ? "top" : "marginLeft"; 9424 slider.args = {}; 9425 // SLIDESHOW: 9426 slider.manualPause = false; 9427 slider.stopped = false; 9428 //PAUSE WHEN INVISIBLE 9429 slider.started = false; 9430 slider.startTimeout = null; 9431 // TOUCH/USECSS: 9432 slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() { 9433 var obj = document.createElement('div'), 9434 props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']; 9435 for (var i in props) { 9436 if ( obj.style[ props[i] ] !== undefined ) { 9437 slider.pfx = props[i].replace('Perspective','').toLowerCase(); 9438 slider.prop = "-" + slider.pfx + "-transform"; 9439 return true; 9440 } 9441 } 9442 return false; 9443 }()); 9444 slider.ensureAnimationEnd = ''; 9445 // CONTROLSCONTAINER: 9446 if (slider.vars.controlsContainer !== "") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer); 9447 // MANUAL: 9448 if (slider.vars.manualControls !== "") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls); 9449 9450 // CUSTOM DIRECTION NAV: 9451 if (slider.vars.customDirectionNav !== "") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav); 9452 9453 // RANDOMIZE: 9454 if (slider.vars.randomize) { 9455 slider.slides.sort(function() { return (Math.round(Math.random())-0.5); }); 9456 slider.container.empty().append(slider.slides); 9457 } 9458 9459 slider.doMath(); 9460 9461 // INIT 9462 slider.setup("init"); 9463 9464 // CONTROLNAV: 9465 if (slider.vars.controlNav) { methods.controlNav.setup(); } 9466 9467 // DIRECTIONNAV: 9468 if (slider.vars.directionNav) { methods.directionNav.setup(); } 9469 9470 // KEYBOARD: 9471 if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) { 9472 $(document).bind('keyup', function(event) { 9473 var keycode = event.keyCode; 9474 if (!slider.animating && (keycode === 39 || keycode === 37)) { 9475 var target = (keycode === 39) ? slider.getTarget('next') : 9476 (keycode === 37) ? slider.getTarget('prev') : false; 9477 slider.flexAnimate(target, slider.vars.pauseOnAction); 9478 } 9479 }); 9480 } 9481 // MOUSEWHEEL: 9482 if (slider.vars.mousewheel) { 9483 slider.bind('mousewheel', function(event, delta, deltaX, deltaY) { 9484 event.preventDefault(); 9485 var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev'); 9486 slider.flexAnimate(target, slider.vars.pauseOnAction); 9487 }); 9488 } 9489 9490 // PAUSEPLAY 9491 if (slider.vars.pausePlay) { methods.pausePlay.setup(); } 9492 9493 //PAUSE WHEN INVISIBLE 9494 if (slider.vars.slideshow && slider.vars.pauseInvisible) { methods.pauseInvisible.init(); } 9495 9496 // SLIDSESHOW 9497 if (slider.vars.slideshow) { 9498 if (slider.vars.pauseOnHover) { 9499 slider.hover(function() { 9500 if (!slider.manualPlay && !slider.manualPause) { slider.pause(); } 9501 }, function() { 9502 if (!slider.manualPause && !slider.manualPlay && !slider.stopped) { slider.play(); } 9503 }); 9504 } 9505 // initialize animation 9506 //If we're visible, or we don't use PageVisibility API 9507 if(!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) { 9508 (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play(); 9509 } 9510 } 9511 9512 // ASNAV: 9513 if (asNav) { methods.asNav.setup(); } 9514 9515 // TOUCH 9516 if (touch && slider.vars.touch) { methods.touch(); } 9517 9518 // FADE&&SMOOTHHEIGHT || SLIDE: 9519 if (!fade || (fade && slider.vars.smoothHeight)) { $(window).bind("resize orientationchange focus", methods.resize); } 9520 9521 slider.find("img").attr("draggable", "false"); 9522 9523 // API: start() Callback 9524 setTimeout(function(){ 9525 slider.vars.start(slider); 9526 }, 200); 9527 }, 9528 asNav: { 9529 setup: function() { 9530 slider.asNav = true; 9531 slider.animatingTo = Math.floor(slider.currentSlide/slider.move); 9532 slider.currentItem = slider.currentSlide; 9533 slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide"); 9534 if(!msGesture){ 9535 slider.slides.on(eventType, function(e){ 9536 e.preventDefault(); 9537 var $slide = $(this), 9538 target = $slide.index(); 9539 var posFromLeft = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container 9540 if( posFromLeft <= 0 && $slide.hasClass( namespace + 'active-slide' ) ) { 9541 slider.flexAnimate(slider.getTarget("prev"), true); 9542 } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + "active-slide")) { 9543 slider.direction = (slider.currentItem < target) ? "next" : "prev"; 9544 slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true); 9545 } 9546 }); 9547 }else{ 9548 el._slider = slider; 9549 slider.slides.each(function (){ 9550 var that = this; 9551 that._gesture = new MSGesture(); 9552 that._gesture.target = that; 9553 that.addEventListener("MSPointerDown", function (e){ 9554 e.preventDefault(); 9555 if(e.currentTarget._gesture) { 9556 e.currentTarget._gesture.addPointer(e.pointerId); 9557 } 9558 }, false); 9559 that.addEventListener("MSGestureTap", function (e){ 9560 e.preventDefault(); 9561 var $slide = $(this), 9562 target = $slide.index(); 9563 if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) { 9564 slider.direction = (slider.currentItem < target) ? "next" : "prev"; 9565 slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true); 9566 } 9567 }); 9568 }); 9569 } 9570 } 9571 }, 9572 controlNav: { 9573 setup: function() { 9574 if (!slider.manualControls) { 9575 methods.controlNav.setupPaging(); 9576 } else { // MANUALCONTROLS: 9577 methods.controlNav.setupManual(); 9578 } 9579 }, 9580 setupPaging: function() { 9581 var type = (slider.vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging', 9582 j = 1, 9583 item, 9584 slide; 9585 9586 slider.controlNavScaffold = $('<ol class="'+ namespace + 'control-nav ' + namespace + type + '"></ol>'); 9587 9588 if (slider.pagingCount > 1) { 9589 for (var i = 0; i < slider.pagingCount; i++) { 9590 slide = slider.slides.eq(i); 9591 item = (slider.vars.controlNav === "thumbnails") ? '<img src="' + slide.attr( 'data-thumb' ) + '"/>' : '<a>' + j + '</a>'; 9592 if ( 'thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions ) { 9593 var captn = slide.attr( 'data-thumbcaption' ); 9594 if ( '' !== captn && undefined !== captn ) { item += '<span class="' + namespace + 'caption">' + captn + '</span>'; } 9595 } 9596 slider.controlNavScaffold.append('<li>' + item + '</li>'); 9597 j++; 9598 } 9599 } 9600 9601 // CONTROLSCONTAINER: 9602 (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold); 9603 methods.controlNav.set(); 9604 9605 methods.controlNav.active(); 9606 9607 slider.controlNavScaffold.delegate('a, img', eventType, function(event) { 9608 event.preventDefault(); 9609 9610 if (watchedEvent === "" || watchedEvent === event.type) { 9611 var $this = $(this), 9612 target = slider.controlNav.index($this); 9613 9614 if (!$this.hasClass(namespace + 'active')) { 9615 slider.direction = (target > slider.currentSlide) ? "next" : "prev"; 9616 slider.flexAnimate(target, slider.vars.pauseOnAction); 9617 } 9618 } 9619 9620 // setup flags to prevent event duplication 9621 if (watchedEvent === "") { 9622 watchedEvent = event.type; 9623 } 9624 methods.setToClearWatchedEvent(); 9625 9626 }); 9627 }, 9628 setupManual: function() { 9629 slider.controlNav = slider.manualControls; 9630 methods.controlNav.active(); 9631 9632 slider.controlNav.bind(eventType, function(event) { 9633 event.preventDefault(); 9634 9635 if (watchedEvent === "" || watchedEvent === event.type) { 9636 var $this = $(this), 9637 target = slider.controlNav.index($this); 9638 9639 if (!$this.hasClass(namespace + 'active')) { 9640 (target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev"; 9641 slider.flexAnimate(target, slider.vars.pauseOnAction); 9642 } 9643 } 9644 9645 // setup flags to prevent event duplication 9646 if (watchedEvent === "") { 9647 watchedEvent = event.type; 9648 } 9649 methods.setToClearWatchedEvent(); 9650 }); 9651 }, 9652 set: function() { 9653 var selector = (slider.vars.controlNav === "thumbnails") ? 'img' : 'a'; 9654 slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider); 9655 }, 9656 active: function() { 9657 slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active"); 9658 }, 9659 update: function(action, pos) { 9660 if (slider.pagingCount > 1 && action === "add") { 9661 slider.controlNavScaffold.append($('<li><a>' + slider.count + '</a></li>')); 9662 } else if (slider.pagingCount === 1) { 9663 slider.controlNavScaffold.find('li').remove(); 9664 } else { 9665 slider.controlNav.eq(pos).closest('li').remove(); 9666 } 9667 methods.controlNav.set(); 9668 (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active(); 9669 } 9670 }, 9671 directionNav: { 9672 setup: function() { 9673 var directionNavScaffold = $('<ul class="' + namespace + 'direction-nav"><li class="' + namespace + 'nav-prev"><a class="' + namespace + 'prev" href="#">' + slider.vars.prevText + '</a></li><li class="' + namespace + 'nav-next"><a class="' + namespace + 'next" href="#">' + slider.vars.nextText + '</a></li></ul>'); 9674 9675 // CUSTOM DIRECTION NAV: 9676 if (slider.customDirectionNav) { 9677 slider.directionNav = slider.customDirectionNav; 9678 // CONTROLSCONTAINER: 9679 } else if (slider.controlsContainer) { 9680 $(slider.controlsContainer).append(directionNavScaffold); 9681 slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer); 9682 } else { 9683 slider.append(directionNavScaffold); 9684 slider.directionNav = $('.' + namespace + 'direction-nav li a', slider); 9685 } 9686 9687 methods.directionNav.update(); 9688 9689 slider.directionNav.bind(eventType, function(event) { 9690 event.preventDefault(); 9691 var target; 9692 9693 if (watchedEvent === "" || watchedEvent === event.type) { 9694 target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev'); 9695 slider.flexAnimate(target, slider.vars.pauseOnAction); 9696 } 9697 9698 // setup flags to prevent event duplication 9699 if (watchedEvent === "") { 9700 watchedEvent = event.type; 9701 } 9702 methods.setToClearWatchedEvent(); 9703 }); 9704 }, 9705 update: function() { 9706 var disabledClass = namespace + 'disabled'; 9707 if (slider.pagingCount === 1) { 9708 slider.directionNav.addClass(disabledClass).attr('tabindex', '-1'); 9709 } else if (!slider.vars.animationLoop) { 9710 if (slider.animatingTo === 0) { 9711 slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass).attr('tabindex', '-1'); 9712 } else if (slider.animatingTo === slider.last) { 9713 slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass).attr('tabindex', '-1'); 9714 } else { 9715 slider.directionNav.removeClass(disabledClass).removeAttr('tabindex'); 9716 } 9717 } else { 9718 slider.directionNav.removeClass(disabledClass).removeAttr('tabindex'); 9719 } 9720 } 9721 }, 9722 pausePlay: { 9723 setup: function() { 9724 var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a></a></div>'); 9725 9726 // CONTROLSCONTAINER: 9727 if (slider.controlsContainer) { 9728 slider.controlsContainer.append(pausePlayScaffold); 9729 slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer); 9730 } else { 9731 slider.append(pausePlayScaffold); 9732 slider.pausePlay = $('.' + namespace + 'pauseplay a', slider); 9733 } 9734 9735 methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play'); 9736 9737 slider.pausePlay.bind(eventType, function(event) { 9738 event.preventDefault(); 9739 9740 if (watchedEvent === "" || watchedEvent === event.type) { 9741 if ($(this).hasClass(namespace + 'pause')) { 9742 slider.manualPause = true; 9743 slider.manualPlay = false; 9744 slider.pause(); 9745 } else { 9746 slider.manualPause = false; 9747 slider.manualPlay = true; 9748 slider.play(); 9749 } 9750 } 9751 9752 // setup flags to prevent event duplication 9753 if (watchedEvent === "") { 9754 watchedEvent = event.type; 9755 } 9756 methods.setToClearWatchedEvent(); 9757 }); 9758 }, 9759 update: function(state) { 9760 (state === "play") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').html(slider.vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').html(slider.vars.pauseText); 9761 } 9762 }, 9763 touch: function() { 9764 var startX, 9765 startY, 9766 offset, 9767 cwidth, 9768 dx, 9769 startT, 9770 onTouchStart, 9771 onTouchMove, 9772 onTouchEnd, 9773 scrolling = false, 9774 localX = 0, 9775 localY = 0, 9776 accDx = 0; 9777 9778 if(!msGesture){ 9779 onTouchStart = function(e) { 9780 if (slider.animating) { 9781 e.preventDefault(); 9782 } else if ( ( window.navigator.msPointerEnabled ) || e.touches.length === 1 ) { 9783 slider.pause(); 9784 // CAROUSEL: 9785 cwidth = (vertical) ? slider.h : slider. w; 9786 startT = Number(new Date()); 9787 // CAROUSEL: 9788 9789 // Local vars for X and Y points. 9790 localX = e.touches[0].pageX; 9791 localY = e.touches[0].pageY; 9792 9793 offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 : 9794 (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) : 9795 (carousel && slider.currentSlide === slider.last) ? slider.limit : 9796 (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide : 9797 (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth; 9798 startX = (vertical) ? localY : localX; 9799 startY = (vertical) ? localX : localY; 9800 9801 el.addEventListener('touchmove', onTouchMove, false); 9802 el.addEventListener('touchend', onTouchEnd, false); 9803 } 9804 }; 9805 9806 onTouchMove = function(e) { 9807 // Local vars for X and Y points. 9808 9809 localX = e.touches[0].pageX; 9810 localY = e.touches[0].pageY; 9811 9812 dx = (vertical) ? startX - localY : startX - localX; 9813 scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY)); 9814 9815 var fxms = 500; 9816 9817 if ( ! scrolling || Number( new Date() ) - startT > fxms ) { 9818 e.preventDefault(); 9819 if (!fade && slider.transitions) { 9820 if (!slider.vars.animationLoop) { 9821 dx = dx/((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx)/cwidth+2) : 1); 9822 } 9823 slider.setProps(offset + dx, "setTouch"); 9824 } 9825 } 9826 }; 9827 9828 onTouchEnd = function(e) { 9829 // finish the touch by undoing the touch session 9830 el.removeEventListener('touchmove', onTouchMove, false); 9831 9832 if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) { 9833 var updateDx = (reverse) ? -dx : dx, 9834 target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev'); 9835 9836 if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) { 9837 slider.flexAnimate(target, slider.vars.pauseOnAction); 9838 } else { 9839 if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); } 9840 } 9841 } 9842 el.removeEventListener('touchend', onTouchEnd, false); 9843 9844 startX = null; 9845 startY = null; 9846 dx = null; 9847 offset = null; 9848 }; 9849 9850 el.addEventListener('touchstart', onTouchStart, false); 9851 }else{ 9852 el.style.msTouchAction = "none"; 9853 el._gesture = new MSGesture(); 9854 el._gesture.target = el; 9855 el.addEventListener("MSPointerDown", onMSPointerDown, false); 9856 el._slider = slider; 9857 el.addEventListener("MSGestureChange", onMSGestureChange, false); 9858 el.addEventListener("MSGestureEnd", onMSGestureEnd, false); 9859 9860 function onMSPointerDown(e){ 9861 e.stopPropagation(); 9862 if (slider.animating) { 9863 e.preventDefault(); 9864 }else{ 9865 slider.pause(); 9866 el._gesture.addPointer(e.pointerId); 9867 accDx = 0; 9868 cwidth = (vertical) ? slider.h : slider. w; 9869 startT = Number(new Date()); 9870 // CAROUSEL: 9871 9872 offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 : 9873 (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) : 9874 (carousel && slider.currentSlide === slider.last) ? slider.limit : 9875 (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide : 9876 (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth; 9877 } 9878 } 9879 9880 function onMSGestureChange(e) { 9881 e.stopPropagation(); 9882 var slider = e.target._slider; 9883 if(!slider){ 9884 return; 9885 } 9886 var transX = -e.translationX, 9887 transY = -e.translationY; 9888 9889 //Accumulate translations. 9890 accDx = accDx + ((vertical) ? transY : transX); 9891 dx = accDx; 9892 scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY)); 9893 9894 if(e.detail === e.MSGESTURE_FLAG_INERTIA){ 9895 setImmediate(function (){ 9896 el._gesture.stop(); 9897 }); 9898 9899 return; 9900 } 9901 9902 if (!scrolling || Number(new Date()) - startT > 500) { 9903 e.preventDefault(); 9904 if (!fade && slider.transitions) { 9905 if (!slider.vars.animationLoop) { 9906 dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1); 9907 } 9908 slider.setProps(offset + dx, "setTouch"); 9909 } 9910 } 9911 } 9912 9913 function onMSGestureEnd(e) { 9914 e.stopPropagation(); 9915 var slider = e.target._slider; 9916 if(!slider){ 9917 return; 9918 } 9919 if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) { 9920 var updateDx = (reverse) ? -dx : dx, 9921 target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev'); 9922 9923 if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) { 9924 slider.flexAnimate(target, slider.vars.pauseOnAction); 9925 } else { 9926 if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); } 9927 } 9928 } 9929 9930 startX = null; 9931 startY = null; 9932 dx = null; 9933 offset = null; 9934 accDx = 0; 9935 } 9936 } 9937 }, 9938 resize: function() { 9939 if (!slider.animating && slider.is(':visible')) { 9940 if (!carousel) { slider.doMath(); } 9941 9942 if (fade) { 9943 // SMOOTH HEIGHT: 9944 methods.smoothHeight(); 9945 } else if (carousel) { //CAROUSEL: 9946 slider.slides.width(slider.computedW); 9947 slider.update(slider.pagingCount); 9948 slider.setProps(); 9949 } 9950 else if (vertical) { //VERTICAL: 9951 slider.viewport.height(slider.h); 9952 slider.setProps(slider.h, "setTotal"); 9953 } else { 9954 // SMOOTH HEIGHT: 9955 if (slider.vars.smoothHeight) { methods.smoothHeight(); } 9956 slider.newSlides.width(slider.computedW); 9957 slider.setProps(slider.computedW, "setTotal"); 9958 } 9959 } 9960 }, 9961 smoothHeight: function(dur) { 9962 if (!vertical || fade) { 9963 var $obj = (fade) ? slider : slider.viewport; 9964 (dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingTo).height()}, dur) : $obj.height(slider.slides.eq(slider.animatingTo).height()); 9965 } 9966 }, 9967 sync: function(action) { 9968 var $obj = $(slider.vars.sync).data("flexslider"), 9969 target = slider.animatingTo; 9970 9971 switch (action) { 9972 case "animate": $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true); break; 9973 case "play": if (!$obj.playing && !$obj.asNav) { $obj.play(); } break; 9974 case "pause": $obj.pause(); break; 9975 } 9976 }, 9977 uniqueID: function($clone) { 9978 // Append _clone to current level and children elements with id attributes 9979 $clone.filter( '[id]' ).add($clone.find( '[id]' )).each(function() { 9980 var $this = $(this); 9981 $this.attr( 'id', $this.attr( 'id' ) + '_clone' ); 9982 }); 9983 return $clone; 9984 }, 9985 pauseInvisible: { 9986 visProp: null, 9987 init: function() { 9988 var visProp = methods.pauseInvisible.getHiddenProp(); 9989 if (visProp) { 9990 var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange'; 9991 document.addEventListener(evtname, function() { 9992 if (methods.pauseInvisible.isHidden()) { 9993 if(slider.startTimeout) { 9994 clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible 9995 } else { 9996 slider.pause(); //Or just pause 9997 } 9998 } 9999 else { 10000 if(slider.started) { 10001 slider.play(); //Initiated before, just play 10002 } else { 10003 if (slider.vars.initDelay > 0) { 10004 setTimeout(slider.play, slider.vars.initDelay); 10005 } else { 10006 slider.play(); //Didn't init before: simply init or wait for it 10007 } 10008 } 10009 } 10010 }); 10011 } 10012 }, 10013 isHidden: function() { 10014 var prop = methods.pauseInvisible.getHiddenProp(); 10015 if (!prop) { 10016 return false; 10017 } 10018 return document[prop]; 10019 }, 10020 getHiddenProp: function() { 10021 var prefixes = ['webkit','moz','ms','o']; 10022 // if 'hidden' is natively supported just return it 10023 if ('hidden' in document) { 10024 return 'hidden'; 10025 } 10026 // otherwise loop over all the known prefixes until we find one 10027 for ( var i = 0; i < prefixes.length; i++ ) { 10028 if ((prefixes[i] + 'Hidden') in document) { 10029 return prefixes[i] + 'Hidden'; 10030 } 10031 } 10032 // otherwise it's not supported 10033 return null; 10034 } 10035 }, 10036 setToClearWatchedEvent: function() { 10037 clearTimeout(watchedEventClearTimer); 10038 watchedEventClearTimer = setTimeout(function() { 10039 watchedEvent = ""; 10040 }, 3000); 10041 } 10042 }; 10043 10044 // public methods 10045 slider.flexAnimate = function(target, pause, override, withSync, fromNav) { 10046 if (!slider.vars.animationLoop && target !== slider.currentSlide) { 10047 slider.direction = (target > slider.currentSlide) ? "next" : "prev"; 10048 } 10049 10050 if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev"; 10051 10052 if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) { 10053 if (asNav && withSync) { 10054 var master = $(slider.vars.asNavFor).data('flexslider'); 10055 slider.atEnd = target === 0 || target === slider.count - 1; 10056 master.flexAnimate(target, true, false, true, fromNav); 10057 slider.direction = (slider.currentItem < target) ? "next" : "prev"; 10058 master.direction = slider.direction; 10059 10060 if (Math.ceil((target + 1)/slider.visible) - 1 !== slider.currentSlide && target !== 0) { 10061 slider.currentItem = target; 10062 slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide"); 10063 target = Math.floor(target/slider.visible); 10064 } else { 10065 slider.currentItem = target; 10066 slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide"); 10067 return false; 10068 } 10069 } 10070 10071 slider.animating = true; 10072 slider.animatingTo = target; 10073 10074 // SLIDESHOW: 10075 if (pause) { slider.pause(); } 10076 10077 // API: before() animation Callback 10078 slider.vars.before(slider); 10079 10080 // SYNC: 10081 if (slider.syncExists && !fromNav) { methods.sync("animate"); } 10082 10083 // CONTROLNAV 10084 if (slider.vars.controlNav) { methods.controlNav.active(); } 10085 10086 // !CAROUSEL: 10087 // CANDIDATE: slide active class (for add/remove slide) 10088 if (!carousel) { slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide'); } 10089 10090 // INFINITE LOOP: 10091 // CANDIDATE: atEnd 10092 slider.atEnd = target === 0 || target === slider.last; 10093 10094 // DIRECTIONNAV: 10095 if (slider.vars.directionNav) { methods.directionNav.update(); } 10096 10097 if (target === slider.last) { 10098 // API: end() of cycle Callback 10099 slider.vars.end(slider); 10100 // SLIDESHOW && !INFINITE LOOP: 10101 if (!slider.vars.animationLoop) { slider.pause(); } 10102 } 10103 10104 // SLIDE: 10105 if (!fade) { 10106 var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW, 10107 margin, slideString, calcNext; 10108 10109 // INFINITE LOOP / REVERSE: 10110 if (carousel) { 10111 //margin = (slider.vars.itemWidth > slider.w) ? slider.vars.itemMargin * 2 : slider.vars.itemMargin; 10112 margin = slider.vars.itemMargin; 10113 calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo; 10114 slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext; 10115 } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== "next") { 10116 slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0; 10117 } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== "prev") { 10118 slideString = (reverse) ? 0 : (slider.count + 1) * dimension; 10119 } else { 10120 slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension; 10121 } 10122 slider.setProps(slideString, "", slider.vars.animationSpeed); 10123 if (slider.transitions) { 10124 if (!slider.vars.animationLoop || !slider.atEnd) { 10125 slider.animating = false; 10126 slider.currentSlide = slider.animatingTo; 10127 } 10128 10129 // Unbind previous transitionEnd events and re-bind new transitionEnd event 10130 slider.container.unbind("webkitTransitionEnd transitionend"); 10131 slider.container.bind("webkitTransitionEnd transitionend", function() { 10132 clearTimeout(slider.ensureAnimationEnd); 10133 slider.wrapup(dimension); 10134 }); 10135 10136 // Insurance for the ever-so-fickle transitionEnd event 10137 clearTimeout(slider.ensureAnimationEnd); 10138 slider.ensureAnimationEnd = setTimeout(function() { 10139 slider.wrapup(dimension); 10140 }, slider.vars.animationSpeed + 100); 10141 10142 } else { 10143 slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){ 10144 slider.wrapup(dimension); 10145 }); 10146 } 10147 } else { // FADE: 10148 if (!touch) { 10149 //slider.slides.eq(slider.currentSlide).fadeOut(slider.vars.animationSpeed, slider.vars.easing); 10150 //slider.slides.eq(target).fadeIn(slider.vars.animationSpeed, slider.vars.easing, slider.wrapup); 10151 10152 slider.slides.eq(slider.currentSlide).css({"zIndex": 1}).animate({"opacity": 0}, slider.vars.animationSpeed, slider.vars.easing); 10153 slider.slides.eq(target).css({"zIndex": 2}).animate({"opacity": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup); 10154 10155 } else { 10156 slider.slides.eq(slider.currentSlide).css({ "opacity": 0, "zIndex": 1 }); 10157 slider.slides.eq(target).css({ "opacity": 1, "zIndex": 2 }); 10158 slider.wrapup(dimension); 10159 } 10160 } 10161 // SMOOTH HEIGHT: 10162 if (slider.vars.smoothHeight) { methods.smoothHeight(slider.vars.animationSpeed); } 10163 } 10164 }; 10165 slider.wrapup = function(dimension) { 10166 // SLIDE: 10167 if (!fade && !carousel) { 10168 if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) { 10169 slider.setProps(dimension, "jumpEnd"); 10170 } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) { 10171 slider.setProps(dimension, "jumpStart"); 10172 } 10173 } 10174 slider.animating = false; 10175 slider.currentSlide = slider.animatingTo; 10176 // API: after() animation Callback 10177 slider.vars.after(slider); 10178 }; 10179 10180 // SLIDESHOW: 10181 slider.animateSlides = function() { 10182 if (!slider.animating && focused ) { slider.flexAnimate(slider.getTarget("next")); } 10183 }; 10184 // SLIDESHOW: 10185 slider.pause = function() { 10186 clearInterval(slider.animatedSlides); 10187 slider.animatedSlides = null; 10188 slider.playing = false; 10189 // PAUSEPLAY: 10190 if (slider.vars.pausePlay) { methods.pausePlay.update("play"); } 10191 // SYNC: 10192 if (slider.syncExists) { methods.sync("pause"); } 10193 }; 10194 // SLIDESHOW: 10195 slider.play = function() { 10196 if (slider.playing) { clearInterval(slider.animatedSlides); } 10197 slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed); 10198 slider.started = slider.playing = true; 10199 // PAUSEPLAY: 10200 if (slider.vars.pausePlay) { methods.pausePlay.update("pause"); } 10201 // SYNC: 10202 if (slider.syncExists) { methods.sync("play"); } 10203 }; 10204 // STOP: 10205 slider.stop = function () { 10206 slider.pause(); 10207 slider.stopped = true; 10208 }; 10209 slider.canAdvance = function(target, fromNav) { 10210 // ASNAV: 10211 var last = (asNav) ? slider.pagingCount - 1 : slider.last; 10212 return (fromNav) ? true : 10213 (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true : 10214 (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false : 10215 (target === slider.currentSlide && !asNav) ? false : 10216 (slider.vars.animationLoop) ? true : 10217 (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false : 10218 (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false : 10219 true; 10220 }; 10221 slider.getTarget = function(dir) { 10222 slider.direction = dir; 10223 if (dir === "next") { 10224 return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1; 10225 } else { 10226 return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1; 10227 } 10228 }; 10229 10230 // SLIDE: 10231 slider.setProps = function(pos, special, dur) { 10232 var target = (function() { 10233 var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo, 10234 posCalc = (function() { 10235 if (carousel) { 10236 return (special === "setTouch") ? pos : 10237 (reverse && slider.animatingTo === slider.last) ? 0 : 10238 (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) : 10239 (slider.animatingTo === slider.last) ? slider.limit : posCheck; 10240 } else { 10241 switch (special) { 10242 case "setTotal": return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos; 10243 case "setTouch": return (reverse) ? pos : pos; 10244 case "jumpEnd": return (reverse) ? pos : slider.count * pos; 10245 case "jumpStart": return (reverse) ? slider.count * pos : pos; 10246 default: return pos; 10247 } 10248 } 10249 }()); 10250 10251 return (posCalc * -1) + "px"; 10252 }()); 10253 10254 if (slider.transitions) { 10255 target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + target + ",0,0)"; 10256 dur = (dur !== undefined) ? (dur/1000) + "s" : "0s"; 10257 slider.container.css("-" + slider.pfx + "-transition-duration", dur); 10258 slider.container.css("transition-duration", dur); 10259 } 10260 10261 slider.args[slider.prop] = target; 10262 if (slider.transitions || dur === undefined) { slider.container.css(slider.args); } 10263 10264 slider.container.css('transform',target); 10265 }; 10266 10267 slider.setup = function(type) { 10268 // SLIDE: 10269 if (!fade) { 10270 var sliderOffset, arr; 10271 10272 if (type === "init") { 10273 slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({"overflow": "hidden", "position": "relative"}).appendTo(slider).append(slider.container); 10274 // INFINITE LOOP: 10275 slider.cloneCount = 0; 10276 slider.cloneOffset = 0; 10277 // REVERSE: 10278 if (reverse) { 10279 arr = $.makeArray(slider.slides).reverse(); 10280 slider.slides = $(arr); 10281 slider.container.empty().append(slider.slides); 10282 } 10283 } 10284 // INFINITE LOOP && !CAROUSEL: 10285 if (slider.vars.animationLoop && !carousel) { 10286 slider.cloneCount = 2; 10287 slider.cloneOffset = 1; 10288 // clear out old clones 10289 if (type !== "init") { slider.container.find('.clone').remove(); } 10290 slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true')) 10291 .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true')); 10292 } 10293 slider.newSlides = $(slider.vars.selector, slider); 10294 10295 sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset; 10296 // VERTICAL: 10297 if (vertical && !carousel) { 10298 slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%"); 10299 setTimeout(function(){ 10300 slider.newSlides.css({"display": "block"}); 10301 slider.doMath(); 10302 slider.viewport.height(slider.h); 10303 slider.setProps(sliderOffset * slider.h, "init"); 10304 }, (type === "init") ? 100 : 0); 10305 } else { 10306 slider.container.width((slider.count + slider.cloneCount) * 200 + "%"); 10307 slider.setProps(sliderOffset * slider.computedW, "init"); 10308 setTimeout(function(){ 10309 slider.doMath(); 10310 slider.newSlides.css({"width": slider.computedW, "float": "left", "display": "block"}); 10311 // SMOOTH HEIGHT: 10312 if (slider.vars.smoothHeight) { methods.smoothHeight(); } 10313 }, (type === "init") ? 100 : 0); 10314 } 10315 } else { // FADE: 10316 slider.slides.css({"width": "100%", "float": "left", "marginRight": "-100%", "position": "relative"}); 10317 if (type === "init") { 10318 if (!touch) { 10319 //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing); 10320 if (slider.vars.fadeFirstSlide == false) { 10321 slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).css({"opacity": 1}); 10322 } else { 10323 slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).animate({"opacity": 1},slider.vars.animationSpeed,slider.vars.easing); 10324 } 10325 } else { 10326 slider.slides.css({ "opacity": 0, "display": "block", "webkitTransition": "opacity " + slider.vars.animationSpeed / 1000 + "s ease", "zIndex": 1 }).eq(slider.currentSlide).css({ "opacity": 1, "zIndex": 2}); 10327 } 10328 } 10329 // SMOOTH HEIGHT: 10330 if (slider.vars.smoothHeight) { methods.smoothHeight(); } 10331 } 10332 // !CAROUSEL: 10333 // CANDIDATE: active slide 10334 if (!carousel) { slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide"); } 10335 10336 //FlexSlider: init() Callback 10337 slider.vars.init(slider); 10338 }; 10339 10340 slider.doMath = function() { 10341 var slide = slider.slides.first(), 10342 slideMargin = slider.vars.itemMargin, 10343 minItems = slider.vars.minItems, 10344 maxItems = slider.vars.maxItems; 10345 10346 slider.w = (slider.viewport===undefined) ? slider.width() : slider.viewport.width(); 10347 slider.h = slide.height(); 10348 slider.boxPadding = slide.outerWidth() - slide.width(); 10349 10350 // CAROUSEL: 10351 if (carousel) { 10352 slider.itemT = slider.vars.itemWidth + slideMargin; 10353 slider.minW = (minItems) ? minItems * slider.itemT : slider.w; 10354 slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w; 10355 slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1)))/minItems : 10356 (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1)))/maxItems : 10357 (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth; 10358 10359 slider.visible = Math.floor(slider.w/(slider.itemW)); 10360 slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible; 10361 slider.pagingCount = Math.ceil(((slider.count - slider.visible)/slider.move) + 1); 10362 slider.last = slider.pagingCount - 1; 10363 slider.limit = (slider.pagingCount === 1) ? 0 : 10364 (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin; 10365 } else { 10366 slider.itemW = slider.w; 10367 slider.pagingCount = slider.count; 10368 slider.last = slider.count - 1; 10369 } 10370 slider.computedW = slider.itemW - slider.boxPadding; 10371 }; 10372 10373 slider.update = function(pos, action) { 10374 slider.doMath(); 10375 10376 // update currentSlide and slider.animatingTo if necessary 10377 if (!carousel) { 10378 if (pos < slider.currentSlide) { 10379 slider.currentSlide += 1; 10380 } else if (pos <= slider.currentSlide && pos !== 0) { 10381 slider.currentSlide -= 1; 10382 } 10383 slider.animatingTo = slider.currentSlide; 10384 } 10385 10386 // update controlNav 10387 if (slider.vars.controlNav && !slider.manualControls) { 10388 if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) { 10389 methods.controlNav.update("add"); 10390 } else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) { 10391 if (carousel && slider.currentSlide > slider.last) { 10392 slider.currentSlide -= 1; 10393 slider.animatingTo -= 1; 10394 } 10395 methods.controlNav.update("remove", slider.last); 10396 } 10397 } 10398 // update directionNav 10399 if (slider.vars.directionNav) { methods.directionNav.update(); } 10400 10401 }; 10402 10403 slider.addSlide = function(obj, pos) { 10404 var $obj = $(obj); 10405 10406 slider.count += 1; 10407 slider.last = slider.count - 1; 10408 10409 // append new slide 10410 if (vertical && reverse) { 10411 (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj); 10412 } else { 10413 (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj); 10414 } 10415 10416 // update currentSlide, animatingTo, controlNav, and directionNav 10417 slider.update(pos, "add"); 10418 10419 // update slider.slides 10420 slider.slides = $(slider.vars.selector + ':not(.clone)', slider); 10421 // re-setup the slider to accomdate new slide 10422 slider.setup(); 10423 10424 //FlexSlider: added() Callback 10425 slider.vars.added(slider); 10426 }; 10427 slider.removeSlide = function(obj) { 10428 var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj; 10429 10430 // update count 10431 slider.count -= 1; 10432 slider.last = slider.count - 1; 10433 10434 // remove slide 10435 if (isNaN(obj)) { 10436 $(obj, slider.slides).remove(); 10437 } else { 10438 (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove(); 10439 } 10440 10441 // update currentSlide, animatingTo, controlNav, and directionNav 10442 slider.doMath(); 10443 slider.update(pos, "remove"); 10444 10445 // update slider.slides 10446 slider.slides = $(slider.vars.selector + ':not(.clone)', slider); 10447 // re-setup the slider to accomdate new slide 10448 slider.setup(); 10449 10450 // FlexSlider: removed() Callback 10451 slider.vars.removed(slider); 10452 }; 10453 10454 //FlexSlider: Initialize 10455 methods.init(); 10456 }; 10457 10458 // Ensure the slider isn't focussed if the window loses focus. 10459 $( window ).blur( function ( e ) { 10460 focused = false; 10461 }).focus( function ( e ) { 10462 focused = true; 10463 }); 10464 10465 //FlexSlider: Default Settings 10466 $.flexslider.defaults = { 10467 namespace: "flex-", //{NEW} String: Prefix string attached to the class of every element generated by the plugin 10468 selector: ".slides > li", //{NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril 10469 animation: "fade", //String: Select your animation type, "fade" or "slide" 10470 easing: "swing", //{NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported! 10471 direction: "horizontal", //String: Select the sliding direction, "horizontal" or "vertical" 10472 reverse: false, //{NEW} Boolean: Reverse the animation direction 10473 animationLoop: true, //Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end 10474 smoothHeight: false, //{NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode 10475 startAt: 0, //Integer: The slide that the slider should start on. Array notation (0 = first slide) 10476 slideshow: true, //Boolean: Animate slider automatically 10477 slideshowSpeed: 7000, //Integer: Set the speed of the slideshow cycling, in milliseconds 10478 animationSpeed: 600, //Integer: Set the speed of animations, in milliseconds 10479 initDelay: 0, //{NEW} Integer: Set an initialization delay, in milliseconds 10480 randomize: false, //Boolean: Randomize slide order 10481 fadeFirstSlide: true, //Boolean: Fade in the first slide when animation type is "fade" 10482 thumbCaptions: false, //Boolean: Whether or not to put captions on thumbnails when using the "thumbnails" controlNav. 10483 10484 // Usability features 10485 pauseOnAction: true, //Boolean: Pause the slideshow when interacting with control elements, highly recommended. 10486 pauseOnHover: false, //Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering 10487 pauseInvisible: true, //{NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage. 10488 useCSS: true, //{NEW} Boolean: Slider will use CSS3 transitions if available 10489 touch: true, //{NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices 10490 video: false, //{NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches 10491 10492 // Primary Controls 10493 controlNav: true, //Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage 10494 directionNav: true, //Boolean: Create navigation for previous/next navigation? (true/false) 10495 prevText: "Previous", //String: Set the text for the "previous" directionNav item 10496 nextText: "Next", //String: Set the text for the "next" directionNav item 10497 10498 // Secondary Navigation 10499 keyboard: true, //Boolean: Allow slider navigating via keyboard left/right keys 10500 multipleKeyboard: false, //{NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present. 10501 mousewheel: false, //{UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
10502 pausePlay: false, //Boolean: Create pause/play dynamic element 10503 pauseText: "Pause", //String: Set the text for the "pause" pausePlay item 10504 playText: "Play", //String: Set the text for the "play" pausePlay item 10505 10506 // Special properties 10507 controlsContainer: "", //{UPDATED} jQuery Object/Selector: Declare which container the navigation elements should be appended too. Default container is the FlexSlider element. Example use would be $(".flexslider-container"). Property is ignored if given element is not found. 10508 manualControls: "", //{UPDATED} jQuery Object/Selector: Declare custom control navigation. Examples would be $(".flex-control-nav li") or "#tabs-nav li img", etc. The number of elements in your controlNav should match the number of slides/tabs. 10509 customDirectionNav: "", //{NEW} jQuery Object/Selector: Custom prev / next button. Must be two jQuery elements. In order to make the events work they have to have the classes "prev" and "next" (plus namespace) 10510 sync: "", //{NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care. 10511 asNavFor: "", //{NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider 10512 10513 // Carousel Options 10514 itemWidth: 0, //{NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding. 10515 itemMargin: 0, //{NEW} Integer: Margin between carousel items. 10516 minItems: 1, //{NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this. 10517 maxItems: 0, //{NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit. 10518 move: 0, //{NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items. 10519 allowOneSlide: true, //{NEW} Boolean: Whether or not to allow a slider comprised of a single slide 10520 10521 // Callback API 10522 start: function(){}, //Callback: function(slider) - Fires when the slider loads the first slide 10523 before: function(){}, //Callback: function(slider) - Fires asynchronously with each slider animation 10524 after: function(){}, //Callback: function(slider) - Fires after each slider animation completes 10525 end: function(){}, //Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous) 10526 added: function(){}, //{NEW} Callback: function(slider) - Fires after a slide is added 10527 removed: function(){}, //{NEW} Callback: function(slider) - Fires after a slide is removed 10528 init: function() {} //{NEW} Callback: function(slider) - Fires after the slider is initially setup 10529 }; 10530 10531 //FlexSlider: Plugin Function 10532 $.fn.flexslider = function(options) { 10533 if (options === undefined) { options = {}; } 10534 10535 if (typeof options === "object") { 10536 return this.each(function() { 10537 var $this = $(this), 10538 selector = (options.selector) ? options.selector : ".slides > li", 10539 $slides = $this.find(selector); 10540 10541 if ( ( $slides.length === 1 && options.allowOneSlide === true ) || $slides.length === 0 ) { 10542 $slides.fadeIn(400); 10543 if (options.start) { options.start($this); } 10544 } else if ($this.data('flexslider') === undefined) { 10545 new $.flexslider(this, options); 10546 } 10547 }); 10548 } else { 10549 // Helper strings to quickly perform functions on the slider 10550 var $slider = $(this).data('flexslider'); 10551 switch (options) { 10552 case "play": $slider.play(); break; 10553 case "pause": $slider.pause(); break; 10554 case "stop": $slider.stop(); break; 10555 case "next": $slider.flexAnimate($slider.getTarget("next"), true); break; 10556 case "prev": 10557 case "previous": $slider.flexAnimate($slider.getTarget("prev"), true); break; 10558 default: if (typeof options === "number") { $slider.flexAnimate(options, true); } 10559 } 10560 } 10561 }; 10562})(jQuery); 10563 10564/*! odometer 0.4.7 */ 10565(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G=[].slice;q='<span class="odometer-value"></span>
10565',n='<span class="odometer-ribbon"><span class="odometer-ribbon-inner">'+q+"</span></span>",d='<span class="odometer-digit"><span class="odometer-digit-spacer">8</span><span class="odometer-digit-inner">'+n+"</span></span>",g='<span class="odometer-formatting-mark"></span>',c="(,ddd).dd",h=/^\(?([^)]*)\)?(?:(.)(d+))?$/,i=30,f=2e3,a=20,j=2,e=.5,k=1e3/i,b=1e3/a,o="transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd",y=document.createElement("div").style,p=null!=y.transition||null!=y.webkitTransition||null!=y.mozTransition||null!=y.oTransition,w=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,l=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,s=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.children[0]},v=function(a,b){return a.className=a.className.replace(new RegExp("(^| )"+b.split(" ").join("|")+"( |$)","gi")," ")},r=function(a,b){return v(a,b),a.className+=" "+b},z=function(a,b){var c;return null!=document.createEvent?(c=document.createEvent("HTMLEvents"),c.initEvent(b,!0,!0),a.dispatchEvent(c)):void 0},u=function(){var a,b;return null!=(a=null!=(b=window.performance)&&"function"==typeof b.now?b.now():void 0)?a:+new Date},x=function(a,b){return null==b&&(b=0),b?(a*=Math.pow(10,b),a+=.5,a=Math.floor(a),a/=Math.pow(10,b)):Math.round(a)},A=function(a){return 0>a?Math.ceil(a):Math.floor(a)},t=function(a){return a-x(a)},C=!1,(B=function(){var a,b,c,d,e;if(!C&&null!=window.jQuery){for(C=!0,d=["html","text"],e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(function(a){var b;return b=window.jQuery.fn[a],window.jQuery.fn[a]=function(a){var c;return null==a||null==(null!=(c=this[0])?c.odometer:void 0)?b.apply(this,arguments):this[0].odometer.update(a)}}(a));return e}})(),setTimeout(B,0),m=function(){function a(b){var c,d,e,g,h,i,l,m,n,o,p=this;if(this.options=b,this.el=this.options.el,null!=this.el.odometer)return this.el.odometer;this.el.odometer=this,m=a.options;for(d in m)g=m[d],null==this.options[d]&&(this.options[d]=g);null==(h=this.options).duration&&(h.duration=f),this.MAX_VALUES=this.options.duration/k/j|0,this.resetFormat(),this.value=this.cleanValue(null!=(n=this.options.value)?n:""),this.renderInside(),this.render();try{for(o=["innerHTML","innerText","textContent"],i=0,l=o.length;l>i;i++)e=o[i],null!=this.el[e]&&!function(a){return Object.defineProperty(p.el,a,{get:function(){var b;return"innerHTML"===a?p.inside.outerHTML:null!=(b=p.inside.innerText)?b:p.inside.textContent},set:function(a){return p.update(a)}})}(e)}catch(q){c=q,this.watchForMutations()}}return a.prototype.renderInside=function(){return this.inside=document.createElement("div"),this.inside.className="odometer-inside",this.el.innerHTML="",this.el.appendChild(this.inside)},a.prototype.watchForMutations=function(){var a,b=this;if(null!=l)try{return null==this.observer&&(this.observer=new l(function(){var a;return a=b.el.innerText,b.renderInside(),b.render(b.value),b.update(a)})),this.watchMutations=!0,this.startWatchingMutations()}catch(c){a=c}},a.prototype.startWatchingMutations=function(){return this.watchMutations?this.observer.observe(this.el,{childList:!0}):void 0},a.prototype.stopWatchingMutations=function(){var a;return null!=(a=this.observer)?a.disconnect():void 0},a.prototype.cleanValue=function(a){var b;return"string"==typeof a&&(a=a.replace(null!=(b=this.format.radix)?b:".","<radix>"),a=a.replace(/[.,]/g,""),a=a.replace("<radix>","."),a=parseFloat(a,10)||0),x(a,this.format.precision)},a.prototype.bindTransitionEnd=function(){var a,b,c,d,e,f,g=this;if(!this.transitionEndBound){for(this.transitionEndBound=!0,b=!1,e=o.split(" "),f=[],c=0,d=e.length;d>c;c++)a=e[c],f.push(this.el.addEventListener(a,function(){return b?!0:(b=!0,setTimeout(function(){return g.render(),b=!1,z(g.el,"odometerdone")},0),!0)},!1));return f}},a.prototype.resetFormat=function(){var a,b,d,e,f,g,i,j;if(a=null!=(i=this.options.format)?i:c,a||(a="d"),d=h.exec(a),!d)throw new Error("Odometer: Unparsable digit format");return j=d.slice(1,4),g=j[0],f=j[1],b=j[2],e=(null!=b?b.length:void 0)||0,this.format={repeating:g,radix:f,precision:e}},a.prototype.render=function(a){var b,c,d,e,f,g,h;for(null==a&&(a=this.value),this.stopWatchingMutations(),this.resetFormat(),this.inside.innerHTML="",f=this.options.theme,b=this.el.className.split(" "),e=[],g=0,h=b.length;h>g;g++)c=b[g],c.length&&((d=/^odometer-theme-(.+)$/.exec(c))?f=d[1]:/^odometer(-|$)/.test(c)||e.push(c));return e.push("odometer"),p||e.push("odometer-no-transitions"),e.push(f?"odometer-theme-"+f:"odometer-auto-theme"),this.el.className=e.join(" "),this.ribbons={},this.formatDigits(a),this.startWatchingMutations()},a.prototype.formatDigits=function(a){var b,c,d,e,f,g,h,i,j,k;if(this.digits=[],this.options.formatFunction)for(d=this.options.formatFunction(a),j=d.split("").reverse(),f=0,h=j.length;h>f;f++)c=j[f],c.match(/0-9/)?(b=this.renderDigit(),b.querySelector(".odometer-value").innerHTML=c,this.digits.push(b),this.insertDigit(b)):this.addSpacer(c);else for(e=!this.format.precision||!t(a)||!1,k=a.toString().split("").reverse(),g=0,i=k.length;i>g;
vendor: 4,592 bytes, line 10565
10565g++)b=k[g],"."===b&&(e=!0),this.addDigit(b,e)},a.prototype.update=function(a){var b,c=this;return a=this.cleanValue(a),(b=a-this.value)?(v(this.el,"odometer-animating-up odometer-animating-down odometer-animating"),b>0?r(this.el,"odometer-animating-up"):r(this.el,"odometer-animating-down"),this.stopWatchingMutations(),this.animate(a),this.startWatchingMutations(),setTimeout(function(){return c.el.offsetHeight,r(c.el,"odometer-animating")},0),this.value=a):void 0},a.prototype.renderDigit=function(){return s(d)},a.prototype.insertDigit=function(a,b){return null!=b?this.inside.insertBefore(a,b):this.inside.children.length?this.inside.insertBefore(a,this.inside.children[0]):this.inside.appendChild(a)},a.prototype.addSpacer=function(a,b,c){var d;return d=s(g),d.innerHTML=a,c&&r(d,c),this.insertDigit(d,b)},a.prototype.addDigit=function(a,b){var c,d,e,f;if(null==b&&(b=!0),"-"===a)return this.addSpacer(a,null,"odometer-negation-mark");if("."===a)return this.addSpacer(null!=(f=this.format.radix)?f:".",null,"odometer-radix-mark");if(b)for(e=!1;;){if(!this.format.repeating.length){if(e)throw new Error("Bad odometer format without digits");this.resetFormat(),e=!0}if(c=this.format.repeating[this.format.repeating.length-1],this.format.repeating=this.format.repeating.substring(0,this.format.repeating.length-1),"d"===c)break;this.addSpacer(c)}return d=this.renderDigit(),d.querySelector(".odometer-value").innerHTML=a,this.digits.push(d),this.insertDigit(d)},a.prototype.animate=function(a){return p&&"count"!==this.options.animation?this.animateSlide(a):this.animateCount(a)},a.prototype.animateCount=function(a){var c,d,e,f,g,h=this;if(d=+a-this.value)return f=e=u(),c=this.value,(g=function(){var i,j,k;return u()-f>h.options.duration?(h.value=a,h.render(),void z(h.el,"odometerdone")):(i=u()-e,i>b&&(e=u(),k=i/h.options.duration,j=d*k,c+=j,h.render(Math.round(c))),null!=w?w(g):setTimeout(g,b))})()},a.prototype.getDigitCount=function(){var a,b,c,d,e,f;for(d=1<=arguments.length?G.call(arguments,0):[],a=e=0,f=d.length;f>e;a=++e)c=d[a],d[a]=Math.abs(c);return b=Math.max.apply(Math,d),Math.ceil(Math.log(b+1)/Math.log(10))},a.prototype.getFractionalDigitCount=function(){var a,b,c,d,e,f,g;for(e=1<=arguments.length?G.call(arguments,0):[],b=/^\-?\d*\.(\d*?)0*$/,a=f=0,g=e.length;g>f;a=++f)d=e[a],e[a]=d.toString(),c=b.exec(e[a]),e[a]=null==c?0:c[1].length;return Math.max.apply(Math,e)},a.prototype.resetDigits=function(){return this.digits=[],this.ribbons=[],this.inside.innerHTML="",this.resetFormat()},a.prototype.animateSlide=function(a){var b,c,d,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y,z,B,C,D,E;if(s=this.value,j=this.getFractionalDigitCount(s,a),j&&(a*=Math.pow(10,j),s*=Math.pow(10,j)),d=a-s){for(this.bindTransitionEnd(),f=this.getDigitCount(s,a),g=[],b=0,m=v=0;f>=0?f>v:v>f;m=f>=0?++v:--v){if(t=A(s/Math.pow(10,f-m-1)),i=A(a/Math.pow(10,f-m-1)),h=i-t,Math.abs(h)>this.MAX_VALUES){for(l=[],n=h/(this.MAX_VALUES+this.MAX_VALUES*b*e),c=t;h>0&&i>c||0>h&&c>i;)l.push(Math.round(c)),c+=n;l[l.length-1]!==i&&l.push(i),b++}else l=function(){E=[];for(var a=t;i>=t?i>=a:a>=i;i>=t?a++:a--)E.push(a);return E}.apply(this);for(m=w=0,y=l.length;y>w;m=++w)k=l[m],l[m]=Math.abs(k%10);g.push(l)}for(this.resetDigits(),D=g.reverse(),m=x=0,z=D.length;z>x;m=++x)for(l=D[m],this.digits[m]||this.addDigit(" ",m>=j),null==(u=this.ribbons)[m]&&(u[m]=this.digits[m].querySelector(".odometer-ribbon-inner")),this.ribbons[m].innerHTML="",0>d&&(l=l.reverse()),o=C=0,B=l.length;B>C;o=++C)k=l[o],q=document.createElement("div"),q.className="odometer-value",q.innerHTML=k,this.ribbons[m].appendChild(q),o===l.length-1&&r(q,"odometer-last-value"),0===o&&r(q,"odometer-first-value");return 0>t&&this.addDigit("-"),p=this.inside.querySelector(".odometer-radix-mark"),null!=p&&p.parent.removeChild(p),j?this.addSpacer(this.format.radix,this.digits[j-1],"odometer-radix-mark"):void 0}},a}(),m.options=null!=(E=window.odometerOptions)?E:{},setTimeout(function(){var a,b,c,d,e;if(window.odometerOptions){d=window.odometerOptions,e=[];for(a in d)b=d[a],e.push(null!=(c=m.options)[a]?(c=m.options)[a]:c[a]=b);return e}},0),m.init=function(){var a,b,c,d,e,f;if(null!=document.querySelectorAll){for(b=document.querySelectorAll(m.options.selector||".odometer"),f=[],c=0,d=b.length;d>c;c++)a=b[c],f.push(a.odometer=new m({el:a,value:null!=(e=a.innerText)?e:a.textContent}));return f}},null!=(null!=(F=document.documentElement)?F.doScroll:void 0)&&null!=document.createEventObject?(D=document.onreadystatechange,document.onreadystatechange=function(){return"complete"===document.readyState&&m.options.auto!==!1&&m.init(
10565),null!=D?D.apply(this,arguments):void 0}):document.addEventListener("DOMContentLoaded",function(){return m.options.auto!==!1?m.init():void 0},!1),"function"==typeof define&&define.amd?define(["jquery"],function(){return m}):typeof exports===!1?module.exports=m:window.Odometer=m}).call(this); 10566/*! 10567 * Chart.js 10568 * http://chartjs.org/ 10569 * Version: 1.0.2 10570 * 10571 * Copyright 2015 Nick Downie 10572 * Released under the MIT license 10573 * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md 10574 */ 10575(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;var i=function(t,i){return t["offset"+i]?t["offset"+i]:document.defaultView.getComputedStyle(t).getPropertyValue(i)},e=this.width=i(t.canvas,"Width"),n=this.height=i(t.canvas,"Height");t.canvas.width=e,t.canvas.height=n;var e=this.width=t.canvas.width,n=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n<t.length;n++)i.apply(e,[t[n],n].concat(s))}else for(var o in t)i.apply(e,[t[o],o].concat(s))},o=s.clone=function(t){var i={};return n(t,function(e,s){t.hasOwnProperty(s)&&(i[s]=e)}),i},a=s.extend=function(t){return n(Array.prototype.slice.call(arguments,1),function(i){n(i,function(e,s){i.hasOwnProperty(s)&&(t[s]=e)})}),t},h=s.merge=function(){var t=Array.prototype.slice.call(arguments,0);return t.unshift({}),a.apply(null,t)},l=s.indexOf=function(t,i){if(Array.prototype.indexOf)return t.indexOf(i);for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1},r=(s.where=function(t,i){var e=[];return s.each(t,function(t){i(t)&&e.push(t)}),e},s.findNextWhere=function(t,i,e){e||(e=-1);for(var s=e+1;s<t.length;s++){var n=t[s];if(i(n))return n}},s.findPreviousWhere=function(t,i,e){e||(e=t.length);for(var s=e-1;s>=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof define&&define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),S=s.radians=function(t){return t*(Math.PI/180)},x=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}
10575),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),S=Math.round(f/v);(S>a||a>2*S)&&!h;)if(S>a)v*=2,S=Math.round(f/v),S%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,S=Math.round(f/v)}else v/=2,S=Math.round(f/v);return h&&(S=o,v=f/S),{steps:S,stepValue:v,min:p,max:p+S*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),w=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),-(s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)))},easeOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),s*Math.pow(2,-10*t)*Math.sin(2*(1*t-i)*Math.PI/e)+1)},easeInOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:2==(t/=.5)?1:(e||(e=.3*1.5),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),1>t?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-w.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*w.easeInBounce(2*t):.5*w.easeOutBounce(2*t-1)+.5}}),b=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),L=(s.animationLoop=function(t,i,e,s,n,o){var a=0,h=w[e]||w.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=b(l):n.apply(o)};b(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),k=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},F=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},L(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){k(t.chart.canvas,e,i)})}),R=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},T=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),M=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},W=s.fontString=function(t,i,e){return i+" "+t+"px "+e},z=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},B=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e
10575+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return M(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=R(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:T(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),F(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)<Math.pow(e,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),e.Arc=e.Element.extend({inRange:function(t,i){var e=s.getAngleFromPoint(this,{x:t,y:i}),n=e.angle>=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,
10575i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=this.caretPadding=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}B(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=W(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=z(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{B(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?z(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()}
10575,calculateXLabelRotation:function(){this.ctx.font=this.font;var t,i,e=this.ctx.measureText(this.xLabels[0]).width,s=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=s/2+3,this.xScalePaddingLeft=e/2>this.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=z(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(S(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(S(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),l&&(t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+x(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+x(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==e||a||(a=!0),a&&t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*S(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;i<this.valuesCount;i++)t=this.getPointPosition(i,d),e=this.ctx.measureText(C(this.templateString,{value:this.labels[i]})).width+5,0===i||i===this.valuesCount/2?(s=e/2,t.x+s>p&&(p=t.x+s,n=i),t.x-s<g&&(g=t.x-s,a=i)):i<this.valuesCount/2?t.x+e>p&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e<g&&(g=t.x-e,a=i);l=g,r=Math.ceil(p-this.width),o=this.getIndexAngle(n),h=this.getIndexAngle(a),c=r/Math.sin(o+Math.PI/2),u=l/Math.sin(h+Math.PI/2),c=f(c)?c:0,u=f(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,i){var e=this.width-i-this.drawingArea,s=t+this.drawingArea;this.xCenter=(s+e)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var i=2*Math.PI/this.valuesCount;return t*i-Math.PI/2},getPointPosition:function(t,i){var e=this.getIndexAngle(t);return{x:Math.cos(e)*i+this.xCenter,y:Math.sin(e)*i+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(n(this.yLabels,function(i,e){if(e>0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)s=this.getPointPosition(a,this.calculateCenterOffset(this.min+e*this.stepValue)),0===a?t.moveTo(s.x,s.y):t.lineTo(s.x,s.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var h=t.measureText(i).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-h/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,h+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(i,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var i=this.valuesCount-1;i>=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)}
10575,this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<this.datasets.length;a++)for(i=0;i<this.datasets[a].bars.length;i++)if(this.datasets[a].bars[i].inRange(n.x,n.y))return e.each(this.datasets,o),s;return s},buildScale:function(t){var i=this,s=function(){var t=[];return i.eachBars(function(i){t.push(i.value)}),t},n={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(n,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(n)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].bars.push(new this.BarClass({value:t,label:i,x:this.scale.calculateBarX(this.datasets.length,e,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),base:this.scale.endPoint,strokeColor:this.datasets[e].strokeColor,fillColor:this.datasets[e].fillColor})) 10576},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.get
10576SegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle)},this)}}),i.types.Doughnut.extend({name:"Pie",defaults:e.merge(s,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,i){e.extend(t,{x:this.scale.calculateX(i),y:this.scale.endPoint}),t.save()},this)},this),this.render()}
10576,update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.datasets,function(t){e.each(t.points,function(t){t.inRange(s.x,s.y)&&i.push(t)})},this),i},buildScale:function(t){var s=this,n=function(){var t=[];return s.eachPoints(function(i){t.push(i.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(o,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new i.Scale(o)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();var s=this.chart.ctx,n=function(t){return null!==t.value},o=function(t,i,s){return e.findNextWhere(i,n,s)||t},a=function(t,i,s){return e.findPreviousWhere(i,n,s)||t};this.scale.draw(i),e.each(this.datasets,function(t){var h=e.where(t.points,n);e.each(t.points,function(t,e){t.hasValue()&&t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(e)},i)},this),this.options.bezierCurve&&e.each(h,function(t,i){var s=i>0&&i<h.length-1?this.options.bezierCurveTension:0;t.controlPoints=e.splineCurve(a(t,h,i),t,o(t,h,i),s),t.controlPoints.outer.y>this.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.y<this.scale.startPoint&&(t.controlPoints.outer.y=this.scale.startPoint),t.controlPoints.inner.y>this.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y<this.scale.startPoint&&(t.controlPoints.inner.y=this.scale.startPoint)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(h,function(t,i){if(0===i)s.moveTo(t.x,t.y);else if(this.options.bezierCurve){var e=a(t,h,i);s.bezierCurveTo(e.controlPoints.outer.x,e.controlPoints.outer.y,t.controlPoints.inner.x,t.controlPoints.inner.y,t.x,t.y)}else s.lineTo(t.x,t.y)},this),s.stroke(),this.options.datasetFill&&h.length>0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}
10576),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers;i.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); 10577/*! 10578 * jQuery Color Animations v@VERSION 10579 * https://github.com/jquery/jquery-color 10580 * 10581 * Copyright 2013 jQuery Foundation and other contributors 10582 * Released under the MIT license. 10583 * http://jquery.org/license 10584 * 10585 * Date: @DATE 10586 */ 10587(function( jQuery, undefined ) { 10588 10589 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 10590 10591 // plusequals test for += 100 -= 100 10592 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 10593 // a set of RE's that can match strings and generate color tuples. 10594 stringParsers = [{ 10595 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 10596 parse: function( execResult ) { 10597 return [ 10598 execResult[ 1 ], 10599 execResult[ 2 ], 10600 execResult[ 3 ], 10601 execResult[ 4 ] 10602 ]; 10603 } 10604 }, { 10605 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 10606 parse: function( execResult ) { 10607 return [ 10608 execResult[ 1 ] * 2.55, 10609 execResult[ 2 ] * 2.55, 10610 execResult[ 3 ] * 2.55, 10611 execResult[ 4 ] 10612 ]; 10613 } 10614 }, { 10615 // this regex ignores A-F because it's compared against an already lowercased string 10616 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, 10617 parse: function( execResult ) { 10618 return [ 10619 parseInt( execResult[ 1 ], 16 ), 10620 parseInt( execResult[ 2 ], 16 ), 10621 parseInt( execResult[ 3 ], 16 ) 10622 ]; 10623 } 10624 }, { 10625 // this regex ignores A-F because it's compared against an already lowercased string 10626 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, 10627 parse: function( execResult ) { 10628 return [ 10629 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 10630 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 10631 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 10632 ]; 10633 } 10634 }, { 10635 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 10636 space: "hsla", 10637 parse: function( execResult ) { 10638 return [ 10639 execResult[ 1 ], 10640 execResult[ 2 ] / 100, 10641 execResult[ 3 ] / 100, 10642 execResult[ 4 ] 10643 ]; 10644 } 10645 }], 10646 10647 // jQuery.Color( ) 10648 color = jQuery.Color = function( color, green, blue, alpha ) { 10649 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 10650 }, 10651 spaces = { 10652 rgba: { 10653 props: { 10654 red: { 10655 idx: 0, 10656 type: "byte" 10657 }, 10658 green: { 10659 idx: 1, 10660 type: "byte" 10661 }, 10662 blue: { 10663 idx: 2, 10664 type: "byte" 10665 } 10666 } 10667 }, 10668 10669 hsla: { 10670 props: { 10671 hue: { 10672 idx: 0, 10673 type: "degrees" 10674 }, 10675 saturation: { 10676 idx: 1, 10677 type: "percent" 10678 }, 10679 lightness: { 10680 idx: 2, 10681 type: "percent" 10682 } 10683 } 10684 } 10685 },
vendor: 15,480 bytes, lines 10686-11291
10686 propTypes = { 10687 "byte": { 10688 floor: true, 10689 max: 255 10690 }, 10691 "percent": { 10692 max: 1 10693 }, 10694 "degrees": { 10695 mod: 360, 10696 floor: true 10697 } 10698 }, 10699 support = color.support = {}, 10700 10701 // element for support tests 10702 supportElem = jQuery( "<p>" )[ 0 ], 10703 10704 // colors = jQuery.Color.names 10705 colors, 10706 10707 // local aliases of functions called often 10708 each = jQuery.each; 10709 10710// determine rgba support immediately 10711supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 10712support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 10713 10714// define cache name and alpha properties 10715// for rgba and hsla spaces 10716each( spaces, function( spaceName, space ) { 10717 space.cache = "_" + spaceName; 10718 space.props.alpha = { 10719 idx: 3, 10720 type: "percent", 10721 def: 1 10722 }; 10723}); 10724 10725function clamp( value, prop, allowEmpty ) { 10726 var type = propTypes[ prop.type ] || {}; 10727 10728 if ( value == null ) { 10729 return (allowEmpty || !prop.def) ? null : prop.def; 10730 } 10731 10732 // ~~ is an short way of doing floor for positive numbers 10733 value = type.floor ? ~~value : parseFloat( value ); 10734 10735 // IE will pass in empty strings as value for alpha, 10736 // which will hit this case 10737 if ( isNaN( value ) ) { 10738 return prop.def; 10739 } 10740 10741 if ( type.mod ) { 10742 // we add mod before modding to make sure that negatives values 10743 // get converted properly: -10 -> 350 10744 return (value + type.mod) % type.mod; 10745 } 10746 10747 // for now all property types without mod have min and max 10748 return 0 > value ? 0 : type.max < value ? type.max : value; 10749} 10750 10751function stringParse( string ) { 10752 var inst = color(), 10753 rgba = inst._rgba = []; 10754 10755 string = string.toLowerCase(); 10756 10757 each( stringParsers, function( i, parser ) { 10758 var parsed, 10759 match = parser.re.exec( string ), 10760 values = match && parser.parse( match ), 10761 spaceName = parser.space || "rgba"; 10762 10763 if ( values ) { 10764 parsed = inst[ spaceName ]( values ); 10765 10766 // if this was an rgba parse the assignment might happen twice 10767 // oh well.... 10768 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 10769 rgba = inst._rgba = parsed._rgba; 10770 10771 // exit each( stringParsers ) here because we matched 10772 return false; 10773 } 10774 }); 10775 10776 // Found a stringParser that handled it 10777 if ( rgba.length ) { 10778 10779 // if this came from a parsed string, force "transparent" when alpha is 0 10780 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 10781 if ( rgba.join() === "0,0,0,0" ) { 10782 jQuery.extend( rgba, colors.transparent ); 10783 } 10784 return inst; 10785 } 10786 10787 // named colors 10788 return colors[ string ]; 10789} 10790 10791color.fn = jQuery.extend( color.prototype, { 10792 parse: function( red, green, blue, alpha ) { 10793 if ( red === undefined ) { 10794 this._rgba = [ null, null, null, null ]; 10795 return this; 10796 } 10797 if ( red.jquery || red.nodeType ) { 10798 red = jQuery( red ).css( green ); 10799 green = undefined; 10800 } 10801 10802 var inst = this, 10803 type = jQuery.type( red ), 10804 rgba = this._rgba = []; 10805 10806 // more than 1 argument specified - assume ( red, green, blue, alpha ) 10807 if ( green !== undefined ) { 10808 red = [ red, green, blue, alpha ]; 10809 type = "array"; 10810 } 10811 10812 if ( type === "string" ) { 10813 return this.parse( stringParse( red ) || colors._default ); 10814 } 10815 10816 if ( type === "array" ) { 10817 each( spaces.rgba.props, function( key, prop ) { 10818 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 10819 }); 10820 return this; 10821 } 10822 10823 if ( type === "object" ) { 10824 if ( red instanceof color ) { 10825 each( spaces, function( spaceName, space ) { 10826 if ( red[ space.cache ] ) { 10827 inst[ space.cache ] = red[ space.cache ].slice(); 10828 } 10829 }); 10830 } else { 10831 each( spaces, function( spaceName, space ) { 10832 var cache = space.cache; 10833 each( space.props, function( key, prop ) { 10834 10835 // if the cache doesn't exist, and we know how to convert 10836 if ( !inst[ cache ] && space.to ) { 10837 10838 // if the value was null, we don't need to copy it 10839 // if the key was alpha, we don't need to copy it either 10840 if ( key === "alpha" || red[ key ] == null ) { 10841 return; 10842 } 10843 inst[ cache ] = space.to( inst._rgba ); 10844 } 10845 10846 // this is the only case where we allow nulls for ALL properties. 10847 // call clamp with alwaysAllowEmpty 10848 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 10849 }); 10850 10851 // everything defined but alpha? 10852 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 10853 // use the default of 1 10854 inst[ cache ][ 3 ] = 1; 10855 if ( space.from ) { 10856 inst._rgba = space.from( inst[ cache ] ); 10857 } 10858 } 10859 }); 10860 } 10861 return this; 10862 } 10863 }, 10864 is: function( compare ) { 10865 var is = color( compare ), 10866 same = true, 10867 inst = this; 10868 10869 each( spaces, function( _, space ) { 10870 var localCache, 10871 isCache = is[ space.cache ]; 10872 if (isCache) { 10873 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 10874 each( space.props, function( _, prop ) { 10875 if ( isCache[ prop.idx ] != null ) { 10876 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 10877 return same; 10878 } 10879 }); 10880 } 10881 return same; 10882 }); 10883 return same; 10884 }, 10885 _space: function() { 10886 var used = [], 10887 inst = this; 10888 each( spaces, function( spaceName, space ) { 10889 if ( inst[ space.cache ] ) { 10890 used.push( spaceName ); 10891 } 10892 }); 10893 return used.pop(); 10894 }, 10895 transition: function( other, distance ) { 10896 var end = color( other ), 10897 spaceName = end._space(), 10898 space = spaces[ spaceName ], 10899 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 10900 start = startColor[ space.cache ] || space.to( startColor._rgba ), 10901 result = start.slice(); 10902 10903 end = end[ space.cache ]; 10904 each( space.props, function( key, prop ) { 10905 var index = prop.idx, 10906 startValue = start[ index ], 10907 endValue = end[ index ], 10908 type = propTypes[ prop.type ] || {}; 10909 10910 // if null, don't override start value 10911 if ( endValue === null ) { 10912 return; 10913 } 10914 // if null - use end 10915 if ( startValue === null ) { 10916 result[ index ] = endValue; 10917 } else { 10918 if ( type.mod ) { 10919 if ( endValue - startValue > type.mod / 2 ) { 10920 startValue += type.mod; 10921 } else if ( startValue - endValue > type.mod / 2 ) { 10922 startValue -= type.mod; 10923 } 10924 } 10925 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 10926 } 10927 }); 10928 return this[ spaceName ]( result ); 10929 }, 10930 blend: function( opaque ) { 10931 // if we are already opaque - return ourself 10932 if ( this._rgba[ 3 ] === 1 ) { 10933 return this; 10934 } 10935 10936 var rgb = this._rgba.slice(), 10937 a = rgb.pop(), 10938 blend = color( opaque )._rgba; 10939 10940 return color( jQuery.map( rgb, function( v, i ) { 10941 return ( 1 - a ) * blend[ i ] + a * v; 10942 })); 10943 }, 10944 toRgbaString: function() { 10945 var prefix = "rgba(", 10946 rgba = jQuery.map( this._rgba, function( v, i ) { 10947 return v == null ? ( i > 2 ? 1 : 0 ) : v; 10948 }); 10949 10950 if ( rgba[ 3 ] === 1 ) { 10951 rgba.pop(); 10952 prefix = "rgb("; 10953 } 10954 10955 return prefix + rgba.join() + ")"; 10956 }, 10957 toHslaString: function() { 10958 var prefix = "hsla(", 10959 hsla = jQuery.map( this.hsla(), function( v, i ) { 10960 if ( v == null ) { 10961 v = i > 2 ? 1 : 0; 10962 } 10963 10964 // catch 1 and 2 10965 if ( i && i < 3 ) { 10966 v = Math.round( v * 100 ) + "%"; 10967 } 10968 return v; 10969 }); 10970 10971 if ( hsla[ 3 ] === 1 ) { 10972 hsla.pop(); 10973 prefix = "hsl("; 10974 } 10975 return prefix + hsla.join() + ")"; 10976 }, 10977 toHexString: function( includeAlpha ) { 10978 var rgba = this._rgba.slice(), 10979 alpha = rgba.pop(); 10980 10981 if ( includeAlpha ) { 10982 rgba.push( ~~( alpha * 255 ) ); 10983 } 10984 10985 return "#" + jQuery.map( rgba, function( v ) { 10986 10987 // default to 0 when nulls exist 10988 v = ( v || 0 ).toString( 16 ); 10989 return v.length === 1 ? "0" + v : v; 10990 }).join(""); 10991 }, 10992 toString: function() { 10993 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 10994 } 10995}); 10996color.fn.parse.prototype = color.fn; 10997 10998// hsla conversions adapted from: 10999// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 11000 11001function hue2rgb( p, q, h ) { 11002 h = ( h + 1 ) % 1; 11003 if ( h * 6 < 1 ) { 11004 return p + (q - p) * h * 6; 11005 } 11006 if ( h * 2 < 1) { 11007 return q; 11008 } 11009 if ( h * 3 < 2 ) { 11010 return p + (q - p) * ((2/3) - h) * 6; 11011 } 11012 return p; 11013} 11014 11015spaces.hsla.to = function ( rgba ) { 11016 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 11017 return [ null, null, null, rgba[ 3 ] ]; 11018 } 11019 var r = rgba[ 0 ] / 255, 11020 g = rgba[ 1 ] / 255, 11021 b = rgba[ 2 ] / 255, 11022 a = rgba[ 3 ], 11023 max = Math.max( r, g, b ), 11024 min = Math.min( r, g, b ), 11025 diff = max - min, 11026 add = max + min, 11027 l = add * 0.5, 11028 h, s; 11029 11030 if ( min === max ) { 11031 h = 0; 11032 } else if ( r === max ) { 11033 h = ( 60 * ( g - b ) / diff ) + 360; 11034 } else if ( g === max ) { 11035 h = ( 60 * ( b - r ) / diff ) + 120; 11036 } else { 11037 h = ( 60 * ( r - g ) / diff ) + 240; 11038 } 11039 11040 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 11041 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 11042 if ( diff === 0 ) { 11043 s = 0; 11044 } else if ( l <= 0.5 ) { 11045 s = diff / add; 11046 } else { 11047 s = diff / ( 2 - add ); 11048 } 11049 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; 11050}; 11051 11052spaces.hsla.from = function ( hsla ) { 11053 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 11054 return [ null, null, null, hsla[ 3 ] ]; 11055 } 11056 var h = hsla[ 0 ] / 360, 11057 s = hsla[ 1 ], 11058 l = hsla[ 2 ], 11059 a = hsla[ 3 ], 11060 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 11061 p = 2 * l - q; 11062 11063 return [ 11064 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 11065 Math.round( hue2rgb( p, q, h ) * 255 ), 11066 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 11067 a 11068 ]; 11069}; 11070 11071 11072each( spaces, function( spaceName, space ) { 11073 var props = space.props, 11074 cache = space.cache, 11075 to = space.to, 11076 from = space.from; 11077 11078 // makes rgba() and hsla() 11079 color.fn[ spaceName ] = function( value ) { 11080 11081 // generate a cache for this space if it doesn't exist 11082 if ( to && !this[ cache ] ) { 11083 this[ cache ] = to( this._rgba ); 11084 } 11085 if ( value === undefined ) { 11086 return this[ cache ].slice(); 11087 } 11088 11089 var ret, 11090 type = jQuery.type( value ), 11091 arr = ( type === "array" || type === "object" ) ? value : arguments, 11092 local = this[ cache ].slice(); 11093 11094 each( props, function( key, prop ) { 11095 var val = arr[ type === "object" ? key : prop.idx ]; 11096 if ( val == null ) { 11097 val = local[ prop.idx ]; 11098 } 11099 local[ prop.idx ] = clamp( val, prop ); 11100 }); 11101 11102 if ( from ) { 11103 ret = color( from( local ) ); 11104 ret[ cache ] = local; 11105 return ret; 11106 } else { 11107 return color( local ); 11108 } 11109 }; 11110 11111 // makes red() green() blue() alpha() hue() saturation() lightness() 11112 each( props, function( key, prop ) { 11113 // alpha is included in more than one space 11114 if ( color.fn[ key ] ) { 11115 return; 11116 } 11117 color.fn[ key ] = function( value ) { 11118 var vtype = jQuery.type( value ), 11119 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), 11120 local = this[ fn ](), 11121 cur = local[ prop.idx ], 11122 match; 11123 11124 if ( vtype === "undefined" ) { 11125 return cur; 11126 } 11127 11128 if ( vtype === "function" ) { 11129 value = value.call( this, cur ); 11130 vtype = jQuery.type( value ); 11131 } 11132 if ( value == null && prop.empty ) { 11133 return this; 11134 } 11135 if ( vtype === "string" ) { 11136 match = rplusequals.exec( value ); 11137 if ( match ) { 11138 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 11139 } 11140 } 11141 local[ prop.idx ] = value; 11142 return this[ fn ]( local ); 11143 }; 11144 }); 11145}); 11146 11147// add cssHook and .fx.step function for each named hook. 11148// accept a space separated string of properties 11149color.hook = function( hook ) { 11150 var hooks = hook.split( " " ); 11151 each( hooks, function( i, hook ) { 11152 jQuery.cssHooks[ hook ] = { 11153 set: function( elem, value ) { 11154 var parsed, curElem, 11155 backgroundColor = ""; 11156 11157 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { 11158 value = color( parsed || value ); 11159 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 11160 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 11161 while ( 11162 (backgroundColor === "" || backgroundColor === "transparent") && 11163 curElem && curElem.style 11164 ) { 11165 try { 11166 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 11167 curElem = curElem.parentNode; 11168 } catch ( e ) { 11169 } 11170 } 11171 11172 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 11173 backgroundColor : 11174 "_default" ); 11175 } 11176 11177 value = value.toRgbaString(); 11178 } 11179 try { 11180 elem.style[ hook ] = value; 11181 } catch( e ) { 11182 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' 11183 } 11184 } 11185 }; 11186 jQuery.fx.step[ hook ] = function( fx ) { 11187 if ( !fx.colorInit ) { 11188 fx.start = color( fx.elem, hook ); 11189 fx.end = color( fx.end ); 11190 fx.colorInit = true; 11191 } 11192 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 11193 }; 11194 }); 11195 11196}; 11197 11198color.hook( stepHooks ); 11199 11200jQuery.cssHooks.borderColor = { 11201 expand: function( value ) { 11202 var expanded = {}; 11203 11204 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { 11205 expanded[ "border" + part + "Color" ] = value; 11206 }); 11207 return expanded; 11208 } 11209}; 11210 11211// Basic color names only. 11212// Usage of any of the other color names requires adding yourself or including 11213// jquery.color.svg-names.js. 11214colors = jQuery.Color.names = { 11215 // 4.1. Basic color keywords 11216 aqua: "#00ffff", 11217 black: "#000000", 11218 blue: "#0000ff", 11219 fuchsia: "#ff00ff", 11220 gray: "#808080", 11221 green: "#008000", 11222 lime: "#00ff00", 11223 maroon: "#800000", 11224 navy: "#000080", 11225 olive: "#808000", 11226 purple: "#800080", 11227 red: "#ff0000", 11228 silver: "#c0c0c0", 11229 teal: "#008080", 11230 white: "#ffffff", 11231 yellow: "#ffff00", 11232 11233 // 4.2.3. "transparent" color keyword 11234 transparent: [ null, null, null, 0 ], 11235 11236 _default: "#ffffff" 11237}; 11238 11239})( jQuery ); 11240 11241/*! 11242 * skrollr core 11243 * 11244 * Alexander Prinzhorn - https://github.com/Prinzhorn/skrollr 11245 * 11246 * Free to use under terms of MIT license 11247 */ 11248(function(window, document, undefined) { 11249 'use strict'; 11250 11251 /* 11252 * Global api. 11253 */ 11254 var skrollr = { 11255 get: function() { 11256 return _instance; 11257 }, 11258 //Main entry point. 11259 init: function(options) { 11260 return _instance || new Skrollr(options); 11261 }, 11262 VERSION: '0.6.29' 11263 }; 11264 11265 //Minify optimization. 11266 var hasProp = Object.prototype.hasOwnProperty; 11267 var Math = window.Math; 11268 var getStyle = window.getComputedStyle; 11269 11270 //They will be filled when skrollr gets initialized. 11271 var documentElement; 11272 var body; 11273 11274 var EVENT_TOUCHSTART = 'touchstart'; 11275 var EVENT_TOUCHMOVE = 'touchmove'; 11276 var EVENT_TOUCHCANCEL = 'touchcancel'; 11277 var EVENT_TOUCHEND = 'touchend'; 11278 11279 var SKROLLABLE_CLASS = 'skrollable'; 11280 var SKROLLABLE_BEFORE_CLASS = SKROLLABLE_CLASS + '-before'; 11281 var SKROLLABLE_BETWEEN_CLASS = SKROLLABLE_CLASS + '-between'; 11282 var SKROLLABLE_AFTER_CLASS = SKROLLABLE_CLASS + '-after'; 11283 11284 var SKROLLR_CLASS = 'skrollr'; 11285 var NO_SKROLLR_CLASS = 'no-' + SKROLLR_CLASS; 11286 var SKROLLR_DESKTOP_CLASS = SKROLLR_CLASS + '-desktop'; 11287 var SKROLLR_MOBILE_CLASS = SKROLLR_CLASS + '-mobile'; 11288 11289 var DEFAULT_EASING = 'linear'; 11290 var DEFAULT_DURATION = 1000;//ms 11291 var DEFAULT_MOBILE_DECELERATION = 0.004;
11291//pixel/ms² 11292 11293 var DEFAULT_SKROLLRBODY = 'skrollr-body'; 11294 11295 var DEFAULT_SMOOTH_SCROLLING_DURATION = 200;//ms 11296 11297 var ANCHOR_START = 'start'; 11298 var ANCHOR_END = 'end'; 11299 var ANCHOR_CENTER = 'center'; 11300 var ANCHOR_BOTTOM = 'bottom'; 11301 11302 //The property which will be added to the DOM element to hold the ID of the skrollable. 11303 var SKROLLABLE_ID_DOM_PROPERTY = '___skrollable_id'; 11304 11305 var rxTouchIgnoreTags = /^(?:input|textarea|button|select)$/i; 11306 11307 var rxTrim = /^\s+|\s+$/g; 11308 11309 //Find all data-attributes. data-[_constant]-[offset]-[anchor]-[anchor]. 11310 var rxKeyframeAttribute = /^data(?:-(_\w+))?(?:-?(-?\d*\.?\d+p?))?(?:-?(start|end|top|center|bottom))?(?:-?(top|center|bottom))?$/; 11311 11312 var rxPropValue = /\s*(@?[\w\-\[\]]+)\s*:\s*(.+?)\s*(?:;|$)/gi; 11313 11314 //Easing function names follow the property in square brackets. 11315 var rxPropEasing = /^(@?[a-z\-]+)\[(\w+)\]$/; 11316 11317 var rxCamelCase = /-([a-z0-9_])/g; 11318 var rxCamelCaseFn = function(str, letter) { 11319 return letter.toUpperCase(); 11320 }; 11321 11322 //Numeric values with optional sign.
11323 var rxNumericValue = /[\-+]?[\d]*\.?[\d]+/g; 11324 11325 //Used to replace occurences of {?} with a number. 11326 var rxInterpolateString = /\{\?\}/g; 11327 11328 //Finds rgb(a) colors, which don't use the percentage notation. 11329 var rxRGBAIntegerColor = /rgba?\(\s*-?\d+\s*,\s*-?\d+\s*,\s*-?\d+/g; 11330 11331 //Finds all gradients. 11332 var rxGradient = /[a-z\-]+-gradient/g; 11333 11334 //Vendor prefix. Will be set once skrollr gets initialized. 11335 var theCSSPrefix = ''; 11336 var theDashedCSSPrefix = ''; 11337 11338 //Will be called once (when skrollr gets initialized). 11339 var detectCSSPrefix = function() { 11340 //Only relevant prefixes. May be extended. 11341 //Could be dangerous if there will ever be a CSS property which actually starts with "ms". Don't hope so. 11342 var rxPrefixes = /^(?:O|Moz|webkit|ms)|(?:-(?:o|moz|webkit|ms)-)/; 11343 11344 //Detect prefix for current browser by finding the first property using a prefix. 11345 if(!getStyle) { 11346 return; 11347 } 11348 11349 var style = getStyle(body, null); 11350 11351 for(var k in style) { 11352 //We check the key and if the key is a number, we check the value as well, because safari's getComputedStyle returns some weird array-like thingy. 11353 theCSSPrefix = (k.match(rxPrefixes) || (+k == k && style[k].match(rxPrefixes))); 11354 11355 if(theCSSPrefix) { 11356 break; 11357 } 11358 } 11359 11360 //Did we even detect a prefix? 11361 if(!theCSSPrefix) { 11362 theCSSPrefix = theDashedCSSPrefix = ''; 11363 11364 return; 11365 } 11366 11367 theCSSPrefix = theCSSPrefix[0]; 11368 11369 //We could have detected either a dashed prefix or this camelCaseish-inconsistent stuff. 11370 if(theCSSPrefix.slice(0,1) === '-') { 11371 theDashedCSSPrefix = theCSSPrefix; 11372 11373 //There's no logic behind these. Need a look up. 11374 theCSSPrefix = ({ 11375 '-webkit-': 'webkit', 11376 '-moz-': 'Moz',
11377 '-ms-': 'ms', 11378 '-o-': 'O' 11379 })[theCSSPrefix]; 11380 } else { 11381 theDashedCSSPrefix = '-' + theCSSPrefix.toLowerCase() + '-'; 11382 } 11383 }; 11384 11385 var polyfillRAF = function() { 11386 var requestAnimFrame = window.requestAnimationFrame || window[theCSSPrefix.toLowerCase() + 'RequestAnimationFrame']; 11387 11388 var lastTime = _now(); 11389 11390 if(_isMobile || !requestAnimFrame) { 11391 requestAnimFrame = function(callback) { 11392 //How long did it take to render? 11393 var deltaTime = _now() - lastTime; 11394 var delay = Math.max(0, 1000 / 60 - deltaTime); 11395 11396 return window.setTimeout(function() { 11397 lastTime = _now(); 11398 callback(); 11399 }, delay); 11400 }; 11401 } 11402 11403 return requestAnimFrame; 11404 }; 11405 11406 var polyfillCAF = function() { 11407 var cancelAnimFrame = window.cancelAnimationFrame || window[theCSSPrefix.toLowerCase() + 'CancelAnimationFrame']; 11408 11409 if(_isMobile || !cancelAnimFrame) { 11410 cancelAnimFrame = function(timeout) { 11411 return window.clearTimeout(timeout); 11412 }; 11413 } 11414 11415 return cancelAnimFrame; 11416 }; 11417 11418 //Built-in easing functions. 11419 var easings = { 11420 begin: function() { 11421 return 0; 11422 }, 11423 end: function() { 11424 return 1; 11425 }, 11426 linear: function(p) { 11427 return p; 11428 }, 11429 quadratic: function(p) { 11430 return p * p; 11431 }, 11432 cubic: function(p) { 11433 return p * p * p; 11434 }, 11435 swing: function(p) { 11436 return (-Math.cos(p * Math.PI) / 2) + 0.5; 11437 }, 11438 sqrt: function(p) { 11439 return Math.sqrt(p); 11440 }, 11441 outCubic: function(p) { 11442 return (Math.pow((p - 1), 3) + 1); 11443 }, 11444 //see https://www.desmos.com/calculator/tbr20s8vd2 for how I did this 11445 bounce: function(p) { 11446 var a; 11447 11448 if(p <= 0.5083) { 11449 a = 3; 11450 } else if(p <= 0.8489) { 11451 a = 9; 11452 } else if(p <= 0.96208) { 11453 a = 27; 11454 } else if(p <= 0.99981) { 11455 a = 91; 11456 } else { 11457 return 1; 11458 } 11459 11460 return 1 - Math.abs(3 * Math.cos(p * a * 1.028) / a); 11461 } 11462 }; 11463 11464 /** 11465 * Constructor. 11466 */ 11467 function Skrollr(options) { 11468 documentElement = document.documentElement; 11469 body = document.body; 11470 11471 detectCSSPrefix(); 11472 11473 _instance = this; 11474 11475 options = options || {}; 11476 11477 _constants = options.constants || {}; 11478 11479 //We allow defining custom easings or overwrite existing. 11480 if(options.easing) { 11481 for(var e in options.easing) { 11482 easings[e] = options.easing[e]; 11483 } 11484 } 11485 11486 _edgeStrategy = options.edgeStrategy || 'set'; 11487 11488 _listeners = { 11489 //Function to be called right before rendering. 11490 beforerender: options.beforerender, 11491 11492 //Function to be called right after finishing rendering. 11493 render: options.render, 11494 11495 //Function to be called whenever an element with the `data-emit-events` attribute passes a keyframe. 11496 keyframe: options.keyframe 11497 }; 11498 11499 //forceHeight is true by default 11500 _forceHeight = options.forceHeight !== false; 11501 11502 if(_forceHeight) { 11503 _scale = options.scale || 1; 11504 } 11505 11506 _mobileDeceleration = options.mobileDeceleration || DEFAULT_MOBILE_DECELERATION; 11507 11508 _smoothScrollingEnabled = options.smoothScrolling !== false; 11509 _smoothScrollingDuration = options.smoothScrollingDuration || DEFAULT_SMOOTH_SCROLLING_DURATION; 11510 11511 //Dummy object. Will be overwritten in the _render method when smooth scrolling is calculated. 11512 _smoothScrolling = { 11513 targetTop: _instance.getScrollTop() 11514 }; 11515 11516 //A custom check function may be passed. 11517 _isMobile = ((options.mobileCheck || function() { 11518 return (/Android|iPhone|iPad|iPod|BlackBerry/i).test(navigator.userAgent || navigator.vendor || window.opera); 11519 })()); 11520 11521 if(_isMobile) { 11522 _skrollrBody = document.getElementById(options.skrollrBody || DEFAULT_SKROLLRBODY); 11523 11524 //Detect 3d transform if there's a skrollr-body (only needed for #skrollr-body). 11525 if(_skrollrBody) { 11526 _detect3DTransforms(); 11527 } 11528 11529 _initMobile(); 11530 _updateClass(documentElement, [SKROLLR_CLASS, SKROLLR_MOBILE_CLASS], [NO_SKROLLR_CLASS]); 11531 } else { 11532 _updateClass(documentElement, [SKROLLR_CLASS, SKROLLR_DESKTOP_CLASS], [NO_SKROLLR_CLASS]); 11533 } 11534 11535 //Triggers parsing of elements and a first reflow. 11536 _instance.refresh(); 11537 11538 _addEvent(window, 'resize orientationchange', function() { 11539 var width = documentElement.clientWidth; 11540 var height = documentElement.clientHeight; 11541 11542 //Only reflow if the size actually changed (#271).
11543 if(height !== _lastViewportHeight || width !== _lastViewportWidth) { 11544 _lastViewportHeight = height; 11545 _lastViewportWidth = width; 11546 11547 _requestReflow = true; 11548 } 11549 }); 11550 11551 var requestAnimFrame = polyfillRAF(); 11552 11553 //Let's go. 11554 (function animloop(){ 11555 _render(); 11556 _animFrame = requestAnimFrame(animloop); 11557 }()); 11558 11559 return _instance; 11560 } 11561 11562 /** 11563 * (Re)parses some or all elements. 11564 */ 11565 Skrollr.prototype.refresh = function(elements) { 11566 var elementIndex; 11567 var elementsLength; 11568 var ignoreID = false; 11569 11570 //Completely reparse anything without argument. 11571 if(elements === undefined) { 11572 //Ignore that some elements may already have a skrollable ID. 11573 ignoreID = true; 11574 11575 _skrollables = []; 11576 _skrollableIdCounter = 0; 11577 11578 elements = document.getElementsByTagName('*'); 11579 } else if(elements.length === undefined) { 11580 //We also accept a single element as parameter. 11581 elements = [elements]; 11582 } 11583 11584 elementIndex = 0; 11585 elementsLength = elements.length; 11586 11587 for(; elementIndex < elementsLength; elementIndex++) { 11588 var el = elements[elementIndex]; 11589 var anchorTarget = el; 11590 var keyFrames = []; 11591 11592 //If this particular element should be smooth scrolled. 11593 var smoothScrollThis = _smoothScrollingEnabled; 11594 11595 //The edge strategy for this particular element. 11596 var edgeStrategy = _edgeStrategy; 11597 11598 //If this particular element should emit keyframe events. 11599 var emitEvents = false; 11600 11601 //If we're reseting the counter, remove any old element ids that may be hanging around. 11602 if(ignoreID && SKROLLABLE_ID_DOM_PROPERTY in el) { 11603 delete el[SKROLLABLE_ID_DOM_PROPERTY]; 11604 } 11605 11606 if(!el.attributes) { 11607 continue; 11608 } 11609 11610 //Iterate over all attributes and search for key frame attributes. 11611 var attributeIndex = 0; 11612 var attributesLength = el.attributes.length; 11613 11614 for (; attributeIndex < attributesLength; attributeIndex++) { 11615 var attr = el.attributes[attributeIndex]; 11616 11617 if(attr.name === 'data-anchor-target') { 11618 anchorTarget = document.querySelector(attr.value); 11619 11620 if(anchorTarget === null) { 11621 throw 'Unable to find anchor target "' + attr.value + '"'; 11622 } 11623 11624 continue; 11625 } 11626 11627 //Global smooth scrolling can be overridden by the element attribute. 11628 if(attr.name === 'data-smooth-scrolling') { 11629 smoothScrollThis = attr.value !== 'off'; 11630 11631 continue; 11632 } 11633 11634 //Global edge strategy can be overridden by the element attribute. 11635 if(attr.name === 'data-edge-strategy') { 11636 edgeStrategy = attr.value; 11637 11638 continue; 11639 } 11640 11641 //Is this element tagged with the `data-emit-events` attribute? 11642 if(attr.name === 'data-emit-events') { 11643 emitEvents = true; 11644 11645 continue; 11646 } 11647 11648 var match = attr.name.match(rxKeyframeAttribute); 11649 11650 if(match === null) { 11651 continue; 11652 } 11653 11654 var kf = { 11655 props: attr.value, 11656 //Point back to the element as well. 11657 element: el, 11658 //The name of the event which this keyframe will fire, if emitEvents is 11659 eventType: attr.name.replace(rxCamelCase, rxCamelCaseFn) 11660 }; 11661 11662 keyFrames.push(kf); 11663 11664 var constant = match[1]; 11665 11666 if(constant) { 11667 //Strip the underscore prefix. 11668 kf.constant = constant.substr(1); 11669 } 11670 11671 //Get the key frame offset. 11672 var offset = match[2]; 11673 11674 //Is it a percentage offset? 11675 if(/p$/.test(offset)) { 11676 kf.isPercentage = true; 11677 kf.offset = (offset.slice(0, -1) | 0) / 100; 11678 } else { 11679 kf.offset = (offset | 0); 11680 } 11681 11682 var anchor1 = match[3]; 11683 11684 //If second anchor is not set, the first will be taken for both. 11685 var anchor2 = match[4] || anchor1; 11686 11687 //"absolute" (or "classic") mode, where numbers mean absolute scroll offset. 11688 if(!anchor1 || anchor1 === ANCHOR_START || anchor1 === ANCHOR_END) { 11689 kf.mode = 'absolute'; 11690 11691 //data-end needs to be calculated after all key frames are known. 11692 if(anchor1 === ANCHOR_END) { 11693 kf.isEnd = true; 11694 } else if(!kf.isPercentage) {
11695 //For data-start we can already set the key frame w/o calculations. 11696 //#59: "scale" options should only affect absolute mode. 11697 kf.offset = kf.offset * _scale; 11698 } 11699 } 11700 //"relative" mode, where numbers are relative to anchors. 11701 else { 11702 kf.mode = 'relative'; 11703 kf.anchors = [anchor1, anchor2]; 11704 } 11705 } 11706 11707 //Does this element have key frames? 11708 if(!keyFrames.length) { 11709 continue; 11710 } 11711 11712 //Will hold the original style and class attributes before we controlled the element (see #80). 11713 var styleAttr, classAttr; 11714 11715 var id; 11716 11717 if(!ignoreID && SKROLLABLE_ID_DOM_PROPERTY in el) { 11718 //We already have this element under control. Grab the corresponding skrollable id. 11719 id = el[SKROLLABLE_ID_DOM_PROPERTY]; 11720 styleAttr = _skrollables[id].styleAttr; 11721 classAttr = _skrollables[id].classAttr; 11722 } else { 11723 //It's an unknown element. Asign it a new skrollable id. 11724 id = (el[SKROLLABLE_ID_DOM_PROPERTY] = _skrollableIdCounter++); 11725 styleAttr = el.style.cssText; 11726 classAttr = _getClass(el); 11727 } 11728 11729 _skrollables[id] = { 11730 element: el, 11731 styleAttr: styleAttr, 11732 classAttr: classAttr, 11733 anchorTarget: anchorTarget, 11734 keyFrames: keyFrames, 11735 smoothScrolling: smoothScrollThis, 11736 edgeStrategy: edgeStrategy, 11737 emitEvents: emitEvents, 11738 lastFrameIndex: -1 11739 }; 11740 11741 _updateClass(el, [SKROLLABLE_CLASS], []); 11742 } 11743 11744 //Reflow for the first time. 11745 _reflow(); 11746 11747 //Now that we got all key frame numbers right, actually parse the properties. 11748 elementIndex = 0; 11749 elementsLength = elements.length; 11750 11751 for(; elementIndex < elementsLength; elementIndex++) { 11752 var sk = _skrollables[elements[elementIndex][SKROLLABLE_ID_DOM_PROPERTY]]; 11753 11754 if(sk === undefined) { 11755 continue; 11756 } 11757 11758 //Parse the property string to objects 11759 _parseProps(sk); 11760 11761 //Fill key frames with missing properties from left and right 11762 _fillProps(sk); 11763 } 11764 11765 return _instance; 11766 }; 11767 11768 /** 11769 * Transform "relative" mode to "absolute" mode. 11770 * That is, calculate anchor position and offset of element. 11771 */ 11772 Skrollr.prototype.relativeToAbsolute = function(element, viewportAnchor, elementAnchor) { 11773 var viewportHeight = documentElement.clientHeight; 11774 var box = element.getBoundingClientRect(); 11775 var absolute = box.top; 11776 11777 //#100: IE doesn't supply "height" with getBoundingClientRect. 11778 var boxHeight = box.bottom - box.top; 11779 11780 if(viewportAnchor === ANCHOR_BOTTOM) { 11781 absolute -= viewportHeight; 11782 } else if(viewportAnchor === ANCHOR_CENTER) { 11783 absolute -= viewportHeight / 2; 11784 } 11785 11786 if(elementAnchor === ANCHOR_BOTTOM) { 11787 absolute += boxHeight; 11788 } else if(elementAnchor === ANCHOR_CENTER) { 11789 absolute += boxHeight / 2; 11790 } 11791 11792 //Compensate scrolling since getBoundingClientRect is relative to viewport. 11793 absolute += _instance.getScrollTop(); 11794 11795 return (absolute + 0.5) | 0; 11796 }; 11797 11798 /** 11799 * Animates scroll top to new position. 11800 */ 11801 Skrollr.prototype.animateTo = function(top, options) { 11802 options = options || {}; 11803 11804 var now = _now(); 11805 var scrollTop = _instance.getScrollTop(); 11806 var duration = options.duration === undefined ? DEFAULT_DURATION : options.duration; 11807 11808 //Setting this to a new value will automatically cause the current animation to stop, if any. 11809 _scrollAnimation = { 11810 startTop: scrollTop, 11811 topDiff: top - scrollTop, 11812 targetTop: top, 11813 duration: duration, 11814 startTime: now, 11815 endTime: now + duration, 11816 easing: easings[options.easing || DEFAULT_EASING], 11817 done: options.done 11818 }; 11819 11820 //Don't queue the animation if there's nothing to animate. 11821 if(!_scrollAnimation.topDiff) { 11822 if(_scrollAnimation.done) { 11823 _scrollAnimation.done.call(_instance, false); 11824 } 11825 11826 _scrollAnimation = undefined; 11827 } 11828 11829 return _instance; 11830 }; 11831 11832 /** 11833 * Stops animateTo animation. 11834 */ 11835 Skrollr.prototype.stopAnimateTo = function() { 11836 if(_scrollAnimation && _scrollAnimation.done) { 11837 _scrollAnimation.done.call(_instance, true); 11838 } 11839 11840 _scrollAnimation = undefined; 11841 }; 11842 11843 /** 11844 * Returns if an animation caused by animateTo is currently running. 11845 */ 11846 Skrollr.prototype.isAnimatingTo = function() { 11847 return !!_scrollAnimation; 11848 }; 11849 11850 Skrollr.prototype.isMobile = function() { 11851 return _isMobile; 11852 }; 11853 11854 Skrollr.prototype.setScrollTop = function(top, force) { 11855 _forceRender = (force === true); 11856 11857 if(_isMobile) { 11858 _mobileOffset = Math.min(Math.max(top, 0), _maxKeyFrame); 11859 } else { 11860 window.scrollTo(0, top); 11861 } 11862 11863 return _instance; 11864 }; 11865 11866 Skrollr.prototype.getScrollTop = function() { 11867 if(_isMobile) { 11868 return _mobileOffset; 11869 } else { 11870 return window.pageYOffset || documentElement.scrollTop || body.scrollTop || 0; 11871 } 11872 }; 11873 11874 Skrollr.prototype.getMaxScrollTop = function() { 11875 return _maxKeyFrame; 11876 }; 11877 11878 Skrollr.prototype.on = function(name, fn) { 11879 _listeners[name] = fn; 11880 11881 return _instance; 11882 }; 11883 11884 Skrollr.prototype.off = function(name) { 11885 delete _listeners[name]; 11886 11887 return _instance; 11888 }; 11889 11890 Skrollr.prototype.destroy = function() { 11891 var cancelAnimFrame = polyfillCAF();
11892 cancelAnimFrame(_animFrame); 11893 _removeAllEvents(); 11894 11895 _updateClass(documentElement, [NO_SKROLLR_CLASS], [SKROLLR_CLASS, SKROLLR_DESKTOP_CLASS, SKROLLR_MOBILE_CLASS]); 11896 11897 var skrollableIndex = 0; 11898 var skrollablesLength = _skrollables.length; 11899 11900 for(; skrollableIndex < skrollablesLength; skrollableIndex++) { 11901 _reset(_skrollables[skrollableIndex].element); 11902 } 11903 11904 documentElement.style.overflow = body.style.overflow = ''; 11905 documentElement.style.height = body.style.height = ''; 11906 11907 if(_skrollrBody) { 11908 skrollr.setStyle(_skrollrBody, 'transform', 'none'); 11909 } 11910 11911 _instance = undefined; 11912 _skrollrBody = undefined; 11913 _listeners = undefined; 11914 _forceHeight = undefined; 11915 _maxKeyFrame = 0; 11916 _scale = 1; 11917 _constants = undefined; 11918 _mobileDeceleration = undefined; 11919 _direction = 'down'; 11920 _lastTop = -1; 11921 _lastViewportWidth = 0; 11922 _lastViewportHeight = 0; 11923 _requestReflow = false; 11924 _scrollAnimation = undefined; 11925 _smoothScrollingEnabled = undefined; 11926 _smoothScrollingDuration = undefined; 11927 _smoothScrolling = undefined; 11928 _forceRender = undefined; 11929 _skrollableIdCounter = 0; 11930 _edgeStrategy = undefined; 11931 _isMobile = false; 11932 _mobileOffset = 0; 11933 _translateZ = undefined; 11934 }; 11935 11936 /* 11937 Private methods. 11938 */ 11939 11940 var _initMobile = function() { 11941 var initialElement; 11942 var initialTouchY; 11943 var initialTouchX; 11944 var currentElement; 11945 var currentTouchY; 11946 var currentTouchX; 11947 var lastTouchY; 11948 var deltaY; 11949 11950 var initialTouchTime; 11951 var currentTouchTime; 11952 var lastTouchTime; 11953 var deltaTime; 11954 11955 _addEvent(documentElement, [EVENT_TOUCHSTART, EVENT_TOUCHMOVE, EVENT_TOUCHCANCEL, EVENT_TOUCHEND].join(' '), function(e) { 11956 var touch = e.changedTouches[0]; 11957 11958 currentElement = e.target; 11959 11960 //We don't want text nodes. 11961 while(currentElement.nodeType === 3) { 11962 currentElement = currentElement.parentNode; 11963 } 11964 11965 currentTouchY = touch.clientY; 11966 currentTouchX = touch.clientX; 11967 currentTouchTime = e.timeStamp; 11968 11969 if(!rxTouchIgnoreTags.test(currentElement.tagName)) { 11970 e.preventDefault(); 11971 } 11972 11973 switch(e.type) { 11974 case EVENT_TOUCHSTART: 11975 //The last element we tapped on. 11976 if(initialElement) { 11977 initialElement.blur(); 11978 } 11979 11980 _instance.stopAnimateTo(); 11981 11982 initialElement = currentElement; 11983 11984 initialTouchY = lastTouchY = currentTouchY; 11985 initialTouchX = currentTouchX; 11986 initialTouchTime = currentTouchTime; 11987 11988 break; 11989 case EVENT_TOUCHMOVE: 11990 //Prevent default event on touchIgnore elements in case they don't have focus yet. 11991 if(rxTouchIgnoreTags.test(currentElement.tagName) && document.activeElement !== currentElement) { 11992 e.preventDefault(); 11993 } 11994 11995 deltaY = currentTouchY - lastTouchY; 11996 deltaTime = currentTouchTime - lastTouchTime; 11997 11998 _instance.setScrollTop(_mobileOffset - deltaY, true); 11999 12000 lastTouchY = currentTouchY; 12001 lastTouchTime = currentTouchTime; 12002 break; 12003 default: 12004 case EVENT_TOUCHCANCEL: 12005 case EVENT_TOUCHEND: 12006 var distanceY = initialTouchY - currentTouchY; 12007 var distanceX = initialTouchX - currentTouchX; 12008 var distance2 = distanceX * distanceX + distanceY * distanceY; 12009 12010 //Check if it was more like a tap (moved less than 7px). 12011 if(distance2 < 49) { 12012 if(!rxTouchIgnoreTags.test(initialElement.tagName)) { 12013 initialElement.focus(); 12014 12015 //It was a tap, click the element. 12016 var clickEvent = document.createEvent('MouseEvents'); 12017 clickEvent.initMouseEvent('click', true, true, e.view, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 0, null); 12018 initialElement.dispatchEvent(clickEvent); 12019 } 12020 12021 return; 12022 } 12023 12024 initialElement = undefined; 12025 12026 var speed = deltaY / deltaTime; 12027 12028 //Cap speed at 3 pixel/ms. 12029 speed = Math.max(Math.min(speed, 3), -3); 12030 12031 var duration = Math.abs(speed / _mobileDeceleration); 12032 var targetOffset = speed * duration + 0.5 * _mobileDeceleration * duration * duration; 12033 var targetTop = _instance.getScrollTop() - targetOffset; 12034 12035 //Relative duration change for when scrolling above bounds. 12036 var targetRatio = 0; 12037 12038 //Change duration proportionally when scrolling would leave bounds. 12039 if(targetTop > _maxKeyFrame) { 12040 targetRatio = (_maxKeyFrame - targetTop) / targetOffset; 12041 12042 targetTop = _maxKeyFrame; 12043 } else if(targetTop < 0) { 12044 targetRatio = -targetTop / targetOffset; 12045 12046 targetTop = 0; 12047 } 12048 12049 duration = duration * (1 - targetRatio); 12050 12051 _instance.animateTo((targetTop + 0.5) | 0, {easing: 'outCubic', duration: duration}); 12052 break; 12053 } 12054 }); 12055 12056 //Just in case there has already been some native scrolling, reset it. 12057 window.scrollTo(0, 0); 12058 documentElement.style.overflow = body.style.overflow = 'hidden'; 12059 }; 12060 12061 /**
12062 * Updates key frames which depend on others / need to be updated on resize. 12063 * That is "end" in "absolute" mode and all key frames in "relative" mode. 12064 * Also handles constants, because they may change on resize. 12065 */ 12066 var _updateDependentKeyFrames = function() { 12067 var viewportHeight = documentElement.clientHeight; 12068 var processedConstants = _processConstants(); 12069 var skrollable; 12070 var element; 12071 var anchorTarget; 12072 var keyFrames; 12073 var keyFrameIndex; 12074 var keyFramesLength; 12075 var kf; 12076 var skrollableIndex; 12077 var skrollablesLength; 12078 var offset; 12079 var constantValue; 12080 12081 //First process all relative-mode elements and find the max key frame. 12082 skrollableIndex = 0; 12083 skrollablesLength = _skrollables.length; 12084 12085 for(; skrollableIndex < skrollablesLength; skrollableIndex++) { 12086 skrollable = _skrollables[skrollableIndex]; 12087 element = skrollable.element; 12088 anchorTarget = skrollable.anchorTarget; 12089 keyFrames = skrollable.keyFrames; 12090 12091 keyFrameIndex = 0; 12092 keyFramesLength = keyFrames.length; 12093 12094 for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) { 12095 kf = keyFrames[keyFrameIndex]; 12096 12097 offset = kf.offset; 12098 constantValue = processedConstants[kf.constant] || 0; 12099 12100 kf.frame = offset; 12101 12102 if(kf.isPercentage) { 12103 //Convert the offset to percentage of the viewport height. 12104 offset = offset * viewportHeight; 12105 12106 //Absolute + percentage mode. 12107 kf.frame = offset; 12108 } 12109 12110 if(kf.mode === 'relative') { 12111 _reset(element); 12112 12113 kf.frame = _instance.relativeToAbsolute(anchorTarget, kf.anchors[0], kf.anchors[1]) - offset; 12114 12115 _reset(element, true); 12116 } 12117 12118 kf.frame += constantValue; 12119 12120 //Only search for max key frame when forceHeight is enabled. 12121 if(_forceHeight) { 12122 //Find the max key frame, but don't use one of the data-end ones for comparison. 12123 if(!kf.isEnd && kf.frame > _maxKeyFrame) { 12124 _maxKeyFrame = kf.frame; 12125 } 12126 } 12127 } 12128 } 12129 12130 //#133: The document can be larger than the maxKeyFrame we found. 12131 _maxKeyFrame = Math.max(_maxKeyFrame, _getDocumentHeight()); 12132 12133 //Now process all data-end keyframes. 12134 skrollableIndex = 0; 12135 skrollablesLength = _skrollables.length; 12136 12137 for(; skrollableIndex < skrollablesLength; skrollableIndex++) { 12138 skrollable = _skrollables[skrollableIndex]; 12139 keyFrames = skrollable.keyFrames; 12140 12141 keyFrameIndex = 0; 12142 keyFramesLength = keyFrames.length; 12143 12144 for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) { 12145 kf = keyFrames[keyFrameIndex]; 12146 12147 constantValue = processedConstants[kf.constant] || 0; 12148 12149 if(kf.isEnd) { 12150 kf.frame = _maxKeyFrame - kf.offset + constantValue; 12151 } 12152 } 12153 12154 skrollable.keyFrames.sort(_keyFrameComparator); 12155 } 12156 }; 12157 12158 /** 12159 * Calculates and sets the style properties for the element at the given frame. 12160 * @param fakeFrame The frame to render at when smooth scrolling is enabled. 12161 * @param actualFrame The actual frame we are at. 12162 */ 12163 var _calcSteps = function(fakeFrame, actualFrame) { 12164 //Iterate over all skrollables. 12165 var skrollableIndex = 0; 12166 var skrollablesLength = _skrollables.length; 12167 12168 for(; skrollableIndex < skrollablesLength; skrollableIndex++) { 12169 var skrollable = _skrollables[skrollableIndex]; 12170 var element = skrollable.element; 12171 var frame = skrollable.smoothScrolling ? fakeFrame : actualFrame; 12172 var frames = skrollable.keyFrames; 12173 var framesLength = frames.length; 12174 var firstFrame = frames[0]; 12175 var lastFrame = frames[frames.length - 1]; 12176 var beforeFirst = frame < firstFrame.frame; 12177 var afterLast = frame > lastFrame.frame; 12178 var firstOrLastFrame = beforeFirst ? firstFrame : lastFrame; 12179 var emitEvents = skrollable.emitEvents; 12180 var lastFrameIndex = skrollable.lastFrameIndex; 12181 var key; 12182 var value; 12183 12184 //If we are before/after the first/last frame, set the styles according to the given edge strategy. 12185 if(beforeFirst || afterLast) { 12186 //Check if we already handled this edge case last time. 12187 //Note: using setScrollTop it's possible that we jumped from one edge to the other. 12188 if(beforeFirst && skrollable.edge === -1 || afterLast && skrollable.edge === 1) { 12189 continue; 12190 } 12191 12192 //Add the skrollr-before or -after class. 12193 if(beforeFirst) {
12194 _updateClass(element, [SKROLLABLE_BEFORE_CLASS], [SKROLLABLE_AFTER_CLASS, SKROLLABLE_BETWEEN_CLASS]); 12195 12196 //This handles the special case where we exit the first keyframe. 12197 if(emitEvents && lastFrameIndex > -1) { 12198 _emitEvent(element, firstFrame.eventType, _direction); 12199 skrollable.lastFrameIndex = -1; 12200 } 12201 } else { 12202 _updateClass(element, [SKROLLABLE_AFTER_CLASS], [SKROLLABLE_BEFORE_CLASS, SKROLLABLE_BETWEEN_CLASS]); 12203 12204 //This handles the special case where we exit the last keyframe. 12205 if(emitEvents && lastFrameIndex < framesLength) { 12206 _emitEvent(element, lastFrame.eventType, _direction); 12207 skrollable.lastFrameIndex = framesLength; 12208 } 12209 } 12210 12211 //Remember that we handled the edge case (before/after the first/last keyframe). 12212 skrollable.edge = beforeFirst ? -1 : 1; 12213 12214 switch(skrollable.edgeStrategy) { 12215 case 'reset': 12216 _reset(element); 12217 continue; 12218 case 'ease': 12219 //Handle this case like it would be exactly at first/last keyframe and just pass it on. 12220 frame = firstOrLastFrame.frame; 12221 break; 12222 default: 12223 case 'set': 12224 var props = firstOrLastFrame.props; 12225 12226 for(key in props) { 12227 if(hasProp.call(props, key)) { 12228 value = _interpolateString(props[key].value); 12229 12230 //Set style or attribute. 12231 if(key.indexOf('@') === 0) { 12232 element.setAttribute(key.substr(1), value); 12233 } else { 12234 skrollr.setStyle(element, key, value); 12235 } 12236 } 12237 } 12238 12239 continue; 12240 } 12241 } else { 12242 //Did we handle an edge last time? 12243 if(skrollable.edge !== 0) { 12244 _updateClass(element, [SKROLLABLE_CLASS, SKROLLABLE_BETWEEN_CLASS], [SKROLLABLE_BEFORE_CLASS, SKROLLABLE_AFTER_CLASS]); 12245 skrollable.edge = 0; 12246 } 12247 } 12248 12249 //Find out between which two key frames we are right now. 12250 var keyFrameIndex = 0; 12251 12252 for(; keyFrameIndex < framesLength - 1; keyFrameIndex++) { 12253 if(frame >= frames[keyFrameIndex].frame && frame <= frames[keyFrameIndex + 1].frame) { 12254 var left = frames[keyFrameIndex]; 12255 var right = frames[keyFrameIndex + 1]; 12256 12257 for(key in left.props) { 12258 if(hasProp.call(left.props, key)) { 12259 var progress = (frame - left.frame) / (right.frame - left.frame); 12260 12261 //Transform the current progress using the given easing function. 12262 progress = left.props[key].easing(progress); 12263 12264 //Interpolate between the two values 12265 value = _calcInterpolation(left.props[key].value, right.props[key].value, progress); 12266 12267 value = _interpolateString(value); 12268 12269 //Set style or attribute. 12270 if(key.indexOf('@') === 0) { 12271 element.setAttribute(key.substr(1), value); 12272 } else { 12273 skrollr.setStyle(element, key, value); 12274 } 12275 } 12276 } 12277 12278 //Are events enabled on this element? 12279 //This code handles the usual cases of scrolling through different keyframes. 12280 //The special cases of before first and after last keyframe are handled above. 12281 if(emitEvents) { 12282 //Did we pass a new keyframe? 12283 if(lastFrameIndex !== keyFrameIndex) { 12284 if(_direction === 'down') { 12285 _emitEvent(element, left.eventType, _direction); 12286 } else { 12287 _emitEvent(element, right.eventType, _direction); 12288 } 12289 12290 skrollable.lastFrameIndex = keyFrameIndex; 12291 } 12292 } 12293 12294 break; 12295 } 12296 } 12297 } 12298 }; 12299 12300 /** 12301 * Renders all elements. 12302 */ 12303 var _render = function() { 12304 if(_requestReflow) { 12305 _requestReflow = false; 12306 _reflow(); 12307 } 12308 12309 //We may render something else than the actual scrollbar position. 12310 var renderTop = _instance.getScrollTop(); 12311 12312 //If there's an animation, which ends in current render call, call the callback after rendering. 12313 var afterAnimationCallback; 12314 var now = _now(); 12315 var progress; 12316 12317 //Before actually rendering handle the scroll animation, if any. 12318 if(_scrollAnimation) { 12319 //It's over 12320 if(now >= _scrollAnimation.endTime) { 12321 renderTop = _scrollAnimation.targetTop; 12322 afterAnimationCallback = _scrollAnimation.done; 12323 _scrollAnimation = undefined; 12324 } else { 12325 //Map the current progress to the new progress using given easing function. 12326 progress = _scrollAnimation.easing((now - _scrollAnimation.startTime) / _scrollAnimation.duration); 12327 12328 renderTop = (_scrollAnimation.startTop + progress * _scrollAnimation.topDiff) | 0; 12329 } 12330 12331 _instance.setScrollTop(renderTop, true); 12332 } 12333 //Smooth scrolling only if there's no animation running and if we're not forcing the rendering. 12334 else if(!_forceRender) { 12335 var smoothScrollingDiff = _smoothScrolling.targetTop - renderTop; 12336 12337 //The user scrolled, start new smooth scrolling. 12338 if(smoothScrollingDiff) { 12339 _smoothScrolling = { 12340 startTop: _lastTop, 12341 topDiff: renderTop - _lastTop, 12342 targetTop: renderTop, 12343 startTime: _lastRenderCall, 12344 endTime: _lastRenderCall + _smoothScrollingDuration 12345 }; 12346 } 12347 12348 //Interpolate the internal scroll position (not the actual scrollbar). 12349 if(now <= _smoothScrolling.endTime) { 12350 //Map the current progress to the new progress using easing function. 12351 progress = easings.sqrt((now - _smoothScrolling.startTime) / _smoothScrollingDuration); 12352 12353 renderTop = (_smoothScrolling.startTop + progress * _smoothScrolling.to
12353pDiff) | 0; 12354 } 12355 } 12356 12357 //Did the scroll position even change? 12358 if(_forceRender || _lastTop !== renderTop) { 12359 //Remember in which direction are we scrolling? 12360 _direction = (renderTop > _lastTop) ? 'down' : (renderTop < _lastTop ? 'up' : _direction); 12361 12362 _forceRender = false; 12363 12364 var listenerParams = { 12365 curTop: renderTop, 12366 lastTop: _lastTop, 12367 maxTop: _maxKeyFrame, 12368 direction: _direction 12369 }; 12370 12371 //Tell the listener we are about to render. 12372 var continueRendering = _listeners.beforerender && _listeners.beforerender.call(_instance, listenerParams); 12373 12374 //The beforerender listener function is able the cancel rendering. 12375 if(continueRendering !== false) { 12376 //Now actually interpolate all the styles. 12377 _calcSteps(renderTop, _instance.getScrollTop()); 12378 12379 //That's were we actually "scroll" on mobile. 12380 if(_isMobile && _skrollrBody) { 12381 //Set the transform ("scroll it"). 12382 skrollr.setStyle(_skrollrBody, 'transform', 'translate(0, ' + -(_mobileOffset) + 'px) ' + _translateZ); 12383 } 12384 12385 //Remember when we last rendered. 12386 _lastTop = renderTop; 12387 12388 if(_listeners.render) { 12389 _listeners.render.call(_instance, listenerParams); 12390 } 12391 } 12392 12393 if(afterAnimationCallback) { 12394 afterAnimationCallback.call(_instance, false); 12395 } 12396 } 12397 12398 _lastRenderCall = now; 12399 }; 12400 12401 /** 12402 * Parses the properties for each key frame of the given skrollable. 12403 */ 12404 var _parseProps = function(skrollable) { 12405 //Iterate over all key frames 12406 var keyFrameIndex = 0; 12407 var keyFramesLength = skrollable.keyFrames.length; 12408 12409 for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) { 12410 var frame = skrollable.keyFrames[keyFrameIndex]; 12411 var easing; 12412 var value; 12413 var prop; 12414 var props = {}; 12415 12416 var match; 12417 12418 while((match = rxPropValue.exec(frame.props)) !== null) { 12419 prop = match[1]; 12420 value = match[2]; 12421 12422 easing = prop.match(rxPropEasing); 12423 12424 //Is there an easing specified for this prop? 12425 if(easing !== null) { 12426 prop = easing[1]; 12427 easing = easing[2]; 12428 } else { 12429 easing = DEFAULT_EASING; 12430 } 12431 12432 //Exclamation point at first position forces the value to be taken literal. 12433 value = value.indexOf('!') ? _parseProp(value) : [value.slice(1)]; 12434 12435 //Save the prop for this key frame with his value and easing function 12436 props[prop] = { 12437 value: value, 12438 easing: easings[easing] 12439 }; 12440 } 12441 12442 frame.props = props; 12443 } 12444 }; 12445 12446 /** 12447 * Parses a value extracting numeric values and generating a format string 12448 * for later interpolation of the new values in old string. 12449 * 12450 * @param val The CSS value to be parsed. 12451 * @return Something like ["rgba(?%,?%, ?%,?)", 100, 50, 0, .7] 12452 * where the first element is the format string later used 12453 * and all following elements are the numeric value. 12454 */ 12455 var _parseProp = function(val) { 12456 var numbers = []; 12457 12458 //One special case, where floats don't work. 12459 //We replace all occurences of rgba colors 12460 //which don't use percentage notation with the percentage notation. 12461 rxRGBAIntegerColor.lastIndex = 0; 12462 val = val.replace(rxRGBAIntegerColor, function(rgba) { 12463 return rgba.replace(rxNumericValue, function(n) { 12464 return n / 255 * 100 + '%'; 12465 }); 12466 }); 12467 12468 //Handle prefixing of "gradient" values. 12469 //For now only the prefixed value will be set. Unprefixed isn't supported anyway. 12470 if(theDashedCSSPrefix) { 12471 rxGradient.lastIndex = 0; 12472 val = val.replace(rxGradient, function(s) { 12473 return theDashedCSSPrefix + s; 12474 }); 12475 } 12476 12477 //Now parse ANY number inside this string and create a format string. 12478 val = val.replace(rxNumericValue, function(n) { 12479 numbers.push(+n); 12480 return '{?}'; 12481 }); 12482 12483 //Add the formatstring as first value. 12484 numbers.unshift(val); 12485 12486 return numbers; 12487 }; 12488 12489 /** 12490 * Fills the key frames with missing left and right hand properties. 12491 * If key frame 1 has property X and key frame 2 is missing X, 12492 * but key frame 3 has X again, then we need to assign X to key frame 2 too. 12493 * 12494 * @param sk A skrollable. 12495 */ 12496 var _fillProps = function(sk) { 12497 //Will collect the properties key frame by key frame 12498 var propList = {}; 12499 var keyFrameIndex; 12500 var keyFramesLength; 12501 12502 //Iterate over all key frames from left to right 12503 keyFrameIndex = 0; 12504 keyFramesLength = sk.keyFrames.length; 12505 12506 for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) { 12507 _fillPropForFrame(sk.keyFrames[keyFrameIndex], propList); 12508 } 12509 12510 //Now do the same from right to fill the last gaps 12511 12512 propList = {}; 12513 12514 //Iterate over all key frames from right to left 12515 keyFrameIndex = sk.keyFrames.length - 1; 12516 12517 for(; keyFrameIndex >= 0; keyFrameIndex--) { 12518 _fillPropForFrame(sk.keyFrames[keyFrameIndex], propList); 12519 } 12520 }; 12521 12522 var _fillPropForFrame = function(frame, propList) { 12523 var key; 12524 12525 //For each key frame iterate over all right hand properties and assign them, 12526 //but only if the current key frame doesn't have the property by itself 12527 for(key in propList) { 12528 //The current frame misses this property, so assign it. 12529 if(!hasProp.call(frame.props, key)) { 12530 frame.props[key] = propList[key]; 12531 } 12532 } 12533 12534 //Iterate over all props of the current frame and collect them 12535 for(key in frame.props) { 12536 propList[key] = frame.props[key]; 12537 } 12538 }; 12539 12540 /** 12541 * Calculates the new values for two given values array. 12542 */ 12543 var _calcInterpolation = function(val1, val2, progress) { 12544 var valueIndex; 12545 var val1Length = val1.length; 12546 12547 //They both need to have the same length 12548 if(val1Length !== val2.length) { 12549 throw 'Can\'t interpolate between "' + val1[0] + '" and "' + val2[0] + '"'; 12550 } 12551
12552 //Add the format string as first element. 12553 var interpolated = [val1[0]]; 12554 12555 valueIndex = 1; 12556 12557 for(; valueIndex < val1Length; valueIndex++) { 12558 //That's the line where the two numbers are actually interpolated. 12559 interpolated[valueIndex] = val1[valueIndex] + ((val2[valueIndex] - val1[valueIndex]) * progress); 12560 } 12561 12562 return interpolated; 12563 }; 12564 12565 /** 12566 * Interpolates the numeric values into the format string. 12567 */ 12568 var _interpolateString = function(val) { 12569 var valueIndex = 1; 12570 12571 rxInterpolateString.lastIndex = 0; 12572 12573 return val[0].replace(rxInterpolateString, function() { 12574 return val[valueIndex++]; 12575 }); 12576 }; 12577 12578 /** 12579 * Resets the class and style attribute to what it was before skrollr manipulated the element. 12580 * Also remembers the values it had before reseting, in order to undo the reset. 12581 */ 12582 var _reset = function(elements, undo) { 12583 //We accept a single element or an array of elements. 12584 elements = [].concat(elements); 12585 12586 var skrollable; 12587 var element; 12588 var elementsIndex = 0; 12589 var elementsLength = elements.length; 12590 12591 for(; elementsIndex < elementsLength; elementsIndex++) { 12592 element = elements[elementsIndex]; 12593 skrollable = _skrollables[element[SKROLLABLE_ID_DOM_PROPERTY]]; 12594 12595 //Couldn't find the skrollable for this DOM element. 12596 if(!skrollable) { 12597 continue; 12598 } 12599 12600 if(undo) { 12601 //Reset class and style to the "dirty" (set by skrollr) values. 12602 element.style.cssText = skrollable.dirtyStyleAttr; 12603 _updateClass(element, skrollable.dirtyClassAttr); 12604 } else { 12605 //Remember the "dirty" (set by skrollr) class and style. 12606 skrollable.dirtyStyleAttr = element.style.cssText; 12607 skrollable.dirtyClassAttr = _getClass(element); 12608 12609 //Reset class and style to what it originally was. 12610 element.style.cssText = skrollable.styleAttr; 12611 _updateClass(element, skrollable.classAttr); 12612 } 12613 } 12614 }; 12615 12616 /** 12617 * Detects support for 3d transforms by applying it to the skrollr-body. 12618 */ 12619 var _detect3DTransforms = function() { 12620 _translateZ = 'translateZ(0)'; 12621 skrollr.setStyle(_skrollrBody, 'transform', _translateZ); 12622 12623 var computedStyle = getStyle(_skrollrBody); 12624 var computedTransform = computedStyle.getPropertyValue('transform'); 12625 var computedTransformWithPrefix = computedStyle.getPropertyValue(theDashedCSSPrefix + 'transform'); 12626 var has3D = (computedTransform && computedTransform !== 'none') || (computedTransformWithPrefix && computedTransformWithPrefix !== 'none'); 12627 12628 if(!has3D) { 12629 _translateZ = ''; 12630 } 12631 }; 12632 12633 /** 12634 * Set the CSS property on the given element. Sets prefixed properties as well. 12635 */ 12636 skrollr.setStyle = function(el, prop, val) { 12637 var style = el.style; 12638 12639 //Camel case. 12640 prop = prop.replace(rxCamelCase, rxCamelCaseFn).replace('-', ''); 12641 12642 //Make sure z-index gets a <integer>. 12643 //This is the only <integer> case we need to handle. 12644 if(prop === 'zIndex') { 12645 if(isNaN(val)) { 12646 //If it's not a number, don't touch it. 12647 //It could for example be "auto" (#351). 12648 style[prop] = val; 12649 } else { 12650 //Floor the number. 12651 style[prop] = '' + (val | 0); 12652 } 12653 } 12654 //#64: "float" can't be set across browsers. Needs to use "cssFloat" for all except IE. 12655 else if(prop === 'float') { 12656 style.styleFloat = style.cssFloat = val; 12657 } 12658 else { 12659 //Need try-catch for old IE. 12660 try { 12661 //Set prefixed property if there's a prefix. 12662 if(theCSSPrefix) { 12663 style[theCSSPrefix + prop.slice(0,1).toUpperCase() + prop.slice(1)] = val; 12664 } 12665 12666 //Set unprefixed. 12667 style[prop] = val; 12668 } catch(ignore) {} 12669 } 12670 }; 12671 12672 /** 12673 * Cross browser event handling. 12674 */ 12675 var _addEvent = skrollr.addEvent = function(element, names, callback) { 12676 var intermediate = function(e) { 12677 //Normalize IE event stuff. 12678 e = e || window.event; 12679 12680 if(!e.target) { 12681 e.target = e.srcElement; 12682 } 12683 12684 if(!e.preventDefault) { 12685 e.preventDefault = function() { 12686 e.returnValue = false; 12687 e.defaultPrevented = true; 12688 }; 12689 } 12690 12691 return callback.call(this, e); 12692 }; 12693 12694 names = names.split(' '); 12695 12696 var name; 12697 var nameCounter = 0; 12698 var namesLength = names.length; 12699 12700 for(; nameCounter < namesLength; nameCounter++) { 12701 name = names[nameCounter]; 12702 12703 if(element.addEventListener) { 12704 element.addEventListener(name, callback, false); 12705 } else { 12706 element.attachEvent('on' + name, intermediate); 12707 } 12708 12709 //Remember the events to be able to flush them later. 12710 _registeredEvents.push({ 12711 element: element, 12712 name: name, 12713 listener: callback 12714 }); 12715 } 12716 }; 12717 12718 var _removeEvent = skrollr.removeEvent = function(element, names, callback) { 12719 names = names.split(' '); 12720 12721 var nameCounter = 0; 12722 var namesLength = names.length; 12723 12724 for(; nameCounter < namesLength; nameCounter++) { 12725 if(element.removeEventListener) { 12726 element.removeEventListener(names[nameCounter], callback, false); 12727 } else { 12728 element.detachEvent('on' + names[nameCounter], callback); 12729 } 12730 } 12731 }; 12732 12733 var _removeAllEvents = function() { 12734 var eventData; 12735 var eventCounter = 0; 12736 var eventsLength = _registeredEvents.length; 12737 12738 for(; eventCounter < eventsLength; eventCounter++) { 12739 eventData = _registeredEvents[eventCounter]; 12740 12741 _removeEvent(eventData.element, eventData.name, eventData.listener); 12742 } 12743 12744 _registeredEvents = []; 12745 }; 12746 12747 var _emitEvent = function(element, name, direction) { 12748 if(_listeners.keyframe) { 12749 _listeners.keyframe.call(_instance, element, name, direction); 12750 } 12751 }; 12752 12753 var _reflow = function() { 12754 var pos = _instance.getScrollTop(); 12755 12756 //Will be recalculated by _updateDependentKeyFrames. 12757 _maxKeyFrame = 0; 12758 12759 if(_forceHeight && !_isMobile) { 12760 //un-"force" the height to not mess with the calculations in _updateDependentKeyFrames (#216). 12761 body.style.height = ''; 12762 } 12763 12764 _updateDependentKeyFrames(); 12765 12766 if(_forceHeight && !_isMobile) { 12767 //"force" the height. 12768 body.style.height = (_maxKeyFrame + documentElement.clientHeight) + 'px'; 12769 } 12770 12771 //The scroll offset may now be larger than needed (on desktop the browser/os prevents scrolling farther than the bottom). 12772 if(_isMobile) { 12773 _instance.setScrollTop(Math.min(_instance.getScrollTop(), _maxKeyFrame)); 12774 } else { 12775 //Remember and reset the scroll pos (#217). 12776 _instance.setScrollTop(pos, true); 12777 } 12778 12779 _forceRender = true; 12780 }; 12781 12782 /* 12783 * Returns a copy of the constants object where all functions and strings have been evaluated. 12784 */ 12785 var _processConstants = function() {
12786 var viewportHeight = documentElement.clientHeight; 12787 var copy = {}; 12788 var prop; 12789 var value; 12790 12791 for(prop in _constants) { 12792 value = _constants[prop]; 12793 12794 if(typeof value === 'function') { 12795 value = value.call(_instance); 12796 } 12797 //Percentage offset. 12798 else if((/p$/).test(value)) { 12799 value = (value.slice(0, -1) / 100) * viewportHeight; 12800 } 12801 12802 copy[prop] = value; 12803 } 12804 12805 return copy; 12806 }; 12807 12808 /* 12809 * Returns the height of the document. 12810 */ 12811 var _getDocumentHeight = function() { 12812 var skrollrBodyHeight = 0; 12813 var bodyHeight; 12814 12815 if(_skrollrBody) { 12816 skrollrBodyHeight = Math.max(_skrollrBody.offsetHeight, _skrollrBody.scrollHeight); 12817 } 12818 12819 bodyHeight = Math.max(skrollrBodyHeight, body.scrollHeight, body.offsetHeight, documentElement.scrollHeight, documentElement.offsetHeight, documentElement.clientHeight); 12820 12821 return bodyHeight - documentElement.clientHeight; 12822 }; 12823 12824 /** 12825 * Returns a string of space separated classnames for the current element. 12826 * Works with SVG as well. 12827 */ 12828 var _getClass = function(element) { 12829 var prop = 'className'; 12830 12831 //SVG support by using className.baseVal instead of just className. 12832 if(window.SVGElement && element instanceof window.SVGElement) { 12833 element = element[prop]; 12834 prop = 'baseVal'; 12835 } 12836 12837 return element[prop]; 12838 }; 12839 12840 /** 12841 * Adds and removes a CSS classes. 12842 * Works with SVG as well.
12843 * add and remove are arrays of strings, 12844 * or if remove is ommited add is a string and overwrites all classes. 12845 */ 12846 var _updateClass = function(element, add, remove) { 12847 var prop = 'className'; 12848 12849 //SVG support by using className.baseVal instead of just className. 12850 if(window.SVGElement && element instanceof window.SVGElement) { 12851 element = element[prop]; 12852 prop = 'baseVal'; 12853 } 12854 12855 //When remove is ommited, we want to overwrite/set the classes. 12856 if(remove === undefined) { 12857 element[prop] = add; 12858 return; 12859 } 12860 12861 //Cache current classes. We will work on a string before passing back to DOM. 12862 var val = element[prop]; 12863 12864 //All classes to be removed. 12865 var classRemoveIndex = 0; 12866 var removeLength = remove.length; 12867 12868 for(; classRemoveIndex < removeLength; classRemoveIndex++) { 12869 val = _untrim(val).replace(_untrim(remove[classRemoveIndex]), ' '); 12870 } 12871 12872 val = _trim(val); 12873 12874 //All classes to be added. 12875 var classAddIndex = 0; 12876 var addLength = add.length; 12877 12878 for(; classAddIndex < addLength; classAddIndex++) { 12879 //Only add if el not already has class. 12880 if(_untrim(val).indexOf(_untrim(add[classAddIndex])) === -1) { 12881 val += ' ' + add[classAddIndex]; 12882 } 12883 } 12884 12885 element[prop] = _trim(val); 12886 }; 12887 12888 var _trim = function(a) { 12889 return a.replace(rxTrim, ''); 12890 }; 12891 12892 /** 12893 * Adds a space before and after the string. 12894 */ 12895 var _untrim = function(a) { 12896 return ' ' + a + ' '; 12897 }; 12898 12899 var _now = Date.now || function() { 12900 return +new Date(); 12901 }; 12902 12903 var _keyFrameComparator = function(a, b) { 12904 return a.frame - b.frame; 12905 }; 12906 12907 /* 12908 * Private variables. 12909 */ 12910 12911 //Singleton 12912 var _instance; 12913 12914 /* 12915 A list of all elements which should be animated associated with their the metadata. 12916 Exmaple skrollable with two key frames animating from 100px width to 20px: 12917 12918 skrollable = { 12919 element: <the DOM element>, 12920 styleAttr: <style attribute of the element before skrollr>, 12921 classAttr: <class attribute of the element before skrollr>, 12922 keyFrames: [ 12923 { 12924 frame: 100, 12925 props: { 12926 width: { 12927 value: ['{?}px', 100], 12928 easing: <reference to easing function> 12929 } 12930 }, 12931 mode: "absolute" 12932 }, 12933 { 12934 frame: 200, 12935 props: { 12936 width: { 12937 value: ['{?}px', 20], 12938 easing: <reference to easing function> 12939 } 12940 }, 12941 mode: "absolute" 12942 } 12943 ] 12944 }; 12945 */ 12946 var _skrollables; 12947 12948 var _skrollrBody; 12949 12950 var _listeners; 12951 var _forceHeight; 12952 var _maxKeyFrame = 0; 12953 12954 var _scale = 1; 12955 var _constants; 12956 12957 var _mobileDeceleration; 12958 12959 //Current direction (up/down). 12960 var _direction = 'down'; 12961 12962 //The last top offset value. Needed to determine direction. 12963 var _lastTop = -1; 12964 12965 //The last time we called the render method (doesn't mean we rendered!). 12966 var _lastRenderCall = _now(); 12967 12968 //For detecting if it actually resized (#271). 12969 var _lastViewportWidth = 0; 12970 var _lastViewportHeight = 0; 12971 12972 var _requestReflow = false; 12973 12974 //Will contain data about a running scrollbar animation, if any. 12975 var _scrollAnimation; 12976 12977 var _smoothScrollingEnabled; 12978 12979 var _smoothScrollingDuration; 12980 12981 //Will contain settins for smooth scrolling if enabled. 12982 var _smoothScrolling; 12983 12984 //Can be set by any operation/event to force rendering even if the scrollbar didn't move. 12985 var _forceRender; 12986 12987 //Each skrollable gets an unique ID incremented for each skrollable. 12988 //The ID is the index in the _skrollables array. 12989 var _skrollableIdCounter = 0; 12990 12991 var _edgeStrategy; 12992 12993 12994 //Mobile specific vars. Will be stripped by UglifyJS when not in use. 12995 var _isMobile = false; 12996 12997 //The virtual scroll offset when using mobile scrolling. 12998 var _mobileOffset = 0; 12999 13000 //If the browser supports 3d transforms, this will be filled with 'translateZ(0)' (empty string otherwise). 13001 var _translateZ; 13002 13003 //Will contain data about registered events by skrollr. 13004 var _registeredEvents = []; 13005 13006 //Animation frame id returned by RequestAnimationFrame (or timeout when RAF is not supported). 13007 var _animFrame; 13008 13009 //Expose skrollr as either a global variable or a require.js module. 13010 if(typeof define === 'function' && define.amd) { 13011 define([], function () { 13012 return skrollr; 13013 }); 13014 } else if (typeof module !== 'undefined' && module.exports) { 13015 module.exports = skrollr; 13016 } else { 13017 window.skrollr = skrollr; 13018 } 13019 13020}(window, document)); 13021 13022(function(window, $) { 13023 "use strict"; 13024 13025 var counter = 0, 13026 $headCache = $('head'), 13027 oldBigText = window.BigText, 13028 oldjQueryMethod = $.fn.bigtext, 13029 BigText = { 13030 DEBUG_MODE: false, 13031 DEFAULT_MIN_FONT_SIZE_PX: null, 13032 DEFAULT_MAX_FONT_SIZE_PX: 528, 13033 GLOBAL_STYLE_ID: 'bigtext-style', 13034 STYLE_ID: 'bigtext-id', 13035 LINE_CLASS_PREFIX: 'bigtext-line', 13036 EXEMPT_CLASS: 'bigtext-exempt', 13037 noConflict: function(restore) 13038 { 13039 if(restore) { 13040 $.fn.bigtext = oldjQueryMethod; 13041 window.BigText = oldBigText; 13042 } 13043 return BigText; 13044 }, 13045 supports: { 13046 wholeNumberFontSizeOnly: (function() { 13047 if( !( 'getComputedStyle' in window ) ) { 13048 return true; 13049 } 13050 var test = $('<div/>').css({ 13051 position: 'absolute', 13052 'font-size': '14.1px' 13053 }).insertBefore( $('script').eq(0) ), 13054 computedStyle = window.getComputedStyle( test[0], null ); 13055 13056 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 13057 test.remove(); 13058 return ret; 13059 })() 13060 }, 13061 init: function() { 13062 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 13063 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 13064 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 13065 } 13066 }, 13067 bindResize: function(eventName, resizeFunction) { 13068 var timeoutId; 13069 $(window).unbind(eventName).bind(eventName, function() { 13070 if( timeoutId ) { 13071 clearTimeout( timeoutId ); 13072 } 13073 timeoutId = setTimeout( resizeFunction, 100 ); 13074 }); 13075 }, 13076 getStyleId: function(id) 13077 { 13078 return BigText.STYLE_ID + '-' + id; 13079 }, 13080 generateStyleTag: function(id, css) 13081 { 13082 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 13083 }, 13084 clearCss: function(id) 13085 { 13086 var styleId = BigText.getStyleId(id); 13087 $('#' + styleId).remove(); 13088 }, 13089 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 13090 { 13091 var css = []; 13092 13093 BigText.clearCss(id); 13094 13095 for(var j=0, k=linesFontSizes.length; j<k; j++) { 13096 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 13097 (minFontSizes[j] ? ' white-space: normal;' : '') + 13098 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 13099 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 13100 '}'); 13101 } 13102 13103 return BigText.generateStyleTag(BigText.getStyleId(id), css); 13104 }, 13105 jQueryMethod: function(options) 13106 {
13107 BigText.init(); 13108 13109 options = $.extend({ 13110 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 13111 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 13112 childSelector: '', 13113 resize: true 13114 }, options || {}); 13115 13116 this.each(function() 13117 { 13118 var $t = $(this).addClass('bigtext'), 13119 maxWidth = $t.width(), 13120 id = $t.attr('id'), 13121 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 13122 13123 if(!id) { 13124 id = 'bigtext-id' + (counter++); 13125 $t.attr('id', id); 13126 } 13127 13128 if(options.resize) { 13129 BigText.bindResize('resize.bigtext-event-' + id, function() 13130 { 13131 // TODO only call this if the width has changed. 13132 BigText.jQueryMethod.call($('#' + id), options); 13133 }); 13134 } 13135 13136 BigText.clearCss(id); 13137 13138 $children.addClass(function(lineNumber, className) 13139 { 13140 // remove existing line classes. 13141 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 13142 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 13143 }); 13144 13145 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 13146 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 13147 }); 13148 13149 return this.trigger('bigtext:complete'); 13150 } 13151 }; 13152 13153 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 13154 { 13155 var width; 13156 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 13157 $line.css(property, size + units); 13158 13159 width = $line.width(); 13160 13161 if(width >= maxWidth) { 13162// console.log(width, ' previous: ' + previousWidth, property + ' at ' + interval, 'prior: ' + (parseFloat(size) - interval), 'new:' + parseFloat(size)); 13163 $line.css(property, ''); 13164 13165 if(width === maxWidth) { 13166 return { 13167 match: 'exact', 13168 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 13169 }; 13170 } 13171 13172 // Since this is an estimate, we calculate how far over the width we went with the new value. 13173 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 13174 // Otherwise, we revert to the underestimate. 13175 var under = maxWidth - previousWidth, 13176 over = width - maxWidth; 13177 13178 return { 13179 match: 'estimate', 13180 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 13181 }; 13182 } 13183 13184 return width; 13185 } 13186 13187 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 13188 { 13189 var $c = $t.clone(true) 13190 .addClass('bigtext-cloned') 13191 .css({ 13192 fontFamily: $t.css('font-family'), 13193 textTransform: $t.css('text-transform'), 13194 wordSpacing: $t.css('word-spacing'), 13195 letterSpacing: $t.css('letter-spacing'), 13196 position: 'absolute', 13197 left: BigText.DEBUG_MODE ? 0 : -9999, 13198 top: BigText.DEBUG_MODE ? 0 : -9999 13199 }) 13200 .appendTo(document.body); 13201 13202 // font-size isn't the only thing we can modify, we can also mess with: 13203 // word-spacing and letter-spacing. WebKit does not respect subpixel 13204 // letter-spacing, word-spacing, or font-size. 13205 // TODO try -webkit-transform: scale() as a workaround. 13206 var fontSizes = [], 13207 wordSpacings = [], 13208 minFontSizes = [], 13209 ratios = []; 13210 13211 $children.css('float', 'left').each(function() { 13212 var $line = $(this), 13213 // TODO replace 8, 4 with a proportional size to the calculated font-size. 13214 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 13215 lineMax, 13216 newFontSize; 13217 13218 if($line.hasClass(BigText.EXEMPT_CLASS)) { 13219 fontSizes.push(null); 13220 ratios.push(null); 13221 minFontSizes.push(false); 13222 return; 13223 } 13224 13225 // TODO we can cache this ratio? 13226 var autoGuessSubtraction = 32, // font size in px 13227 currentFontSize = parseFloat($line.css('font-size')), 13228 ratio = ( $line.width() / currentFontSize ).toFixed(6); 13229 13230 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 13231 13232 outer: for(var m=0, n=intervals.length; m<n; m++) { 13233 inner: for(var j=1, k=10; j<=k; j++) { 13234 if(newFontSize + j*intervals[m] > maxFontSize) { 13235 newFontSize = maxFontSize; 13236 break outer; 13237 } 13238 13239 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 13240 if(typeof lineMax !== 'number') { 13241 newFontSize = lineMax.size; 13242 13243 if(lineMax.match === 'exact') { 13244 break outer; 13245 } 13246 break inner; 13247 } 13248 } 13249 } 13250 13251 ratios.push(maxWidth / newFontSize); 13252 13253 if(newFontSize > maxFontSize) { 13254 fontSizes.push(maxFontSize); 13255 minFontSizes.push(false); 13256 } else if(!!minFontSize && newFontSize < minFontSize) { 13257 fontSizes.push(minFontSize); 13258 minFontSizes.push(true); 13259 } else { 13260 fontSizes.push(newFontSize); 13261 minFontSizes.push(false); 13262 } 13263 }).each(function(lineNumber) { 13264 var $line = $(this), 13265 wordSpacing = 0, 13266 interval = 1, 13267 maxWordSpacing; 13268 13269 if($line.hasClass(BigText.EXEMPT_CLASS)) { 13270 wordSpacings.push(null); 13271 return; 13272 } 13273 13274 // must re-use font-size, even though it was removed above. 13275 $line.css('font-size', fontSizes[lineNumber] + 'px'); 13276 13277 for(var m=1, n=3; m<n; m+=interval) { 13278 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 13279 if(typeof maxWordSpacing !== 'number') { 13280 wordSpacing = maxWordSpacing.size; 13281 break; 13282 } 13283 } 13284 13285 $line.css('font-size', ''); 13286 wordSpacings.push(wordSpacing); 13287 }).removeAttr('style'); 13288 13289 if( !BigText.DEBUG_MODE ) { 13290 $c.remove(); 13291 } else { 13292 $c.css({ 13293 'background-color': 'rgba(255,255,255,.4)' 13294 }); 13295 } 13296 13297 return { 13298 fontSizes: fontSizes, 13299 wordSpacings: wordSpacings, 13300 ratios: ratios, 13301 minFontSizes: minFontSizes 13302 }; 13303 } 13304 13305 $.fn.bigtext = BigText.jQueryMethod; 13306 window.BigText = BigText; 13307 13308})(this, jQuery); 13309 13310/* ======================================================================== 13311 * Omega: theme.js 13312 * Main Theme Javascript file 13313 * ======================================================================== 13314 * Copyright 2014 Oxygenna LTD 13315 * ======================================================================== */ 13316 13317'use strict'; 13318 13319// ignore camel case because it breaks jshint for vars from php localisation 13320/* jshint camelcase: false */ 13321 13322/* global jQuery: false, skrollr: false, Odometer: false, paceOptions: false, Pace: false, Waypoint: false */ 13323 13324// If script is not localized apply defaults 13325 13326var oxyThemeData = oxyThemeData || { 13327 navbarHeight : 100, 13328 navbarScrolled : 70, 13329 navbarScrolledPoint : 200, 13330 menuClose : 'off', 13331 scrollFinishedMessage : 'No more items to load.',
13332 hoverMenu : { 13333 hoverActive : false, 13334 hoverDelay : 1, 13335 hoverFadeDelay : 200 13336 }, 13337 siteLoader: 'on' 13338}; 13339 13340window.paceOptions = { 13341 startOnPageLoad: oxyThemeData.siteLoader === 'on', 13342 restartOnRequestAfter: false 13343}; 13344// Loading Slabtext on window load to make sure fonts are loaded 13345jQuery(window).on('load', function () { 13346 jQuery( '.bigtext' ).bigtext( 13347 { 13348 minfontsize: 16 13349 }); 13350}); 13351 13352jQuery(document).ready(function( $ ) { 13353 // Parallax Scrolling - on desktops only 13354 // ====================== 13355 if(!(/Android|iPhone|iPad|iPod|BlackBerry|Windows Phone/i).test(navigator.userAgent || navigator.vendor || window.opera)){ 13356 skrollr.init({ 13357 forceHeight: false 13358 }); 13359 } else { 13360 // Assign the 'oxy-agent' class when not assigned by PHP - for the html Version 13361 // ====================== 13362 $('body:not([class*="oxy-agent-"])').addClass('oxy-agent-'); 13363 if((/iPhone/i).test(navigator.userAgent || navigator.vendor || window.opera)){ 13364 $('body').not('.oxy-agent-iphone').addClass('oxy-agent-iphone'); 13365 } 13366 if((/iPad/i).test(navigator.userAgent || navigator.vendor || window.opera)){ 13367 $('body').not('.oxy-agent-ipad').addClass('oxy-agent-ipad'); 13368 } 13369 } 13370 13371 var isMobile = !$('body:not([class*="oxy-agent-"])').length; 13372 13373 // Flexslider Init 13374 // ====================== 13375 13376 function flexInit( element ) { 13377 // We use data atributes on the flexslider items to control the behaviour of the slideshow 13378 var slider = $(element), 13379 13380 //data-slideshow: defines if the slider will start automatically (true) or not 13381 sliderShow = slider.attr('data-flex-slideshow') === 'false' ? false : true, 13382 13383 //data-flex-animation: defines the animation type, slide (default) or fade 13384 sliderAnimation = !slider.attr('data-flex-animation') ? 'slide' : slider.attr('data-flex-animation'), 13385 13386 //data-flex-speed: defines the animation speed, 7000 (default) or any number 13387 sliderSpeed = !slider.attr('data-flex-speed') ? 7000 : slider.attr('data-flex-speed'), 13388 13389 //data-flex-sliderdirection: defines the slide direction 13390 direction = !slider.attr('data-flex-sliderdirection') ? 'horizontal' : slider.attr('data-flex-sliderdirection'), 13391 13392 //data-flex-duration: defines the transition speed in milliseconds 13393 sliderDuration = !slider.attr('data-flex-duration') ? 600 : slider.attr('data-flex-duration'), 13394 13395 //data-flex-directions: defines the visibillity of the nanigation arrows, hide (default) or show 13396 sliderDirections = slider.attr('data-flex-directions') === 'hide' ? false : true, 13397 13398 //data-flex-controls: defines the visibillity of the nanigation controls, hide (default) or show 13399 sliderControls = slider.attr('data-flex-controls') === 'thumbnails' ? 'thumbnails' : slider.attr('data-flex-controls') === 'hide' ? false : true, 13400 13401 //data-flex-controlsposition: defines the positioning of the controls, inside (default) absolute positioning on the slideshow, or outside 13402 sliderControlsPosition = slider.attr('data-flex-controlsposition') === 'inside' ? 'flex-controls-inside' : 'flex-controls-outside', 13403 13404 //data-flex-controlsalign: defines the alignment of the controls, center (default) left or right 13405 sliderControlsAlign = !slider.attr('data-flex-controlsalign') ? 'flex-controls-center' : 'flex-controls-' + slider.attr('data-flex-controlsalign'), 13406 13407 //data-flex-controlsalign: defines the alignment of the controls, center (default) left or right 13408 sliderControlsVericalAlign = !slider.attr('data-flex-controlsvertical') ? '' : 'flex-controls-' + slider.attr('data-flex-controlsvertical'), 13409 13410 //data-flex-itemwidth: the width of each item in case of a multiitem carousel, 0 (default for 100%) or a nymber representing pixels 13411 sliderItemWidth = !slider.attr('data-flex-itemwidth') ? 0 : parseInt(slider.attr('data-flex-itemwidth'), 10), 13412 13413 //data-flex-itemmax: the max number of items in a carousel 13414 sliderItemMax = !slider.attr('data-flex-itemmax') ? 0 : parseInt(slider.attr('data-flex-itemmax'), 0), 13415 13416 //data-flex-itemmin: the max number of items in a carousel 13417 sliderItemMin = !slider.attr('data-flex-itemmin') ? 0 : parseInt(slider.attr('data-flex-itemmin'), 0), 13418
13419 //data-flex-captionvertical: defines the horizontal positioning of the captions, left or right or alternate 13420 sliderCaptionsHorizontal = slider.attr('data-flex-captionhorizontal') === 'alternate' ? 'flex-caption-alternate' : 'flex-caption-' + slider.attr('data-flex-captionhorizontal'); 13421 13422 slider.addClass(sliderControlsPosition).addClass(sliderControlsAlign).addClass(sliderControlsVericalAlign).addClass(sliderCaptionsHorizontal); 13423 13424 slider.flexslider({ 13425 slideshow: sliderShow, 13426 animation: sliderAnimation, 13427 direction: direction, 13428 slideshowSpeed: parseInt(sliderSpeed), 13429 animationSpeed: parseInt(sliderDuration), 13430 itemWidth: sliderItemWidth, 13431 minItems: sliderItemMin, 13432 maxItems: sliderItemMax, 13433 controlNav: sliderControls, 13434 directionNav: sliderDirections, 13435 prevText: '', 13436 nextText: '', 13437 smoothHeight: true, 13438 useCSS : false 13439 }); 13440 } 13441 13442 // Flexslider Init 13443 $( '.flexslider[id]' ).each(function() { 13444 var that = this; 13445 $(this).imagesLoaded().done( function( instance ) { 13446 flexInit(that); 13447 }); 13448 }); 13449 13450 // Portfolio Isotope 13451 // ====================== 13452 13453 function isotopeInit() { 13454 $('.masonry').each( function( index, element ) { 13455 var $container = $(element); 13456 var $items = $container.find( '.masonry-item' ); 13457 var padding = $container.attr( 'data-padding' ); 13458 var isFullWidth = $container.parents( '.container-fullwidth' ).length > 0; 13459 // On fullscreen portfolio add negative margin on left and right and add 4pixel upon that for the loss after rounding 13460 var containerPadding = -padding / 2; 13461 13462 $container.css({ 13463 margin: '0 ' + containerPadding + 'px' 13464 }); 13465 $container.imagesLoaded().always( function( loadedContainer ) { 13466 setTimeout( function() { 13467 var columns = 3; 13468 var screenWidth = $(window).width(); 13469 13470 var wideColumns = 2; 13471 13472 if( screenWidth < 768 ) { 13473 columns = $container.attr( 'data-col-xs' ); 13474 wideColumns = 1; 13475 } 13476 else if( screenWidth < 992 ) { 13477 columns = $container.attr( 'data-col-sm' ); 13478 wideColumns = 1; 13479 } 13480 else if( screenWidth < 1200 ) { 13481 columns = $container.attr( 'data-col-md' ); 13482 wideColumns = 2 ; 13483 } 13484 else if( screenWidth > 1200 ) { 13485 columns = $container.attr( 'data-col-lg' ); 13486 wideColumns = 2 ; 13487 } 13488 13489 // calculate item width and paddings 13490 var itemWidth; 13491 if ( $container.hasClass( 'use-masonry' ) ) { 13492 $items.each(function() { 13493 // Set the masonry column width 13494 itemWidth = Math.floor( $container.width() / columns ); 13495 13496 var item = $(this); 13497 if( item.hasClass( 'masonry-wide' ) ) { 13498 item.css( 'width', itemWidth * wideColumns ); 13499 } 13500 else { 13501 item.css( 'width', itemWidth ); 13502 } 13503 }); 13504 } 13505 else { 13506 itemWidth = Math.floor( $container.width() / columns ); 13507 $items.css( 'width', itemWidth ); 13508 } 13509 13510 $items.find('.figure,.post-masonry-inner').css( 'padding', padding / 2 + 'px' ); 13511 13512 // wait for possible flexsliders to render before rendering isotope 13513 $container.isotope( { 13514 itemSelector: '.masonry-item', 13515 getSortData : { 13516 default: function ( $elem ) { 13517 return parseInt( $elem.attr( 'data-menu-order' ) ); 13518 }, 13519 title: function ( $elem ) { 13520 return $elem.attr( 'data-title' ); 13521 }, 13522 date: function ( $elem ) { 13523 return Date.parse( $elem.attr( 'data-date' ) ); 13524 }, 13525 comments: function( $elem ) { 13526 return parseInt( $elem.attr( 'data-comments') ); 13527 } 13528 }, 13529 sortBy: 'default', 13530 layoutMode: $container.attr( 'data-layout' ), 13531 resizable: false, 13532 masonry: { 13533 columnWidth: itemWidth, 13534 gutter: padding 13535 } 13536 }, function(){ 13537 // refresh waypoints after layout 13538 Waypoint.refreshAll(); 13539 $container.removeClass( 'no-transition' ); 13540 onScrollInit( $items.find( '.portfolio-os-animation' ), $container ); 13541 onScrollInit( $items.find( '.blog-os-animation' ), $container ); 13542 }); 13543 },200);
13544 }); 13545 }); 13546 } 13547 13548 // Re initialise isotope on window resize 13549 $(window).smartresize(function(){ 13550 isotopeInit(); 13551 }); 13552 13553 // Init the isotope 13554 isotopeInit(); 13555 13556 // Portfolio Filters 13557 // ====================== 13558 /* 13559 $('.portfolio-filter').click( function() { 13560 var $button = $(this); 13561 var filter = $button.attr( 'data-filter' ); 13562 var $filtersRow = $button.parents('div.row'); 13563 $filtersRow.find( '.portfolio-title span' ).text( $button.text() ); 13564 var $portfolio = $filtersRow.next(); 13565 $portfolio.isotope( { filter: filter } ); 13566 }); 13567 */ 13568 13569 $('.portfolio-filter').click( function() { 13570 var $button = $(this); 13571 var filter = $button.attr( 'data-filter' ); 13572 console.log('filter:' + filter); 13573 var $filtersRow = $button.parents('div.row'); 13574 $filtersRow.find( '.portfolio-title span' ).text( $button.text() ); 13575 var $portfolio = $('.portfolio table tr'); 13576 console.log('filter:' + $filtersRow.next()); 13577 $portfolio.isotope( { filter: filter } ); 13578 }); 13579 13580 $('.portfolio-order').click( function() { 13581 var $button = $(this); 13582 var order = $button.attr( 'data-value' ); 13583 var $portfolio = $button.parents( 'div.row' ).next(); 13584 $portfolio.isotope( { sortAscending: order === 'true' } ); 13585 }); 13586 13587 $('.portfolio-sort').click( function() { 13588 var $button = $(this); 13589 var sort = $button.attr( 'data-sort' ); 13590 var $portfolio = $button.parents('div.row').next(); 13591 $portfolio.isotope( { sortBy: sort } ); 13592 }); 13593 13594 // Theme Sections 13595 // ====================== 13596 13597 // Adjust full height sections on IOS 13598 $('[class*="oxy-agent-"] .section-fullheight').removeClass('section-fullheight').css('min-height', $(window).height()).find('.container, .container-fullwidth, .container > .row, .container-fullwidth > .row ').css('min-height', $(window).height()).find('.row, [class*="col-md"]').css('position', 'static'); 13599 13600 // fix placeholders for IE 8 & 9 13601 $('html.ie9').find('input, textarea').placeholder(); 13602 13603 // Setiing responsive videos 13604 $( '.video-wrapper' ).fitVids(); 13605 13606 // Play videos & audio 13607 $('audio').mediaelementplayer({ 13608 pauseOtherPlayers: false, 13609 enableAutosize: false, 13610 setDimensions:false, 13611 }); 13612 13613 $('.section-background-video').mediaelementplayer({ 13614 pauseOtherPlayers: false, 13615 enableAutosize: false, 13616 setDimensions:false, 13617 success: function(mediaElement, node, player) { 13618 // video tag is initially hidden ( in order to hide the poster and display the cover bg only ) 13619 var attr = $(mediaElement).attr('poster'); 13620 var hasPoster = false; 13621 13622 if(typeof attr !== typeof undefined && attr !== '') { 13623 hasPoster = true; 13624 $(mediaElement).parent().css('background-image','url(\'' + $(mediaElement).attr('poster') + '\')'); 13625 } 13626 var $section = $(mediaElement).closest('section'); 13627 13628 // loadded data event does not trigger on ios, its dektop only 13629 mediaElement.addEventListener('loadeddata', function () { 13630 // player arg has media property filled only after loadeddata even triggers ( first frame loaded! ) 13631 var containerHeight = $section.outerHeight(); 13632 var containerWidth = $section.outerWidth(); 13633 var playerHeight = player.media.videoHeight; 13634 var playerWidth = player.media.videoWidth; 13635 var aspectRatio = ( playerHeight / playerWidth * 100 ) + '%'; 13636 var scaleFactor = containerWidth /playerWidth;
13637 var playerActualHeight = playerHeight * scaleFactor; 13638 13639 $(mediaElement).parent().css('padding-bottom', aspectRatio); 13640 if( playerActualHeight >= containerHeight ){ 13641 $(mediaElement).css('top', ( containerHeight - (playerHeight * scaleFactor) )/2 ); 13642 } 13643 else { 13644 $(mediaElement).css('background-image', ''); 13645 } 13646 13647 $(mediaElement).show(); 13648 13649 $(window).smartresize(function(){ 13650 containerHeight = $section.outerHeight(); 13651 containerWidth = $section.outerWidth(); 13652 scaleFactor = containerWidth /playerWidth; 13653 playerActualHeight = playerHeight * scaleFactor; 13654 if( playerActualHeight >= containerHeight ){ 13655 $(mediaElement).css('top', ( containerHeight - (playerHeight * scaleFactor) )/2 ); 13656 } 13657 else { 13658 $(mediaElement).css('background-image', ''); 13659 } 13660 }); 13661 }); 13662 13663 // mobile needs a javascript controller for the video 13664 if( $('body[class*="oxy-agent-"]').length ) { 13665 $section.on('click', function (e) { 13666 if(mediaElement.paused) { 13667 mediaElement.play(); 13668 } 13669 else{ 13670 // ipad-only control, since it does not go fullscreen automatically 13671 mediaElement.pause(); 13672 } 13673 }); 13674 13675 // display the play button if not an iphone or mobile video has a poster 13676 if(hasPoster || !$('body').hasClass('oxy-agent-iphone')){ 13677 $section.find('.mejs-overlay-play').show(); 13678 } 13679 // when pausing mobile videos, display the play button 13680 // and hide the video if there is a poster 13681 if(hasPoster){ 13682 mediaElement.addEventListener('pause', function () { 13683 $section.find('.mejs-overlay-play').show(); 13684 $(mediaElement).hide(); 13685 }); 13686 13687 mediaElement.addEventListener('play', function () { 13688 $(mediaElement).show(); 13689 }); 13690 } 13691 } 13692 } 13693 }); 13694 13695 // Feature List Shortcode 13696 // ====================== 13697 13698 // Feature list lines 13699 $('ul.features-connected').each(function() { 13700 var element = $(this); 13701 var div = $('<div class="features-connected-line"></div>').css('border-color' , element.attr('data-linecolor')); 13702 element.find('li').append( div ); 13703 }); 13704 13705 // Countdown Shortcode 13706 // ====================== 13707 13708 $('.countdown').each(function() { 13709 var countdown = $(this); 13710 var date = countdown.attr('data-date' ); 13711 countdown.countdown( date ).on('update.countdown', function(event) { 13712 $(this).find('.counter-days').html( event.offset.totalDays ); 13713 $(this).find('.counter-hours').html( event.offset.hours ); 13714 $(this).find('.counter-minutes').html( event.offset.minutes ); 13715 $(this).find('.counter-seconds').html( event.offset.seconds ); 13716 }); 13717 }); 13718 13719 $('.counter').each(function() { 13720 var $counter = $(this); 13721 var $odometer = $counter.find('.odometer-counter'); 13722 if($odometer.length > 0 ) { 13723 var od = new Odometer({ 13724 el: $odometer[0], 13725 value: $odometer.text(), 13726 format: $counter.attr('data-format') 13727 }); 13728 $counter.waypoint(function() { 13729 window.setTimeout(function() { 13730 $odometer.html( $counter.attr( 'data-count' ) ); 13731 }, 500); 13732 },{ 13733 triggerOnce: true, 13734 offset: 'bottom-in-view' 13735 }); 13736 } 13737 });
13738 13739 // Theme Forms 13740 // ====================== 13741 13742 // Add wrapper to select boxes 13743 $('select').not('.country_to_state, #billing_state, #shipping_state, #calc_shipping_state').wrap('<div class="select-wrap">'); 13744 13745 13746 // Bullet navigation 13747 // ====================== 13748 var menu = $('#masthead'); 13749 var menuInitOffset = $('#masthead').position(); 13750 menuInitOffset = menuInitOffset === undefined ? 0 : menuInitOffset.top; 13751 13752 var menuItems = $('.menu').find('a'); 13753 var scrollMenuItems = menuItems.map(function(){ 13754 var item = this.hash; 13755 if (item && $(item).length ) { 13756 return item; 13757 } 13758 }); 13759 13760 var bulletNav = $('article .bullet-nav'); 13761 if( bulletNav.length || scrollMenuItems.length ) { 13762 var sections = []; 13763 $('article').find('section').each( function() { 13764 // if section has an id 13765 if( this.id ) { 13766 sections.push(this); 13767 } 13768 }); 13769 if( sections.length ) { 13770 if( scrollMenuItems.length ) { 13771 menuItems.parent().removeClass('active current-menu-item'); 13772 } 13773 $.each( sections, function( index, section) { 13774 var $section = $(section); 13775 // create bullet nav 13776 if( bulletNav.length ){ 13777 var list = bulletNav.find('ul'); 13778 var tooltipAtts = ''; 13779 if( 'on' === bulletNav.attr( 'data-show-tooltips' ) ) { 13780 tooltipAtts = 'data-toggle="tooltip" data-placement="left" title="' + $section.attr('data-label') + '"'; 13781 } 13782 list.append('<li><a href="#' + section.id + '" ' + tooltipAtts + '>' + section.id + '</a>'); 13783 } 13784 // set all section up waypoints 13785 $section.waypoint({ 13786 offset: function() { 13787 return sectionWaypointOffset( $section, 'up', menu ); 13788 }, 13789 handler: function(direction) { 13790 if( 'up' === direction ) { 13791 sectionWaypointHandler( scrollMenuItems, menuItems, bulletNav, section ); 13792 } 13793 } 13794 }); 13795 // set all section down waypoints 13796 $section.waypoint({ 13797 offset: function() { 13798 return sectionWaypointOffset( $section, 'down', menu ); 13799 }, 13800 handler: function(direction) { 13801 if( 'down' === direction ) { 13802 sectionWaypointHandler( scrollMenuItems, menuItems, bulletNav, section ); 13803 } 13804 } 13805 }); 13806 }); 13807 // show the bullets if we have any 13808 if( bulletNav.length ){ 13809 bulletNav.show(); 13810 bulletNav.css('top', ( $(window).height() - bulletNav.height() )/ 2 ); 13811 } 13812 } 13813 } 13814 13815 function sectionWaypointOffset( $section, direction, menu ) { 13816 // if we are going up start from -1 to make sure event triggers 13817 var offset = direction === 'up' ? -($section.height() / 2) : 0; 13818 var menuHeight = parseInt(oxyThemeData.navbarHeight); 13819 if( menu.length && menu.hasClass('navbar-sticky') && menu.hasClass('navbar-scrolled') ){ 13820 menuHeight = parseInt(oxyThemeData.navbarScrolled); 13821 } 13822 var sectionOffset = $section.offset().top; 13823 var menuOffset = menu.length? menu.position().top : 0; 13824 if( menu.length && menu.hasClass('navbar-sticky') && ( (menuOffset + menuHeight) <= sectionOffset ) && !isMobile ){ 13825 offset += menuHeight; 13826 } 13827 return offset; 13828 } 13829 13830 function sectionWaypointHandler( scrollMenuItems, menuItems, bulletNav, section ) { 13831 if( scrollMenuItems.length ) { 13832 menuItems.parent().removeClass('active current-menu-item').end().filter('[href$="' + section.id + '"]').parent().addClass('active current-menu-item'); 13833 } 13834 if( bulletNav.length ) { 13835 bulletNav.find('a').removeClass('active').filter('[href$="' + section.id + '"]').addClass('active'); 13836 } 13837 } 13838 13839 // Scroll To Section 13840 // ====================== 13841 13842 $('.menu a, a.scroll-to-id, .bullet-nav a').on('click', function(e) { 13843 var target = this.hash; 13844 var offset = 0; 13845 13846 if(target && $(target).length){ 13847 e.preventDefault(); 13848 13849 var targetOffset = $(target).offset().top; 13850 var menuHeight = parseInt(oxyThemeData.navbarHeight); 13851 13852 if(menu !== undefined && menu.hasClass('navbar-sticky') && ( menuInitOffset + menuHeight <= targetOffset) && !isMobile){ 13853 var scrollPoint = parseInt( oxyThemeData.navbarScrolledPoint ); 13854 var navHeightBeforeScrollPoint = parseInt( oxyThemeData.navbarHeight ); 13855 var navHeightAfterScrollPoint = parseInt( oxyThemeData.navbarScrolled ); 13856 13857 offset = scrollPoint <= targetOffset ? navHeightAfterScrollPoint : navHeightBeforeScrollPoint; 13858 } 13859 13860 $.scrollTo( $(target), 800, { 13861 axis: 'y', 13862 offset: -offset + 1 13863 } ); 13864 } 13865 });
13866 13867 // Calendar Widget 13868 // ====================== 13869 13870 // make WP calendar use boostrap table class 13871 $('#wp-calendar').addClass( 'table' ); 13872 13873 13874 // Search Widget in Navbar 13875 // ====================== 13876 13877 // Add top bar functionallity 13878 $('body').on('click', '.top-search:not(.active) .search-trigger', function() { 13879 $('.top-search').toggleClass('active'); 13880 $('#content').addClass('fade-content'); 13881 if( $('.top-search').closest('.top-bar').length > 0 ) { 13882 $('#masthead').addClass('fade-content'); 13883 } 13884 $('#masthead').toggleClass('search-active'); 13885 $('.top-search').find('form').fadeToggle(300).find('input').focus(); 13886 13887 }); 13888 $('body').on('click', '.top-search.active .search-trigger', function() { 13889 $('.top-search').toggleClass('active'); 13890 $('#content, #masthead').removeClass('fade-content'); 13891 $('.top-search').find('form').fadeToggle(300); 13892 $('#masthead').toggleClass('search-active'); 13893 }); 13894 13895 // Scrolling Events 13896 // ====================== 13897 13898 // header menu changes 13899 var header = $('body').find('.navbar-sticky'); 13900 if(header.length > 0) { 13901 // stop navbar when at top of the page 13902 var sticky = new Waypoint.Sticky({ 13903 element: header[0], 13904 stuckClass: 'navbar-stuck' 13905 }); 13906 } 13907 13908 // fix for menus in content 13909 $('#masthead').parents('.section').css({ 13910 'overflow': 'visible', 13911 'position': 'relative', 13912 'z-index': '1100' 13913 }); 13914 13915 // trigger the waypoint only for fixed position navbar 13916 var menuContainer = $('#masthead.navbar-sticky'); 13917 if(menuContainer.length && menuContainer.hasClass('navbar-sticky')){ 13918 // calculate menu offset in case menu is placed inside the page 13919 var menuOffset = menuContainer.position().top; 13920 $('body').waypoint({ 13921 offset: -( parseInt( oxyThemeData.navbarScrolledPoint ) + menuOffset ), 13922 handler: function(direction) { 13923 // add / remove scrolled class 13924 menuContainer.toggleClass('navbar-scrolled'); 13925 // remove swatch class 13926 var prefix = 'swatch-'; 13927 var classes = menuContainer[0].className.split(' ').filter(function(c) { 13928 return c.lastIndexOf(prefix, 0) !== 0; 13929 }); 13930 menuContainer[0].className = classes.join(' '); 13931 // add back swatch class depending on direction above / below scroll point 13932 // menuContainer.addClass(oxyThemeData.navbarScrolledSwatches[direction]); 13933 13934 menuContainer.one('MSTransitionEnd webkitTransitionEnd oTransitionEnd transitionend', function(){ 13935 // refresh waypoints only once transition ends in order to get correct offsets for sections. 13936 if( !menuContainer.hasClass( 'refreshing' ) ) { 13937 Waypoint.refreshAll(); 13938 } 13939 menuContainer.toggleClass('refreshing'); 13940 }); 13941 } 13942 }); 13943 } 13944 13945 $('body').waypoint({ 13946 offset: -200, 13947 handler: function(direction) { 13948 if(direction === 'down'){ 13949 $('.go-top').css('bottom', '12px').css('opacity', '1'); 13950 } 13951 else{ 13952 $('.go-top').css('bottom', '-44px').css('opacity', '0'); 13953 } 13954 } 13955 }); 13956 13957 // Init On scroll animations 13958 function onScrollInit( items, trigger ) { 13959 items.each( function() { 13960 var osElement = $(this), 13961 osAnimationClass = osElement.attr('data-os-animation'), 13962 osAnimationDelay = osElement.attr('data-os-animation-delay'); 13963 13964 osElement.css({ 13965 '-webkit-animation-delay': osAnimationDelay, 13966 '-moz-animation-delay': osAnimationDelay, 13967 'animation-delay': osAnimationDelay 13968 }); 13969 13970 var osTrigger = ( trigger ) ? trigger : osElement; 13971
13972 osTrigger.waypoint(function() { 13973 osElement.addClass('animated').addClass(osAnimationClass); 13974 },{ 13975 triggerOnce: true, 13976 offset: '90%' 13977 }); 13978 }); 13979 } 13980 13981 function initialisePageScrollAnimations() { 13982 onScrollInit( $('.os-animation') ); 13983 onScrollInit( $( '.staff-os-animation' ), $('.staff-list-container') ); 13984 onScrollInit( $( '.recent-simple-os-animation' ), $('.recent-simple-os-container') ); 13985 } 13986 13987 13988 // if we have page loader on wait for it to finish before init animations 13989 if(oxyThemeData.siteLoader === 'on') { 13990 Pace.on('done', function() { 13991 setTimeout(function() { 13992 initialisePageScrollAnimations(); 13993 }, 500); 13994 }); 13995 } 13996 else { 13997 initialisePageScrollAnimations(); 13998 } 13999 14000 // Goto top button 14001 // ====================== 14002 14003 // Animate the scroll to top 14004 $('.go-top').click(function(event) { 14005 event.preventDefault(); 14006 $('html, body').animate({scrollTop: 0}, 300); 14007 }); 14008 14009 14010 // Bootstrap Tooltips 14011 // ====================== 14012 14013 // Function to init bootstrap's tooltip 14014 $('[data-toggle="tooltip"]').tooltip(); 14015 14016 14017 // Bootstrap Carousel 14018 // ====================== 14019 14020 $('.carousel').carousel({ 14021 interval: 7000 14022 }); 14023 14024 // Bootstrap Accordion Arrows 14025 // ====================== 14026 14027 // Function to fix accordion arrows 14028 $('.accordion-body').on('hide', function () { 14029 $(this).parent('.accordion-group').find('.accordion-toggle').addClass('collapsed'); 14030 }); 14031 14032 // Side Menu 14033 $('body').on('show.bs.collapse', function () { 14034 if($(this).hasClass('slide-menu')) { 14035 $(this).addClass('slide-on'); 14036 } 14037 $('.navbar-toggle').removeClass('collapsed'); 14038 }); 14039 $('body').on('hide.bs.collapse', function () { 14040 if($(this).hasClass('slide-menu')) { 14041 $(this).removeClass('slide-on'); 14042 } 14043 $('.navbar-toggle').addClass('collapsed'); 14044 }); 14045 14046 if(oxyThemeData.menuClose === 'on') { 14047 $('body.slide-menu').on('click', function() { 14048 if($(this).hasClass('slide-on')) { 14049 $('#navbar-slide').collapse('hide'); 14050 } 14051 }); 14052 } 14053 14054 // PIE Chart 14055 // ====================== 14056 14057 $('.chart').each( function() { 14058 var $chart = $(this); 14059 $chart.waypoint(function() { 14060 $chart.easyPieChart({ 14061 barColor: $chart.attr('data-bar-color'), 14062 trackColor: $chart.attr('data-track-color'), 14063 lineWidth: $chart.attr('data-line-width'), 14064 scaleColor: false, 14065 animate: 1000, 14066 size: $chart.attr('data-size'), 14067 lineCap: 'square' 14068 }); 14069 },{ 14070 triggerOnce: true, 14071 offset: 'bottom-in-view' 14072 }); 14073 14074 $chart.css('left', '50%'); 14075 $chart.css('margin-left', - $chart.attr('data-size') / 2 ); 14076 }); 14077 14078 14079 // Fix for embedded videos 14080 // ====================== 14081 14082 var frames = $( '.video-wrapper iframe' ); 14083 for( var i = 0; i < frames.length; i++ ) { 14084 if( frames[i].src.indexOf('?') === -1 ) { 14085 frames[i].src += '?wmode=opaque'; 14086 } 14087 else{ 14088 frames[i].src += '&wmode=opaque'; 14089 } 14090 } 14091 14092 // Icon Animations 14093 // ====================== 14094 14095 $('[data-animation]').each(function(){ 14096 var element = $(this); 14097 14098 element.on('mouseenter', function(){ 14099 if( element.attr('data-animation') !== 'none' ){ 14100 element.addClass('animated ' + element.attr('data-animation')); 14101 } 14102 }); 14103 14104 element.on('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(e) { 14105 element.removeClass('animated ' + element.attr('data-animation')); 14106 }); 14107 14108 }); 14109 14110 14111 // Isotope Infinite Scroll 14112 // ====================== 14113 14114 var $container = $('div.blog-masonry.isotope'); 14115 if($container.length > 0){ 14116 $container.infinitescroll({ 14117 navSelector : 'div.infinite-scroll', // selector for the paged navigation 14118 nextSelector : 'div.infinite-scroll a', // selector for the NEXT link (to page 2) 14119 itemSelector : '.masonry-item', // selector for all items
14119you'll retrieve 14120 loading: { 14121 finishedMsg: oxyThemeData.scrollFinishedMessage, 14122 }, 14123 prefill:true 14124 }, 14125 // call Isotope as a callback 14126 function( newElements ) { 14127 $(newElements).each(function(index, element){ 14128 14129 // Set the masonry column width 14130 var columns = 3; 14131 var screenWidth = $(window).width(); 14132 var wideColumns = 2; 14133 var padding = $container.attr( 'data-padding' ); 14134 14135 if( screenWidth < 768 ) { 14136 columns = $container.attr( 'data-col-xs' ); 14137 wideColumns = 1; 14138 } 14139 else if( screenWidth < 992 ) { 14140 columns = $container.attr( 'data-col-sm' ); 14141 wideColumns = 1; 14142 } 14143 else if( screenWidth < 1200 ) { 14144 columns = $container.attr( 'data-col-md' ); 14145 wideColumns = 2 ; 14146 } 14147 else if( screenWidth > 1200 ) { 14148 columns = $container.attr( 'data-col-lg' ); 14149 wideColumns = 2 ; 14150 } 14151 14152 var itemWidth = Math.floor( $container.width() / columns ); 14153 14154 var item = $(this); 14155 if( item.hasClass( 'masonry-wide' ) ) { 14156 item.css( 'width', itemWidth * wideColumns ); 14157 } 14158 else { 14159 item.css( 'width', itemWidth ); 14160 } 14161 item.find('.post-masonry-inner').css( 'padding', padding / 2 + 'px' ); 14162 }); 14163 $container.isotope( 'appended', $( newElements ), function(){ 14164 $container.isotope( 'reLayout', function() { 14165 Waypoint.refreshAll(); 14166 }); 14167 }); 14168 } 14169 ); 14170 } 14171 14172 // Magnific Image Popup 14173 // ====================== 14174 14175 $('.magnific').each(function(index, value){ 14176 var myimage = $(this); 14177 var imageTitle = ''; 14178 14179 if ($(this).data('captions') !== undefined) { 14180 imageTitle = $(this).data('captions'); 14181 } 14182 14183 myimage.magnificPopup({ 14184 type:'image', 14185 removalDelay: 300, 14186 items: { 14187 src: myimage.attr('href'), 14188 title: imageTitle 14189 }, 14190 mainClass: 'mfp-fade', 14191 }); 14192 14193 }); 14194 14195 // Magnific Video Popup 14196 // ====================== 14197 14198 $('.magnific-youtube, .magnific-vimeo, .magnific-gmaps').magnificPopup({ 14199 type: 'iframe', 14200 mainClass: 'mfp-fade', 14201 removalDelay: 300, 14202 preloader: false, 14203 fixedContentPos: false 14204 }); 14205 14206 // Magnific Gallery Popup 14207 // ====================== 14208 14209 $('.magnific-gallery').each(function(index , value){ 14210 var gallery = $(this); 14211 var galleryImages = $(this).data('links').split(','); 14212 var galleryTitle = ''; 14213 14214 if ($(this).data('captions') !== undefined) { 14215 galleryTitle = $(this).data('captions').split(','); 14216 } 14217 14218 var items = []; 14219 for(var i=0;i<galleryImages.length; i++){ 14220 items.push({ 14221 src:galleryImages[i], 14222 title:galleryTitle[i] 14223 }); 14224 } 14225 gallery.magnificPopup({ 14226 mainClass: 'mfp-fade', 14227 items:items, 14228 gallery:{ 14229 enabled:true, 14230 tPrev: $(this).data('prev-text'), 14231 tNext: $(this).data('next-text') 14232 }, 14233 type: 'image' 14234 }); 14235 }); 14236 14237 $('.magnific-all').each(function() { 14238 var $portfolio = $(this); 14239 var $imageLinks = $portfolio.find('.image-all'); 14240 14241 var items = []; 14242 $imageLinks.each(function() { 14243 var $item = $(this); 14244 var galleryTitle = ''; 14245 14246 if ($item.attr('title') !== undefined) { 14247 galleryTitle = $item.attr('title'); 14248 } 14249 var type = 'image'; 14250 if ($item.hasClass('magnific-youtube') || $item.hasClass('magnific-vimeo')) { 14251 type = 'iframe'; 14252 } 14253 var magItem = { 14254 src: $item.attr('href'), 14255 type: type, 14256 title: galleryTitle 14257 }; 14258 items.push(magItem); 14259 }); 14260 14261 $imageLinks.magnificPopup({ 14262 mainClass: 'mfp-fade', 14263 items: items, 14264 gallery:{ 14265 enabled:true, 14266 tPrev: $(this).data('prev-text'), 14267 tNext: $(this).data('next-text') 14268 }, 14269 type: 'image', 14270 callbacks: { 14271 beforeOpen: function() { 14272 var index = $imageLinks.index(this.st.el); 14273 if (-1 !== index) { 14274 this.goTo(index); 14275 } 14276 } 14277 } 14278 }); 14279 });
14280 14281 // Magnific Product Popup 14282 // ====================== 14283 14284 $('.product-gallery').magnificPopup({ 14285 delegate: 'li:not(.clone) figcaption a', 14286 type: 'image', 14287 mainClass: 'mfp-fade', 14288 gallery:{ 14289 enabled:true, 14290 navigateByImgClick:true 14291 } 14292 }); 14293 14294 14295 // Social Icons Hover Colours 14296 // ====================== 14297 14298 $('[data-iconcolor]').each(function(){ 14299 var element = $(this); 14300 var originalColor = $(element).css('background-color'); 14301 var originalTextColor = $(element).find('i').css('color'); 14302 element.on('mouseenter', function(){ 14303 element.css('background-color' , element.attr('data-iconcolor')); 14304 element.find('i').css('color' , '#ffffff'); 14305 if (element.parents('.social-icons').hasClass('social-simple')) { 14306 element.find('i').css('color' , element.attr('data-iconcolor')); 14307 } 14308 }); 14309 element.on('mouseleave', function(){ 14310 element.css('background-color' ,originalColor); 14311 element.find('i').css('color' , originalTextColor); 14312 if (element.parents('.social-icons').hasClass('social-simple')) { 14313 element.find('i').css('color' , originalTextColor); 14314 } 14315 }); 14316 14317 }); 14318 14319 // Hover menu 14320 // ====================== 14321 if (oxyThemeData.hoverMenu.hoverActive === true) { 14322 if($('body:not([class*="oxy-agent"])').length) { 14323 $('.navbar .dropdown').hover(function() { 14324 $(this).find('.dropdown-menu').first().stop(true, true).delay(oxyThemeData.hoverMenu.hoverDelay).fadeIn(parseInt(oxyThemeData.hoverMenu.hoverFadeDelay)); 14325 }, function() { 14326 $(this).find('.dropdown-menu').first().stop(true, true).delay(oxyThemeData.hoverMenu.hoverDelay).fadeOut(parseInt(oxyThemeData.hoverMenu.hoverFadeDelay)); 14327 }); 14328 } 14329 14330 $('#masthead .nav li.dropdown a').on('click', function(){ 14331 var $dropdown = $(this); 14332 if($dropdown.parent().hasClass('open') && ($dropdown.attr('data-link') !== undefined) ) { 14333 window.location = $dropdown.attr('data-link'); 14334 } 14335 }); 14336 } 14337 14338 // woocommerce 14339 14340 // if country changed and js injects text input make sure it has a form-control class 14341 $('body').on( 'country_to_state_changed', function(e, data) { 14342 $('.input-text').addClass('form-control'); 14343 $('#calc_shipping_state').addClass('form-control'); 14344 }); 14345}); 14346(function() { 14347 var AjaxMonitor, Bar, DocumentMonitor, ElementMonitor, ElementTracker, EventLagMonitor, Evented, Events, NoTargetError, Pace, RequestIntercept, SOURCE_KEYS, Scaler, SocketRequestTracker, XHRRequestTracker, animation, avgAmplitude, bar, cancelAnimation, cancelAnimationFrame, defaultOptions, extend, extendNative, getFromDOM, getIntercept, handlePushState, ignoreStack, init, now, options, requestAnimationFrame, result, runAnimation, scalers, shouldIgnoreURL, shouldTrack, source, sources, uniScaler, _WebSocket, _XDomainRequest, _XMLHttpRequest, _i, _intercept, _len, _pushState, _ref, _ref1, _replaceState, 14348 __slice = [].slice, 14349 __hasProp = {}.hasOwnProperty, 14350 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 14351 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 14352 14353 defaultOptions = { 14354 catchupTime: 100, 14355 initialRate: .03, 14356 minTime: 250, 14357 ghostTime: 100, 14358 maxProgressPerFrame: 20, 14359 easeFactor: 1.25, 14360 startOnPageLoad: true, 14361 restartOnPushState: true, 14362 restartOnRequestAfter: 500, 14363 target: 'body', 14364 elements: { 14365 checkInterval: 100, 14366 selectors: ['body'] 14367 }, 14368 eventLag: { 14369 minSamples: 10, 14370 sampleCount: 3, 14371 lagThreshold: 3 14372 }, 14373 ajax: { 14374 trackMethods: ['GET'], 14375 trackWebSockets: true, 14376 ignoreURLs: [] 14377 } 14378 }; 14379 14380 now = function() { 14381 var _ref; 14382 return (_ref = typeof performance !== "undefined" && performance !== null ? typeof performance.now === "function" ? performance.now() : void 0 : void 0) != null ? _ref : +(new Date); 14383 }; 14384 14385 requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; 14386 14387 cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame; 14388 14389 if (requestAnimationFrame == null) { 14390 requestAnimationFrame = function(fn) { 14391 return setTimeout(fn, 50); 14392 }; 14393 cancelAnimationFrame = function(id) { 14394 return clearTimeout(id); 14395 }; 14396 } 14397 14398 runAnimation = function(fn) { 14399 var last, tick; 14400 last = now(); 14401 tick = function() { 14402 var diff; 14403 diff = now() - last; 14404 if (diff >= 33) { 14405 last = now(); 14406 return fn(diff, function() { 14407 return requestAnimationFrame(tick); 14408 }); 14409 } else { 14410 return setTimeout(tick, 33 - diff); 14411 } 14412 }; 14413 return tick(); 14414 }; 14415 14416 result = function() { 14417 var args, key, obj; 14418 obj = arguments[0], key = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; 14419 if (typeof obj[key] === 'function') { 14420 return obj[key].apply(obj, args); 14421 } else { 14422 return obj[key]; 14423 } 14424 }; 14425 14426 extend = function() { 14427 var key, out, source, sources, val, _i, _len; 14428 out = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 14429 for (_i = 0, _len = sources.length; _i < _len; _i++) { 14430 source = sources[_i]; 14431 if (source) { 14432 for (key in source) { 14433 if (!__hasProp.call(source, key)) continue; 14434 val = source[key]; 14435 if ((out[key] != null) && typeof out[key] === 'object' && (val != null) && typeof val === 'object') { 14436 extend(out[key], val); 14437 } else { 14438 out[key] = val; 14439 } 14440 } 14441 } 14442 } 14443 return out; 14444 }; 14445 14446 avgAmplitude = function(arr) { 14447 var count, sum, v, _i, _len; 14448 sum = count = 0; 14449 for (_i = 0, _len = arr.length; _i < _len; _i++) { 14450 v = arr[_i]; 14451 sum += Math.abs(v); 14452 count++; 14453 } 14454 return sum / count; 14455 }; 14456 14457 getFromDOM = function(key, json) { 14458 var data, e, el; 14459 if (key == null) { 14460 key = 'options'; 14461 } 14462 if (json == null) { 14463 json = true; 14464 } 14465 el = document.querySelector("[data-pace-" + key + "]"); 14466 if (!el) { 14467 return; 14468 } 14469 data = el.getAttribute("data-pace-" + key); 14470 if (!json) { 14471 return data; 14472 } 14473 try { 14474 return JSON.parse(data); 14475 } catch (_error) { 14476 e = _error; 14477 return typeof console !== "undefined" && console !== null ? console.error("Error parsing inline pace options", e) : void 0; 14478 } 14479 }; 14480 14481 Evented = (function() { 14482 function Evented() {} 14483 14484 Evented.prototype.on = function(event, handler, ctx, once) { 14485 var _base; 14486 if (once == null) { 14487 once = false; 14488 } 14489 if (this.bindings == null) { 14490 this.bindings = {}; 14491 } 14492 if ((_base = this.bindings)[event] == null) { 14493 _base[event] = []; 14494 } 14495 return this.bindings[event].push({ 14496 handler: handler, 14497 ctx: ctx, 14498 once: once 14499 }); 14500 }; 14501 14502 Evented.prototype.once = function(event, handler, ctx) { 14503 return this.on(event, handler, ctx, true); 14504 }; 14505 14506 Evented.prototype.off = function(event, handler) { 14507 var i, _ref, _results; 14508 if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) { 14509 return; 14510 } 14511 if (handler == null) { 14512 return delete this.bindings[event]; 14513 } else { 14514 i = 0; 14515 _results = []; 14516 while (i < this.bindings[event].length) { 14517 if (this.bindings[event][i].handler === handler) { 14518 _results.push(this.bindings[event].splice(i, 1)); 14519 } else { 14520 _results.push(i++); 14521 } 14522 } 14523 return _results; 14524 } 14525 }; 14526 14527 Evented.prototype.trigger = function() { 14528 var args, ctx, event, handler, i, once, _ref, _ref1, _results; 14529 event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 14530 if ((_ref = this.bindings) != null ? _ref[event] : void 0) { 14531 i = 0; 14532 _results = []; 14533 while (i < this.bindings[event].length) { 14534 _ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once; 14535 handler.apply(ctx != null ? ctx : this, args); 14536 if (once) { 14537 _results.push(this.bindings[event].splice(i, 1)); 14538 } else { 14539 _results.push(i++); 14540 } 14541 } 14542 return _results; 14543 } 14544 }; 14545 14546 return Evented; 14547 14548 })();
vendor: 20,905 bytes, lines 14549-15280
14549 14550 Pace = window.Pace || {}; 14551 14552 window.Pace = Pace; 14553 14554 extend(Pace, Evented.prototype); 14555 14556 options = Pace.options = extend({}, defaultOptions, window.paceOptions, getFromDOM()); 14557 14558 _ref = ['ajax', 'document', 'eventLag', 'elements']; 14559 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 14560 source = _ref[_i]; 14561 if (options[source] === true) { 14562 options[source] = defaultOptions[source]; 14563 } 14564 } 14565 14566 NoTargetError = (function(_super) { 14567 __extends(NoTargetError, _super); 14568 14569 function NoTargetError() { 14570 _ref1 = NoTargetError.__super__.constructor.apply(this, arguments); 14571 return _ref1; 14572 } 14573 14574 return NoTargetError; 14575 14576 })(Error); 14577 14578 Bar = (function() { 14579 function Bar() { 14580 this.progress = 0; 14581 } 14582 14583 Bar.prototype.getElement = function() { 14584 var targetElement; 14585 if (this.el == null) { 14586 targetElement = document.querySelector(options.target); 14587 if (!targetElement) { 14588 throw new NoTargetError; 14589 } 14590 this.el = document.createElement('div'); 14591 this.el.className = "pace pace-active"; 14592 document.body.className = document.body.className.replace(/pace-done/g, ''); 14593 document.body.className += ' pace-running'; 14594 this.el.innerHTML = '<div class="pace-progress">\n <div class="pace-progress-inner"></div>\n</div>\n<div class="pace-activity"></div>'; 14595 if (targetElement.firstChild != null) { 14596 targetElement.insertBefore(this.el, targetElement.firstChild); 14597 } else { 14598 targetElement.appendChild(this.el); 14599 } 14600 } 14601 return this.el; 14602 }; 14603 14604 Bar.prototype.finish = function() { 14605 var el; 14606 el = this.getElement(); 14607 el.className = el.className.replace('pace-active', ''); 14608 el.className += ' pace-inactive'; 14609 document.body.className = document.body.className.replace('pace-running', ''); 14610 return document.body.className += ' pace-done'; 14611 }; 14612 14613 Bar.prototype.update = function(prog) { 14614 this.progress = prog; 14615 return this.render(); 14616 }; 14617 14618 Bar.prototype.destroy = function() { 14619 try { 14620 this.getElement().parentNode.removeChild(this.getElement()); 14621 } catch (_error) { 14622 NoTargetError = _error; 14623 } 14624 return this.el = void 0; 14625 }; 14626 14627 Bar.prototype.render = function() { 14628 var el, key, progressStr, transform, _j, _len1, _ref2; 14629 if (document.querySelector(options.target) == null) { 14630 return false; 14631 } 14632 el = this.getElement(); 14633 transform = "translate3d(" + this.progress + "%, 0, 0)"; 14634 _ref2 = ['webkitTransform', 'msTransform', 'transform']; 14635 for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { 14636 key = _ref2[_j]; 14637 el.children[0].style[key] = transform; 14638 } 14639 if (!this.lastRenderedProgress || this.lastRenderedProgress | 0 !== this.progress | 0) { 14640 el.children[0].setAttribute('data-progress-text', "" + (this.progress | 0) + "%"); 14641 if (this.progress >= 100) { 14642 progressStr = '99'; 14643 } else { 14644 progressStr = this.progress < 10 ? "0" : ""; 14645 progressStr += this.progress | 0; 14646 } 14647 el.children[0].setAttribute('data-progress', "" + progressStr); 14648 } 14649 return this.lastRenderedProgress = this.progress; 14650 }; 14651 14652 Bar.prototype.done = function() { 14653 return this.progress >= 100; 14654 }; 14655 14656 return Bar; 14657 14658 })(); 14659 14660 Events = (function() { 14661 function Events() { 14662 this.bindings = {}; 14663 } 14664 14665 Events.prototype.trigger = function(name, val) { 14666 var binding, _j, _len1, _ref2, _results; 14667 if (this.bindings[name] != null) { 14668 _ref2 = this.bindings[name]; 14669 _results = []; 14670 for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { 14671 binding = _ref2[_j]; 14672 _results.push(binding.call(this, val)); 14673 } 14674 return _results; 14675 } 14676 }; 14677 14678 Events.prototype.on = function(name, fn) { 14679 var _base; 14680 if ((_base = this.bindings)[name] == null) { 14681 _base[name] = []; 14682 } 14683 return this.bindings[name].push(fn); 14684 }; 14685 14686 return Events; 14687 14688 })(); 14689 14690 _XMLHttpRequest = window.XMLHttpRequest; 14691 14692 _XDomainRequest = window.XDomainRequest; 14693 14694 _WebSocket = window.WebSocket; 14695 14696 extendNative = function(to, from) { 14697 var e, key, _results; 14698 _results = []; 14699 for (key in from.prototype) { 14700 try { 14701 if ((to[key] == null) && typeof from[key] !== 'function') { 14702 if (typeof Object.defineProperty === 'function') { 14703 _results.push(Object.defineProperty(to, key, { 14704 get: function() { 14705 return from.prototype[key]; 14706 }, 14707 configurable: true, 14708 enumerable: true 14709 })); 14710 } else { 14711 _results.push(to[key] = from.prototype[key]); 14712 } 14713 } else { 14714 _results.push(void 0); 14715 } 14716 } catch (_error) { 14717 e = _error; 14718 } 14719 } 14720 return _results; 14721 }; 14722 14723 ignoreStack = []; 14724 14725 Pace.ignore = function() { 14726 var args, fn, ret; 14727 fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 14728 ignoreStack.unshift('ignore'); 14729 ret = fn.apply(null, args); 14730 ignoreStack.shift(); 14731 return ret; 14732 }; 14733 14734 Pace.track = function() { 14735 var args, fn, ret; 14736 fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 14737 ignoreStack.unshift('track'); 14738 ret = fn.apply(null, args); 14739 ignoreStack.shift(); 14740 return ret; 14741 }; 14742 14743 shouldTrack = function(method) { 14744 var _ref2; 14745 if (method == null) { 14746 method = 'GET'; 14747 } 14748 if (ignoreStack[0] === 'track') { 14749 return 'force'; 14750 } 14751 if (!ignoreStack.length && options.ajax) { 14752 if (method === 'socket' && options.ajax.trackWebSockets) { 14753 return true; 14754 } else if (_ref2 = method.toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref2) >= 0) { 14755 return true; 14756 } 14757 } 14758 return false; 14759 }; 14760 14761 RequestIntercept = (function(_super) { 14762 __extends(RequestIntercept, _super); 14763 14764 function RequestIntercept() { 14765 var monitorXHR, 14766 _this = this; 14767 RequestIntercept.__super__.constructor.apply(this, arguments); 14768 monitorXHR = function(req) { 14769 var _open; 14770 _open = req.open; 14771 return req.open = function(type, url, async) { 14772 if (shouldTrack(type)) { 14773 _this.trigger('request', { 14774 type: type, 14775 url: url, 14776 request: req 14777 }); 14778 } 14779 return _open.apply(req, arguments); 14780 }; 14781 }; 14782 window.XMLHttpRequest = function(flags) { 14783 var req; 14784 req = new _XMLHttpRequest(flags); 14785 monitorXHR(req); 14786 return req; 14787 }; 14788 try { 14789 extendNative(window.XMLHttpRequest, _XMLHttpRequest); 14790 } catch (_error) {} 14791 if (_XDomainRequest != null) { 14792 window.XDomainRequest = function() { 14793 var req; 14794 req = new _XDomainRequest; 14795 monitorXHR(req); 14796 return req; 14797 }; 14798 try { 14799 extendNative(window.XDomainRequest, _XDomainRequest); 14800 } catch (_error) {} 14801 } 14802 if ((_WebSocket != null) && options.ajax.trackWebSockets) { 14803 window.WebSocket = function(url, protocols) { 14804 var req; 14805 if (protocols != null) { 14806 req = new _WebSocket(url, protocols); 14807 } else { 14808 req = new _WebSocket(url); 14809 } 14810 if (shouldTrack('socket')) { 14811 _this.trigger('request', { 14812 type: 'socket', 14813 url: url, 14814 protocols: protocols, 14815 request: req 14816 }); 14817 } 14818 return req; 14819 }; 14820 try { 14821 extendNative(window.WebSocket, _WebSocket); 14822 } catch (_error) {} 14823 } 14824 } 14825 14826 return RequestIntercept; 14827 14828 })(Events); 14829 14830 _intercept = null; 14831 14832 getIntercept = function() { 14833 if (_intercept == null) { 14834 _intercept = new RequestIntercept; 14835 } 14836 return _intercept; 14837 }; 14838 14839 shouldIgnoreURL = function(url) { 14840 var pattern, _j, _len1, _ref2; 14841 _ref2 = options.ajax.ignoreURLs; 14842 for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { 14843 pattern = _ref2[_j]; 14844 if (typeof pattern === 'string') { 14845 if (url.indexOf(pattern) !== -1) { 14846 return true; 14847 } 14848 } else { 14849 if (pattern.test(url)) { 14850 return true; 14851 } 14852 } 14853 } 14854 return false; 14855 }; 14856 14857 getIntercept().on('request', function(_arg) { 14858 var after, args, request, type, url; 14859 type = _arg.type, request = _arg.request, url = _arg.url; 14860 if (shouldIgnoreURL(url)) { 14861 return; 14862 } 14863 if (!Pace.running && (options.restartOnRequestAfter !== false || shouldTrack(type) === 'force')) { 14864 args = arguments; 14865 after = options.restartOnRequestAfter || 0; 14866 if (typeof after === 'boolean') { 14867 after = 0; 14868 } 14869 return setTimeout(function() { 14870 var stillActive, _j, _len1, _ref2, _ref3, _results; 14871 if (type === 'socket') { 14872 stillActive = request.readyState < 2; 14873 } else { 14874 stillActive = (0 < (_ref2 = request.readyState) && _ref2 < 4); 14875 } 14876 if (stillActive) { 14877 Pace.restart(); 14878 _ref3 = Pace.sources; 14879 _results = []; 14880 for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { 14881 source = _ref3[_j]; 14882 if (source instanceof AjaxMonitor) { 14883 source.watch.apply(source, args); 14884 break; 14885 } else { 14886 _results.push(void 0); 14887 } 14888 } 14889 return _results; 14890 } 14891 }, after); 14892 } 14893 }); 14894 14895 AjaxMonitor = (function() { 14896 function AjaxMonitor() { 14897 var _this = this; 14898 this.elements = []; 14899 getIntercept().on('request', function() { 14900 return _this.watch.apply(_this, arguments); 14901 }); 14902 } 14903 14904 AjaxMonitor.prototype.watch = function(_arg) { 14905 var request, tracker, type, url; 14906 type = _arg.type, request = _arg.request, url = _arg.url; 14907 if (shouldIgnoreURL(url)) { 14908 return; 14909 } 14910 if (type === 'socket') { 14911 tracker = new SocketRequestTracker(request); 14912 } else { 14913 tracker = new XHRRequestTracker(request); 14914 } 14915 return this.elements.push(tracker); 14916 }; 14917 14918 return AjaxMonitor; 14919 14920 })(); 14921 14922 XHRRequestTracker = (function() { 14923 function XHRRequestTracker(request) { 14924 var event, size, _j, _len1, _onreadystatechange, _ref2, 14925 _this = this; 14926 this.progress = 0; 14927 if (window.ProgressEvent != null) { 14928 size = null; 14929 request.addEventListener('progress', function(evt) { 14930 if (evt.lengthComputable) { 14931 return _this.progress = 100 * evt.loaded / evt.total; 14932 } else { 14933 return _this.progress = _this.progress + (100 - _this.progress) / 2; 14934 } 14935 }, false); 14936 _ref2 = ['load', 'abort', 'timeout', 'error']; 14937 for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { 14938 event = _ref2[_j]; 14939 request.addEventListener(event, function() { 14940 return _this.progress = 100; 14941 }, false); 14942 } 14943 } else { 14944 _onreadystatechange = request.onreadystatechange; 14945 request.onreadystatechange = function() { 14946 var _ref3; 14947 if ((_ref3 = request.readyState) === 0 || _ref3 === 4) { 14948 _this.progress = 100; 14949 } else if (request.readyState === 3) { 14950 _this.progress = 50; 14951 } 14952 return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0; 14953 }; 14954 } 14955 } 14956 14957 return XHRRequestTracker; 14958 14959 })(); 14960 14961 SocketRequestTracker = (function() { 14962 function SocketRequestTracker(request) { 14963 var event, _j, _len1, _ref2, 14964 _this = this; 14965 this.progress = 0; 14966 _ref2 = ['error', 'open']; 14967 for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { 14968 event = _ref2[_j]; 14969 request.addEventListener(event, function() { 14970 return _this.progress = 100; 14971 }, false); 14972 } 14973 } 14974 14975 return SocketRequestTracker; 14976 14977 })(); 14978 14979 ElementMonitor = (function() { 14980 function ElementMonitor(options) { 14981 var selector, _j, _len1, _ref2; 14982 if (options == null) { 14983 options = {}; 14984 } 14985 this.elements = []; 14986 if (options.selectors == null) { 14987 options.selectors = []; 14988 } 14989 _ref2 = options.selectors; 14990 for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { 14991 selector = _ref2[_j]; 14992 this.elements.push(new ElementTracker(selector)); 14993 } 14994 } 14995 14996 return ElementMonitor; 14997 14998 })(); 14999 15000 ElementTracker = (function() { 15001 function ElementTracker(selector) { 15002 this.selector = selector; 15003 this.progress = 0; 15004 this.check(); 15005 } 15006 15007 ElementTracker.prototype.check = function() { 15008 var _this = this; 15009 if (document.querySelector(this.selector)) { 15010 return this.done(); 15011 } else { 15012 return setTimeout((function() { 15013 return _this.check(); 15014 }), options.elements.checkInterval); 15015 } 15016 }; 15017 15018 ElementTracker.prototype.done = function() { 15019 return this.progress = 100; 15020 }; 15021 15022 return ElementTracker; 15023 15024 })(); 15025 15026 DocumentMonitor = (function() { 15027 DocumentMonitor.prototype.states = { 15028 loading: 0, 15029 interactive: 50, 15030 complete: 100 15031 }; 15032 15033 function DocumentMonitor() { 15034 var _onreadystatechange, _ref2, 15035 _this = this; 15036 this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100; 15037 _onreadystatechange = document.onreadystatechange; 15038 document.onreadystatechange = function() { 15039 if (_this.states[document.readyState] != null) { 15040 _this.progress = _this.states[document.readyState]; 15041 } 15042 return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0; 15043 }; 15044 } 15045 15046 return DocumentMonitor; 15047 15048 })(); 15049 15050 EventLagMonitor = (function() { 15051 function EventLagMonitor() { 15052 var avg, interval, last, points, samples, 15053 _this = this; 15054 this.progress = 0; 15055 avg = 0; 15056 samples = []; 15057 points = 0; 15058 last = now(); 15059 interval = setInterval(function() { 15060 var diff; 15061 diff = now() - last - 50; 15062 last = now(); 15063 samples.push(diff); 15064 if (samples.length > options.eventLag.sampleCount) { 15065 samples.shift(); 15066 } 15067 avg = avgAmplitude(samples); 15068 if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) { 15069 _this.progress = 100; 15070 return clearInterval(interval); 15071 } else { 15072 return _this.progress = 100 * (3 / (avg + 3)); 15073 } 15074 }, 50); 15075 } 15076 15077 return EventLagMonitor; 15078 15079 })(); 15080 15081 Scaler = (function() { 15082 function Scaler(source) { 15083 this.source = source; 15084 this.last = this.sinceLastUpdate = 0; 15085 this.rate = options.initialRate; 15086 this.catchup = 0; 15087 this.progress = this.lastProgress = 0; 15088 if (this.source != null) { 15089 this.progress = result(this.source, 'progress'); 15090 } 15091 } 15092 15093 Scaler.prototype.tick = function(frameTime, val) { 15094 var scaling; 15095 if (val == null) { 15096 val = result(this.source, 'progress'); 15097 } 15098 if (val >= 100) { 15099 this.done = true; 15100 } 15101 if (val === this.last) { 15102 this.sinceLastUpdate += frameTime; 15103 } else { 15104 if (this.sinceLastUpdate) { 15105 this.rate = (val - this.last) / this.sinceLastUpdate; 15106 } 15107 this.catchup = (val - this.progress) / options.catchupTime; 15108 this.sinceLastUpdate = 0; 15109 this.last = val; 15110 } 15111 if (val > this.progress) { 15112 this.progress += this.catchup * frameTime; 15113 } 15114 scaling = 1 - Math.pow(this.progress / 100, options.easeFactor); 15115 this.progress += scaling * this.rate * frameTime; 15116 this.progress = Math.min(this.lastProgress + options.maxProgressPerFrame, this.progress); 15117 this.progress = Math.max(0, this.progress); 15118 this.progress = Math.min(100, this.progress); 15119 this.lastProgress = this.progress; 15120 return this.progress; 15121 }; 15122 15123 return Scaler; 15124 15125 })(); 15126 15127 sources = null; 15128 15129 scalers = null; 15130 15131 bar = null; 15132 15133 uniScaler = null; 15134 15135 animation = null; 15136 15137 cancelAnimation = null; 15138 15139 Pace.running = false; 15140 15141 handlePushState = function() { 15142 if (options.restartOnPushState) { 15143 return Pace.restart(); 15144 } 15145 }; 15146 15147 if (window.history.pushState != null) { 15148 _pushState = window.history.pushState; 15149 window.history.pushState = function() { 15150 handlePushState(); 15151 return _pushState.apply(window.history, arguments); 15152 }; 15153 } 15154 15155 if (window.history.replaceState != null) { 15156 _replaceState = window.history.replaceState; 15157 window.history.replaceState = function() { 15158 handlePushState(); 15159 return _replaceState.apply(window.history, arguments); 15160 }; 15161 } 15162 15163 SOURCE_KEYS = { 15164 ajax: AjaxMonitor, 15165 elements: ElementMonitor, 15166 document: DocumentMonitor, 15167 eventLag: EventLagMonitor 15168 }; 15169 15170 (init = function() { 15171 var type, _j, _k, _len1, _len2, _ref2, _ref3, _ref4; 15172 Pace.sources = sources = []; 15173 _ref2 = ['ajax', 'elements', 'document', 'eventLag']; 15174 for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { 15175 type = _ref2[_j]; 15176 if (options[type] !== false) { 15177 sources.push(new SOURCE_KEYS[type](options[type])); 15178 } 15179 } 15180 _ref4 = (_ref3 = options.extraSources) != null ? _ref3 : []; 15181 for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { 15182 source = _ref4[_k]; 15183 sources.push(new source(options)); 15184 } 15185 Pace.bar = bar = new Bar; 15186 scalers = []; 15187 return uniScaler = new Scaler; 15188 })(); 15189 15190 Pace.stop = function() { 15191 Pace.trigger('stop'); 15192 Pace.running = false; 15193 bar.destroy(); 15194 cancelAnimation = true; 15195 if (animation != null) { 15196 if (typeof cancelAnimationFrame === "function") { 15197 cancelAnimationFrame(animation); 15198 } 15199 animation = null; 15200 } 15201 return init(); 15202 }; 15203 15204 Pace.restart = function() { 15205 Pace.trigger('restart'); 15206 Pace.stop(); 15207 return Pace.start(); 15208 }; 15209 15210 Pace.go = function() { 15211 var start; 15212 Pace.running = true; 15213 bar.render(); 15214 start = now(); 15215 cancelAnimation = false; 15216 return animation = runAnimation(function(frameTime, enqueueNextFrame) { 15217 var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, sum, _j, _k, _len1, _len2, _ref2; 15218 remaining = 100 - bar.progress; 15219 count = sum = 0; 15220 done = true; 15221 for (i = _j = 0, _len1 = sources.length; _j < _len1; i = ++_j) { 15222 source = sources[i]; 15223 scalerList = scalers[i] != null ? scalers[i] : scalers[i] = []; 15224 elements = (_ref2 = source.elements) != null ? _ref2 : [source]; 15225 for (j = _k = 0, _len2 = elements.length; _k < _len2; j = ++_k) { 15226 element = elements[j]; 15227 scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element); 15228 done &= scaler.done; 15229 if (scaler.done) { 15230 continue; 15231 } 15232 count++; 15233 sum += scaler.tick(frameTime); 15234 } 15235 } 15236 avg = sum / count; 15237 bar.update(uniScaler.tick(frameTime, avg)); 15238 if (bar.done() || done || cancelAnimation) { 15239 bar.update(100); 15240 Pace.trigger('done'); 15241 return setTimeout(function() { 15242 bar.finish(); 15243 Pace.running = false; 15244 return Pace.trigger('hide'); 15245 }, Math.max(options.ghostTime, Math.max(options.minTime - (now() - start), 0))); 15246 } else { 15247 return enqueueNextFrame(); 15248 } 15249 }); 15250 }; 15251 15252 Pace.start = function(_options) { 15253 extend(options, _options); 15254 Pace.running = true; 15255 try { 15256 bar.render(); 15257 } catch (_error) { 15258 NoTargetError = _error; 15259 } 15260 if (!document.querySelector('.pace')) { 15261 return setTimeout(Pace.start, 50); 15262 } else { 15263 Pace.trigger('start'); 15264 return Pace.go(); 15265 } 15266 }; 15267 15268 if (typeof define === 'function' && define.amd) { 15269 define(['pace'], function() { 15270 return Pace; 15271 }); 15272 } else if (typeof exports === 'object') { 15273 module.exports = Pace; 15274 } else { 15275 if (options.startOnPageLoad) { 15276 Pace.start(); 15277 } 15278 } 15279 15280}).call(this);
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.