PageSourceSearch

https://www.adrbi.ro/scripts/theme-nojquery.js

js adrbi.ro collected 2026-09-24 09:34:52 UTC 622,671 bytes, 15,280 lines download raw bytes

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("&amp;").split("<").join("&lt;").split('"').join("&quot;")},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("&amp;")+'" /><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&amp;playerapiid="+a.pluginId+"&amp;version=3&amp;autoplay=0&amp;controls=0&amp;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={"&":"&amp;",'"':"&quot;","<":"&lt;",">":"&gt;"};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)+"&ndash;"+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">&times;</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 = '&shy;<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.