event-timeline/app/static/timeline/js/timeline.js
2022-04-12 14:49:56 +01:00

2757 lines
260 KiB
JavaScript

/*!
TL
*/
/* Timeline Error class */
function TL_Error(t,e){this.name="TL.Error",this.message=t||"error",this.message_key=this.message,this.detail=e||"";
// Grab stack?
var i=new Error;i.hasOwnProperty("stack")&&(this.stack=i.stack)}!function(t){t.TL={VERSION:"0.1",_originalL:t.TL}}(this),
/* TL.Debug
Debug mode
================================================== */
TL.debug=!1,
/* TL.Bind
================================================== */
TL.Bind=function(/*Function*/t,/*Object*/e){return function(){return t.apply(e,arguments)}},
/* Trace (console.log)
================================================== */
trace=function(t){TL.debug&&(window.console?console.log(t):"undefined"!=typeof jsTrace&&jsTrace.send(t))},TL_Error.prototype=Object.create(Error.prototype),TL_Error.prototype.constructor=TL_Error,TL.Error=TL_Error,
/* TL.Util
Class of utilities
================================================== */
TL.Util={mergeData:function(t,e){var i;for(i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t},
// like TL.Util.mergeData but takes an arbitrarily long list of sources to merge.
extend:function(/*Object*/t){for(// merge src properties into dest
var e=Array.prototype.slice.call(arguments,1),i=0,n=e.length,a;i<n;i++)a=e[i]||{},TL.Util.mergeData(t,a);return t},isEven:function(t){return t==parseFloat(t)?!(t%2):void 0},isTrue:function(t){return null!=t&&(1==t||"true"==String(t).toLowerCase()||1==Number(t))},findArrayNumberByUniqueID:function(t,e,i,n){for(var a=n||0,s=0;s<e.length;s++)e[s].data[i]==t&&(a=s);return a},convertUnixTime:function(t){var e,i,n,a,s,o,r=[],l={ymd:"",time:"",time_array:[],date_array:[],full_array:[]};l.ymd=t.split(" ")[0],l.time=t.split(" ")[1],l.date_array=l.ymd.split("-"),l.time_array=l.time.split(":"),l.full_array=l.date_array.concat(l.time_array);for(var h=0;h<l.full_array.length;h++)r.push(parseInt(l.full_array[h]));return i=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],n=(e=new Date(r[0],r[1],r[2],r[3],r[4],r[5])).getFullYear(),o=(a=i[e.getMonth()])+", "+(s=e.getDate())+" "+n},setData:function(t,e){t.data=TL.Util.extend({},t.data,e),""===t.data.unique_id&&(t.data.unique_id=TL.Util.unique_ID(6))},stamp:function(){var e=0,i="_tl_id";return function(/*Object*/t){return t[i]=t[i]||++e,t[i]}}(),isArray:function(){
// Use compiler's own isArray when available
if(Array.isArray)return Array.isArray;
// Retain references to variables for performance
// optimization
var e=Object.prototype.toString,i=e.call([]);return function(t){return e.call(t)===i}}(),getRandomNumber:function(t){return Math.floor(Math.random()*t)},unique_ID:function(t,e){var i=function(t){return Math.floor(Math.random()*t)},n=function(){var t;return"abcdefghijklmnopqurstuvwxyz".substr(i(32),1)},a=function(t){for(var e="",i=0;i<t;i++)e+=n();return e};return e?e+"-"+a(t):"tl-"+a(t)},ensureUniqueKey:function(t,e){if(e||(e=TL.Util.unique_ID(6)),!(e in t))return e;var i=e.match(/^(.+)(-\d+)?$/)[1],n=[];
// get an alternative
for(key in t)key.match(/^(.+?)(-\d+)?$/)[1]==i&&n.push(key);e=i+"-"+(n.length+1);for(var a=n.length;-1!=n.indexOf(e);a++)e=i+"-"+a;return e},htmlify:function(t){
//if (str.match(/<\s*p[^>]*>([^<]*)<\s*\/\s*p\s*>/)) {
return t.match(/<p>[\s\S]*?<\/p>/)?t:"<p>"+t+"</p>"},unhtmlify:function(t){return(t=t.replace(/(<[^>]*>)+/g,"")).replace('"',"'")},
/* * Turns plain text links into real links
================================================== */
linkify:function(t,e,i){var s=function(t,e,i){i||(i="");var n=30;return e&&30<e.length&&(e=e.substring(0,30)+"…"),i+"<a class='tl-makelink' href='"+t+"' onclick='void(0)'>"+e+"</a>"}
// http://, https://, ftp://
,n=/\b(?:https?|ftp):\/\/([a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|])/gim,a=/(^|[^\/>])(www\.[\S]+(\b|$))/gim,o=/([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)/gim;return t.replace(n,function(t,e,i,n){
// Javascript doesn't support negative lookbehind assertions, so
// we need to handle risk of matching URLs in legit hrefs
if(0<i){var a=n[i-1];if('"'==a||"'"==a||"="==a)return t}return s(t,e)}).replace(a,function(t,e,i,n,a){return s("http://"+i,i,e)}).replace(o,function(t,e,i,n){return s("mailto:"+e,e)})},unlinkify:function(t){return t?t=(t=t.replace(/<a\b[^>]*>/i,"")).replace(/<\/a>/i,""):t},getParamString:function(t){var e=[];for(var i in t)t.hasOwnProperty(i)&&e.push(i+"="+t[i]);return"?"+e.join("&")},formatNum:function(t,e){var i=Math.pow(10,e||5);return Math.round(t*i)/i},falseFn:function(){return!1},requestAnimFrame:function(){function a(t){window.setTimeout(t,1e3/60)}var s=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||a;return function(t,e,i,n){t=e?TL.Util.bind(t,e):t,i&&s===a?t():s(t,n)}}(),bind:function(/*Function*/t,/*Object*/e){return function(){return t.apply(e,arguments)}},template:function(t,n){return t.replace(/\{ *([\w_]+) *\}/g,function(t,e){var i=n[e];if(!n.hasOwnProperty(e))throw new TL.Error("template_value_err",t);return i})},hexToRgb:function(t){
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
TL.Util.css_named_colors[t.toLowerCase()]&&(t=TL.Util.css_named_colors[t.toLowerCase()]);var e=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(e,function(t,e,i,n){return e+e+i+i+n+n});var i=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return i?{r:parseInt(i[1],16),g:parseInt(i[2],16),b:parseInt(i[3],16)}:null},
// given an object with r, g, and b keys, or a string of the form 'rgb(mm,nn,ll)', return a CSS hex string including the leading '#' character
rgbToHex:function(t){var e,i,n;if("object"==typeof t)e=t.r,i=t.g,n=t.b;else if("function"==typeof t.match){var a=t.match(/^rgb\((\d+),(\d+),(\d+)\)$/);a&&(e=a[1],i=a[2],n=a[3])}if(isNaN(e)||isNaN(n)||isNaN(i))throw new TL.Error("invalid_rgb_err");return"#"+TL.Util.intToHexString(e)+TL.Util.intToHexString(i)+TL.Util.intToHexString(n)},colorObjToHex:function(t){var e=[t.r,t.g,t.b];return TL.Util.rgbToHex("rgb("+e.join(",")+")")},css_named_colors:{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},ratio:{square:function(t){var e={w:0,h:0};return t.w>t.h&&0<t.h?(e.h=t.h,e.w=t.h):(e.w=t.w,e.h=t.w),e},r16_9:function(t){return null!==t.w&&""!==t.w?Math.round(t.w/16*9):null!==t.h&&""!==t.h?Math.round(t.h/9*16):0},r4_3:function(t){return null!==t.w&&""!==t.w?Math.round(t.w/4*3):null!==t.h&&""!==t.h?Math.round(t.h/3*4):void 0}},getObjectAttributeByIndex:function(t,e){if(void 0===t)return"";var i=0;for(var n in t){if(e===i)return t[n];i++}return""},getUrlVars:function(t){var e,i=[],n,a;(e=t.toString()).match("&#038;")?e=e.replace("&#038;","&"):e.match("&#38;")?e=e.replace("&#38;","&"):e.match("&amp;")&&(e=e.replace("&amp;","&")),a=e.slice(e.indexOf("?")+1).split("&");for(var s=0;s<a.length;s++)n=a[s].split("="),i.push(n[0]),i[n[0]]=n[1];return i},
/**
* Remove any leading or trailing whitespace from the given string.
* If `str` is undefined or does not have a `replace` function, return
* an empty string.
*/
trim:function(t){return t&&"function"==typeof t.replace?t.replace(/^\s+|\s+$/g,""):""},slugify:function(t){t=(
// borrowed from http://stackoverflow.com/a/5782563/102476
t=TL.Util.trim(t)).toLowerCase();for(
// remove accents, swap ñ for n, etc
var e="ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;",i="aaaaaeeeeeiiiiooooouuuunc------",n=0,a=e.length;n<a;n++)t=t.replace(new RegExp(e.charAt(n),"g"),i.charAt(n));// collapse dashes
return t=(t=t.replace(/[^a-z0-9 -]/g,"").replace(/\s+/g,"-").replace(/-+/g,"-")).replace(/^([0-9])/,"_$1")},maxDepth:function(t){for(
// given a sorted array of 2-tuples of numbers, count how many "deep" the items are.
// that is, what is the maximum number of tuples that occupy any one moment
// each tuple should also be sorted
var e=[],i=0,n=0;n<t.length;n++){if(e.push(t[n]),1<e.length){for(var a=e[e.length-1],s=-1,o=0;o<e.length-1;o++)e[o][1]<a[0]&&(s=o);0<=s&&(e=e.slice(s+1))}e.length>i&&(i=e.length)}return i},pad:function(t,e){for(t=String(t),e=e||2;t.length<e;)t="0"+t;return t},intToHexString:function(t){return TL.Util.pad(parseInt(t,10).toString(16))},findNextGreater:function(t,e,i){
// given a sorted list and a current value which *might* be in the list,
// return the next greatest value if the current value is >= the last item in the list, return default,
// or if default is undefined, return input value
for(var n=0;n<t.length;n++)if(e<t[n])return t[n];return i||e},findNextLesser:function(t,e,i){
// given a sorted list and a current value which *might* be in the list,
// return the next lesser value if the current value is <= the last item in the list, return default,
// or if default is undefined, return input value
for(var n=t.length-1;0<=n;n--)if(e>t[n])return t[n];return i||e},isEmptyObject:function(t){var e=[];if(Object.keys)e=Object.keys(t);else// all this to support IE 8
for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&e.push(i);for(var n=0;n<e.length;n++){var a=e[n];if(null!=t[a]&&"string"!=typeof t[a])return!1;if(0!=TL.Util.trim(t[a]).length)return!1}return!0},parseYouTubeTime:function(t){
// given a YouTube start time string in a reasonable format, reduce it to a number of seconds as an integer.
if("string"==typeof t){if(parts=t.match(/^\s*(\d+h)?(\d+m)?(\d+s)?\s*/i),parts){var e=parseInt(parts[1])||0,i=parseInt(parts[2])||0,n;return(parseInt(parts[3])||0)+60*i+60*e*60}}else if("number"==typeof t)return t;return 0},
/**
* Try to make seamless the process of interpreting a URL to a web page which embeds an image for sharing purposes
* as a direct image link. Some services have predictable transformations we can use rather than explain to people
* this subtlety.
*/
transformImageURL:function(t){return t.replace(/(.*)www.dropbox.com\/(.*)/,"$1dl.dropboxusercontent.com/$2")},base58:function(t){var a="123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ",s=a.length;return{encode:function(t){if("number"!=typeof t||t!==parseInt(t))throw'"encode" only accepts integers.';for(var e="";t;){var i=t%s;t=Math.floor(t/s),e=a[i].toString()+e}return e},decode:function(t){if("string"!=typeof t)throw'"decode" only accepts strings.';for(var e=0;t;){var i=a.indexOf(t[0]);if(i<0)throw'"decode" can\'t find "'+t[0]+'" in the alphabet: "'+a+'"';var n=t.length-1;e+=i*Math.pow(s,n),t=t.substring(1)}return e}}}()},function(uc){
/* Zepto v1.1.2-15-g59d3fe5 - zepto event ajax form ie - zeptojs.com/license */
var vc=function(){function r(t){return null==t?String(t):Q[$.call(t)]||"object"}function o(t){return"function"==r(t)}function s(t){return null!=t&&t==t.window}function l(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function n(t){return"object"==r(t)}function h(t){return n(t)&&!s(t)&&Object.getPrototypeOf(t)==Object.prototype}function d(t){return"number"==typeof t.length}function a(t){return E.call(t,function(t){return null!=t})}function c(t){return 0<t.length?k.fn.concat.apply([],t):t}function u(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function i(t){return t in e?e[t]:e[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function m(t,e){return"number"!=typeof e||N[u(t)]?e:e+"px"}function t(t){var e,i;return C[t]||(e=S.createElement(t),S.body.appendChild(e),i=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==i&&(i="block"),C[t]=i),C[t]}function _(t){return"children"in t?D.call(t.children):k.map(t.childNodes,function(t){if(1==t.nodeType)return t})}
// `$.zepto.fragment` takes a html string and an optional tag name
// to generate DOM nodes nodes from the given html string.
// The generated DOM nodes are returned as an array.
// This function can be overriden in plugins for example to make
// it compatible with browsers that don't support the DOM fully.
function p(t,e,i){for(b in e)i&&(h(e[b])||K(e[b]))?(h(e[b])&&!h(t[b])&&(t[b]={}),K(e[b])&&!K(t[b])&&(t[b]=[]),p(t[b],e[b],i)):e[b]!==w&&(t[b]=e[b])}
// Copy all but undefined properties from one or more
// objects to the `target` object.
function f(t,e){return null==e?k(t):k(t).filter(e)}function g(t,e,i,n){return o(e)?e.call(t,i,n):e}function v(t,e,i){null==i?t.removeAttribute(e):t.setAttribute(e,i)}
// access className property while respecting SVGAnimatedString
function y(t,e){var i=t.className,n=i&&i.baseVal!==w;if(e===w)return n?i.baseVal:i;n?i.baseVal=e:t.className=e}
// "true" => true
// "false" => false
// "null" => null
// "42" => 42
// "42.5" => 42.5
// "08" => "08"
// JSON => parse if valid
// String => self
function T(e){var t;try{return e?"true"==e||"false"!=e&&("null"==e?null:/^0/.test(e)||isNaN(t=Number(e))?/^[\[\{]/.test(e)?k.parseJSON(e):e:t):e}catch(t){return e}}function L(t,e){for(var i in e(t),t.childNodes)L(t.childNodes[i],e)}
// Generate the `after`, `prepend`, `before`, `append`,
// `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.
var w,b,k,x,M=[],D=M.slice,E=M.filter,S=window.document,C={},e={},N={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},I=/^\s*<(\w+|!)[^>]*>/,U=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,A=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,j=/^(?:body|html)$/i,O=/([A-Z])/g,
// special attributes that should be get/set via method calls
P=["val","css","html","text","data","width","height","offset"],B=["after","prepend","before","append"],z=S.createElement("table"),R=S.createElement("tr"),q={tr:S.createElement("tbody"),tbody:z,thead:z,tfoot:z,td:R,th:R,"*":S.createElement("div")},H=/complete|loaded|interactive/,F=/^\.([\w-]+)$/,Y=/^#([\w-]*)$/,W=/^[\w-]*$/,Q={},$=Q.toString,Z={},G,J,V=S.createElement("div"),X={tabindex:"tabIndex",readonly:"readOnly",for:"htmlFor",class:"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},K=Array.isArray||function(t){return t instanceof Array};return Z.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var i=t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(i)return i.call(t,e);
// fall back to performing a selector:
var n,a=t.parentNode,s=!a;return s&&(a=V).appendChild(t),n=~Z.qsa(a,e).indexOf(t),s&&V.removeChild(t),n},G=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},J=function(i){return E.call(i,function(t,e){return i.indexOf(t)==e})},Z.fragment=function(t,e,i){var n,a,s;
// A special case optimization for a single tag
return U.test(t)&&(n=k(S.createElement(RegExp.$1))),n||(t.replace&&(t=t.replace(A,"<$1></$2>")),e===w&&(e=I.test(t)&&RegExp.$1),e in q||(e="*"),(s=q[e]).innerHTML=""+t,n=k.each(D.call(s.childNodes),function(){s.removeChild(this)})),h(i)&&(a=k(n),k.each(i,function(t,e){-1<P.indexOf(t)?a[t](e):a.attr(t,e)})),n}
// `$.zepto.Z` swaps out the prototype of the given `dom` array
// of nodes with `$.fn` and thus supplying all the Zepto functions
// to the array. Note that `__proto__` is not supported on Internet
// Explorer. This method can be overriden in plugins.
,Z.Z=function(t,e){return(t=t||[]).__proto__=k.fn,t.selector=e||"",t}
// `$.zepto.isZ` should return `true` if the given object is a Zepto
// collection. This method can be overriden in plugins.
,Z.isZ=function(t){return t instanceof Z.Z}
// `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and
// takes a CSS selector and an optional context (and handles various
// special cases).
// This method can be overriden in plugins.
,Z.init=function(t,e){var i;
// If nothing given, return an empty Zepto collection
if(!t)return Z.Z();
// Optimize for string selectors
// create a new Zepto collection from the nodes found
if("string"==typeof t)
// If it's a html fragment, create nodes from it
// Note: In both Chrome 21 and Firefox 15, DOM error 12
// is thrown if the fragment doesn't begin with <
if("<"==(t=t.trim())[0]&&I.test(t))i=Z.fragment(t,RegExp.$1,e),t=null;
// If there's a context, create a collection on that context first, and select
// nodes from there
else{if(e!==w)return k(e).find(t);
// If it's a CSS selector, use it to select nodes.
i=Z.qsa(S,t)}else{if(o(t))return k(S).ready(t);
// If a Zepto collection is given, just return it
if(Z.isZ(t))return t;
// normalize array if an array of nodes is given
if(K(t))i=a(t);
// Wrap DOM nodes.
else if(n(t))i=[t],t=null;
// If it's a html fragment, create nodes from it
else if(I.test(t))i=Z.fragment(t.trim(),RegExp.$1,e),t=null;
// If there's a context, create a collection on that context first, and select
// nodes from there
else{if(e!==w)return k(e).find(t);
// And last but no least, if it's a CSS selector, use it to select nodes.
i=Z.qsa(S,t)}}return Z.Z(i,t)}
// `$` will be the base `Zepto` object. When calling this
// function just call `$.zepto.init, which makes the implementation
// details of selecting nodes and creating Zepto collections
// patchable in plugins.
,(k=function(t,e){return Z.init(t,e)}).extend=function(e){var i,t=D.call(arguments,1);return"boolean"==typeof e&&(i=e,e=t.shift()),t.forEach(function(t){p(e,t,i)}),e}
// `$.zepto.qsa` is Zepto's CSS selector implementation which
// uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.
// This method can be overriden in plugins.
,Z.qsa=function(t,e){var i,n="#"==e[0],a=!n&&"."==e[0],s=n||a?e.slice(1):e,// Ensure that a 1 char tag name still gets checked
o=W.test(s);return l(t)&&o&&n?(i=t.getElementById(s))?[i]:[]:1!==t.nodeType&&9!==t.nodeType?[]:D.call(o&&!n?a?t.getElementsByClassName(s):// If it's simple, it could be a class
t.getElementsByTagName(e):// Or a tag
t.querySelectorAll(e))},k.contains=function(t,e){return t!==e&&t.contains(e)},k.type=r,k.isFunction=o,k.isWindow=s,k.isArray=K,k.isPlainObject=h,k.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},k.inArray=function(t,e,i){return M.indexOf.call(e,t,i)},k.camelCase=G,k.trim=function(t){return null==t?"":String.prototype.trim.call(t)}
// plugin compatibility
,k.uuid=0,k.support={},k.expr={},k.map=function(t,e){var i,n=[],a,s;if(d(t))for(a=0;a<t.length;a++)null!=(i=e(t[a],a))&&n.push(i);else for(s in t)null!=(i=e(t[s],s))&&n.push(i);return c(n)},k.each=function(t,e){var i,n;if(d(t)){for(i=0;i<t.length;i++)if(!1===e.call(t[i],i,t[i]))return t}else for(n in t)if(!1===e.call(t[n],n,t[n]))return t;return t},k.grep=function(t,e){return E.call(t,e)},window.JSON&&(k.parseJSON=JSON.parse),
// Populate the class2type map
k.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(t,e){Q["[object "+e+"]"]=e.toLowerCase()}),
// Define methods that will be available on all
// Zepto collections
k.fn={
// Because a collection acts like an array
// copy over these useful array functions.
forEach:M.forEach,reduce:M.reduce,push:M.push,sort:M.sort,indexOf:M.indexOf,concat:M.concat,
// `map` and `slice` in the jQuery API work differently
// from their array counterparts
map:function(i){return k(k.map(this,function(t,e){return i.call(t,e,t)}))},slice:function(){return k(D.apply(this,arguments))},ready:function(t){
// need to check if document.body exists for IE as that browser reports
// document ready when it hasn't yet created the body element
return H.test(S.readyState)&&S.body?t(k):S.addEventListener("DOMContentLoaded",function(){t(k)},!1),this},get:function(t){return t===w?D.call(this):this[0<=t?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(i){return M.every.call(this,function(t,e){return!1!==i.call(t,e,t)}),this},filter:function(e){return o(e)?this.not(this.not(e)):k(E.call(this,function(t){return Z.matches(t,e)}))},add:function(t,e){return k(J(this.concat(k(t,e))))},is:function(t){return 0<this.length&&Z.matches(this[0],t)},not:function(e){var i=[];if(o(e)&&e.call!==w)this.each(function(t){e.call(this,t)||i.push(this)});else{var n="string"==typeof e?this.filter(e):d(e)&&o(e.item)?D.call(e):k(e);this.forEach(function(t){n.indexOf(t)<0&&i.push(t)})}return k(i)},has:function(t){return this.filter(function(){return n(t)?k.contains(this,t):k(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!n(t)?t:k(t)},last:function(){var t=this[this.length-1];return t&&!n(t)?t:k(t)},find:function(t){var e,i=this;return e="object"==typeof t?k(t).filter(function(){var e=this;return M.some.call(i,function(t){return k.contains(t,e)})}):1==this.length?k(Z.qsa(this[0],t)):this.map(function(){return Z.qsa(this,t)})},closest:function(t,e){var i=this[0],n=!1;for("object"==typeof t&&(n=k(t));i&&!(n?0<=n.indexOf(i):Z.matches(i,t));)i=i!==e&&!l(i)&&i.parentNode;return k(i)},parents:function(t){for(var e=[],i=this;0<i.length;)i=k.map(i,function(t){if((t=t.parentNode)&&!l(t)&&e.indexOf(t)<0)return e.push(t),t});return f(e,t)},parent:function(t){return f(J(this.pluck("parentNode")),t)},children:function(t){return f(this.map(function(){return _(this)}),t)},contents:function(){return this.map(function(){return D.call(this.childNodes)})},siblings:function(t){return f(this.map(function(t,e){return E.call(_(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},
// `pluck` is borrowed from Prototype.js
pluck:function(e){return k.map(this,function(t){return t[e]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=t(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(e){var i=o(e);if(this[0]&&!i)var n=k(e).get(0),a=n.parentNode||1<this.length;return this.each(function(t){k(this).wrapAll(i?e.call(this,t):a?n.cloneNode(!0):n)})},wrapAll:function(t){if(this[0]){var e;
// drill down to the inmost element
for(k(this[0]).before(t=k(t));(e=t.children()).length;)t=e.first();k(t).append(this)}return this},wrapInner:function(a){var s=o(a);return this.each(function(t){var e=k(this),i=e.contents(),n=s?a.call(this,t):a;i.length?i.wrapAll(n):e.append(n)})},unwrap:function(){return this.parent().each(function(){k(this).replaceWith(k(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(e){return this.each(function(){var t=k(this);(e===w?"none"==t.css("display"):e)?t.show():t.hide()})},prev:function(t){return k(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return k(this.pluck("nextElementSibling")).filter(t||"*")},html:function(i){return 0===arguments.length?0<this.length?this[0].innerHTML:null:this.each(function(t){var e=this.innerHTML;k(this).empty().append(g(this,i,t,e))})},text:function(t){return 0===arguments.length?0<this.length?this[0].textContent:null:this.each(function(){this.textContent=t===w?"":""+t})},attr:function(e,i){var t;return"string"==typeof e&&i===w?0==this.length||1!==this[0].nodeType?w:"value"==e&&"INPUT"==this[0].nodeName?this.val():!(t=this[0].getAttribute(e))&&e in this[0]?this[0][e]:t:this.each(function(t){if(1===this.nodeType)if(n(e))for(b in e)v(this,b,e[b]);else v(this,e,g(this,i,t,this.getAttribute(e)))})},removeAttr:function(t){return this.each(function(){1===this.nodeType&&v(this,t)})},prop:function(e,i){return e=X[e]||e,i===w?this[0]&&this[0][e]:this.each(function(t){this[e]=g(this,i,t,this[e])})},data:function(t,e){var i=this.attr("data-"+t.replace(O,"-$1").toLowerCase(),e);return null!==i?T(i):w},val:function(e){return 0===arguments.length?this[0]&&(this[0].multiple?k(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value):this.each(function(t){this.value=g(this,e,t,this.value)})},offset:function(s){if(s)return this.each(function(t){var e=k(this),i=g(this,s,t,e.offset()),n=e.offsetParent().offset(),a={top:i.top-n.top,left:i.left-n.left};"static"==e.css("position")&&(a.position="relative"),e.css(a)});if(0==this.length)return null;var t=this[0].getBoundingClientRect();return{left:t.left+window.pageXOffset,top:t.top+window.pageYOffset,width:Math.round(t.width),height:Math.round(t.height)}},css:function(t,e){if(arguments.length<2){var i=this[0],n=getComputedStyle(i,"");if(!i)return;if("string"==typeof t)return i.style[G(t)]||n.getPropertyValue(t);if(K(t)){var a={};return k.each(K(t)?t:[t],function(t,e){a[e]=i.style[G(e)]||n.getPropertyValue(e)}),a}}var s="";if("string"==r(t))e||0===e?s=u(t)+":"+m(t,e):this.each(function(){this.style.removeProperty(u(t))});else for(b in t)t[b]||0===t[b]?s+=u(b)+":"+m(b,t[b])+";":this.each(function(){this.style.removeProperty(u(b))});return this.each(function(){this.style.cssText+=";"+s})},index:function(t){return t?this.indexOf(k(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&M.some.call(this,function(t){return this.test(y(t))},i(t))},addClass:function(n){return n?this.each(function(t){x=[];var e=y(this),i;g(this,n,t,e).split(/\s+/g).forEach(function(t){k(this).hasClass(t)||x.push(t)},this),x.length&&y(this,e+(e?" ":"")+x.join(" "))}):this},removeClass:function(e){return this.each(function(t){if(e===w)return y(this,"");x=y(this),g(this,e,t,x).split(/\s+/g).forEach(function(t){x=x.replace(i(t)," ")}),y(this,x.trim())})},toggleClass:function(n,a){return n?this.each(function(t){var e=k(this),i;g(this,n,t,y(this)).split(/\s+/g).forEach(function(t){(a===w?!e.hasClass(t):a)?e.addClass(t):e.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e="scrollTop"in this[0];return t===w?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e="scrollLeft"in this[0];return t===w?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],
// Get *real* offsetParent
e=this.offsetParent(),
// Get correct offsets
i=this.offset(),n=j.test(e[0].nodeName)?{top:0,left:0}:e.offset();
// Subtract element margins
// note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0
// Subtract the two offsets
return i.top-=parseFloat(k(t).css("margin-top"))||0,i.left-=parseFloat(k(t).css("margin-left"))||0,
// Add offsetParent borders
n.top+=parseFloat(k(e[0]).css("border-top-width"))||0,n.left+=parseFloat(k(e[0]).css("border-left-width"))||0,{top:i.top-n.top,left:i.left-n.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||S.body;t&&!j.test(t.nodeName)&&"static"==k(t).css("position");)t=t.offsetParent;return t})}},
// for now
k.fn.detach=k.fn.remove,["width","height"].forEach(function(n){var a=n.replace(/./,function(t){return t[0].toUpperCase()});k.fn[n]=function(e){var t,i=this[0];return e===w?s(i)?i["inner"+a]:l(i)?i.documentElement["scroll"+a]:(t=this.offset())&&t[n]:this.each(function(t){(i=k(this)).css(n,g(this,e,t,i[n]()))})}}),B.forEach(function(e,s){var o=s%2;//=> prepend, append
k.fn[e]=function(){
// arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
var e,i=k.map(arguments,function(t){return"object"==(e=r(t))||"array"==e||null==t?t:Z.fragment(t)}),n,a=1<this.length;return i.length<1?this:this.each(function(t,e){n=o?e:e.parentNode,
// convert all methods to a "before" operation
e=0==s?e.nextSibling:1==s?e.firstChild:2==s?e:null,i.forEach(function(t){if(a)t=t.cloneNode(!0);else if(!n)return k(t).remove();L(n.insertBefore(t,e),function(t){null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src||window.eval.call(window,t.innerHTML)})})})}
// after => insertAfter
// prepend => prependTo
// before => insertBefore
// append => appendTo
,k.fn[o?e+"To":"insert"+(s?"Before":"After")]=function(t){return k(t)[e](this),this}}),Z.Z.prototype=k.fn,
// Export internal API functions in the `$.zepto` namespace
Z.uniq=J,Z.deserializeValue=T,k.zepto=Z,k}(),Um;window.Zepto=vc,void 0===window.$&&(window.$=vc),function(d){function c(t){return t._zid||(t._zid=e++)}function o(t,e,i,n){if((e=u(e)).ns)var a=s(e.ns);return(w[c(t)]||[]).filter(function(t){return t&&(!e.e||t.e==e.e)&&(!e.ns||a.test(t.ns))&&(!i||c(t.fn)===c(i))&&(!n||t.sel==n)})}function u(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function s(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function m(t,e){return t.del&&!i&&t.e in n||!!e}function _(t){return b[t]||i&&n[t]||t}function h(a,t,e,s,o,r,l){var i=c(a),h=w[i]||(w[i]=[]);t.split(/\s/).forEach(function(t){if("ready"==t)return d(document).ready(e);var i=u(t);i.fn=e,i.sel=o,
// emulate mouseenter, mouseleave
i.e in b&&(e=function(t){var e=t.relatedTarget;if(!e||e!==this&&!d.contains(this,e))return i.fn.apply(this,arguments)});var n=(i.del=r)||e;i.proxy=function(t){if(!(t=f(t)).isImmediatePropagationStopped()){t.data=s;var e=n.apply(a,t._args==v?[t]:[t].concat(t._args));return!1===e&&(t.preventDefault(),t.stopPropagation()),e}},i.i=h.length,h.push(i),"addEventListener"in a&&a.addEventListener(_(i.e),i.proxy,m(i,l))})}function p(e,t,i,n,a){var s=c(e);(t||"").split(/\s/).forEach(function(t){o(e,t,i,n).forEach(function(t){delete w[s][t.i],"removeEventListener"in e&&e.removeEventListener(_(t.e),t.proxy,m(t,a))})})}function f(n,a){return!a&&n.isDefaultPrevented||(a||(a=n),d.each(x,function(t,e){var i=a[t];n[t]=function(){return this[e]=l,i&&i.apply(a,arguments)},n[e]=k}),(a.defaultPrevented!==v?a.defaultPrevented:"returnValue"in a?!1===a.returnValue:a.getPreventDefault&&a.getPreventDefault())&&(n.isDefaultPrevented=l)),n}function g(t){var e,i={originalEvent:t};for(e in t)a.test(e)||t[e]===v||(i[e]=t[e]);return f(i,t)}var t=d.zepto.qsa,e=1,v,y=Array.prototype.slice,T=d.isFunction,L=function(t){return"string"==typeof t},w={},r={},i="onfocusin"in window,n={focus:"focusin",blur:"focusout"},b={mouseenter:"mouseover",mouseleave:"mouseout"};r.click=r.mousedown=r.mouseup=r.mousemove="MouseEvents",d.event={add:h,remove:p},d.proxy=function(t,e){if(T(t)){var i=function(){return t.apply(e,arguments)};return i._zid=c(t),i}if(L(e))return d.proxy(t[e],t);throw new TypeError("expected function")},d.fn.bind=function(t,e,i){return this.on(t,e,i)},d.fn.unbind=function(t,e){return this.off(t,e)},d.fn.one=function(t,e,i,n){return this.on(t,e,i,n,1)};var l=function(){return!0},k=function(){return!1},a=/^([A-Z]|returnValue$|layer[XY]$)/,x={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};d.fn.delegate=function(t,e,i){return this.on(e,t,i)},d.fn.undelegate=function(t,e,i){return this.off(e,t,i)},d.fn.live=function(t,e){return d(document.body).delegate(this.selector,t,e),this},d.fn.die=function(t,e){return d(document.body).undelegate(this.selector,t,e),this},d.fn.on=function(e,a,i,s,o){var r,l,n=this;return e&&!L(e)?(d.each(e,function(t,e){n.on(t,a,i,e,o)}),n):(L(a)||T(s)||!1===s||(s=i,i=a,a=v),(T(i)||!1===i)&&(s=i,i=v),!1===s&&(s=k),n.each(function(t,n){o&&(r=function(t){return p(n,t.type,s),s.apply(this,arguments)}),a&&(l=function(t){var e,i=d(t.target).closest(a,n).get(0);if(i&&i!==n)return e=d.extend(g(t),{currentTarget:i,liveFired:n}),(r||s).apply(i,[e].concat(y.call(arguments,1)))}),h(n,e,s,i,a,l||r)}))},d.fn.off=function(t,i,e){var n=this;return t&&!L(t)?(d.each(t,function(t,e){n.off(t,i,e)}),n):(L(i)||T(e)||!1===e||(e=i,i=v),!1===e&&(e=k),n.each(function(){p(this,t,e,i)}))},d.fn.trigger=function(t,e){return(t=L(t)||d.isPlainObject(t)?d.Event(t):f(t))._args=e,this.each(function(){
// items in the collection might not be DOM elements
"dispatchEvent"in this?this.dispatchEvent(t):d(this).triggerHandler(t,e)})}
// triggers event handlers on current element just as if an event occurred,
// doesn't trigger an actual event, doesn't bubble
,d.fn.triggerHandler=function(i,n){var a,s;return this.each(function(t,e){(a=g(L(i)?d.Event(i):i))._args=n,a.target=e,d.each(o(e,i.type||i),function(t,e){if(s=e.proxy(a),a.isImmediatePropagationStopped())return!1})}),s}
// shortcut methods for `.bind(event, fn)` for each event type
,"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){d.fn[e]=function(t){return t?this.bind(e,t):this.trigger(e)}}),["focus","blur"].forEach(function(e){d.fn[e]=function(t){return t?this.bind(e,t):this.each(function(){try{this[e]()}catch(t){}}),this}}),d.Event=function(t,e){L(t)||(t=(e=t).type);var i=document.createEvent(r[t]||"Events"),n=!0;if(e)for(var a in e)"bubbles"==a?n=!!e[a]:i[a]=e[a];return i.initEvent(t,n,!0),f(i)}}(vc),function(xk){
// trigger a custom event and return false if it was cancelled
function Ik(t,e,i){var n=xk.Event(e);return xk(t).trigger(n,i),!n.isDefaultPrevented()}
// trigger an Ajax "global" event
function Jk(t,e,i,n){if(t.global)return Ik(e||zk,i,n)}
// Number of active Ajax requests
function Kk(t){t.global&&0==xk.active++&&Jk(t,null,"ajaxStart")}function Lk(t){t.global&&!--xk.active&&Jk(t,null,"ajaxStop")}
// triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable
function Mk(t,e){var i=e.context;if(!1===e.beforeSend.call(i,t,e)||!1===Jk(e,i,"ajaxBeforeSend",[t,e]))return!1;Jk(e,i,"ajaxSend",[t,e])}function Nk(t,e,i,n){var a=i.context,s="success";i.success.call(a,t,s,e),n&&n.resolveWith(a,[t,s,e]),Jk(i,a,"ajaxSuccess",[e,i,t]),Pk(s,e,i)}
// type: "timeout", "error", "abort", "parsererror"
function Ok(t,e,i,n,a){var s=n.context;n.error.call(s,i,e,t),a&&a.rejectWith(s,[i,e,t]),Jk(n,s,"ajaxError",[i,n,t||e]),Pk(e,i,n)}
// status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
function Pk(t,e,i){var n=i.context;i.complete.call(n,e,t),Jk(i,n,"ajaxComplete",[e,i]),Lk(i)}
// Empty function, used as default callback
function Qk(){}function Rk(t){return t&&(t=t.split(";",2)[0]),t&&(t==Gk?"html":t==Fk?"json":Dk.test(t)?"script":Ek.test(t)&&"xml")||"text"}function Sk(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}
// serialize payload and append it to the URL for GET requests
function Tk(t){t.processData&&t.data&&"string"!=xk.type(t.data)&&(t.data=xk.param(t.data,t.traditional)),!t.data||t.type&&"GET"!=t.type.toUpperCase()||(t.url=Sk(t.url,t.data),t.data=void 0)}
// handle optional data/success arguments
function Uk(t,e,i,n){var a=!xk.isFunction(e);return{url:t,data:a?e:void 0,success:a?xk.isFunction(i)?i:void 0:e,dataType:a&&n||i}}function Wk(i,t,n,a){var s,o=xk.isArray(t),r=xk.isPlainObject(t);xk.each(t,function(t,e){s=xk.type(e),a&&(t=n?a:a+"["+(r||"object"==s||"array"==s?t:"")+"]"),
// handle data in serializeArray() format
!a&&o?i.add(e.name,e.value):"array"==s||!n&&"object"==s?Wk(i,e,n,t):i.add(t,e)})}var yk=0,zk=window.document,Ak,Bk,Ck=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,Dk=/^(?:text|application)\/javascript/i,Ek=/^(?:text|application)\/xml/i,Fk="application/json",Gk="text/html",Hk=/^\s*$/;xk.active=0,xk.ajaxJSONP=function(i,n){if(!("type"in i))return xk.ajax(i);var t=i.jsonpCallback,a=(xk.isFunction(t)?t():t)||"jsonp"+ ++yk,s=zk.createElement("script"),o=window[a],r,e=function(t){xk(s).triggerHandler("error",t||"abort")},l={abort:e},h;return n&&n.promise(l),xk(s).on("load error",function(t,e){clearTimeout(h),xk(s).off().remove(),"error"!=t.type&&r?Nk(r[0],l,i,n):Ok(null,e||"error",l,i,n),window[a]=o,r&&xk.isFunction(o)&&o(r[0]),o=r=void 0}),!1===Mk(l,i)?e("abort"):(window[a]=function(){r=arguments},s.src=i.url.replace(/\?(.+)=\?/,"?$1="+a),zk.head.appendChild(s),0<i.timeout&&(h=setTimeout(function(){e("timeout")},i.timeout))),l},xk.ajaxSettings={
// Default type of request
type:"GET",
// Callback that is executed before request
beforeSend:Qk,
// Callback that is executed if the request succeeds
success:Qk,
// Callback that is executed the the server drops error
error:Qk,
// Callback that is executed on request complete (both: error and success)
complete:Qk,
// The context for the callbacks
context:null,
// Whether to trigger "global" Ajax events
global:!0,
// Transport
xhr:function(){return new window.XMLHttpRequest},
// MIME types mapping
// IIS returns Javascript as "application/x-javascript"
accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:Fk,xml:"application/xml, text/xml",html:Gk,text:"text/plain"},
// Whether the request is to another domain
crossDomain:!1,
// Default timeout
timeout:0,
// Whether data should be serialized to string
processData:!0,
// Whether the browser should be allowed to cache GET responses
cache:!0},xk.ajax=function(Pl){var Ql=xk.extend({},Pl||{}),Rl=xk.Deferred&&xk.Deferred();for(Ak in xk.ajaxSettings)void 0===Ql[Ak]&&(Ql[Ak]=xk.ajaxSettings[Ak]);Kk(Ql),Ql.crossDomain||(Ql.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(Ql.url)&&RegExp.$2!=window.location.host),Ql.url||(Ql.url=window.location.toString()),Tk(Ql),!1===Ql.cache&&(Ql.url=Sk(Ql.url,"_="+Date.now()));var Sl=Ql.dataType,Tl=/\?.+=\?/.test(Ql.url);if("jsonp"==Sl||Tl)return Tl||(Ql.url=Sk(Ql.url,Ql.jsonp?Ql.jsonp+"=?":!1===Ql.jsonp?"":"callback=?")),xk.ajaxJSONP(Ql,Rl);var Ul=Ql.accepts[Sl],Vl={},Wl=function(t,e){Vl[t.toLowerCase()]=[t,e]},Xl=/^([\w-]+:)\/\//.test(Ql.url)?RegExp.$1:window.location.protocol,Yl=Ql.xhr(),Zl=Yl.setRequestHeader,$l;if(Rl&&Rl.promise(Yl),Ql.crossDomain||Wl("X-Requested-With","XMLHttpRequest"),Wl("Accept",Ul||"*/*"),(Ul=Ql.mimeType||Ul)&&(-1<Ul.indexOf(",")&&(Ul=Ul.split(",",2)[0]),Yl.overrideMimeType&&Yl.overrideMimeType(Ul)),(Ql.contentType||!1!==Ql.contentType&&Ql.data&&"GET"!=Ql.type.toUpperCase())&&Wl("Content-Type",Ql.contentType||"application/x-www-form-urlencoded"),Ql.headers)for(Bk in Ql.headers)Wl(Bk,Ql.headers[Bk]);if(Yl.setRequestHeader=Wl,!(Yl.onreadystatechange=function(){if(4==Yl.readyState){Yl.onreadystatechange=Qk,clearTimeout($l);var cm,dm=!1;if(200<=Yl.status&&Yl.status<300||304==Yl.status||0==Yl.status&&"file:"==Xl){Sl=Sl||Rk(Ql.mimeType||Yl.getResponseHeader("content-type")),cm=Yl.responseText;try{
// http://perfectionkills.com/global-eval-what-are-the-options/
"script"==Sl?eval(cm):"xml"==Sl?cm=Yl.responseXML:"json"==Sl&&(cm=Hk.test(cm)?null:xk.parseJSON(cm))}catch(t){dm=t}dm?Ok(dm,"parsererror",Yl,Ql,Rl):Nk(cm,Yl,Ql,Rl)}else Ok(Yl.statusText||null,Yl.status?"error":"abort",Yl,Ql,Rl)}})===Mk(Yl,Ql))return Yl.abort(),Ok(null,"abort",Yl,Ql,Rl),Yl;if(Ql.xhrFields)for(Bk in Ql.xhrFields)Yl[Bk]=Ql.xhrFields[Bk];var _l=!("async"in Ql)||Ql.async;for(Bk in Yl.open(Ql.type,Ql.url,_l,Ql.username,Ql.password),Vl)Zl.apply(Yl,Vl[Bk]);return 0<Ql.timeout&&($l=setTimeout(function(){Yl.onreadystatechange=Qk,Yl.abort(),Ok(null,"timeout",Yl,Ql,Rl)},Ql.timeout)),
// avoid sending empty string (#319)
Yl.send(Ql.data?Ql.data:null),Yl},xk.get=function(t,e,i,n){return xk.ajax(Uk.apply(null,arguments))},xk.post=function(t,e,i,n){var a=Uk.apply(null,arguments);return a.type="POST",xk.ajax(a)},xk.getJSON=function(t,e,i){var n=Uk.apply(null,arguments);return n.dataType="json",xk.ajax(n)},xk.fn.load=function(t,e,i){if(!this.length)return this;var n=this,a=t.split(/\s/),s,o=Uk(t,e,i),r=o.success;return 1<a.length&&(o.url=a[0],s=a[1]),o.success=function(t){n.html(s?xk("<div>").html(t.replace(Ck,"")).find(s):t),r&&r.apply(n,arguments)},xk.ajax(o),this};var Vk=encodeURIComponent;xk.param=function(t,e){var i=[];return i.add=function(t,e){this.push(Vk(t)+"="+Vk(e))},Wk(i,t,e),i.join("&").replace(/%20/g,"+")}}(vc),(Um=vc).fn.serializeArray=function(){var e=[],i;return Um([].slice.call(this.get(0).elements)).each(function(){var t=(i=Um(this)).attr("type");"fieldset"!=this.nodeName.toLowerCase()&&!this.disabled&&"submit"!=t&&"reset"!=t&&"button"!=t&&("radio"!=t&&"checkbox"!=t||this.checked)&&e.push({name:i.attr("name"),value:i.val()})}),e},Um.fn.serialize=function(){var e=[];return this.serializeArray().forEach(function(t){e.push(encodeURIComponent(t.name)+"="+encodeURIComponent(t.value))}),e.join("&")},Um.fn.submit=function(t){if(t)this.bind("submit",t);else if(this.length){var e=Um.Event("submit");this.eq(0).trigger(e),e.isDefaultPrevented()||this.get(0).submit()}return this},function(i){
// __proto__ doesn't exist on IE<11, so redefine
// the Z function to use object extension instead
"__proto__"in{}||i.extend(i.zepto,{Z:function(t,e){return t=t||[],i.extend(t,i.fn),t.selector=e||"",t.__Z=!0,t},
// this is a kludge but works
isZ:function(t){return"array"===i.type(t)&&"__Z"in t}});
// getComputedStyle shouldn't freak out when called
// without a valid element as argument
try{getComputedStyle(void 0)}catch(t){var n=getComputedStyle;window.getComputedStyle=function(t,e){try{return n(t,e)}catch(t){return null}}}}(vc),uc.getJSON=vc.getJSON,uc.ajax=vc.ajax}(TL),
/* TL.Class
Class powers the OOP facilities of the library.
================================================== */
TL.Class=function(){},TL.Class.extend=function(/*Object*/t){
// extended class with the new prototype
var e=function(){this.initialize&&this.initialize.apply(this,arguments)},i=function(){};
// instantiate class without calling constructor
i.prototype=this.prototype;var n=new i;
// add class name
//proto.className = props;
//inherit parent's statics
for(var a in(n.constructor=e).prototype=n,
// add superclass access
e.superclass=this.prototype,this)this.hasOwnProperty(a)&&"prototype"!==a&&"superclass"!==a&&(e[a]=this[a]);
// mix static properties into the class
return t.statics&&(TL.Util.extend(e,t.statics),delete t.statics),
// mix includes into the prototype
t.includes&&(TL.Util.extend.apply(null,[n].concat(t.includes)),delete t.includes),
// merge options
t.options&&n.options&&(t.options=TL.Util.extend({},n.options,t.options)),
// mix given properties into the prototype
TL.Util.extend(n,t),
// allow inheriting further
e.extend=TL.Class.extend,
// method for adding properties to prototype
e.include=function(t){TL.Util.extend(this.prototype,t)},e},
/* TL.Events
adds custom events functionality to TL classes
================================================== */
TL.Events={addEventListener:function(/*String*/t,/*Function*/e,/*(optional) Object*/i){var n=this._tl_events=this._tl_events||{};return n[t]=n[t]||[],n[t].push({action:e,context:i||this}),this},hasEventListeners:function(/*String*/t){var e="_tl_events";return e in this&&t in this[e]&&0<this[e][t].length},removeEventListener:function(/*String*/t,/*Function*/e,/*(optional) Object*/i){if(!this.hasEventListeners(t))return this;for(var n=0,a=this._tl_events,s=a[t].length;n<s;n++)if(a[t][n].action===e&&(!i||a[t][n].context===i))return a[t].splice(n,1),this;return this},fireEvent:function(/*String*/t,/*(optional) Object*/e){if(!this.hasEventListeners(t))return this;for(var i=TL.Util.mergeData({type:t,target:this},e),n=this._tl_events[t].slice(),a=0,s=n.length;a<s;a++)n[a].action.call(n[a].context||this,i);return this}},TL.Events.on=TL.Events.addEventListener,TL.Events.off=TL.Events.removeEventListener,TL.Events.fire=TL.Events.fireEvent,
/*
Based on Leaflet Browser
TL.Browser handles different browser and feature detections for internal use.
*/
function(){var t=navigator.userAgent.toLowerCase(),e=document.documentElement,i="ActiveXObject"in window,n=-1!==t.indexOf("webkit"),a=-1!==t.indexOf("phantom"),s=-1!==t.search("android [23]"),o="undefined"!=typeof orientation,r=navigator.msPointerEnabled&&navigator.msMaxTouchPoints&&!window.PointerEvent,l=window.PointerEvent&&navigator.pointerEnabled&&navigator.maxTouchPoints||r,h=i&&"transition"in e.style,d="WebKitCSSMatrix"in window&&"m11"in new window.WebKitCSSMatrix&&!s,c="MozPerspective"in e.style,u="OTransition"in e.style,m=window.opera,_="devicePixelRatio"in window&&1<window.devicePixelRatio;if(!_&&"matchMedia"in window){var p=window.matchMedia("(min-resolution:144dpi)");_=p&&p.matches}var f=!window.L_NO_TOUCH&&!a&&(l||"ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch);TL.Browser={ie:i,ua:t,ie9:Boolean(i&&t.match(/MSIE 9/i)),ielt9:i&&!document.addEventListener,webkit:n,
//gecko: (ua.indexOf('gecko') !== -1) && !webkit && !window.opera && !ie,
firefox:-1!==t.indexOf("gecko")&&!n&&!window.opera&&!i,android:-1!==t.indexOf("android"),android23:s,chrome:-1!==t.indexOf("chrome"),edge:-1!==t.indexOf("edge/"),ie3d:h,webkit3d:d,gecko3d:c,opera3d:u,any3d:!window.L_DISABLE_3D&&(h||d||c||u)&&!a,mobile:o,mobileWebkit:o&&n,mobileWebkit3d:o&&d,mobileOpera:o&&window.opera,touch:!!f,msPointer:!!r,pointer:!!l,retina:!!_,orientation:function(){var t=window.innerWidth,e,i="portrait";return window.innerHeight<t&&(i="landscape"),Math.abs(window.orientation),trace(i),i}}}(),
/* TL.Load
Loads External Javascript and CSS
================================================== */
TL.Load=function(t){function a(t){var e=0,i=!1;for(e=0;e<n.length;e++)n[e]==t&&(i=!0);return!!i||(n.push(t),!1)}var n=[];return{css:function(t,e,i,n){a(t)?e():TL.LoadIt.css(t,e,i,n)},js:function(t,e,i,n){a(t)?e():TL.LoadIt.js(t,e,i,n)}}}(this.document),
/*jslint browser: true, eqeqeq: true, bitwise: true, newcap: true, immed: true, regexp: false */
/*
LazyLoad makes it easy and painless to lazily load one or more external
JavaScript or CSS files on demand either during or after the rendering of a web
page.
Supported browsers include Firefox 2+, IE6+, Safari 3+ (including Mobile
Safari), Google Chrome, and Opera 9+. Other browsers may or may not work and
are not officially supported.
Visit https://github.com/rgrove/lazyload/ for more info.
Copyright (c) 2011 Ryan Grove <ryan@wonko.com>
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the 'Software'), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@module lazyload
@class LazyLoad
@static
@version 2.0.3 (git)
*/
TL.LoadIt=function(_){
// -- Private Methods --------------------------------------------------------
/**
Creates and returns an HTML element with the specified name and attributes.
@method createNode
@param {String} name element name
@param {Object} attrs name/value mapping of element attributes
@return {HTMLElement}
@private
*/
function p(t,e){var i=_.createElement(t),n;for(n in e)e.hasOwnProperty(n)&&i.setAttribute(n,e[n]);return i}
/**
Called when the current pending resource of the specified type has finished
loading. Executes the associated callback (if any) and loads the next
resource in the queue.
@method finish
@param {String} type resource type ('css' or 'js')
@private
*/function f(t){var e=w[t],i,n;e&&(i=e.callback,(n=e.urls).shift(),s=0,
// If this is the last of the pending URLs, execute the callback and
// start the next request in the queue (if any).
n.length||(i&&i.call(e.context,e.obj),w[t]=null,b[t].length&&a(t)))}
/**
Populates the <code>env</code> variable with user agent and feature test
information.
@method getEnv
@private
*/function g(){var t=navigator.userAgent;((T={
// True if this browser supports disabling async mode on dynamically
// created script nodes. See
// http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
async:!0===_.createElement("script").async}).webkit=/AppleWebKit\//.test(t))||(T.ie=/MSIE/.test(t))||(T.opera=/Opera/.test(t))||(T.gecko=/Gecko\//.test(t))||(T.unknown=!0)}
/**
Loads the specified resources, or the next resource of the specified type
in the queue if no resources are specified. If a resource of the specified
type is already being loaded, the new request will be queued until the
first request has been finished.
When an array of resource URLs is specified, those URLs will be loaded in
parallel if it is possible to do so while preserving execution order. All
browsers support parallel loading of CSS, but only Firefox and Opera
support parallel loading of scripts. In other browsers, scripts will be
queued and loaded one at a time to ensure correct execution order.
@method load
@param {String} type resource type ('css' or 'js')
@param {String|Array} urls (optional) URL or array of URLs to load
@param {Function} callback (optional) callback function to execute when the
resource is loaded
@param {Object} obj (optional) object to pass to the callback function
@param {Object} context (optional) if provided, the callback function will
be executed in this object's context
@private
*/function a(t,e,i,n,a){var s=function(){f(t)},o="css"===t,r=[],l,h,d,c,u,m;if(T||g(),e)
// Create a request object for each URL. If multiple URLs are specified,
// the callback will only be executed after all URLs have been loaded.
//
// Sadly, Firefox and Opera are the only browsers capable of loading
// scripts in parallel while preserving execution order. In all other
// browsers, scripts must be loaded sequentially.
//
// All browsers respect CSS specificity based on the order of the link
// elements in the DOM, regardless of the order in which the stylesheets
// are actually downloaded.
if(
// If urls is a string, wrap it in an array. Otherwise assume it's an
// array and create a copy of it so modifications won't be made to the
// original.
e="string"==typeof e?[e]:e.concat(),o||T.async||T.gecko||T.opera)
// Load in parallel.
b[t].push({urls:e,callback:i,obj:n,context:a});else
// Load sequentially.
for(l=0,h=e.length;l<h;++l)b[t].push({urls:[e[l]],callback:l===h-1?i:null,// callback is only added to the last URL
obj:n,context:a});
// If a previous load request of this type is currently in progress, we'll
// wait our turn. Otherwise, grab the next item in the queue.
if(!w[t]&&(c=w[t]=b[t].shift())){for(L||(L=_.head||_.getElementsByTagName("head")[0]),l=0,h=(u=c.urls).length;l<h;++l)m=u[l],o?d=T.gecko?p("style"):p("link",{href:m,rel:"stylesheet"}):(d=p("script",{src:m})).async=!1,d.className="lazyload",d.setAttribute("charset","utf-8"),T.ie&&!o?d.onreadystatechange=function(){/loaded|complete/.test(d.readyState)&&(d.onreadystatechange=null,s())}:o&&(T.gecko||T.webkit)?
// Gecko and WebKit don't support the onload event on link nodes.
T.webkit?(
// In WebKit, we can poll for changes to document.styleSheets to
// figure out when stylesheets have loaded.
c.urls[l]=d.href,// resolve relative URLs (or polling won't work)
y()):(
// In Gecko, we can import the requested URL into a <style> node and
// poll for the existence of node.sheet.cssRules. Props to Zach
// Leatherman for calling my attention to this technique.
d.innerHTML='@import "'+m+'";',v(d)):d.onload=d.onerror=s,r.push(d);for(l=0,h=r.length;l<h;++l)L.appendChild(r[l])}}
/**
Begins polling to determine when the specified stylesheet has finished loading
in Gecko. Polling stops when all pending stylesheets have loaded or after 10
seconds (to prevent stalls).
Thanks to Zach Leatherman for calling my attention to the @import-based
cross-domain technique used here, and to Oleg Slobodskoi for an earlier
same-domain implementation. See Zach's blog for more details:
http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
@method pollGecko
@param {HTMLElement} node Style node to poll.
@private
*/function v(e){var i;try{
// We don't really need to store this value or ever refer to it again, but
// if we don't store it, Closure Compiler assumes the code is useless and
// removes it.
i=!!e.sheet.cssRules}catch(t){
// An exception means the stylesheet is still loading.
return void((s+=1)<200?setTimeout(function(){v(e)},50):
// We've been polling for 10 seconds and nothing's happened. Stop
// polling and finish the pending requests to avoid blocking further
// requests.
i&&f("css"))}
// If we get here, the stylesheet has loaded.
f("css")}
/**
Begins polling to determine when pending stylesheets have finished loading
in WebKit. Polling stops when all pending stylesheets have loaded or after 10
seconds (to prevent stalls).
@method pollWebKit
@private
*/function y(){var t=w.css,e;if(t){
// Look for a stylesheet matching the pending URL.
for(e=i.length;0<=--e;)if(i[e].href===t.urls[0]){f("css");break}s+=1,t&&(s<200?setTimeout(y,50):
// We've been polling for 10 seconds and nothing's happened, which may
// indicate that the stylesheet has been removed from the document
// before it had a chance to load. Stop polling and finish the pending
// request to prevent blocking further requests.
f("css"))}}
// -- Private Variables ------------------------------------------------------
// User agent and feature test information.
var T,
// Reference to the <head> element (populated lazily).
L,
// Requests currently in progress, if any.
w={},
// Number of times we've polled to check whether a pending stylesheet has
// finished loading. If this gets too high, we're probably stalled.
s=0,
// Queued requests.
b={css:[],js:[]},
// Reference to the browser's list of stylesheets.
i=_.styleSheets;return{
/**
Requests the specified CSS URL or URLs and executes the specified
callback (if any) when they have finished loading. If an array of URLs is
specified, the stylesheets will be loaded in parallel and the callback
will be executed after all stylesheets have finished loading.
@method css
@param {String|Array} urls CSS URL or array of CSS URLs to load
@param {Function} callback (optional) callback function to execute when
the specified stylesheets are loaded
@param {Object} obj (optional) object to pass to the callback function
@param {Object} context (optional) if provided, the callback function
will be executed in this object's context
@static
*/
css:function(t,e,i,n){a("css",t,e,i,n)},
/**
Requests the specified JavaScript URL or URLs and executes the specified
callback (if any) when they have finished loading. If an array of URLs is
specified and the browser supports it, the scripts will be loaded in
parallel and the callback will be executed after all scripts have
finished loading.
Currently, only Firefox and Opera support parallel loading of scripts while
preserving execution order. In other browsers, scripts will be
queued and loaded one at a time to ensure correct execution order.
@method js
@param {String|Array} urls JS URL or array of JS URLs to load
@param {Function} callback (optional) callback function to execute when
the specified scripts are loaded
@param {Object} obj (optional) object to pass to the callback function
@param {Object} context (optional) if provided, the callback function
will be executed in this object's context
@static
*/
js:function(t,e,i,n){a("js",t,e,i,n)}}}(this.document),
/* TL.TimelineConfig
separate the configuration from the display (TL.Timeline)
to make testing easier
================================================== */
TL.TimelineConfig=TL.Class.extend({includes:[],initialize:function(t){
// Initialize the data
if(this.title="",this.scale="",this.events=[],this.eras=[],this.event_dict={},// despite name, all slides (events + title) indexed by slide.unique_id
this.messages={errors:[],warnings:[]},"object"==typeof t&&t.events){if(this.scale=t.scale,this.events=[],this._ensureValidScale(t.events),t.title){var e=this._assignID(t.title);this._tidyFields(t.title),this.title=t.title,this.event_dict[e]=this.title}for(var i=0;i<t.events.length;i++)try{this.addEvent(t.events[i],!0)}catch(t){this.logError(t)}if(t.eras)for(var i=0;i<t.eras.length;i++)try{this.addEra(t.eras[i],!0)}catch(t){this.logError("Era "+i+": "+t)}TL.DateUtil.sortByDate(this.events),TL.DateUtil.sortByDate(this.eras)}},logError:function(t){trace(t),this.messages.errors.push(t)},
/*
* Return any accumulated error messages. If `sep` is passed, it should be a string which will be used to join all messages, resulting in a string return value. Otherwise,
* errors will be returned as an array.
*/
getErrors:function(t){return t?this.messages.errors.join(t):this.messages.errors},
/*
* Perform any sanity checks we can before trying to use this to make a timeline. Returns nothing, but errors will be logged
* such that after this is called, one can test `this.isValid()` to see if everything is OK.
*/
validate:function(){void 0!==this.events&&void 0!==this.events.length&&0!=this.events.length||this.logError("Timeline configuration has no events.");
// make sure all eras have start and end dates
for(var t=0;t<this.eras.length;t++){var e;if(void 0===this.eras[t].start_date||void 0===this.eras[t].end_date)e=this.eras[t].text&&this.eras[t].text.headline?this.eras[t].text.headline:"era "+(t+1),this.logError("All eras must have start and end dates. ["+e+"]")}},isValid:function(){return 0==this.messages.errors.length},
/* Add an event (including cleaning/validation) and return the unique id.
* All event data validation should happen in here.
* Throws: TL.Error for any validation problems.
*/
addEvent:function(t,e){var i=this._assignID(t);if(void 0===t.start_date)throw new TL.Error("missing_start_date_err",i);return this._processDates(t),this._tidyFields(t),this.events.push(t),this.event_dict[i]=t,e||TL.DateUtil.sortByDate(this.events),i},addEra:function(t,e){var i=this._assignID(t);if(void 0===t.start_date)throw new TL.Error("missing_start_date_err",i);return this._processDates(t),this._tidyFields(t),this.eras.push(t),this.event_dict[i]=t,e||TL.DateUtil.sortByDate(this.eras),i},
/**
* Given a slide, verify that its ID is unique, or assign it one which is.
* The assignment happens in this function, and the assigned ID is also
* the return value. Not thread-safe, because ids are not reserved
* when assigned here.
*/
_assignID:function(t){var e=t.unique_id;return TL.Util.trim(e)||(
// give it an ID if it doesn't have one
e=t.text?TL.Util.slugify(t.text.headline):null),
// make sure it's unique and add it.
t.unique_id=TL.Util.ensureUniqueKey(this.event_dict,e),t.unique_id},
/**
* Given an array of slide configs (the events), ensure that each one has a distinct unique_id. The id of the title
* is also passed in because in most ways it functions as an event slide, and the event IDs must also all be unique
* from the title ID.
*/
_makeUniqueIdentifiers:function(t,e){
// establish which IDs are assigned and if any appear twice, clear out successors.
for(var i=[t],n=0;n<e.length;n++)TL.Util.trim(e[n].unique_id)&&(e[n].unique_id=TL.Util.slugify(e[n].unique_id),// enforce valid
-1==i.indexOf(e[n].unique_id)?i.push(e[n].unique_id):// it was already used, wipe it out
e[n].unique_id="");if(i.length!=e.length+1)
// at least some are yet to be assigned
for(var n=0;n<e.length;n++)if(!e[n].unique_id){
// use the headline for the unique ID if it's available
var a=e[n].text?TL.Util.slugify(e[n].text.headline):null;a||(a=TL.Util.unique_ID(6)),-1!=i.indexOf(a)&&(a=a+"-"+n),i.push(a),e[n].unique_id=a}},_ensureValidScale:function(t){if(!this.scale){trace("Determining scale dynamically"),this.scale="human";// default to human unless there's a slide which is explicitly 'cosmological' or one which has a cosmological year
for(var e=0;e<t.length;e++){if("cosmological"==t[e].scale){this.scale="cosmological";break}if(t[e].start_date&&void 0!==t[e].start_date.year){var i,n=new TL.BigDate(t[e].start_date).data.date_obj.year;if(n<-271820||275759<n){this.scale="cosmological";break}}}}var a;TL.DateUtil.SCALE_DATE_CLASSES[this.scale]||this.logError("Don't know how to process dates on scale "+this.scale)},
/*
Given a thing which has a start_date and optionally an end_date, make sure that it is an instance
of the correct date class (for human or cosmological scale). For slides, remove redundant end dates
(people frequently configure an end date which is the same as the start date).
*/
_processDates:function(t){var e=TL.DateUtil.SCALE_DATE_CLASSES[this.scale];if(!(t.start_date instanceof e)){var i=t.start_date;
// eliminate redundant end dates.
if(t.start_date=new e(i),void 0!==t.end_date&&!(t.end_date instanceof e)){var n=t.end_date,a=!0;for(property in i)a=a&&i[property]==n[property];a?(trace("End date same as start date is redundant; dropping end date"),delete t.end_date):t.end_date=new e(n)}}},
/**
* Return the earliest date that this config knows about, whether it's a slide or an era
*/
getEarliestDate:function(){
// counting that dates were sorted in initialization
var t=this.events[0].start_date;return this.eras&&0<this.eras.length&&this.eras[0].start_date.isBefore(t)?this.eras[0].start_date:t},
/**
* Return the latest date that this config knows about, whether it's a slide or an era, taking end_dates into account.
*/
getLatestDate:function(){for(var t=[],e=0;e<this.events.length;e++)this.events[e].end_date?t.push({date:this.events[e].end_date}):t.push({date:this.events[e].start_date});for(var e=0;e<this.eras.length;e++)this.eras[e].end_date?t.push({date:this.eras[e].end_date}):t.push({date:this.eras[e].start_date});return TL.DateUtil.sortByDate(t,"date"),t.slice(-1)[0].date},_tidyFields:function(t){function e(t,e,i){i||(i=""),t.hasOwnProperty(e)||(t[e]=i)}t.group&&(t.group=TL.Util.trim(t.group)),t.text||(t.text={}),e(t.text,"text"),e(t.text,"headline")}}),function(h){
/*
* Convert a URL to a Google Spreadsheet (typically a /pubhtml version but somewhat flexible) into an object with the spreadsheet key (ID) and worksheet ID.
If `url` is actually a string which is only letters, numbers, '-' and '_', then it's assumed to be an ID already. If we had a more precise way of testing to see if the input argument was a valid key, we might apply it, but I don't know where that's documented.
If we're pretty sure this isn't a bare key or a url that could be used to find a Google spreadsheet then return null.
*/
function o(t){parts={key:null,worksheet:0};
// key as url parameter (old-fashioned)
var e=/\bkey=([-_A-Za-z0-9]+)&?/i,i=/docs.google.com\/spreadsheets(.*?)\/d\//;// fixing issue of URLs with u/0/d
if(t.match(e))parts.key=t.match(e)[1];
// can we get a worksheet from this form?
else if(t.match(i)){var n=t.search(i)+t.match(i)[0].length,a=t.substr(n);parts.key=a.split("/")[0],t.match(/\?gid=(\d+)/)&&(parts.worksheet=t.match(/\?gid=(\d+)/)[1])}else t.match(/^\b[-_A-Za-z0-9]+$/)&&(parts.key=t);return parts.key?parts:null}function n(t){var e={};for(k in t)0==k.indexOf("gsx$")&&(e[k.substr(4)]=t[k].$t);if(h.Util.isEmptyObject(e))return null;var i={media:{caption:e.mediacaption||"",credit:e.mediacredit||"",url:e.media||"",thumbnail:e.mediathumbnail||""},text:{headline:e.headline||"",text:e.text||""},group:e.tag||"",type:e.type||""};return e.startdate&&(i.start_date=h.Date.parseDate(e.startdate)),e.enddate&&(i.end_date=h.Date.parseDate(e.enddate)),i}function a(t){function e(t){if(t)return t.replace(/[\s,]+/g,"");// doesn't handle '.' as comma separator, but how to distinguish that from decimal separator?
}var i={};for(k in t)0==k.indexOf("gsx$")&&(i[k.substr(4)]=h.Util.trim(t[k].$t));if(h.Util.isEmptyObject(i))return null;var n={media:{caption:i.mediacaption||"",credit:i.mediacredit||"",url:i.media||"",thumbnail:i.mediathumbnail||""},text:{headline:i.headline||"",text:i.text||""},start_date:{year:e(i.year),month:e(i.month)||"",day:e(i.day)||""},end_date:{year:e(i.endyear)||"",month:e(i.endmonth)||"",day:e(i.endday)||""},display_date:i.displaydate||"",type:i.type||""};if(i.time&&h.Util.mergeData(n.start_date,h.DateUtil.parseTime(i.time)),i.endtime&&h.Util.mergeData(n.end_date,h.DateUtil.parseTime(i.endtime)),i.group&&(n.group=i.group),""==n.end_date.year){var a=n.end_date;if(delete n.end_date,""!=a.month||""!=a.day||""!=a.time){var s=n.text.headline||trace("Invalid end date for spreadsheet row. Must have a year if any other date fields are specified.");trace(t)}}return i.background&&(i.background.match(/^(https?:)?\/\/?/)?// support http, https, protocol relative, site relative
n.background={url:i.background}:// for now we'll trust it's a color
n.background={color:i.background}),n}function s(t,e){function i(t){if(t)return t.replace(/[\s,]+/g,"");// doesn't handle '.' as comma separator, but how to distinguish that from decimal separator?
}
// console.log(item);
for(var n={},a=1;a<e.length;a++){var s;
// console.log(column_name);
// console.log(column[i]);
// console.log("Column:" + column_name + " Value: " + item[i]);
if(t.length>=a)n[t[a].toLowerCase().replace(" ","")]=e[a]}var o={media:{caption:n.mediacaption||"",credit:n.mediacredit||"",url:n.media||"",thumbnail:n.mediathumbnail||""},text:{headline:n.headline||"",text:n.text||""},start_date:{year:i(e[0]),month:i(e[1])||"",day:i(e[2])||""},end_date:{year:i(n.endyear)||"",month:i(n.endmonth)||"",day:i(n.endday)||""},display_date:n.displaydate||"",type:n.type||""};if(n.time&&h.Util.mergeData(o.start_date,h.DateUtil.parseTime(e[3])),n.endtime&&h.Util.mergeData(o.end_date,h.DateUtil.parseTime(n.endtime)),n.group&&(o.group=n.group),""==o.end_date.year){var r=o.end_date;if(delete o.end_date,""!=r.month||""!=r.day||""!=r.time){var l=o.text.headline||trace("Invalid end date for spreadsheet row. Must have a year if any other date fields are specified.");trace(e)}}
// console.log(event);
return console.log(n.background),n.background&&(n.background.match(/^(https?:)?\/\/?/)?// support http, https, protocol relative, site relative
o.background={url:n.background}:// for now we'll trust it's a color
o.background={color:n.background}),o}var t=function(t){if(void 0===t.feed.entry||0==t.feed.entry.length)throw new h.Error("empty_feed_err");var e=t.feed.entry[0];if(void 0!==e.gsx$startdate)
// check headers V1
// var headers_V1 = ['startdate', 'enddate', 'headline','text','media','mediacredit','mediacaption','mediathumbnail','media','type','tag'];
// for (var i = 0; i < headers_V1.length; i++) {
// if (typeof entry['gsx$' + headers_V1[i]] == 'undefined') {
// throw new TL.Error("invalid_data_format_err");
// }
// }
return n;if(void 0===e.gsx$year)throw new h.Error("invalid_data_format_err");
// check rest of V3 headers
var i=["month","day","time","endmonth","endyear","endday","endtime","displaydate","headline","text","media","mediacredit","mediacaption","mediathumbnail","type","group","background"];
// for (var i = 0; i < headers_V3.length; i++) {
// if (typeof entry['gsx$' + headers_V3[i]] == 'undefined') {
// throw new TL.Error("invalid_data_format_err");
// }
// }
return a},r=function(t){
// var api_3 = "https://spreadsheets.google.com/feeds/list/" + parts.key + "/od6/public/values?alt=json";
var e;return"https://sheets.googleapis.com/v4/spreadsheets/"+t.key+"/values/A1:R1000?key=AIzaSyCInR0kjJJ2Co6aQAXjLBQ14CEHam3K0xg"},l=function(t){var t=r(o(t)),e={events:[]},i=h.ajax({url:t,async:!1});return i=JSON.parse(i.responseText),d(i)},d=function(t){for(var e={events:[],errors:[],warnings:[],eras:[]},i=1;i<t.values.length;i++){var n=s(t.values[0],t.values[i]);if(n){// blank rows return null
var a="event";void 0!==n.type&&(a=n.type,delete n.type),"title"==a?e.title?(e.warnings.push("Multiple title slides detected."),e.events.push(n)):e.title=n:"era"==a?e.eras.push(n):e.events.push(n)}}
// var extract = getGoogleItemExtractor(data);
// for (var i = 0; i < data.feed.entry.length; i++) {
// try {
// var event = extract(data.feed.entry[i]);
// if (event) { // blank rows return null
// var row_type = 'event';
// if (typeof(event.type) != 'undefined') {
// row_type = event.type;
// delete event.type;
// }
// if (row_type == 'title') {
// if (!timeline_config.title) {
// timeline_config.title = event;
// } else {
// timeline_config.warnings.push("Multiple title slides detected.");
// timeline_config.events.push(event);
// }
// } else if (row_type == 'era') {
// timeline_config.eras.push(event);
// } else {
// timeline_config.events.push(event);
// }
// }
// } catch(e) {
// if (e.message) {
// e = e.message;
// }
// timeline_config.errors.push(e + " ["+ i +"]");
// }
// };
return console.log(e.events),e},e=function(t,n){var a,e;if(o(t)){try{var i=l(t)}catch(t){return a=new h.TimelineConfig,"NetworkError"==t.name?a.logError(new h.Error("network_err")):"TL.Error"==t.name?a.logError(t):a.logError(new h.Error("unknown_read_err",t.name)),void n(a)}if(a=new h.TimelineConfig(i),i.errors)for(var s=0;s<i.errors.length;s++)a.logError(i.errors[s]);n(a)}else h.ajax({url:t,dataType:"json",success:function(t){try{a=new h.TimelineConfig(t)}catch(t){(a=new h.TimelineConfig).logError(t)}n(a)},error:function(t,e,i){if(a=new h.TimelineConfig,"parsererror"==e)var i=new h.Error("invalid_url_err");else var i=new h.Error("unknown_read_err",e);a.logError(i),n(a)}})};h.ConfigFactory={
// export for unit testing and use by authoring tool
parseGoogleSpreadsheetURL:o,
// export for unit testing
googleFeedJSONtoTimelineJSON:d,fromGoogle:function(t){return console.warn("TL.ConfigFactory.fromGoogle is deprecated and will be removed soon. Use TL.ConfigFactory.makeConfig(url,callback)"),l(t)},
/*
* Given a URL to a Timeline data source, read the data, create a TimelineConfig
* object, and call the given `callback` function passing the created config as
* the only argument. This should be the main public interface to getting configs
* from any kind of URL, Google or direct JSON.
*/
makeConfig:e}}(TL),TL.Language=function(t){
// borrowed from http://stackoverflow.com/a/14446414/102476
for(k in TL.Language.languages.en)this[k]=TL.Language.languages.en[k];if(t&&t.language&&"string"==typeof t.language&&"en"!=t.language){var e=t.language;if(!(e in TL.Language.languages)){if(/\.json$/.test(e))var i=e;else{var n="/locale/"+e+".json",a=t.script_path||TL.Timeline.source_path;/\/$/.test(a)&&(n=n.substr(1));var i=a+n}var s=this,o=TL.ajax({url:i,async:!1});if(200!=o.status)throw"Could not load language ["+e+"]: "+o.statusText;TL.Language.languages[e]=JSON.parse(o.responseText)}TL.Util.mergeData(this,TL.Language.languages[e])}},TL.Language.formatNumber=function(t,e){if(e.match(/%(\.(\d+))?f/)){var i=e.match(/%(\.(\d+))?f/),n=i[0];return i[2]&&(t=t.toFixed(i[2])),e.replace(n,t)}
// use mask as literal display value.
return e}
/* TL.Util.mergeData is shallow, we have nested dicts.
This is a simplistic handling but should work.
*/,TL.Language.prototype.mergeData=function(t){for(k in TL.Language.languages.en)t[k]&&("object"==typeof this[k]?TL.Util.mergeData(t[k],this[k]):this[k]=t[k])},TL.Language.fallback={messages:{}},// placeholder to satisfy IE8 early compilation
TL.Language.prototype.getMessage=function(t){return this.messages[t]||TL.Language.fallback.messages[t]||t},TL.Language.prototype._=TL.Language.prototype.getMessage,// keep it concise
TL.Language.prototype.formatDate=function(t,e){return t.constructor==Date?this.formatJSDate(t,e):t.constructor==TL.BigYear?this.formatBigYear(t,e):t.data&&t.data.date_obj?this.formatDate(t.data.date_obj,e):(trace("Unfamiliar date presented for formatting"),t.toString())},TL.Language.prototype.formatBigYear=function(t,e){var i=t.year,n=this.bigdateformats[e]||this.bigdateformats.fallback;if(n){for(var a=0;a<n.length;a++){var s=n[a];if(1<Math.abs(i/s[0]))
// will we ever deal with distant future dates?
return TL.Language.formatNumber(Math.abs(i/s[0]),s[1])}return i.toString()}return trace("Language file dateformats missing cosmological. Falling back."),TL.Language.formatNumber(i,e)},TL.Language.prototype.formatJSDate=function(t,e){
// ultimately we probably want this to work with TL.Date instead of (in addition to?) JS Date
// utc, timezone and timezoneClip are carry over from Steven Levithan implementation. We probably aren't going to use them.
var n=this,i=function(t,e){var i=n.period_labels[t];if(i)var t=e<12?i[0]:i[1];return"<span class='tl-timeaxis-timesuffix'>"+t+"</span>"},a=!1,s=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,o=/[^-+\dA-Z]/g;e||(e="full");var r=this.dateformats[e]||TL.Language.fallback.dateformats[e];r||(r=e);var l="get",h=t.getDate(),d=t.getDay(),c=t.getMonth(),u=t.getFullYear(),m=t.getHours(),_=t.getMinutes(),p=t.getSeconds(),f=t.getMilliseconds(),g=t.getTimezoneOffset(),v="",y={d:h,dd:TL.Util.pad(h),ddd:this.date.day_abbr[d],dddd:this.date.day[d],m:c+1,mm:TL.Util.pad(c+1),mmm:this.date.month_abbr[c],mmmm:this.date.month[c],yy:String(u).slice(2),yyyy:u<0&&this.has_negative_year_modifier()?Math.abs(u):u,h:m%12||12,hh:TL.Util.pad(m%12||12),H:m,HH:TL.Util.pad(m),M:_,MM:TL.Util.pad(_),s:p,ss:TL.Util.pad(p),l:TL.Util.pad(f,3),L:TL.Util.pad(99<f?Math.round(f/10):f),t:i("t",m),tt:i("tt",m),T:i("T",m),TT:i("TT",m),Z:(String(t).match(s)||[""]).pop().replace(o,""),o:(0<g?"-":"+")+TL.Util.pad(100*Math.floor(Math.abs(g)/60)+Math.abs(g)%60,4),S:["th","st","nd","rd"][3<h%10?0:(h%100-h%10!=10)*h%10]},T=r.replace(TL.Language.DATE_FORMAT_TOKENS,function(t){return t in y?y[t]:t.slice(1,t.length-1)});return this._applyEra(T,u)},TL.Language.prototype.has_negative_year_modifier=function(){return Boolean(this.era_labels.negative_year.prefix||this.era_labels.negative_year.suffix)},TL.Language.prototype._applyEra=function(t,e){
// trusts that the formatted_date was property created with a non-negative year if there are
// negative affixes to be applied
var i=e<0?this.era_labels.negative_year:this.era_labels.positive_year,n="";return i.prefix&&(n+="<span>"+i.prefix+"</span> "),n+=t,i.suffix&&(n+=" <span>"+i.suffix+"</span>"),n},TL.Language.DATE_FORMAT_TOKENS=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,TL.Language.languages={
/*
This represents the canonical list of message keys which translation files should handle. The existence of the 'en.json' file should not mislead you.
It is provided more as a starting point for someone who wants to provide a
new translation since the form for non-default languages (JSON not JS) is slightly different from what appears below. Also, those files have some message keys grandfathered in from TimelineJS2 which we'd rather not have to
get "re-translated" if we use them.
*/
en:{name:"English",lang:"en",api:{wikipedia:"en"},messages:{loading:"Loading",wikipedia:"From Wikipedia, the free encyclopedia",error:"Error",contract_timeline:"Contract Timeline",return_to_title:"Return to Title",loading_content:"Loading Content",expand_timeline:"Expand Timeline",loading_timeline:"Loading Timeline... ",swipe_to_navigate:"Swipe to Navigate<br><span class='tl-button'>OK</span>",unknown_read_err:"An unexpected error occurred trying to read your spreadsheet data",invalid_url_err:"Unable to read Timeline data. Make sure your URL is for a Google Spreadsheet or a Timeline JSON file.",network_err:"Unable to read your Google Spreadsheet. Make sure you have published it to the web.",empty_feed_err:"No data entries found",missing_start_date_err:"Missing start_date",invalid_data_format_err:"Header row has been modified.",date_compare_err:"Can't compare TL.Dates on different scales",invalid_scale_err:"Invalid scale",invalid_date_err:"Invalid date: month, day and year must be numbers.",invalid_separator_error:"Invalid time: misuse of : or . as separator.",invalid_hour_err:"Invalid time (hour)",invalid_minute_err:"Invalid time (minute)",invalid_second_err:"Invalid time (second)",invalid_fractional_err:"Invalid time (fractional seconds)",invalid_second_fractional_err:"Invalid time (seconds and fractional seconds)",invalid_year_err:"Invalid year",flickr_notfound_err:"Photo not found or private",flickr_invalidurl_err:"Invalid Flickr URL",imgur_invalidurl_err:"Invalid Imgur URL",twitter_invalidurl_err:"Invalid Twitter URL",twitter_load_err:"Unable to load Tweet",twitterembed_invalidurl_err:"Invalid Twitter Embed url",wikipedia_load_err:"Unable to load Wikipedia entry",youtube_invalidurl_err:"Invalid YouTube URL",spotify_invalid_url:"Invalid Spotify URL",template_value_err:"No value provided for variable",invalid_rgb_err:"Invalid RGB argument",time_scale_scale_err:"Don't know how to get date from time for scale",axis_helper_no_options_err:"Axis helper must be configured with options",axis_helper_scale_err:"No AxisHelper available for scale",invalid_integer_option:"Invalid option value—must be a whole number."},date:{month:["January","February","March","April","May","June","July","August","September","October","November","December"],month_abbr:["Jan.","Feb.","March","April","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."],day:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],day_abbr:["Sun.","Mon.","Tues.","Wed.","Thurs.","Fri.","Sat."]},era_labels:{// specify prefix or suffix to apply to formatted date. Blanks mean no change.
positive_year:{prefix:"",suffix:""},negative_year:{// if either of these is specified, the year will be converted to positive before they are applied
prefix:"",suffix:"BCE"}},period_labels:{// use of t/tt/T/TT legacy of original Timeline date format
t:["a","p"],tt:["am","pm"],T:["A","P"],TT:["AM","PM"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time:"h:MM:ss TT' <small>'mmmm d',' yyyy'</small>'",time_short:"h:MM:ss TT",time_no_seconds_short:"h:MM TT",time_no_minutes_short:"h TT",time_no_seconds_small_date:"h:MM TT' <small>'mmmm d',' yyyy'</small>'",time_milliseconds:"l",full_long:"mmm d',' yyyy 'at' h:MM TT",full_long_small_date:"h:MM TT' <small>mmm d',' yyyy'</small>'"},bigdateformats:{fallback:[// a list of tuples, with t[0] an order of magnitude and t[1] a format string. format string syntax may change...
[1e9,"%.2f billion years ago"],[1e6,"%.1f million years ago"],[1e3,"%.1f thousand years ago"],[1,"%f years ago"]],compact:[[1e9,"%.2f bya"],[1e6,"%.1f mya"],[1e3,"%.1f kya"],[1,"%f years ago"]],verbose:[[1e9,"%.2f billion years ago"],[1e6,"%.1f million years ago"],[1e3,"%.1f thousand years ago"],[1,"%f years ago"]]}}},TL.Language.fallback=new TL.Language,
/* TL.I18NMixins
assumes that its class has an options object with a TL.Language instance
================================================== */
TL.I18NMixins={getLanguage:function(){return this.options&&this.options.language?this.options.language:(trace("Expected a language option"),TL.Language.fallback)},_:function(t){return this.getLanguage()._(t)}},
/* The equations defined here are open source under BSD License.
* http://www.robertpenner.com/easing_terms_of_use.html (c) 2003 Robert Penner
* Adapted to single time-based by
* Brian Crescimanno <brian.crescimanno@gmail.com>
* Ken Snyder <kendsnyder@gmail.com>
*/
/** MIT License
*
* KeySpline - use bezier curve for transition easing function
* Copyright (c) 2012 Gaetan Renaudeau <renaudeau.gaetan@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* KeySpline - use bezier curve for transition easing function
* is inspired from Firefox's nsSMILKeySpline.cpp
* Usage:
* var spline = new KeySpline(0.25, 0.1, 0.25, 1.0)
* spline.get(x) => returns the easing value | x must be in [0, 1] range
*/
TL.Easings={ease:[.25,.1,.25,1],linear:[0,0,1,1],easein:[.42,0,1,1],easeout:[0,0,.58,1],easeinout:[.42,0,.58,1]},TL.Ease={KeySpline:function(s){function n(t,e){return 1-3*e+3*t}function a(t,e){return 3*e-6*t}function o(t){return 3*t}
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
function r(t,e,i){return((n(e,i)*t+a(e,i))*t+o(e))*t}
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
function l(t,e,i){return 3*n(e,i)*t*t+2*a(e,i)*t+o(e)}function e(t){for(
// Newton raphson iteration
var e=t,i=0;i<4;++i){var n=l(e,s[0],s[2]),a;if(0==n)return e;e-=(r(e,s[0],s[2])-t)/n}return e}
//KeySpline: function(mX1, mY1, mX2, mY2) {
this.get=function(t){return s[0]==s[1]&&s[2]==s[3]?t:r(e(t),s[1],s[3]);// linear
}},easeInSpline:function(t){var e;return new TL.Ease.KeySpline(TL.Easings.easein).get(t)},easeInOutExpo:function(t){var e;return new TL.Ease.KeySpline(TL.Easings.easein).get(t)},easeOut:function(t){return Math.sin(t*Math.PI/2)},easeOutStrong:function(t){return 1==t?1:1-Math.pow(2,-10*t)},easeIn:function(t){return t*t},easeInStrong:function(t){return 0==t?0:Math.pow(2,10*(t-1))},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},bounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bouncePast:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?2-(7.5625*(t-=1.5/2.75)*t+.75):t<2.5/2.75?2-(7.5625*(t-=2.25/2.75)*t+.9375):2-(7.5625*(t-=2.625/2.75)*t+.984375)},swingTo:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},swingFrom:function(t){var e=1.70158;return t*t*((e+1)*t-e)},elastic:function(t){return-1*Math.pow(4,-8*t)*Math.sin((6*t-1)*(2*Math.PI)/2)+1},spring:function(t){return 1-Math.cos(4.5*t*Math.PI)*Math.exp(6*-t)},blink:function(t,e){return Math.round(t*(e||5))%2},pulse:function(t,e){return-Math.cos(t*((e||5)-.5)*2*Math.PI)/2+.5},wobble:function(t){return-Math.cos(t*Math.PI*(9*t))/2+.5},sinusoidal:function(t){return-Math.cos(t*Math.PI)/2+.5},flicker:function(t){var t=t+(Math.random()-.5)/5;return easings.sinusoidal(t<0?0:1<t?1:t)},mirror:function(t){return t<.5?easings.sinusoidal(2*t):easings.sinusoidal(1-2*(t-.5))},
// accelerating from zero velocity
easeInQuad:function(t){return t*t},
// decelerating to zero velocity
easeOutQuad:function(t){return t*(2-t)},
// acceleration until halfway, then deceleration
easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},
// accelerating from zero velocity
easeInCubic:function(t){return t*t*t},
// decelerating to zero velocity
easeOutCubic:function(t){return--t*t*t+1},
// acceleration until halfway, then deceleration
easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},
// accelerating from zero velocity
easeInQuart:function(t){return t*t*t*t},
// decelerating to zero velocity
easeOutQuart:function(t){return 1- --t*t*t*t},
// acceleration until halfway, then deceleration
easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},
// accelerating from zero velocity
easeInQuint:function(t){return t*t*t*t*t},
// decelerating to zero velocity
easeOutQuint:function(t){return 1+--t*t*t*t*t},
// acceleration until halfway, then deceleration
easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}},
/* TL.Animate
Basic animation
================================================== */
TL.Animate=function(t,e){var i,n;
/*
// POSSIBLE ISSUE WITH WEBKIT FUTURE BUILDS
var onWebKitTimeout = function() {
animation.stop(true);
}
if (TL.Browser.webkit) {
webkit_timeout = setTimeout(function(){onWebKitTimeout()}, options.duration);
}
*/return new tlanimate(t,e)},
/* Based on: Morpheus
https://github.com/ded/morpheus - (c) Dustin Diaz 2011
License MIT
================================================== */
window.tlanimate=function(){function n(t,e,i){if(Array.prototype.indexOf)return t.indexOf(e);for(i=0;i<t.length;++i)if(t[i]===e)return i}function a(t){var e,i=P.length;
// if we're using a high res timer, make sure timestamp is not the old epoch-based value.
// http://updates.html5rocks.com/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision
for(r&&1e12<t&&(t=g()),d&&(t=g()),e=i;e--;)P[e](t);P.length&&O(a)}function e(t){1===P.push(t)&&O(a)}function _(t){var e,i=n(P,t);0<=i&&(e=P.slice(i+1),P.length=i,P=P.concat(e))}function L(t,e){var i={},n;return(n=t.match(u))&&(i.rotate=S(n[1],e?e.rotate:null)),(n=t.match(m))&&(i.scale=S(n[1],e?e.scale:null)),(n=t.match(y))&&(i.skewx=S(n[1],e?e.skewx:null),i.skewy=S(n[3],e?e.skewy:null)),(n=t.match(T))&&(i.translatex=S(n[1],e?e.translatex:null),i.translatey=S(n[3],e?e.translatey:null)),i}function w(t){var e="";return"rotate"in t&&(e+="rotate("+t.rotate+"deg) "),"scale"in t&&(e+="scale("+t.scale+") "),"translatex"in t&&(e+="translate("+t.translatex+"px,"+t.translatey+"px) "),"skewx"in t&&(e+="skew("+t.skewx+"deg,"+t.skewy+"deg)"),e}function i(t,e,i){return"#"+(1<<24|t<<16|e<<8|i).toString(16).slice(1)}
// convert rgb and short hex to long hex
function b(t){var e=t.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);return(e?i(e[1],e[2],e[3]):t).replace(/#(\w)(\w)(\w)$/,"#$1$1$2$2$3$3");// short skirt to long jacket
}
// change font-size => fontSize etc.
function k(t){return t.replace(/-(.)/g,function(t,e){return e.toUpperCase()})}
// aren't we having it?
function x(t){return"function"==typeof t}function p(t){
// default to a pleasant-to-the-eye easeOut (like native animations)
return Math.sin(t*Math.PI/2)}
/**
* Core tween method that requests each frame
* @param duration: time in milliseconds. defaults to 1000
* @param fn: tween frame callback function receiving 'position'
* @param done {optional}: complete callback function
* @param ease {optional}: easing method. defaults to easeOut
* @param from {optional}: integer to start from
* @param to {optional}: integer to end at
* @returns method to stop the animation
*/function M(t,i,n,a,s,o){function r(t){var e=t-c;if(l<e||u)return o=isFinite(o)?o:1,u?m&&i(o):i(o),_(r),n&&n.apply(h);
// if you don't specify a 'to' you can use tween as a generic delta tweener
// cool, eh?
isFinite(o)?i(d*a(e/l)+s):i(a(e/l))}a=x(a)?a:f.easings[a]||p;var l=t||v,h=this,d=o-s,c=g(),u=0,m=0;return e(r),{stop:function(t){u=1,// jump to end of animation?
(m=t)||(n=null)}}}
/**
* generic bezier method for animating x|y coordinates
* minimum of 2 points required (start and end).
* first point start, last point end
* additional control points are optional (but why else would you use this anyway ;)
* @param points: array containing control points
[[0, 0], [100, 200], [200, 100]]
* @param pos: current be(tween) position represented as float 0 - 1
* @return [x, y]
*/function D(t,e){var i=t.length,n=[],a,s;for(a=0;a<i;++a)n[a]=[t[a][0],t[a][1]];for(s=1;s<i;++s)for(a=0;a<i-s;++a)n[a][0]=(1-e)*n[a][0]+e*n[parseInt(a+1,10)][0],n[a][1]=(1-e)*n[a][1]+e*n[parseInt(a+1,10)][1];return[n[0][0],n[0][1]]}
// this gets you the next hex in line according to a 'position'
function l(t,e,i){var n=[],a,s,o,r;for(a=0;a<6;a++)o=Math.min(15,parseInt(e.charAt(a),16)),r=Math.min(15,parseInt(i.charAt(a),16)),s=15<(s=Math.floor((r-o)*t+o))?15:s<0?0:s,n[a]=s.toString(16);return"#"+n.join("")}
// this retreives the frame value within a sequence
function E(t,e,i,n,a,s,o){if("transform"!=a)return"string"==typeof i[s][a]?l(t,i[s][a],n[s][a]):(
// round so we don't get crazy long floats
o=Math.round(((n[s][a]-i[s][a])*t+i[s][a])*v)/v,
// some css properties don't require a unit (like zIndex, lineHeight, opacity)
a in I||(o+=e[s][a]||"px"),o);for(var r in o={},i[s][a])o[r]=r in n[s][a]?Math.round(((n[s][a][r]-i[s][a][r])*t+i[s][a][r])*v)/v:i[s][a][r];return o}
// support for relative movement via '+=n' or '-=n'
function S(t,e,i,n,a){return(i=c.exec(t))?(a=parseFloat(i[2]))&&e+("+"==i[1]?1:-1)*a:parseFloat(t)}
/**
* morpheus:
* @param element(s): HTMLElement(s)
* @param options: mixed bag between CSS Style properties & animation options
* - {n} CSS properties|values
* - value can be strings, integers,
* - or callback function that receives element to be animated. method must return value to be tweened
* - relative animations start with += or -= followed by integer
* - duration: time in ms - defaults to 1000(ms)
* - easing: a transition method - defaults to an 'easeOut' algorithm
* - complete: a callback method for when all elements have finished
* - bezier: array of arrays containing x|y coordinates that define the bezier points. defaults to none
* - this may also be a function that receives element to be animated. it must return a value
*/function f(t,a){var s=t?s=isFinite(t.length)?t:[t]:[],o,e=a.complete,i=a.duration,n=a.easing,r=a.bezier,l=[],h=[],d=[],c=[],u,m;for(r&&(
// remember the original values for top|left
u=a.left,m=a.top,delete a.right,delete a.bottom,delete a.left,delete a.top),o=s.length;o--;){
// are we 'moving'?
if(
// record beginning and end states to calculate positions
l[o]={},h[o]={},d[o]={},r){var _=j(s[o],"left"),p=j(s[o],"top"),f=[S(x(u)?u(s[o]):u||0,parseFloat(_)),S(x(m)?m(s[o]):m||0,parseFloat(p))];c[o]=x(r)?r(s[o],f):r,c[o].push(f),c[o].unshift([parseInt(_,10),parseInt(p,10)])}for(var g in a){switch(g){case"complete":case"duration":case"easing":case"bezier":continue}var v=j(s[o],g),y,T=x(a[g])?a[g](s[o]):a[g];"string"!=typeof T||!C.test(T)||C.test(v)?(l[o][g]="transform"==g?L(v):"string"==typeof T&&C.test(T)?b(v).slice(1):parseFloat(v),h[o][g]="transform"==g?L(T,l[o][g]):"string"==typeof T&&"#"==T.charAt(0)?b(T).slice(1):S(T,parseFloat(v)),
// record original unit
"string"==typeof T&&(y=T.match(N))&&(d[o][g]=y[1])):delete a[g]}}
// ONE TWEEN TO RULE THEM ALL
return M.apply(s,[i,function(t,e,i){
// normally not a fan of optimizing for() loops, but we want something
// fast for animating
for(o=s.length;o--;)for(var n in r&&(i=D(c[o],t),s[o].style.left=i[0]+"px",s[o].style.top=i[1]+"px"),a)e=E(t,d,l,h,n,o),"transform"==n?s[o].style[U]=w(e):"opacity"!=n||A?s[o].style[k(n)]=e:s[o].style.filter="alpha(opacity="+100*e+")"},e,n])}
// expose useful methods
var s=document,o=window,t=o.performance,r=t&&(t.now||t.webkitNow||t.msNow||t.mozNow),g=r?function(){return r.call(t)}:function(){return+new Date},h=s.documentElement,d=!1,// feature detected below
v=1e3,C=/^rgb\(|#/,c=/^([+\-])=([\d\.]+)/,N=/^(?:[\+\-]=?)?\d+(?:\.\d+)?(%|in|cm|mm|em|ex|pt|pc|px)$/,u=/rotate\(((?:[+\-]=)?([\-\d\.]+))deg\)/,m=/scale\(((?:[+\-]=)?([\d\.]+))\)/,y=/skew\(((?:[+\-]=)?([\-\d\.]+))deg, ?((?:[+\-]=)?([\-\d\.]+))deg\)/,T=/translate\(((?:[+\-]=)?([\-\d\.]+))px, ?((?:[+\-]=)?([\-\d\.]+))px\)/,
// these elements do not require 'px'
I={lineHeight:1,zoom:1,zIndex:1,opacity:1,transform:1},U=function(){var t=s.createElement("a").style,e=["webkitTransform","MozTransform","OTransform","msTransform","Transform"],i;for(i=0;i<e.length;i++)if(e[i]in t)return e[i]}(),A=void 0!==s.createElement("a").style.opacity,j=s.defaultView&&s.defaultView.getComputedStyle?function(t,e){e=k(e="transform"==e?U:e);var i=null,n=s.defaultView.getComputedStyle(t,"");return n&&(i=n[e]),t.style[e]||i}:h.currentStyle?function(e,t){if("opacity"==(t=k(t))){var i=100;try{i=e.filters["DXImageTransform.Microsoft.Alpha"].opacity}catch(t){try{i=e.filters("alpha").opacity}catch(t){}}return i/100}var n=e.currentStyle?e.currentStyle[t]:null;return e.style[t]||n}:function(t,e){return t.style[k(e)]},O=o.requestAnimationFrame||o.webkitRequestAnimationFrame||o.mozRequestAnimationFrame||o.msRequestAnimationFrame||o.oRequestAnimationFrame||function(t){o.setTimeout(function(){t(+new Date)},17);// when I was 17..
},P=[];
// which property name does this browser use for transform
return O(function(t){
// feature-detect if rAF and now() are of the same scale (epoch or high-res),
// if not, we have to do a timestamp fix on each frame
d=1e12<t!=1e12<g()}),f.tween=M,f.getStyle=j,f.bezier=D,f.transform=U,f.parseTransform=L,f.formatTransform=w,f.easings={},f}(),
/* TL.Point
Inspired by Leaflet
TL.Point represents a point with x and y coordinates.
================================================== */
TL.Point=function(/*Number*/t,/*Number*/e,/*Boolean*/i){this.x=i?Math.round(t):t,this.y=i?Math.round(e):e},TL.Point.prototype={add:function(t){return this.clone()._add(t)},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(t)},
// destructive subtract (faster)
_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t,e){return new TL.Point(this.x/t,this.y/t,e)},multiplyBy:function(t){return new TL.Point(this.x*t,this.y*t)},distanceTo:function(t){var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},round:function(){return this.clone()._round()},
// destructive round
_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},clone:function(){return new TL.Point(this.x,this.y)},toString:function(){return"Point("+TL.Util.formatNum(this.x)+", "+TL.Util.formatNum(this.y)+")"}},
/* TL.DomMixins
DOM methods used regularly
Assumes there is a _el.container and animator
================================================== */
TL.DomMixins={
/* Adding, Hiding, Showing etc
================================================== */
show:function(t){t||(this._el.container.style.display="block")},hide:function(t){this._el.container.style.display="none"},addTo:function(t){t.appendChild(this._el.container),this.onAdd()},removeFrom:function(t){t.removeChild(this._el.container),this.onRemove()},
/* Animate to Position
================================================== */
animatePosition:function(t,e){var i={duration:this.options.duration,easing:this.options.ease};for(var n in t)t.hasOwnProperty(n)&&(i[n]=t[n]+"px");this.animator&&this.animator.stop(),this.animator=TL.Animate(e,i)},
/* Events
================================================== */
onLoaded:function(){this.fire("loaded",this.data)},onAdd:function(){this.fire("added",this.data)},onRemove:function(){this.fire("removed",this.data)},
/* Set the Position
================================================== */
setPosition:function(t,e){for(var i in t)t.hasOwnProperty(i)&&(e?e.style[i]=t[i]+"px":this._el.container.style[i]=t[i]+"px")},getPosition:function(){return TL.Dom.getPosition(this._el.container)}},
/* TL.Dom
Utilities for working with the DOM
================================================== */
TL.Dom={get:function(t){return"string"==typeof t?document.getElementById(t):t},getByClass:function(t){if(t)return document.getElementsByClassName(t)},create:function(t,e,i){var n=document.createElement(t);return n.className=e,i&&i.appendChild(n),n},createText:function(t,e){var i=document.createTextNode(t);return e&&e.appendChild(i),i},getTranslateString:function(t){return TL.Dom.TRANSLATE_OPEN+t.x+"px,"+t.y+"px"+TL.Dom.TRANSLATE_CLOSE},setPosition:function(t,e){t._tl_pos=e,TL.Browser.webkit3d?(t.style[TL.Dom.TRANSFORM]=TL.Dom.getTranslateString(e),TL.Browser.android&&(t.style["-webkit-perspective"]="1000",t.style["-webkit-backface-visibility"]="hidden")):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){for(var e={x:0,y:0};t&&!isNaN(t.offsetLeft)&&!isNaN(t.offsetTop);)e.x+=t.offsetLeft,// - el.scrollLeft;
e.y+=t.offsetTop,// - el.scrollTop;
t=t.offsetParent;return e},testProp:function(t){for(var e=document.documentElement.style,i=0;i<t.length;i++)if(t[i]in e)return t[i];return!1}},TL.Util.mergeData(TL.Dom,{TRANSITION:TL.Dom.testProp(["transition","webkitTransition","OTransition","MozTransition","msTransition"]),TRANSFORM:TL.Dom.testProp(["transformProperty","WebkitTransform","OTransform","MozTransform","msTransform"]),TRANSLATE_OPEN:"translate"+(TL.Browser.webkit3d?"3d(":"("),TRANSLATE_CLOSE:TL.Browser.webkit3d?",0)":")"}),
/* TL.DomUtil
Inspired by Leaflet
TL.DomUtil contains various utility functions for working with DOM
================================================== */
TL.DomUtil={get:function(t){return"string"==typeof t?document.getElementById(t):t},getStyle:function(t,e){var i=t.style[e];if(!i&&t.currentStyle&&(i=t.currentStyle[e]),!i||"auto"===i){var n=document.defaultView.getComputedStyle(t,null);i=n?n[e]:null}return"auto"===i?null:i},getViewportOffset:function(t){var e=0,i=0,n=t,a=document.body;do{if(e+=n.offsetTop||0,i+=n.offsetLeft||0,n.offsetParent===a&&"absolute"===TL.DomUtil.getStyle(n,"position"))break;n=n.offsetParent}while(n);n=t;do{if(n===a)break;e-=n.scrollTop||0,i-=n.scrollLeft||0,n=n.parentNode}while(n);return new TL.Point(i,e)},create:function(t,e,i){var n=document.createElement(t);return n.className=e,i&&i.appendChild(n),n},disableTextSelection:function(){document.selection&&document.selection.empty&&document.selection.empty(),this._onselectstart||(this._onselectstart=document.onselectstart,document.onselectstart=TL.Util.falseFn)},enableTextSelection:function(){document.onselectstart=this._onselectstart,this._onselectstart=null},hasClass:function(t,e){return 0<t.className.length&&new RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className)},addClass:function(t,e){TL.DomUtil.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(t,i){t.className=t.className.replace(/(\S+)\s*/g,function(t,e){return e===i?"":t}).replace(/^\s+/,"")},setOpacity:function(t,e){TL.Browser.ie?t.style.filter="alpha(opacity="+Math.round(100*e)+")":t.style.opacity=e},testProp:function(t){for(var e=document.documentElement.style,i=0;i<t.length;i++)if(t[i]in e)return t[i];return!1},getTranslateString:function(t){return TL.DomUtil.TRANSLATE_OPEN+t.x+"px,"+t.y+"px"+TL.DomUtil.TRANSLATE_CLOSE},getScaleString:function(t,e){var i,n,a;return TL.DomUtil.getTranslateString(e)+(" scale("+t+") ")+TL.DomUtil.getTranslateString(e.multiplyBy(-1))},setPosition:function(t,e){t._tl_pos=e,TL.Browser.webkit3d?(t.style[TL.DomUtil.TRANSFORM]=TL.DomUtil.getTranslateString(e),TL.Browser.android&&(t.style["-webkit-perspective"]="1000",t.style["-webkit-backface-visibility"]="hidden")):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){return t._tl_pos}},
/* TL.DomEvent
Inspired by Leaflet
DomEvent contains functions for working with DOM events.
================================================== */
// TODO stamp
TL.DomEvent={
/* inpired by John Resig, Dean Edwards and YUI addEvent implementations */
addListener:function(/*HTMLElement*/e,/*String*/t,/*Function*/i,/*Object*/n){var a=TL.Util.stamp(i),s="_tl_"+t+a;if(!e[s]){var o=function(t){return i.call(n||e,t||TL.DomEvent._getEvent())};if(TL.Browser.touch&&"dblclick"===t&&this.addDoubleTapListener)this.addDoubleTapListener(e,o,a);else if("addEventListener"in e)if("mousewheel"===t)e.addEventListener("DOMMouseScroll",o,!1),e.addEventListener(t,o,!1);else if("mouseenter"===t||"mouseleave"===t){var r=o,l="mouseenter"===t?"mouseover":"mouseout";o=function(t){if(TL.DomEvent._checkMouse(e,t))return r(t)},e.addEventListener(l,o,!1)}else e.addEventListener(t,o,!1);else"attachEvent"in e&&e.attachEvent("on"+t,o);e[s]=o}},removeListener:function(/*HTMLElement*/t,/*String*/e,/*Function*/i){var n=TL.Util.stamp(i),a="_tl_"+e+n,s=t[a];s&&(TL.Browser.touch&&"dblclick"===e&&this.removeDoubleTapListener?this.removeDoubleTapListener(t,n):"removeEventListener"in t?"mousewheel"===e?(t.removeEventListener("DOMMouseScroll",s,!1),t.removeEventListener(e,s,!1)):"mouseenter"===e||"mouseleave"===e?t.removeEventListener("mouseenter"===e?"mouseover":"mouseout",s,!1):t.removeEventListener(e,s,!1):"detachEvent"in t&&t.detachEvent("on"+e,s),t[a]=null)},_checkMouse:function(t,e){var i=e.relatedTarget;if(!i)return!0;try{for(;i&&i!==t;)i=i.parentNode}catch(t){return!1}return i!==t},
/*jshint noarg:false */ // evil magic for IE
_getEvent:function(){var t=window.event;if(!t)for(var e=arguments.callee.caller;e&&(!(t=e.arguments[0])||window.Event!==t.constructor);)e=e.caller;return t},
/*jshint noarg:false */
stopPropagation:function(/*Event*/t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},
// TODO TL.Draggable.START
disableClickPropagation:function(/*HTMLElement*/t){TL.DomEvent.addListener(t,TL.Draggable.START,TL.DomEvent.stopPropagation),TL.DomEvent.addListener(t,"click",TL.DomEvent.stopPropagation),TL.DomEvent.addListener(t,"dblclick",TL.DomEvent.stopPropagation)},preventDefault:function(/*Event*/t){t.preventDefault?t.preventDefault():t.returnValue=!1},stop:function(t){TL.DomEvent.preventDefault(t),TL.DomEvent.stopPropagation(t)},getWheelDelta:function(t){var e=0;return t.wheelDelta&&(e=t.wheelDelta/120),t.detail&&(e=-t.detail/3),e}},
/* TL.StyleSheet
Style Sheet Object
================================================== */
TL.StyleSheet=TL.Class.extend({includes:[TL.Events],_el:{},
/* Constructor
================================================== */
initialize:function(){
// Borrowed from: http://davidwalsh.name/add-rules-stylesheets
this.style=document.createElement("style"),
// WebKit hack :(
this.style.appendChild(document.createTextNode("")),
// Add the <style> element to the page
document.head.appendChild(this.style),this.sheet=this.style.sheet},addRule:function(t,e,i){var n=0;i&&(n=i),"insertRule"in this.sheet?this.sheet.insertRule(t+"{"+e+"}",n):"addRule"in this.sheet&&this.sheet.addRule(t,e,n)},
/* Events
================================================== */
onLoaded:function(t){this._state.loaded=!0,this.fire("loaded",this.data)}}),
/* TL.Date
Date object
MONTHS are 1-BASED, not 0-BASED (different from Javascript date objects)
================================================== */
//
// Class for human dates
//
TL.Date=TL.Class.extend({
// @data = ms, JS Date object, or JS dictionary with date properties
initialize:function(t,e,i){"number"==typeof t?this.data={format:"yyyy mmmm",date_obj:new Date(t)}:Date==t.constructor?this.data={format:"yyyy mmmm",date_obj:t}:(this.data=JSON.parse(JSON.stringify(t)),// clone don't use by reference.
this._createDateObj()),this._setFormat(e,i)},setDateFormat:function(t){this.data.format=t},getDisplayDate:function(t,e){if(this.data.display_date)return this.data.display_date;t||(t=TL.Language.fallback),t.constructor!=TL.Language&&(trace("First argument to getDisplayDate must be TL.Language"),t=TL.Language.fallback);var i=e||this.data.format;return t.formatDate(this.data.date_obj,i)},getMillisecond:function(){return this.getTime()},getTime:function(){return this.data.date_obj.getTime()},isBefore:function(t){if(!this.data.date_obj.constructor==t.data.date_obj.constructor)throw new TL.Error("date_compare_err");// but should be able to compare 'cosmological scale' dates once we get to that...
return"isBefore"in this.data.date_obj?this.data.date_obj.isBefore(t.data.date_obj):this.data.date_obj<t.data.date_obj},isAfter:function(t){if(!this.data.date_obj.constructor==t.data.date_obj.constructor)throw new TL.Error("date_compare_err");// but should be able to compare 'cosmological scale' dates once we get to that...
return"isAfter"in this.data.date_obj?this.data.date_obj.isAfter(t.data.date_obj):this.data.date_obj>t.data.date_obj},
// Return a new TL.Date which has been 'floored' at the given scale.
// @scale = string value from TL.Date.SCALES
floor:function(t){for(var e=new Date(this.data.date_obj.getTime()),i=0;i<TL.Date.SCALES.length;i++)if(
// for JS dates, we iteratively apply flooring functions
TL.Date.SCALES[i][2](e),TL.Date.SCALES[i][0]==t)return new TL.Date(e);throw new TL.Error("invalid_scale_err",t)},
/* Private Methods
================================================== */
_getDateData:function(){var t={year:0,month:1,// stupid JS dates
day:1,hour:0,minute:0,second:0,millisecond:0};
// Merge data
TL.Util.mergeData(t,this.data);
// Make strings into numbers
var e=TL.Date.DATE_PARTS;for(var i in e){var n;if(!TL.Util.trim(t[e[i]]).match(/^-?\d*$/))throw new TL.Error("invalid_date_err",e[i]+" = '"+t[e[i]]+"'");var a=parseInt(t[e[i]]);isNaN(a)&&(a=4==i||5==i?1:0),t[e[i]]=a}return 0<t.month&&t.month<=12&&(// adjust for JS's weirdness
t.month=t.month-1),t},_createDateObj:function(){var t=this._getDateData();this.data.date_obj=new Date(t.year,t.month,t.day,t.hour,t.minute,t.second,t.millisecond),this.data.date_obj.getFullYear()!=t.year&&
// Javascript has stupid defaults for two-digit years
this.data.date_obj.setFullYear(t.year)},
/* Find Best Format
* this may not work with 'cosmologic' dates, or with TL.Date if we
* support constructing them based on JS Date and time
================================================== */
findBestFormat:function(t){for(var e=TL.Date.DATE_PARTS,i="",n=0;n<e.length;n++)if(this.data[e[n]])return t?t in TL.Date.BEST_DATEFORMATS||(t="short"):t="base",TL.Date.BEST_DATEFORMATS[t][e[n]];return""},_setFormat:function(t,e){t?this.data.format=t:this.data.format||(this.data.format=this.findBestFormat()),e?this.data.format_short=e:this.data.format_short||(this.data.format_short=this.findBestFormat(!0))}}),
// offer something that can figure out the right date class to return
TL.Date.makeDate=function(t){var e=new TL.Date(t);return isNaN(e.getTime())?new TL.BigDate(t):e},TL.BigYear=TL.Class.extend({initialize:function(t){if(this.year=parseInt(t),isNaN(this.year))throw new TL.Error("invalid_year_err",t)},isBefore:function(t){return this.year<t.year},isAfter:function(t){return this.year>t.year},getTime:function(){return this.year}}),function(r){
// human scales
r.SCALES=[// ( name, units_per_tick, flooring function )
["millisecond",1,function(t){}],["second",1e3,function(t){t.setMilliseconds(0)}],["minute",6e4,function(t){t.setSeconds(0)}],["hour",36e5,function(t){t.setMinutes(0)}],["day",864e5,function(t){t.setHours(0)}],["month",2592e6,function(t){t.setDate(1)}],["year",31536e6,function(t){t.setMonth(0)}],["decade",31536e7,function(t){var e=t.getFullYear();t.setFullYear(e-e%10)}],["century",31536e8,function(t){var e=t.getFullYear();t.setFullYear(e-e%100)}],["millennium",31536e9,function(t){var e=t.getFullYear();t.setFullYear(e-e%1e3)}]],
// Date parts from highest to lowest precision
r.DATE_PARTS=["millisecond","second","minute","hour","day","month","year"];var l=/^([\+-]?\d+?)(-\d{2}?)?(-\d{2}?)?$/,h=/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
// regex below from
// http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
/* For now, rather than extract parts from regexp, lets trust the browser.
* Famous last words...
* What about UTC vs local time?
* see also http://stackoverflow.com/questions/10005374/ecmascript-5-date-parse-results-for-iso-8601-test-cases
*/
r.parseISODate=function(t){var e=new Date(t);if(isNaN(e))throw new TL.Error("invalid_date_err",t);return{year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}},r.parseDate=function(t){if(t.match(l)){
// parse short specifically to avoid timezone offset confusion
// most browsers assume short is UTC, not local time.
var e=t.match(l).slice(1),i={year:e[0].replace("+","")};// year can be negative
return e[1]&&(i.month=e[1].replace("-","")),e[2]&&(i.day=e[2].replace("-","")),i}if(t.match(h))return r.parseISODate(t);if(t.match(/^\-?\d+$/))return{year:t};var n={};if(t.match(/\d+\/\d+\/\d+/)){// mm/yy/dddd
var a=t.match(/\d+\/\d+\/\d+/)[0];t=TL.Util.trim(t.replace(a,""));var s=a.split("/");n.month=s[0],n.day=s[1],n.year=s[2]}if(t.match(/\d+\/\d+/)){// mm/yy
var a=t.match(/\d+\/\d+/)[0];t=TL.Util.trim(t.replace(a,""));var s=a.split("/");n.month=s[0],n.year=s[1]}
// todo: handle hours, minutes, seconds, millis other date formats, etc...
if(t.match(":")){var o=t.split(":");n.hour=o[0],n.minute=o[1],o[2]&&(second_parts=o[2].split("."),n.second=second_parts[0],n.millisecond=second_parts[1])}return n},r.BEST_DATEFORMATS={base:{millisecond:"time_short",second:"time",minute:"time_no_seconds_small_date",hour:"time_no_seconds_small_date",day:"full",month:"month",year:"year",decade:"year",century:"year",millennium:"year",age:"fallback",epoch:"fallback",era:"fallback",eon:"fallback",eon2:"fallback"},short:{millisecond:"time_short",second:"time_short",minute:"time_no_seconds_short",hour:"time_no_minutes_short",day:"full_short",month:"month_short",year:"year",decade:"year",century:"year",millennium:"year",age:"fallback",epoch:"fallback",era:"fallback",eon:"fallback",eon2:"fallback"}}}(TL.Date),
//
// Class for cosmological dates
//
TL.BigDate=TL.Date.extend({
// @data = TL.BigYear object or JS dictionary with date properties
initialize:function(t,e,i){TL.BigYear==t.constructor?this.data={date_obj:t}:(this.data=JSON.parse(JSON.stringify(t)),this._createDateObj()),this._setFormat(e,i)},
// Create date_obj
_createDateObj:function(){var t=this._getDateData();this.data.date_obj=new TL.BigYear(t.year)},
// Return a new TL.BigDate which has been 'floored' at the given scale.
// @scale = string value from TL.BigDate.SCALES
floor:function(t){for(var e=0;e<TL.BigDate.SCALES.length;e++)if(TL.BigDate.SCALES[e][0]==t){var i=TL.BigDate.SCALES[e][2](this.data.date_obj);return new TL.BigDate(i)}throw new TL.Error("invalid_scale_err",t)}}),function(t){
// cosmo units are years, not millis
var e=1e6,i=1e7,n=1e8,a=1e9,s=function(i){return function(t){var e=t.getTime();return new TL.BigYear(Math.floor(e/i)*i)}}
// cosmological scales;
t.SCALES=[// ( name, units_per_tick, flooring function )
["year",1,new s(1)],["decade",10,new s(10)],["century",100,new s(100)],["millennium",1e3,new s(1e3)],["age",e,new s(e)],// 1M years
["epoch",i,new s(i)],// 10M years
["era",n,new s(n)],// 100M years
["eon",a,new s(a)]]}(TL.BigDate),
/* TL.DateUtil
Utilities for parsing time
================================================== */
TL.DateUtil={get:function(t){return"string"==typeof t?document.getElementById(t):t},sortByDate:function(t,i){// only for use with slide data objects
var i=i||"start_date";t.sort(function(t,e){return t[i].isBefore(e[i])?-1:t[i].isAfter(e[i])?1:0})},parseTime:function(t){var e={hour:null,minute:null,second:null,millisecond:null},i=null,n=t.match(/(\s*[AaPp]\.?[Mm]\.?\s*)$/);n&&(i=TL.Util.trim(n[0]),t=TL.Util.trim(t.substring(0,t.lastIndexOf(i))));var a=[],s=t.match(/^\s*(\d{1,2})(\d{2})\s*$/);if(s?a=s.slice(1):1==(a=t.split(":")).length&&(a=t.split(".")),4<a.length)throw new TL.Error("invalid_separator_error");if(e.hour=parseInt(a[0]),i&&"p"==i.toLowerCase()[0]&&12!=e.hour?e.hour+=12:i&&"a"==i.toLowerCase()[0]&&12==e.hour&&(e.hour=0),isNaN(e.hour)||e.hour<0||23<e.hour)throw new TL.Error("invalid_hour_err",e.hour);if(1<a.length&&(e.minute=parseInt(a[1]),isNaN(e.minute)))throw new TL.Error("invalid_minute_err",e.minute);if(2<a.length){var o;// deal with various methods of specifying fractional seconds
if(2<(a=a[2].split(/[\.,]/).concat(a.slice(3))).length)throw new TL.Error("invalid_second_fractional_err");if(e.second=parseInt(a[0]),isNaN(e.second))throw new TL.Error("invalid_second_err");if(2==a.length){var r=parseInt(a[1]);if(isNaN(r))throw new TL.Error("invalid_fractional_err");e.millisecond=100*r}}return e},SCALE_DATE_CLASSES:{human:TL.Date,cosmological:TL.BigDate}},
/* TL.Draggable
TL.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too.
TODO Enable constraints
================================================== */
TL.Draggable=TL.Class.extend({includes:TL.Events,_el:{},mousedrag:{down:"mousedown",up:"mouseup",leave:"mouseleave",move:"mousemove"},touchdrag:{down:"touchstart",up:"touchend",leave:"mouseleave",move:"touchmove"},initialize:function(t,e,i){
// DOM ELements
this._el={drag:t,move:t},i&&(this._el.move=i),
//Options
this.options={enable:{x:!0,y:!0},constraint:{top:!1,bottom:!1,left:!1,right:!1},momentum_multiplier:2e3,duration:1e3,ease:TL.Ease.easeInOutQuint},
// Animation Object
this.animator=null,
// Drag Event Type
this.dragevent=this.mousedrag,TL.Browser.touch&&(this.dragevent=this.touchdrag),
// Draggable Data
this.data={sliding:!1,direction:"none",pagex:{start:0,end:0},pagey:{start:0,end:0},pos:{start:{x:0,y:0},end:{x:0,y:0}},new_pos:{x:0,y:0},new_pos_parent:{x:0,y:0},time:{start:0,end:0},touch:!1},
// Merge Data and Options
TL.Util.mergeData(this.options,e)},enable:function(t){this.data.pos.start=0,this._el.move.style.left=this.data.pos.start.x+"px",this._el.move.style.top=this.data.pos.start.y+"px",this._el.move.style.position="absolute"},disable:function(){TL.DomEvent.removeListener(this._el.drag,this.dragevent.down,this._onDragStart,this),TL.DomEvent.removeListener(this._el.drag,this.dragevent.up,this._onDragEnd,this)},stopMomentum:function(){this.animator&&this.animator.stop()},updateConstraint:function(t){this.options.constraint=t},
/* Private Methods
================================================== */
_onDragStart:function(t){TL.Browser.touch?t.originalEvent?(this.data.pagex.start=t.originalEvent.touches[0].screenX,this.data.pagey.start=t.originalEvent.touches[0].screenY):(this.data.pagex.start=t.targetTouches[0].screenX,this.data.pagey.start=t.targetTouches[0].screenY):(this.data.pagex.start=t.pageX,this.data.pagey.start=t.pageY),
// Center element to finger or mouse
this.options.enable.x&&(this._el.move.style.left=this.data.pagex.start-this._el.move.offsetWidth/2+"px"),this.options.enable.y&&(this._el.move.style.top=this.data.pagey.start-this._el.move.offsetHeight/2+"px"),this.data.pos.start=TL.Dom.getPosition(this._el.drag),this.data.time.start=(new Date).getTime(),this.fire("dragstart",this.data),TL.DomEvent.addListener(this._el.drag,this.dragevent.move,this._onDragMove,this),TL.DomEvent.addListener(this._el.drag,this.dragevent.leave,this._onDragEnd,this)},_onDragEnd:function(t){this.data.sliding=!1,TL.DomEvent.removeListener(this._el.drag,this.dragevent.move,this._onDragMove,this),TL.DomEvent.removeListener(this._el.drag,this.dragevent.leave,this._onDragEnd,this),this.fire("dragend",this.data),
// momentum
this._momentum()},_onDragMove:function(t){t.preventDefault(),this.data.sliding=!0,TL.Browser.touch?t.originalEvent?(this.data.pagex.end=t.originalEvent.touches[0].screenX,this.data.pagey.end=t.originalEvent.touches[0].screenY):(this.data.pagex.end=t.targetTouches[0].screenX,this.data.pagey.end=t.targetTouches[0].screenY):(this.data.pagex.end=t.pageX,this.data.pagey.end=t.pageY),this.data.pos.end=TL.Dom.getPosition(this._el.drag),this.data.new_pos.x=-(this.data.pagex.start-this.data.pagex.end-this.data.pos.start.x),this.data.new_pos.y=-(this.data.pagey.start-this.data.pagey.end-this.data.pos.start.y),this.options.enable.x&&(this._el.move.style.left=this.data.new_pos.x+"px"),this.options.enable.y&&(this._el.move.style.top=this.data.new_pos.y+"px"),this.fire("dragmove",this.data)},_momentum:function(){var t={x:0,y:0,time:0},e={x:0,y:0,time:0},i=!1,n="";TL.Browser.touch,t.time=10*((new Date).getTime()-this.data.time.start),e.time=10*((new Date).getTime()-this.data.time.start),e.x=this.options.momentum_multiplier*(Math.abs(this.data.pagex.end)-Math.abs(this.data.pagex.start)),e.y=this.options.momentum_multiplier*(Math.abs(this.data.pagey.end)-Math.abs(this.data.pagey.start)),t.x=Math.round(e.x/e.time),t.y=Math.round(e.y/e.time),this.data.new_pos.x=Math.min(this.data.pos.end.x+t.x),this.data.new_pos.y=Math.min(this.data.pos.end.y+t.y),this.options.enable.x?this.data.new_pos.x<0&&(this.data.new_pos.x=0):this.data.new_pos.x=this.data.pos.start.x,this.options.enable.y?this.data.new_pos.y<0&&(this.data.new_pos.y=0):this.data.new_pos.y=this.data.pos.start.y,
// Detect Swipe
e.time<3e3&&(i=!0),
// Detect Direction
1e4<Math.abs(e.x)&&(this.data.direction="left",0<e.x&&(this.data.direction="right")),
// Detect Swipe
1e4<Math.abs(e.y)&&(this.data.direction="up",0<e.y&&(this.data.direction="down")),this._animateMomentum(),i&&this.fire("swipe_"+this.data.direction,this.data)},_animateMomentum:function(){var t={x:this.data.new_pos.x,y:this.data.new_pos.y},e={duration:this.options.duration,easing:TL.Ease.easeOutStrong};this.options.enable.y&&((this.options.constraint.top||this.options.constraint.bottom)&&(t.y>this.options.constraint.bottom?t.y=this.options.constraint.bottom:t.y<this.options.constraint.top&&(t.y=this.options.constraint.top)),e.top=Math.floor(t.y)+"px"),this.options.enable.x&&((this.options.constraint.left||this.options.constraint.right)&&(t.x>this.options.constraint.left?t.x=this.options.constraint.left:t.x<this.options.constraint.right&&(t.x=this.options.constraint.right)),e.left=Math.floor(t.x)+"px"),this.animator=TL.Animate(this._el.move,e),this.fire("momentum",this.data)}}),
/* TL.Swipable
TL.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too.
TODO Enable constraints
================================================== */
TL.Swipable=TL.Class.extend({includes:TL.Events,_el:{},mousedrag:{down:"mousedown",up:"mouseup",leave:"mouseleave",move:"mousemove"},touchdrag:{down:"touchstart",up:"touchend",leave:"mouseleave",move:"touchmove"},initialize:function(t,e,i){
// DOM ELements
this._el={drag:t,move:t},e&&(this._el.move=e),
//Options
this.options={snap:!1,enable:{x:!0,y:!0},constraint:{top:!1,bottom:!1,left:0,right:!1},momentum_multiplier:2e3,duration:1e3,ease:TL.Ease.easeInOutQuint},
// Animation Object
this.animator=null,
// Drag Event Type
this.dragevent=this.mousedrag,TL.Browser.touch&&(this.dragevent=this.touchdrag),
// Draggable Data
this.data={sliding:!1,direction:"none",pagex:{start:0,end:0},pagey:{start:0,end:0},pos:{start:{x:0,y:0},end:{x:0,y:0}},new_pos:{x:0,y:0},new_pos_parent:{x:0,y:0},time:{start:0,end:0},touch:!1},
// Merge Data and Options
TL.Util.mergeData(this.options,i)},enable:function(t){TL.DomEvent.addListener(this._el.drag,this.dragevent.down,this._onDragStart,this),TL.DomEvent.addListener(this._el.drag,this.dragevent.up,this._onDragEnd,this),this.data.pos.start=0,//TL.Dom.getPosition(this._el.move);
this._el.move.style.left=this.data.pos.start.x+"px",this._el.move.style.top=this.data.pos.start.y+"px",this._el.move.style.position="absolute"},disable:function(){TL.DomEvent.removeListener(this._el.drag,this.dragevent.down,this._onDragStart,this),TL.DomEvent.removeListener(this._el.drag,this.dragevent.up,this._onDragEnd,this)},stopMomentum:function(){this.animator&&this.animator.stop()},updateConstraint:function(t){this.options.constraint=t;
// Temporary until issues are fixed
},
/* Private Methods
================================================== */
_onDragStart:function(t){this.animator&&this.animator.stop(),TL.Browser.touch?t.originalEvent?(this.data.pagex.start=t.originalEvent.touches[0].screenX,this.data.pagey.start=t.originalEvent.touches[0].screenY):(this.data.pagex.start=t.targetTouches[0].screenX,this.data.pagey.start=t.targetTouches[0].screenY):(this.data.pagex.start=t.pageX,this.data.pagey.start=t.pageY),this.options.enable.x,this.options.enable.y,this.data.pos.start={x:this._el.move.offsetLeft,y:this._el.move.offsetTop},this.data.time.start=(new Date).getTime(),this.fire("dragstart",this.data),TL.DomEvent.addListener(this._el.drag,this.dragevent.move,this._onDragMove,this),TL.DomEvent.addListener(this._el.drag,this.dragevent.leave,this._onDragEnd,this)},_onDragEnd:function(t){this.data.sliding=!1,TL.DomEvent.removeListener(this._el.drag,this.dragevent.move,this._onDragMove,this),TL.DomEvent.removeListener(this._el.drag,this.dragevent.leave,this._onDragEnd,this),this.fire("dragend",this.data),
// momentum
this._momentum()},_onDragMove:function(t){var e={x:0,y:0};
//e.preventDefault();
this.data.sliding=!0,TL.Browser.touch?t.originalEvent?(this.data.pagex.end=t.originalEvent.touches[0].screenX,this.data.pagey.end=t.originalEvent.touches[0].screenY):(this.data.pagex.end=t.targetTouches[0].screenX,this.data.pagey.end=t.targetTouches[0].screenY):(this.data.pagex.end=t.pageX,this.data.pagey.end=t.pageY),e.x=this.data.pagex.start-this.data.pagex.end,e.y=this.data.pagey.start-this.data.pagey.end,this.data.pos.end={x:this._el.drag.offsetLeft,y:this._el.drag.offsetTop},this.data.new_pos.x=-(e.x-this.data.pos.start.x),this.data.new_pos.y=-(e.y-this.data.pos.start.y),this.options.enable.x&&Math.abs(e.x)>Math.abs(e.y)&&(t.preventDefault(),this._el.move.style.left=this.data.new_pos.x+"px"),this.options.enable.y&&Math.abs(e.y)>Math.abs(e.y)&&(t.preventDefault(),this._el.move.style.top=this.data.new_pos.y+"px"),this.fire("dragmove",this.data)},_momentum:function(){var t={x:0,y:0,time:0},e={x:0,y:0,time:0},i={x:!1,y:!1},n=!1,a="";this.data.direction=null,t.time=10*((new Date).getTime()-this.data.time.start),e.time=10*((new Date).getTime()-this.data.time.start),e.x=this.options.momentum_multiplier*(Math.abs(this.data.pagex.end)-Math.abs(this.data.pagex.start)),e.y=this.options.momentum_multiplier*(Math.abs(this.data.pagey.end)-Math.abs(this.data.pagey.start)),t.x=Math.round(e.x/e.time),t.y=Math.round(e.y/e.time),this.data.new_pos.x=Math.min(this.data.new_pos.x+t.x),this.data.new_pos.y=Math.min(this.data.new_pos.y+t.y),this.options.enable.x?this.options.constraint.left&&this.data.new_pos.x>this.options.constraint.left&&(this.data.new_pos.x=this.options.constraint.left):this.data.new_pos.x=this.data.pos.start.x,this.options.enable.y?this.data.new_pos.y<0&&(this.data.new_pos.y=0):this.data.new_pos.y=this.data.pos.start.y,
// Detect Swipe
e.time<2e3&&(n=!0),this.options.enable.x&&this.options.enable.y?Math.abs(e.x)>Math.abs(e.y)?i.x=!0:i.y=!0:this.options.enable.x?Math.abs(e.x)>Math.abs(e.y)&&(i.x=!0):Math.abs(e.y)>Math.abs(e.x)&&(i.y=!0),
// Detect Direction and long swipe
i.x&&(
// Long Swipe
Math.abs(e.x)>this._el.drag.offsetWidth/2&&(n=!0),1e4<Math.abs(e.x)&&(this.data.direction="left",0<e.x&&(this.data.direction="right"))),i.y&&(
// Long Swipe
Math.abs(e.y)>this._el.drag.offsetHeight/2&&(n=!0),1e4<Math.abs(e.y)&&(this.data.direction="up",0<e.y&&(this.data.direction="down"))),e.time<1e3||this._animateMomentum(),n&&this.data.direction?this.fire("swipe_"+this.data.direction,this.data):this.data.direction?this.fire("swipe_nodirection",this.data):this.options.snap&&(this.animator.stop(),this.animator=TL.Animate(this._el.move,{top:this.data.pos.start.y,left:this.data.pos.start.x,duration:this.options.duration,easing:TL.Ease.easeOutStrong}))},_animateMomentum:function(){var t={x:this.data.new_pos.x,y:this.data.new_pos.y},e={duration:this.options.duration,easing:TL.Ease.easeOutStrong};this.options.enable.y&&((this.options.constraint.top||this.options.constraint.bottom)&&(t.y>this.options.constraint.bottom?t.y=this.options.constraint.bottom:t.y<this.options.constraint.top&&(t.y=this.options.constraint.top)),e.top=Math.floor(t.y)+"px"),this.options.enable.x&&(this.options.constraint.left&&t.x>=this.options.constraint.left&&(t.x=this.options.constraint.left),this.options.constraint.right&&t.x<this.options.constraint.right&&(t.x=this.options.constraint.right),e.left=Math.floor(t.x)+"px"),this.animator=TL.Animate(this._el.move,e),this.fire("momentum",this.data)}}),
/* TL.MenuBar
Draggable component to control size
================================================== */
TL.MenuBar=TL.Class.extend({includes:[TL.Events,TL.DomMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e,i){
// DOM ELEMENTS
this._el={parent:{},container:{},button_backtostart:{},button_zoomin:{},button_zoomout:{},arrow:{},line:{},coverbar:{},grip:{}},this.collapsed=!1,this._el.container="object"==typeof t?t:TL.Dom.get(t),e&&(this._el.parent=e),
//Options
this.options={width:600,height:600,duration:1e3,ease:TL.Ease.easeInOutQuint,menubar_default_y:0},
// Animation
this.animator={},
// Merge Data and Options
TL.Util.mergeData(this.options,i),this._initLayout(),this._initEvents()},
/* Public
================================================== */
show:function(t){var e=this.options.duration;t&&(e=t)
/*
this.animator = TL.Animate(this._el.container, {
top: this.options.menubar_default_y + "px",
duration: duration,
easing: TL.Ease.easeOutStrong
});
*/},hide:function(t){
/*
this.animator = TL.Animate(this._el.container, {
top: top,
duration: this.options.duration,
easing: TL.Ease.easeOutStrong
});
*/},toogleZoomIn:function(t){t?TL.DomUtil.removeClass(this._el.button_zoomin,"tl-menubar-button-inactive"):TL.DomUtil.addClass(this._el.button_zoomin,"tl-menubar-button-inactive")},toogleZoomOut:function(t){t?TL.DomUtil.removeClass(this._el.button_zoomout,"tl-menubar-button-inactive"):TL.DomUtil.addClass(this._el.button_zoomout,"tl-menubar-button-inactive")},setSticky:function(t){this.options.menubar_default_y=t},
/* Color
================================================== */
setColor:function(t){this._el.container.className=t?"tl-menubar tl-menubar-inverted":"tl-menubar"},
/* Update Display
================================================== */
updateDisplay:function(t,e,i,n){this._updateDisplay(t,e,i,n)},
/* Events
================================================== */
_onButtonZoomIn:function(t){this.fire("zoom_in",t)},_onButtonZoomOut:function(t){this.fire("zoom_out",t)},_onButtonBackToStart:function(t){this.fire("back_to_start",t)},
/* Private Methods
================================================== */
_initLayout:function(){
// Create Layout
this._el.button_zoomin=TL.Dom.create("span","tl-menubar-button",this._el.container),this._el.button_zoomout=TL.Dom.create("span","tl-menubar-button",this._el.container),this._el.button_backtostart=TL.Dom.create("span","tl-menubar-button",this._el.container),TL.Browser.mobile&&this._el.container.setAttribute("ontouchstart"," "),this._el.button_backtostart.innerHTML="<span class='tl-icon-goback'></span>",this._el.button_zoomin.innerHTML="<span class='tl-icon-zoom-in'></span>",this._el.button_zoomout.innerHTML="<span class='tl-icon-zoom-out'></span>"},_initEvents:function(){TL.DomEvent.addListener(this._el.button_backtostart,"click",this._onButtonBackToStart,this),TL.DomEvent.addListener(this._el.button_zoomin,"click",this._onButtonZoomIn,this),TL.DomEvent.addListener(this._el.button_zoomout,"click",this._onButtonZoomOut,this)},
// Update Display
_updateDisplay:function(t,e,i){t&&(this.options.width=t),e&&(this.options.height=e)}}),
/* TL.Message
================================================== */
TL.Message=TL.Class.extend({includes:[TL.Events,TL.DomMixins,TL.I18NMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e,i){
// DOM ELEMENTS
this._el={parent:{},container:{},message_container:{},loading_icon:{},message:{}},
//Options
this.options={width:600,height:600,message_class:"tl-message",message_icon_class:"tl-loading-icon"},this._add_to_container=i||{},// save ref
// Merge Data and Options
TL.Util.mergeData(this.data,t),TL.Util.mergeData(this.options,e),this._el.container=TL.Dom.create("div",this.options.message_class),i&&(i.appendChild(this._el.container),this._el.parent=i),
// Animation
this.animator={},this._initLayout(),this._initEvents()},
/* Public
================================================== */
updateMessage:function(t){this._updateMessage(t)},
/* Update Display
================================================== */
updateDisplay:function(t,e){this._updateDisplay(t,e)},_updateMessage:function(t){this._el.message.innerHTML=t||this._("loading"),
// Re-add to DOM?
!this._el.parent.atrributes&&this._add_to_container.attributes&&(this._add_to_container.appendChild(this._el.container),this._el.parent=this._add_to_container)},
/* Events
================================================== */
_onMouseClick:function(){this.fire("clicked",this.options)},_onRemove:function(){this._el.parent={}},
/* Private Methods
================================================== */
_initLayout:function(){
// Create Layout
this._el.message_container=TL.Dom.create("div","tl-message-container",this._el.container),this._el.loading_icon=TL.Dom.create("div",this.options.message_icon_class,this._el.message_container),this._el.message=TL.Dom.create("div","tl-message-content",this._el.message_container),this._updateMessage()},_initEvents:function(){TL.DomEvent.addListener(this._el.container,"click",this._onMouseClick,this),TL.DomEvent.addListener(this,"removed",this._onRemove,this)},
// Update Display
_updateDisplay:function(t,e,i){}}),
/* TL.MediaType
Determines the type of media the url string is.
returns an object with .type and .id
You can add new media types by adding a regex
to match and the media class name to use to
render the media
The image_only parameter indicates that the
call only wants an image-based media type
that can be resolved to an image URL.
TODO
Allow array so a slideshow can be a mediatype
================================================== */
TL.MediaType=function(t,e){var i={},n=[{type:"youtube",name:"YouTube",match_str:"^(https?:)?/*(www.)?youtube|youtu.be",cls:TL.Media.YouTube},{type:"vimeo",name:"Vimeo",match_str:"^(https?:)?/*(player.)?vimeo.com",cls:TL.Media.Vimeo},{type:"dailymotion",name:"DailyMotion",match_str:"^(https?:)?/*(www.)?dailymotion.com",cls:TL.Media.DailyMotion},{type:"vine",name:"Vine",match_str:"^(https?:)?/*(www.)?vine.co",cls:TL.Media.Vine},{type:"soundcloud",name:"SoundCloud",match_str:"^(https?:)?/*(player.)?soundcloud.com",cls:TL.Media.SoundCloud},{type:"twitter",name:"Twitter",match_str:"^(https?:)?/*(www.)?twitter.com",cls:TL.Media.Twitter},{type:"twitterembed",name:"TwitterEmbed",match_str:"<blockquote class=['\"]twitter-tweet['\"]",cls:TL.Media.Twitter},{type:"googlemaps",name:"Google Map",match_str:/google.+?\/maps\/@([-\d.]+),([-\d.]+),((?:[-\d.]+[zmayht],?)*)|google.+?\/maps\/search\/([\w\W]+)\/@([-\d.]+),([-\d.]+),((?:[-\d.]+[zmayht],?)*)|google.+?\/maps\/place\/([\w\W]+)\/@([-\d.]+),([-\d.]+),((?:[-\d.]+[zmayht],?)*)|google.+?\/maps\/dir\/([\w\W]+)\/([\w\W]+)\/@([-\d.]+),([-\d.]+),((?:[-\d.]+[zmayht],?)*)/,cls:TL.Media.GoogleMap},{type:"googleplus",name:"Google+",match_str:"^(https?:)?/*plus.google",cls:TL.Media.GooglePlus},{type:"flickr",name:"Flickr",match_str:"^(https?:)?/*(www.)?flickr.com/photos",cls:TL.Media.Flickr},{type:"flickr",name:"Flickr",match_str:"^(https?://)?flic.kr/.*",cls:TL.Media.Flickr},{type:"instagram",name:"Instagram",match_str:/^(https?:)?\/*(www.)?(instagr.am|^(https?:)?\/*(www.)?instagram.com)\/p\//,cls:TL.Media.Instagram},{type:"profile",name:"Profile",match_str:/^(https?:)?\/*(www.)?instagr.am\/[a-zA-Z0-9]{2,}|^(https?:)?\/*(www.)?instagram.com\/[a-zA-Z0-9]{2,}/,cls:TL.Media.Profile},{type:"documentcloud",name:"Document Cloud",match_str:/documentcloud.org\//,cls:TL.Media.DocumentCloud},{type:"image",name:"Image",match_str:/(jpg|jpeg|png|gif|svg)(\?.*)?$/i,cls:TL.Media.Image},{type:"imgur",name:"Imgur",match_str:/^.*imgur.com\/.+$|<blockquote class=['\"]imgur-embed-pub['\"]/i,cls:TL.Media.Imgur},{type:"googledocs",name:"Google Doc",match_str:"^(https?:)?/*[^.]*.google.com/[^/]*/d/[^/]*/[^/]*?usp=sharing|^(https?:)?/*drive.google.com/open?id=[^&]*&authuser=0|^(https?:)?/*drive.google.com/open?id=[^&]*|^(https?:)?/*[^.]*.googledrive.com/host/[^/]*/",cls:TL.Media.GoogleDoc},{type:"pdf",name:"PDF",match_str:/^.*\.pdf(\?.*)?(\#.*)?/,cls:TL.Media.PDF},{type:"wikipedia",name:"Wikipedia",match_str:"^(https?:)?/*(www.)?wikipedia.org|^(https?:)?/*([a-z][a-z].)?wikipedia.org",cls:TL.Media.Wikipedia},{type:"spotify",name:"spotify",match_str:"spotify",cls:TL.Media.Spotify},{type:"iframe",name:"iFrame",match_str:"iframe",cls:TL.Media.IFrame},{type:"storify",name:"Storify",match_str:"storify",cls:TL.Media.Storify},{type:"blockquote",name:"Quote",match_str:"blockquote",cls:TL.Media.Blockquote},
// {
// type: "website",
// name: "Website",
// match_str: "https?://",
// cls: TL.Media.Website
// },
{type:"video",name:"Video",match_str:/(mp4)(\?.*)?$/i,cls:TL.Media.Video},{type:"wistia",name:"Wistia",match_str:/https?:\/\/(.+)?(wistia\.com|wi\.st)\/.*/i,cls:TL.Media.Wistia},{type:"audio",name:"Audio",match_str:/(mp3|wav|m4a)(\?.*)?$/i,cls:TL.Media.Audio},{type:"imageblank",name:"Imageblank",match_str:"",cls:TL.Media.Image}];if(e){if(t instanceof Array)return!1;for(var a=0;a<n.length;a++)switch(n[a].type){case"flickr":case"image":case"instagram":if(t.url.match(n[a].match_str))return i=n[a];break;default:break}}else for(var a=0;a<n.length;a++){if(t instanceof Array)return i={type:"slider",cls:TL.Media.Slider};if(t.url.match(n[a].match_str))return i=n[a]}return!1},
/* TL.Media
Main media template for media assets.
Takes a data object and populates a dom object
================================================== */
// TODO add link
TL.Media=TL.Class.extend({includes:[TL.Events,TL.I18NMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e,i){
// DOM ELEMENTS
this._el={container:{},content_container:{},content:{},content_item:{},content_link:{},caption:null,credit:null,parent:{},link:null},
// Player (If Needed)
this.player=null,
// Timer (If Needed)
this.timer=null,this.load_timer=null,
// Message
this.message=null,
// Media ID
this.media_id=null,
// State
this._state={loaded:!1,show_meta:!1,media_loaded:!1},
// Data
this.data={unique_id:null,url:null,credit:null,caption:null,credit_alternate:null,caption_alternate:null,link:null,link_target:null},
//Options
this.options={api_key_flickr:"f2cc870b4d233dd0a5bfe73fd0d64ef0",api_key_googlemaps:"AIzaSyB9dW8e_iRrATFa8g24qB6BDBGdkrLDZYI",api_key_embedly:"",// ae2da610d1454b66abdf2e6a4c44026d
credit_height:0,caption_height:0,background:0},this.animator={},
// Merge Data and Options
TL.Util.mergeData(this.options,e),TL.Util.mergeData(this.data,t),
// Don't create DOM elements if this is background media
this.options.background||(this._el.container=TL.Dom.create("div","tl-media"),this.data.unique_id&&(this._el.container.id=this.data.unique_id),this._initLayout(),i&&(i.appendChild(this._el.container),this._el.parent=i))},loadMedia:function(){var t=this;if(!this._state.loaded)try{this.load_timer=setTimeout(function(){t.loadingMessage(),t._loadMedia(),
// self._state.loaded = true; handled in onLoaded()
t._updateDisplay()},1200)}catch(t){trace("Error loading media for ",this._media),trace(t)}},_updateMessage:function(t){this.message&&this.message.updateMessage(t)},loadingMessage:function(){this._updateMessage(this._("loading")+" "+this.options.media_name)},errorMessage:function(t){t=t?this._("error")+": "+t:this._("error"),this._updateMessage(t)},updateMediaDisplay:function(t){this._state.loaded&&!this.options.background&&(TL.Browser.mobile?this._el.content_item.style.maxHeight=this.options.height/2+"px":this._el.content_item.style.maxHeight=this.options.height-this.options.credit_height-this.options.caption_height-30+"px",
//this._el.content_item.style.maxWidth = this.options.width + "px";
this._el.container.style.maxWidth=this.options.width+"px",
// Fix for max-width issues in Firefox
TL.Browser.firefox&&(this._el.content_item.offsetWidth,this._el.content_item.offsetHeight),this._updateMediaDisplay(t),this._state.media_loaded&&(this._el.credit&&(this._el.credit.style.width=this._el.content_item.offsetWidth+"px"),this._el.caption&&(this._el.caption.style.width=this._el.content_item.offsetWidth+"px")))},
/* Media Specific
================================================== */
_loadMedia:function(){
// All overrides must call this.onLoaded() to set state
this.onLoaded()},_updateMediaDisplay:function(t){
//this._el.content_item.style.maxHeight = (this.options.height - this.options.credit_height - this.options.caption_height - 16) + "px";
TL.Browser.firefox&&(this._el.content_item.style.maxWidth=this.options.width+"px",this._el.content_item.style.width="auto")},_getMeta:function(){},_getImageURL:function(t,e){
// Image-based media types should return <img>-compatible src url
return""},
/* Public
================================================== */
show:function(){},hide:function(){},addTo:function(t){t.appendChild(this._el.container),this.onAdd()},removeFrom:function(t){t.removeChild(this._el.container),this.onRemove()},getImageURL:function(t,e){return this._getImageURL(t,e)},
// Update Display
updateDisplay:function(t,e,i){this._updateDisplay(t,e,i)},stopMedia:function(){this._stopMedia()},loadErrorDisplay:function(t){try{this._el.content.removeChild(this._el.content_item)}catch(t){
// if this._el.content_item isn't a child of this._el then just keep truckin
}this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-loaderror",this._el.content),this._el.content_item.innerHTML="<div class='tl-icon-"+this.options.media_type+"'></div><p>"+t+"</p>",
// After Loaded
this.onLoaded(!0)},
/* Events
================================================== */
onLoaded:function(t){this._state.loaded=!0,this.fire("loaded",this.data),this.message&&this.message.hide(),t||this.options.background||this.showMeta(),this.updateDisplay()},onMediaLoaded:function(t){this._state.media_loaded=!0,this.fire("media_loaded",this.data),this._el.credit&&(this._el.credit.style.width=this._el.content_item.offsetWidth+"px"),this._el.caption&&(this._el.caption.style.width=this._el.content_item.offsetWidth+"px")},showMeta:function(t,e){this._state.show_meta=!0,
// Credit
this.data.credit&&""!=this.data.credit&&(this._el.credit=TL.Dom.create("div","tl-credit",this._el.content_container),this._el.credit.innerHTML=1==this.options.autolink?TL.Util.linkify(this.data.credit):this.data.credit,this.options.credit_height=this._el.credit.offsetHeight),
// Caption
this.data.caption&&""!=this.data.caption&&(this._el.caption=TL.Dom.create("div","tl-caption",this._el.content_container),this._el.caption.innerHTML=1==this.options.autolink?TL.Util.linkify(this.data.caption):this.data.caption,this.options.caption_height=this._el.caption.offsetHeight),this.data.caption&&this.data.credit||this.getMeta()},getMeta:function(){this._getMeta()},updateMeta:function(){!this.data.credit&&this.data.credit_alternate&&(this._el.credit=TL.Dom.create("div","tl-credit",this._el.content_container),this._el.credit.innerHTML=this.data.credit_alternate,this.options.credit_height=this._el.credit.offsetHeight),!this.data.caption&&this.data.caption_alternate&&(this._el.caption=TL.Dom.create("div","tl-caption",this._el.content_container),this._el.caption.innerHTML=this.data.caption_alternate,this.options.caption_height=this._el.caption.offsetHeight),this.updateDisplay()},onAdd:function(){this.fire("added",this.data)},onRemove:function(){this.fire("removed",this.data)},
/* Private Methods
================================================== */
_initLayout:function(){
// Message
this.message=new TL.Message({},this.options),this.message.addTo(this._el.container),
// Create Layout
this._el.content_container=TL.Dom.create("div","tl-media-content-container",this._el.container),
// Link
this.data.link&&""!=this.data.link?(this._el.link=TL.Dom.create("a","tl-media-link",this._el.content_container),this._el.link.href=this.data.link,this.data.link_target&&""!=this.data.link_target?this._el.link.target=this.data.link_target:this._el.link.target="_blank",this._el.content=TL.Dom.create("div","tl-media-content",this._el.link)):this._el.content=TL.Dom.create("div","tl-media-content",this._el.content_container)},
// Update Display
_updateDisplay:function(t,e,i){t&&(this.options.width=t),
//this._el.container.style.width = this.options.width + "px";
e&&(this.options.height=e),i&&(this.options.layout=i),this._el.credit&&(this.options.credit_height=this._el.credit.offsetHeight),this._el.caption&&(this.options.caption_height=this._el.caption.offsetHeight+5),this.updateMediaDisplay(this.options.layout)},_stopMedia:function(){}}),
/* TL.Media.Blockquote
================================================== */
TL.Media.Blockquote=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-blockquote",this._el.content),this._el.content_container.className="tl-media-content-container tl-media-content-container-text",
// Get Media ID
this.media_id=this.data.url,
// API Call
this._el.content_item.innerHTML=this.media_id,
// After Loaded
this.onLoaded()},updateMediaDisplay:function(){},_updateMediaDisplay:function(){}}),
/* TL.Media.DailyMotion
================================================== */
TL.Media.DailyMotion=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe tl-media-dailymotion",this._el.content),
// Get Media ID
this.data.url.match("video")?this.media_id=this.data.url.split("video/")[1].split(/[?&]/)[0]:this.media_id=this.data.url.split("embed/")[1].split(/[?&]/)[0],
// API URL
t="https://www.dailymotion.com/embed/video/"+this.media_id+"?api=postMessage",
// API Call
this._el.content_item.innerHTML="<iframe autostart='false' frameborder='0' width='100%' height='100%' src='"+t+"'></iframe>",
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=TL.Util.ratio.r16_9({w:this._el.content_item.offsetWidth})+"px"},_stopMedia:function(){this._el.content_item.querySelector("iframe").contentWindow.postMessage('{"command":"pause","parameters":[]}',"*")}}),
/* TL.Media.DocumentCloud
================================================== */
TL.Media.DocumentCloud=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t=this;
// Create Dom elements
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-documentcloud tl-media-shadow",this._el.content),this._el.content_item.id=TL.Util.unique_ID(7),
// Check url
this.data.url.match(/\.html$/)?this.data.url=this._transformURL(this.data.url):this.data.url.match(/.(json|js)$/)||trace("DOCUMENT CLOUD IN URL BUT INVALID SUFFIX"),
// Load viewer API
TL.Load.js(["https://assets.documentcloud.org/viewer/loader.js","https://assets.documentcloud.org/viewer/viewer.js"],function(){t.createMedia()})},
// Viewer API needs js, not html
_transformURL:function(t){return t.replace(/(.*)\.html$/,"$1.js")},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=this.options.height+"px";
//this._el.content_item.style.width = this.options.width + "px";
},createMedia:function(){
// DocumentCloud API call
DV.load(this.data.url,{container:"#"+this._el.content_item.id,showSidebar:!1}),this.onLoaded()}}),
/* TL.Media.Flickr
================================================== */
TL.Media.Flickr=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;try{
// Get Media ID
this.establishMediaID(),
// API URL
t="https://api.flickr.com/services/rest/?method=flickr.photos.getSizes&api_key="+this.options.api_key_flickr+"&photo_id="+this.media_id+"&format=json&jsoncallback=?",
// API Call
TL.getJSON(t,function(t){"ok"==t.stat?(e.sizes=t.sizes.size,// store sizes info
e.options.background||e.createMedia(),e.onLoaded()):e.loadErrorDisplay(e._("flickr_notfound_err"))})}catch(t){e.loadErrorDisplay(e._(t.message_key))}},establishMediaID:function(){if(this.data.url.match(/flic.kr\/.+/i)){var t=this.data.url.split("/").slice(-1)[0];this.media_id=TL.Util.base58.decode(t)}else{var e="flickr.com/photos/",i=this.data.url.indexOf(e);if(-1==i)throw new TL.Error("flickr_invalidurl_err");var n=i+e.length;this.media_id=this.data.url.substr(n).split("/")[1]}},createMedia:function(){var e=this;
// Link
this._el.content_link=TL.Dom.create("a","",this._el.content),this._el.content_link.href=this.data.url,this._el.content_link.target="_blank",
// Photo
this._el.content_item=TL.Dom.create("img","tl-media-item tl-media-image tl-media-flickr tl-media-shadow",this._el.content_link),this.data.alt?this._el.content_item.alt=this.data.alt:this.data.caption&&(this._el.content_item.alt=TL.Util.unhtmlify(this.data.caption)),this.data.title?this._el.content_item.title=this.data.title:this.data.caption&&(this._el.content_item.title=TL.Util.unhtmlify(this.data.caption)),
// Media Loaded Event
this._el.content_item.addEventListener("load",function(t){e.onMediaLoaded()}),
// Set Image Source
this._el.content_item.src=this.getImageURL(this.options.width,this.options.height)},getImageURL:function(t,e){for(var i=this.size_label(e),n=this.sizes[this.sizes.length-2].source,a=0;a<this.sizes.length;a++)this.sizes[a].label==i&&(n=this.sizes[a].source);return n},_getMeta:function(){var e=this,t;
// API URL
t="https://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key="+this.options.api_key_flickr+"&photo_id="+this.media_id+"&format=json&jsoncallback=?",
// API Call
TL.getJSON(t,function(t){e.data.credit_alternate="<a href='"+e.data.url+"' target='_blank'>"+t.photo.owner.realname+"</a>",e.data.caption_alternate=t.photo.title._content+" "+t.photo.description._content,e.updateMeta()})},size_label:function(t){var e="";return e=t<=75?t<=0?"Large":"Thumbnail":t<=180?"Small":t<=240?"Small 320":t<=375?"Medium":t<=480?"Medium 640":"Large"}}),
/* TL.Media.GoogleDoc
================================================== */
TL.Media.GoogleDoc=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
// Get Media ID
if(this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe",this._el.content),this.data.url.match("open?id="))this.media_id=this.data.url.split("open?id=")[1],this.data.url.match("&authuser=0")&&(t=this.media_id.match("&authuser=0")[0]);else if(this.data.url.match(/file\/d\/([^/]*)\/?/)){var i;t="https://drive.google.com/file/d/"+this.data.url.match(/file\/d\/([^/]*)\/?/)[1]+"/preview"}else t=this.data.url;
// this URL makes something suitable for an img src but what if it's not an image?
// api_url = "http://www.googledrive.com/host/" + this.media_id + "/";
this._el.content_item.innerHTML="<iframe class='doc' frameborder='0' width='100%' height='100%' src='"+t+"'></iframe>",
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=this.options.height+"px"}}),
/* TL.Media.GooglePlus
================================================== */
TL.Media.GooglePlus=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-googleplus",this._el.content),
// Get Media ID
this.media_id=this.data.url,
// API URL
t=this.media_id,
// API Call
this._el.content_item.innerHTML="<iframe frameborder='0' width='100%' height='100%' src='"+t+"'></iframe>",
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=this.options.height+"px"}}),
/* TL.Media.IFrame
================================================== */
TL.Media.IFrame=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe",this._el.content),
// Get Media ID
this.media_id=this.data.url,
// API URL
t=this.media_id,
// API Call
this._el.content_item.innerHTML=t,
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=this.options.height+"px"}}),
/* TL.Media.Image
Produces image assets.
Takes a data object and populates a dom object
================================================== */
TL.Media.Image=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){
// Loading Message
this.loadingMessage(),
// Create media?
this.options.background||this.createMedia(),
// After loaded
this.onLoaded()},createMedia:function(){var e=this,t="tl-media-item tl-media-image tl-media-shadow";(this.data.url.match(/.png(\?.*)?$/)||this.data.url.match(/.svg(\?.*)?$/))&&(t="tl-media-item tl-media-image"),
// Link
this.data.link?(this._el.content_link=TL.Dom.create("a","",this._el.content),this._el.content_link.href=this.data.link,this._el.content_link.target="_blank",this._el.content_item=TL.Dom.create("img",t,this._el.content_link)):this._el.content_item=TL.Dom.create("img",t,this._el.content),this.data.alt?this._el.content_item.alt=this.data.alt:this.data.caption&&(this._el.content_item.alt=TL.Util.unhtmlify(this.data.caption)),this.data.title?this._el.content_item.title=this.data.title:this.data.caption&&(this._el.content_item.title=TL.Util.unhtmlify(this.data.caption)),
// Media Loaded Event
this._el.content_item.addEventListener("load",function(t){e.onMediaLoaded()}),this._el.content_item.src=this.getImageURL()},getImageURL:function(t,e){return TL.Util.transformImageURL(this.data.url)},_updateMediaDisplay:function(t){TL.Browser.firefox&&(
//this._el.content_item.style.maxWidth = (this.options.width/2) - 40 + "px";
this._el.content_item.style.width="auto")}}),
/* TL.Media.Flickr
================================================== */
TL.Media.Imgur=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){try{var t=this;if(this.data.url.match("<blockquote class=['\"]imgur-embed-pub['\"]")){var e=this.data.url.match(/(imgur\.com)\/(\w+)/);this.media_id=e[2],this.data.url="http://imgur.com/gallery/"+this.media_id}else this.data.url&&(this.media_id=this.data.url.split("/").slice(-1)[0]);TL.Load.js(["https://s.imgur.com/min/embed.js"],function(){t.createMedia()})}catch(t){this.loadErrorDisplay(this._("imgur_invalidurl_err"))}},createMedia:function(){var n=this,t="https://api.imgur.com/oembed.json?url="+this.data.url;
// Content div
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-image tl-media-imgur",this._el.content),
// API Call
TL.ajax({type:"GET",url:t,dataType:"json",success:function(t){try{n._el.content_item.innerHTML=t.html,setInterval(function(){null==document.querySelector("blockquote.imgur-embed-pub")?clearInterval():(imgurEmbed.createIframe(),document.getElementById("imageElement").removeAttribute("style"),document.getElementById("image").removeAttribute("style"))},2e3)}catch(t){}},error:function(t,e,i){if(tc=new TL.TimelineConfig,"parsererror"==e)var i=new TL.Error("invalid_url_err");else var i=new TL.Error("unknown_read_err",e);n.loadErrorDisplay(n._("imgur_invalidurl_err")),tc.logError(i)}}),this.onLoaded()},_updateMediaDisplay:function(){
//this.el.content_item = document.getElementById(this._el.content_item.id);
this._el.content_item.style.width=this.options.width+"px",this._el.content_item.style.height=TL.Util.ratio.r16_9({w:this.options.width})+"px"}}),
/* TL.Media.Instagram
================================================== */
TL.Media.Instagram=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){
// Get Media ID
this.media_id=this.data.url.split("/p/")[1].split("/")[0],this.options.background||this.createMedia(),
// After Loaded
this.onLoaded()},createMedia:function(){var e=this;
// Link
this._el.content_link=TL.Dom.create("a","",this._el.content),this._el.content_link.href=this.data.url,this._el.content_link.target="_blank",
// Photo
this._el.content_item=TL.Dom.create("img","tl-media-item tl-media-image tl-media-instagram tl-media-shadow",this._el.content_link),this.data.alt?this._el.content_item.alt=this.data.alt:this.data.caption&&(this._el.content_item.alt=TL.Util.unhtmlify(this.data.caption)),this.data.title?this._el.content_item.title=this.data.title:this.data.caption&&(this._el.content_item.title=TL.Util.unhtmlify(this.data.caption)),
// Media Loaded Event
this._el.content_item.addEventListener("load",function(t){e.onMediaLoaded()}),this._el.content_item.src=this.getImageURL(this._el.content.offsetWidth)},getImageURL:function(t,e){return"https://instagram.com/p/"+this.media_id+"/media/?size="+this.sizes(t)},_getMeta:function(){var e=this,t;
// API URL
t="https://api.instagram.com/oembed?url=https://instagr.am/p/"+this.media_id+"&callback=?",
// API Call
TL.getJSON(t,function(t){e.data.credit_alternate="<a href='"+t.author_url+"' target='_blank'>"+t.author_name+"</a>",e.data.caption_alternate=t.title,e.updateMeta()})},sizes:function(t){var e="";return e=t<=150?"t":t<=306?"m":"l"}}),
/* TL.Media.Map
================================================== */
TL.Media.GoogleMap=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-map tl-media-shadow",this._el.content),
// Get Media ID
this.media_id=this.data.url,
// API Call
this.mapframe=TL.Dom.create("iframe","",this._el.content_item),(window.stash=this).mapframe.width="100%",this.mapframe.height="100%",this.mapframe.frameBorder="0",this.mapframe.src=this.makeGoogleMapsEmbedURL(this.media_id,this.options.api_key_googlemaps),
// After Loaded
this.onLoaded()},_updateMediaDisplay:function(){if(this._state.loaded){var t=TL.Util.ratio.square({w:this._el.content_item.offsetWidth});this._el.content_item.style.height=t.h+"px"}},makeGoogleMapsEmbedURL:function(t,r){function e(a){function o(t,e){
// Set the zoom param
if("z"==t.slice(-1))e.zoom=t;
// Set the maptype to something other than "roadmap"
else if("m"==t.slice(-1))
// TODO: make this somehow interpret the correct zoom level
// until then fake it by using Google's default zoom level
e.zoom=14,e.maptype="satellite";else if("t"==t.slice(-1)){
// streetview uses "location" instead of "center"
// "place" mode doesn't have the center param, so we may need to grab that now
if(l=!0,"place"==mapmode)var i=a.match(d.place)[3]+","+a.match(d.place)[4];else{var i=e.center;delete e.center}
// Clear out all the other params -- this is so hacky
for(param in(e={}).location=i,streetview_params=t.split(","),h.streetview){var n=parseInt(param)+1;"pitch"==h.streetview[param]&&"90t"==streetview_params[n]?
// Although 90deg is the horizontal default in the URL, 0 is horizontal default for embed URL. WHY??
// https://developers.google.com/maps/documentation/javascript/streetview
e[h.streetview[param]]=0:e[h.streetview[param]]=streetview_params[n].slice(0,-1)}}return e}function t(t,e){var i={},n=e[1],a=e[e.length-1];for(param in h[t]){
// skip first 2 matches, because they reflect the URL and not params
var s=parseInt(param)+2;"center"==h[t][param]?i[h[t][param]]=e[s]+","+e[++s]:i[h[t][param]]=e[s]}return(i=o(a,i)).key=r,1==l&&(t="streetview"),n+"/embed/v1/"+t+TL.Util.getParamString(i)}return mapmode="view",a.match(d.place)?mapmode="place":a.match(d.directions)?mapmode="directions":a.match(d.search)&&(mapmode="search"),t(mapmode,a.match(d[mapmode]))}
// These must be in the order they appear in the original URL
// "key" param not included since it's not in the URL structure
// Streetview "location" param not included since it's captured as "center"
// Place "center" param ...um...
// Test with https://docs.google.com/spreadsheets/d/1zCpvtRdftlR5fBPppmy_-SkGIo7RMwoPUiGFZDAXbTc/edit
var l=!1,h={view:["center"],place:["q","center"],directions:["origin","destination","center"],search:["q","center"],streetview:["fov","heading","pitch"]},i=/(https:\/\/.+google.+?\/maps)/,n=/@([-\d.]+),([-\d.]+)/,a=/([\w\W]+)/,s=/data=[\S]*/,o=/,((?:[-\d.]+[zmayht],?)*)/,d={view:new RegExp(i.source+"/"+n.source+o.source),place:new RegExp(i.source+"/place/"+a.source+"/"+n.source+o.source),directions:new RegExp(i.source+"/dir/"+a.source+"/"+a.source+"/"+n.source+o.source),search:new RegExp(i.source+"/search/"+a.source+"/"+n.source+o.source)};return e(t)}}),
/* TL.Media.PDF
* Chrome and Firefox on both OSes and Safari all support PDFs as iframe src.
* This prompts for a download on IE10/11. We should investigate using
* https://mozilla.github.io/pdf.js/ to support showing PDFs on IE.
================================================== */
TL.Media.PDF=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t=TL.Util.transformImageURL(this.data.url),e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe",this._el.content);var i="";
// not assigning media_id attribute. Seems like a holdover which is no longer used.
i=TL.Browser.ie||TL.Browser.edge||t.match(/dl.dropboxusercontent.com/)?"<iframe class='doc' frameborder='0' width='100%' height='100%' src='//docs.google.com/viewer?url="+t+"&amp;embedded=true'></iframe>":"<iframe class='doc' frameborder='0' width='100%' height='100%' src='"+t+"'></iframe>",this._el.content_item.innerHTML=i,this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=this.options.height+"px"}}),
/* TL.Media.Profile
================================================== */
TL.Media.Profile=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){this._el.content_item=TL.Dom.create("img","tl-media-item tl-media-image tl-media-profile tl-media-shadow",this._el.content),this._el.content_item.src=this.data.url,this.onLoaded()},_updateMediaDisplay:function(t){TL.Browser.firefox&&(this._el.content_item.style.maxWidth=this.options.width/2-40+"px")}}),
/* TL.Media.SLider
Produces a Slider
Takes a data object and populates a dom object
TODO
Placeholder
================================================== */
TL.Media.Slider=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){this._el.content_item=TL.Dom.create("img","tl-media-item tl-media-image",this._el.content),this._el.content_item.src=this.data.url,this.onLoaded()}});
/* TL.Media.SoundCloud
================================================== */
var soundCoudCreated=!1,mediaID;TL.Media.SoundCloud=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe tl-media-soundcloud tl-media-shadow",this._el.content),
// Get Media ID
this.media_id=this.data.url,
// API URL
t="https://soundcloud.com/oembed?url="+this.media_id+"&format=js&callback=?",
// API Call
TL.getJSON(t,function(t){TL.Load.js("https://w.soundcloud.com/player/api.js",function(){//load soundcloud api for pausing.
e.createMedia(t)})})},createMedia:function(t){this._el.content_item.innerHTML=t.html,this.soundCloudCreated=!0,self.widget=SC.Widget(this._el.content_item.querySelector("iframe")),//create widget for api use
// After Loaded
this.onLoaded()},_stopMedia:function(){this.soundCloudCreated&&self.widget.pause()}}),
/* TL.Media.Spotify
================================================== */
TL.Media.Spotify=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
if(this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe tl-media-spotify",this._el.content),
// Get Media ID
(this.data.url.match(/^spotify:track/)||this.data.url.match(/^spotify:album/)||this.data.url.match(/^spotify:user:.+:playlist:/))&&(this.media_id=this.data.url),this.data.url.match(/spotify\.com\/track\/(.+)/))this.media_id="spotify:track:"+this.data.url.match(/spotify\.com\/track\/(.+)/)[1];else if(this.data.url.match(/spotify\.com\/album\/(.+)/))this.media_id="spotify:album:"+this.data.url.match(/spotify\.com\/album\/(.+)/)[1];else if(this.data.url.match(/spotify\.com\/user\/(.+?)\/playlist\/(.+)/)){var i=this.data.url.match(/spotify\.com\/user\/(.+?)\/playlist\/(.+)/)[1],n=this.data.url.match(/spotify\.com\/user\/(.+?)\/playlist\/(.+)/)[2];this.media_id="spotify:user:"+i+":playlist:"+n}else if(this.data.url.match(/spotify\.com\/artist\/(.+)/)){var a=this.data.url.match(/spotify\.com\/artist\/(.+)/)[1];this.media_id="spotify:artist:"+a}this.media_id?(
// API URL
t="https://embed.spotify.com/?uri="+this.media_id+"&theme=white&view=coverart",this.player=TL.Dom.create("iframe","tl-media-shadow",this._el.content_item),this.player.width="100%",this.player.height="100%",this.player.frameBorder="0",this.player.src=t,
// After Loaded
this.onLoaded()):this.loadErrorDisplay(this._("spotify_invalid_url"))},
// Update Media Display
_updateMediaDisplay:function(t){var e=this.options.height,i=0,n=0;e=TL.Browser.mobile?this.options.height/2:this.options.height-this.options.credit_height-this.options.caption_height-30,this._el.content_item.style.maxHeight="none",trace(e),trace(this.options.width),n=e>this.options.width?(trace("height is greater"),i=this.options.width+80+"px",this.options.width+"px"):(trace("width is greater"),trace(this.options.width),i=e+"px",e-80+"px"),this.player.style.width=n,this.player.style.height=i,this._el.credit&&(this._el.credit.style.width=n),this._el.caption&&(this._el.caption.style.width=n)},_stopMedia:function(){
// Need spotify stop code
}}),
/* TL.Media.Storify
================================================== */
TL.Media.Storify=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe tl-media-storify",this._el.content),
// Get Media ID
this.media_id=this.data.url,
// Content
t="<iframe frameborder='0' width='100%' height='100%' src='"+this.media_id+"/embed'></iframe>",t+="<script src='"+this.media_id+".js'><\/script>",
// API Call
this._el.content_item.innerHTML=t,
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=this.options.height+"px"}}),TL.Media.Text=TL.Class.extend({includes:[TL.Events],
// DOM ELEMENTS
_el:{container:{},content_container:{},content:{},headline:{},date:{}},
// Data
data:{unique_id:"",headline:"headline",text:"text"},
// Options
options:{title:!1},
/* Constructor
================================================== */
initialize:function(t,e,i){TL.Util.setData(this,t),
// Merge Options
TL.Util.mergeData(this.options,e),this._el.container=TL.Dom.create("div","tl-text"),this._el.container.id=this.data.unique_id,this._initLayout(),i&&i.appendChild(this._el.container)},
/* Adding, Hiding, Showing etc
================================================== */
show:function(){},hide:function(){},addTo:function(t){t.appendChild(this._el.container);
//this.onAdd();
},removeFrom:function(t){t.removeChild(this._el.container)},headlineHeight:function(){return this._el.headline.offsetHeight+40},addDateText:function(t){this._el.date.innerHTML=t},
/* Events
================================================== */
onLoaded:function(){this.fire("loaded",this.data)},onAdd:function(){this.fire("added",this.data)},onRemove:function(){this.fire("removed",this.data)},
/* Private Methods
================================================== */
_initLayout:function(){
// Headline
if(
// Create Layout
this._el.content_container=TL.Dom.create("div","tl-text-content-container",this._el.container),
// Date
this._el.date=TL.Dom.create("h3","tl-headline-date",this._el.content_container),""!=this.data.headline){var t="tl-headline";this.options.title&&(t="tl-headline tl-headline-title"),this._el.headline=TL.Dom.create("h2",t,this._el.content_container),this._el.headline.innerHTML=this.data.headline}
// Text
if(""!=this.data.text){var e="";e+=TL.Util.htmlify(1==this.options.autolink?TL.Util.linkify(this.data.text):this.data.text),trace(this.data.text),this._el.content=TL.Dom.create("div","tl-text-content",this._el.content_container),this._el.content.innerHTML=e,trace(e),trace(this._el.content)}
// Fire event that the slide is loaded
this.onLoaded()}}),
/* TL.Media.Twitter
Produces Twitter Display
================================================== */
TL.Media.Twitter=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,n=this;
// Create Dom element
// Get Media ID
if(this._el.content_item=TL.Dom.create("div","tl-media-twitter",this._el.content),this._el.content_container.className="tl-media-content-container tl-media-content-container-text",this.data.url.match("^(https?:)?/*(www.)?twitter.com"))this.data.url.match("status/")?this.media_id=this.data.url.split("status/")[1]:this.data.url.match("statuses/")?this.media_id=this.data.url.split("statuses/")[1]:this.media_id="";else if(this.data.url.match("<blockquote class=['\"]twitter-tweet['\"]")){var e=this.data.url.match(/(status|statuses)\/(\d+)/);if(!(e&&2<e.length))return void n.loadErrorDisplay(n._("twitterembed_invalidurl_err"));this.media_id=e[2]}
// API URL
t="https://api.twitter.com/1/statuses/oembed.json?id="+this.media_id+"&omit_script=true&include_entities=true&callback=?",
// API Call
TL.ajax({type:"GET",url:t,dataType:"json",//json data type
success:function(t){n.createMedia(t)},error:function(t,e){var i="";i+=n._("twitter_load_err")+"<br/>"+n.media_id+"<br/>"+e,n.loadErrorDisplay(i)}})},createMedia:function(t){trace("create_media");var e="",i="",n="",a="",s="",o="",r=this;
// TWEET CONTENT
i=t.html.split("</p>&mdash;")[0]+"</p></blockquote>",n=t.author_url.split("twitter.com/")[1],s=(a=t.html.split("</p>&mdash;")[1].split('<a href="')[1]).split('">')[0],o=a.split('">')[1].split("</a>")[0],(
// Open links in new window
i=i.replace(/<a href/gi,'<a target="_blank" href')).includes("pic.twitter.com")?TL.Load.js("https://platform.twitter.com/widgets.js",function(){twttr.widgets.createTweet(r.media_id,r._el.content_item,{conversation:"none",// or all
linkColor:"#cc0000",// default is blue
theme:"light"})}):(
// TWEET CONTENT
e+=i,
// TWEET AUTHOR
e+="<div class='vcard'>",e+="<a href='"+s+"' class='twitter-date' target='_blank'>"+o+"</a>",e+="<img src='' class='tl-media-item tl-media-image' target='_blank'></a>",e+="<div class='author'>",e+="<a class='screen-name url' href='"+t.author_url+"' target='_blank'>",e+="<span class='avatar'></span>",e+="<span class='fn'>"+t.author_name+" <span class='tl-icon-twitter'></span></span>",e+="<span class='nickname'>@"+n+"<span class='thumbnail-inline'></span></span>",e+="</a>",e+="</div>",e+="</div>",
// Add to DOM
this._el.content_item.innerHTML=e),this.onLoaded()},updateMediaDisplay:function(){},_updateMediaDisplay:function(){}}),TL.Media.TwitterEmbed=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,n=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-twitter",this._el.content),this._el.content_container.className="tl-media-content-container tl-media-content-container-text";
// Get Media ID
var e=this.data.url.match(/(status|statuses)\/(\d+)/),i,a,s,o,r,l;e&&2<e.length?(this.media_id=e[2],
// API URL
t="https://api.twitter.com/1/statuses/oembed.json?id="+this.media_id+"&omit_script=true&include_entities=true&callback=?",window.twttr=(i=document,a="script",s="twitter-wjs",r=i.getElementsByTagName(a)[0],l=window.twttr||{},i.getElementById(s)||((o=i.createElement(a)).id=s,o.src="https://platform.twitter.com/widgets.js",r.parentNode.insertBefore(o,r),l._e=[],l.ready=function(t){l._e.push(t)}),l),mediaID=this.media_id,
// API Call
TL.ajax({type:"GET",url:t,dataType:"json",//json data type
success:function(t){n.createMedia(t)},error:function(t,e){var i="";i+=n._("twitter_load_err")+"<br/>"+n.media_id+"<br/>"+e,n.loadErrorDisplay(i)}})):n.loadErrorDisplay(n._("twitterembed_invalidurl_err"))},createMedia:function(t){trace("create_media");var i="",e="",n="",a="",s="",o="";
// TWEET CONTENT
e=t.html.split("</p>&mdash;")[0]+"</p></blockquote>",console.log(e),n=t.author_url.split("twitter.com/")[1],s=(a=t.html.split("</p>&mdash;")[1].split('<a href="')[1]).split('">')[0],o=a.split('">')[1].split("</a>")[0],(
// Open links in new window
e=e.replace(/<a href/gi,'<a target="_blank" href')).includes("pic.twitter.com")?twttr.ready(function(t){i=document.getElementsByClassName("tl-media-twitter")[0];var e=String(mediaID);twttr.widgets.createTweet(e,i,{conversation:"none",// or all
linkColor:"#cc0000",// default is blue
theme:"light"}).then(function(t){this.onLoaded()})}):(
// TWEET CONTENT
i+=e,
// TWEET AUTHOR
i+="<div class='vcard'>",i+="<a href='"+s+"' class='twitter-date' target='_blank'>"+o+"</a>",i+="<div class='author'>",i+="<a class='screen-name url' href='"+t.author_url+"' target='_blank'>",i+="<span class='avatar'></span>",i+="<span class='fn'>"+t.author_name+" <span class='tl-icon-twitter'></span></span>",i+="<span class='nickname'>@"+n+"<span class='thumbnail-inline'></span></span>",i+="</a>",i+="</div>",i+="</div>"),this._el.content_item.innerHTML=i,this.onLoaded()},updateMediaDisplay:function(){},_updateMediaDisplay:function(){}}),
/* TL.Media.Vimeo
================================================== */
TL.Media.Vimeo=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe tl-media-vimeo tl-media-shadow",this._el.content),
// Get Media ID
this.media_id=this.data.url.split(/video\/|\/\/vimeo\.com\//)[1].split(/[?&]/)[0];var i=null;
// Get start time
this.data.url.match(/#t=([^&]+).*/)&&(i=this.data.url.match(/#t=([^&]+).*/)[1]),
// API URL
t="https://player.vimeo.com/video/"+this.media_id+"?api=1&title=0&amp;byline=0&amp;portrait=0&amp;color=ffffff",i&&(t=t+="&amp;#t="+i),this.player=TL.Dom.create("iframe","",this._el.content_item),
// Media Loaded Event
this.player.addEventListener("load",function(t){e.onMediaLoaded()}),this.player.width="100%",this.player.height="100%",this.player.frameBorder="0",this.player.src=t,this.player.setAttribute("allowfullscreen",""),this.player.setAttribute("webkitallowfullscreen",""),this.player.setAttribute("mozallowfullscreen",""),
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=TL.Util.ratio.r16_9({w:this._el.content_item.offsetWidth})+"px"},_stopMedia:function(){try{this.player.contentWindow.postMessage(JSON.stringify({method:"pause"}),"https://player.vimeo.com")}catch(t){trace(t)}}}),
/* TL.Media.Vine
================================================== */
TL.Media.Vine=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe tl-media-vine tl-media-shadow",this._el.content),
// Get Media ID
this.media_id=this.data.url.split("vine.co/v/")[1],
// API URL
t="https://vine.co/v/"+this.media_id+"/embed/simple",
// API Call
this._el.content_item.innerHTML="<iframe frameborder='0' width='100%' height='100%' src='"+t+"'></iframe><script async src='https://platform.vine.co/static/scripts/embed.js' charset='utf-8'><\/script>",
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){var t=TL.Util.ratio.square({w:this._el.content_item.offsetWidth,h:this.options.height});this._el.content_item.style.height=t.h+"px"},_stopMedia:function(){this._el.content_item.querySelector("iframe").contentWindow.postMessage("pause","*")}}),
/* TL.Media.Website
Uses Embedly
http://embed.ly/docs/api/extract/endpoints/1/extract
================================================== */
TL.Media.Website=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var e=this;
// Get Media ID
this.media_id=this.data.url.replace(/.*?:\/\//g,""),this.options.api_key_embedly?(
// API URL
api_url="https://api.embed.ly/1/extract?key="+this.options.api_key_embedly+"&url="+this.media_id+"&callback=?",
// API Call
TL.getJSON(api_url,function(t){e.createMedia(t)})):this.createCardContent()},createCardContent:function(){!function(t,e){var i="embedly-platform",n="script";if(!e.getElementById(i)){t.embedly=t.embedly||function(){(t.embedly.q=t.embedly.q||[]).push(arguments)};var a=e.createElement(n);a.id=i,a.async=1,a.src=("https:"===document.location.protocol?"https":"http")+"://cdn.embedly.com/widgets/platform.js";var s=e.getElementsByTagName(n)[0];s.parentNode.insertBefore(a,s)}}(window,document);var t='<a href="'+this.data.url+'" class="embedly-card">'+this.data.url+"</a>";this._setContent(t)},createMedia:function(t){// this costs API credits...
var e="";e+="<h4><a href='"+this.data.url+"' target='_blank'>"+t.title+"</a></h4>",t.images&&t.images[0]&&(trace(t.images[0].url),e+="<img src='"+t.images[0].url+"' />"),t.favicon_url&&(e+="<img class='tl-media-website-icon' src='"+t.favicon_url+"' />"),e+="<span class='tl-media-website-description'>"+t.provider_name+"</span><br/>",e+="<p>"+t.description+"</p>",this._setContent(e)},_setContent:function(t){
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-website",this._el.content),this._el.content_container.className="tl-media-content-container tl-media-content-container-text",this._el.content_item.innerHTML=t,
// After Loaded
this.onLoaded()},updateMediaDisplay:function(){},_updateMediaDisplay:function(){}}),
/* TL.Media.Wikipedia
================================================== */
TL.Media.Wikipedia=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e,n=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-wikipedia",this._el.content),this._el.content_container.className="tl-media-content-container tl-media-content-container-text",
// Get Media ID
this.media_id=this.data.url.split("wiki/")[1].split("#")[0].replace("_"," "),this.media_id=this.media_id.replace(" ","%20"),
// API URL
t="https://"+(e=this.data.url.split("//")[1].split(".wikipedia")[0])+".wikipedia.org/w/api.php?action=query&prop=extracts|pageimages&redirects=&titles="+this.media_id+"&exintro=1&format=json&callback=?",
// API Call
TL.ajax({type:"GET",url:t,dataType:"json",//json data type
success:function(t){n.createMedia(t)},error:function(t,e){var i="";i+=n._("wikipedia_load_err")+"<br/>"+n.media_id+"<br/>"+e,n.loadErrorDisplay(i)}})},createMedia:function(t){var e="";if(t.query){var i="",e;(e={entry:{},title:"",text:"",extract:"",paragraphs:1,page_image:"",text_array:[]}).entry=TL.Util.getObjectAttributeByIndex(t.query.pages,0),e.extract=e.entry.extract,e.title=e.entry.title,e.page_image=e.entry.thumbnail,e.extract.match("<p>")?e.text_array=e.extract.split("<p>"):e.text_array.push(e.extract);for(var n=0;n<e.text_array.length;n++)n+1<=e.paragraphs&&n+1<e.text_array.length&&(e.text+="<p>"+e.text_array[n+1]);i+="<span class='tl-icon-wikipedia'></span>",i+="<div class='tl-wikipedia-title'><h4><a href='"+this.data.url+"' target='_blank'>"+e.title+"</a></h4>",i+="<span class='tl-wikipedia-source'>"+this._("wikipedia")+"</span></div>",e.page_image,i+=e.text,e.extract.match("REDIRECT")||(
// Add to DOM
this._el.content_item.innerHTML=i,
// After Loaded
this.onLoaded())}},updateMediaDisplay:function(){},_updateMediaDisplay:function(){}}),
/* TL.Media.Wistia
================================================== */
TL.Media.Wistia=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t,e=this;
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-iframe tl-media-wistia tl-media-shadow",this._el.content),
// Get Media ID
this.media_id=this.data.url.split(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/medias\/(.*)/)[3],
// API URL
t="https://fast.wistia.com/embed/iframe/"+this.media_id+"?version=v1&controlsVisibleOnLoad=true&playerColor=aae3d8",this.player=TL.Dom.create("iframe","",this._el.content_item),
// Media Loaded Event
this.player.addEventListener("load",function(t){e.onMediaLoaded()}),this.player.width="100%",this.player.height="100%",this.player.frameBorder="0",this.player.src=t,this.player.setAttribute("allowfullscreen",""),this.player.setAttribute("webkitallowfullscreen",""),this.player.setAttribute("mozallowfullscreen",""),
// After Loaded
this.onLoaded()},
// Update Media Display
_updateMediaDisplay:function(){this._el.content_item.style.height=TL.Util.ratio.r16_9({w:this._el.content_item.offsetWidth})+"px"},_stopMedia:function(){try{this.player.contentWindow.postMessage(JSON.stringify({method:"pause"}),"https://player.vimeo.com")}catch(t){trace(t)}}}),
/* TL.Media.YouTube
================================================== */
TL.Media.YouTube=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){var t=this,e;this.youtube_loaded=!1,
// Create Dom element
this._el.content_item=TL.Dom.create("div","tl-media-item tl-media-youtube tl-media-shadow",this._el.content),this._el.content_item.id=TL.Util.unique_ID(7),
// URL Vars
e=TL.Util.getUrlVars(this.data.url),
// Get Media ID
this.media_id={},this.data.url.match("v=")?this.media_id.id=e.v:this.data.url.match("/embed/")?this.media_id.id=this.data.url.split("embed/")[1].split(/[?&]/)[0]:this.data.url.match(/v\/|v=|youtu\.be\//)?this.media_id.id=this.data.url.split(/v\/|v=|youtu\.be\//)[1].split(/[?&]/)[0]:trace("YOUTUBE IN URL BUT NOT A VALID VIDEO"),
// Get start second
this.data.url.match("start=")?this.media_id.start=parseInt(this.data.url.split("start=")[1],10):this.data.url.match("t=")&&(this.media_id.start=parseInt(this.data.url.split("t=")[1],10)),
//Get end second
this.data.url.match("end=")&&(this.media_id.end=parseInt(this.data.url.split("end=")[1],10)),this.media_id.hd=Boolean(void 0!==e.hd),
// API Call
TL.Load.js("https://www.youtube.com/iframe_api",function(){t.createMedia()})},
// Update Media Display
_updateMediaDisplay:function(){
//this.el.content_item = document.getElementById(this._el.content_item.id);
this._el.content_item.style.height=TL.Util.ratio.r16_9({w:this.options.width})+"px",this._el.content_item.style.width=this.options.width+"px"},_stopMedia:function(){if(this.youtube_loaded)try{this.player.getPlayerState()==YT.PlayerState.PLAYING&&this.player.pauseVideo()}catch(t){trace(t)}},createMedia:function(){var t=this;clearTimeout(this.timer),"undefined"!=typeof YT&&void 0!==YT.Player?
// Create Player
this.player=new YT.Player(this._el.content_item.id,{playerVars:{enablejsapi:1,color:"white",controls:1,start:this.media_id.start,end:this.media_id.end,fs:1},videoId:this.media_id.id,events:{onReady:function(){t.onPlayerReady(),
// After Loaded
t.onLoaded()},onStateChange:t.onStateChange}}):this.timer=setTimeout(function(){t.createMedia()},1e3)},
/* Events
================================================== */
onPlayerReady:function(t){this.youtube_loaded=!0,this._el.content_item=document.getElementById(this._el.content_item.id),this.onMediaLoaded()},onStateChange:function(t){t.data==YT.PlayerState.ENDED&&(t.target.seekTo(0),t.target.pauseVideo())}}),
/* TL.Media.Audio
Produces audio assets.
Takes a data object and populates a dom object
================================================== */
TL.Media.Audio=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){
// Loading Message
this.loadingMessage(),
// Create media?
this.options.background||this.createMedia(),
// After loaded
this.onLoaded()},createMedia:function(){var e=this,t="tl-media-item tl-media-audio tl-media-shadow";
// Link
this.data.link?(this._el.content_link=TL.Dom.create("a","",this._el.content),this._el.content_link.href=this.data.link,this._el.content_link.target="_blank",this._el.content_item=TL.Dom.create("audio",t,this._el.content_link)):this._el.content_item=TL.Dom.create("audio",t,this._el.content),this._el.content_item.controls=!0,this._el.source_item=TL.Dom.create("source","",this._el.content_item),
// Media Loaded Event
this._el.content_item.addEventListener("load",function(t){e.onMediaLoaded()}),this._el.source_item.src=this.data.url,this._el.source_item.type=this._getType(this.data.url,this.data.mediatype.match_str),this._el.content_item.innerHTML+="Your browser doesn't support HTML5 audio with "+this._el.source_item.type},_updateMediaDisplay:function(t){TL.Browser.firefox&&(this._el.content_item.style.width="auto")},_getType:function(t,e){var i,n="audio/";switch(t.match(e)[1]){case"mp3":n+="mpeg";break;case"wav":n+="wav";break;case"m4a":n+="mp4";break;default:n="audio";break}return n}}),
/* TL.Media.Video
Produces video assets.
Takes a data object and populates a dom object
================================================== */
TL.Media.Video=TL.Media.extend({includes:[TL.Events],
/* Load the media
================================================== */
_loadMedia:function(){
// Loading Message
this.loadingMessage(),
// Create media?
this.options.background||this.createMedia(),
// After loaded
this.onLoaded()},createMedia:function(){var e=this,t="tl-media-item tl-media-video tl-media-shadow";
// Link
this.data.link?(this._el.content_link=TL.Dom.create("a","",this._el.content),this._el.content_link.href=this.data.link,this._el.content_link.target="_blank",this._el.content_item=TL.Dom.create("video",t,this._el.content_link)):this._el.content_item=TL.Dom.create("video",t,this._el.content),this._el.content_item.controls=!0,this._el.source_item=TL.Dom.create("source","",this._el.content_item),
// Media Loaded Event
this._el.content_item.addEventListener("load",function(t){e.onMediaLoaded()}),this._el.source_item.src=this.data.url,this._el.source_item.type=this._getType(this.data.url,this.data.mediatype.match_str),this._el.content_item.innerHTML+="Your browser doesn't support HTML5 video with "+this._el.source_item.type},_updateMediaDisplay:function(t){TL.Browser.firefox&&(this._el.content_item.style.width="auto")},_getType:function(t,e){var i,n="video/";switch(t.match(e)[1]){case"mp4":n+="mp4";break;default:n="video";break}return n}}),
/* TL.Slide
Creates a slide. Takes a data object and
populates the slide with content.
================================================== */
TL.Slide=TL.Class.extend({includes:[TL.Events,TL.DomMixins,TL.I18NMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e,i){
// DOM Elements
this._el={container:{},scroll_container:{},background:{},content_container:{},content:{}},
// Components
this._media=null,this._mediaclass={},this._text={},this._background_media=null,
// State
this._state={loaded:!1},this.has={headline:!1,text:!1,media:!1,title:!1,background:{image:!1,color:!1,color_value:""}},this.has.title=i,
// Data
this.data={unique_id:null,background:null,start_date:null,end_date:null,location:null,text:null,media:null,autolink:!0},
// Options
this.options={
// animation
duration:1e3,slide_padding_lr:40,ease:TL.Ease.easeInSpline,width:600,height:600,skinny_size:650,media_name:""},
// Actively Displaying
this.active=!1,
// Animation Object
this.animator={},
// Merge Data and Options
TL.Util.mergeData(this.options,e),TL.Util.mergeData(this.data,t),this._initLayout(),this._initEvents()},
/* Adding, Hiding, Showing etc
================================================== */
show:function(){this.animator=TL.Animate(this._el.slider_container,{left:-this._el.container.offsetWidth*n+"px",duration:this.options.duration,easing:this.options.ease})},hide:function(){},setActive:function(t){this.active=t,this.active?(this.data.background&&this.fire("background_change",this.has.background),this.loadMedia()):this.stopMedia()},addTo:function(t){t.appendChild(this._el.container);
//this.onAdd();
},removeFrom:function(t){t.removeChild(this._el.container)},updateDisplay:function(t,e,i){this._updateDisplay(t,e,i)},loadMedia:function(){var t=this;this._media&&!this._state.loaded&&(this._media.loadMedia(),this._state.loaded=!0),this._background_media&&!this._background_media._state.loaded&&(this._background_media.on("loaded",function(){t._updateBackgroundDisplay()}),this._background_media.loadMedia())},stopMedia:function(){this._media&&this._state.loaded&&this._media.stopMedia()},getBackground:function(){return this.has.background},scrollToTop:function(){this._el.container.scrollTop=0},getFormattedDate:function(){if(0<TL.Util.trim(this.data.display_date).length)return this.data.display_date;var t="";return this.has.title||(this.data.end_date&&(t=" &mdash; "+this.data.end_date.getDisplayDate(this.getLanguage())),this.data.start_date&&(t=this.data.start_date.getDisplayDate(this.getLanguage())+t)),t},
/* Events
================================================== */
/* Private Methods
================================================== */
_initLayout:function(){
// Style Slide Background
if(
// Create Layout
this._el.container=TL.Dom.create("div","tl-slide"),this.has.title&&(this._el.container.className="tl-slide tl-slide-titleslide"),this.data.unique_id&&(this._el.container.id=this.data.unique_id),this._el.scroll_container=TL.Dom.create("div","tl-slide-scrollable-container",this._el.container),this._el.content_container=TL.Dom.create("div","tl-slide-content-container",this._el.scroll_container),this._el.content=TL.Dom.create("div","tl-slide-content",this._el.content_container),this._el.background=TL.Dom.create("div","tl-slide-background",this._el.container),this.data.background){if(this.data.background.url){var t=TL.MediaType(this.data.background,!0);t&&(this._background_media=new t.cls(this.data.background,{background:1}),this.has.background.image=!0,this._el.container.className+=" tl-full-image-background",this.has.background.color_value="#000",this._el.background.style.display="block")}this.data.background.color&&(this.has.background.color=!0,this._el.container.className+=" tl-full-color-background",this.has.background.color_value=this.data.background.color),this.data.background.text_background&&(this._el.container.className+=" tl-text-background")}
// Determine Assets for layout and loading
this.data.media&&this.data.media.url&&""!=this.data.media.url&&(this.has.media=!0),this.data.text&&this.data.text.text&&(this.has.text=!0),this.data.text&&this.data.text.headline&&(this.has.headline=!0),
// Create Media
this.has.media&&(
// Determine the media type
this.data.media.mediatype=TL.MediaType(this.data.media),this.options.media_name=this.data.media.mediatype.name,this.options.media_type=this.data.media.mediatype.type,this.options.autolink=this.data.autolink,
// Create a media object using the matched class name
this._media=new this.data.media.mediatype.cls(this.data.media,this.options)),
// Create Text
(this.has.text||this.has.headline)&&(this._text=new TL.Media.Text(this.data.text,{title:this.has.title,language:this.options.language,autolink:this.data.autolink}),this._text.addDateText(this.getFormattedDate())),
// Add to DOM
this.has.text||this.has.headline||!this.has.media?this.has.headline&&this.has.media&&!this.has.text?(TL.DomUtil.addClass(this._el.container,"tl-slide-media-only"),this._text.addTo(this._el.content),this._media.addTo(this._el.content)):this.has.text&&this.has.media?(this._media.addTo(this._el.content),this._text.addTo(this._el.content)):(this.has.text||this.has.headline)&&(TL.DomUtil.addClass(this._el.container,"tl-slide-text-only"),this._text.addTo(this._el.content)):(TL.DomUtil.addClass(this._el.container,"tl-slide-media-only"),this._media.addTo(this._el.content)),
// Fire event that the slide is loaded
this.onLoaded()},_initEvents:function(){},
// Update Display
_updateDisplay:function(t,e,i){var n,a=this.options.slide_padding_lr,s=this.options.slide_padding_lr;this.options.width=t||this._el.container.offsetWidth,n=this.options.width-2*this.options.slide_padding_lr,TL.Browser.mobile&&this.options.width<=this.options.skinny_size?(s=a=0,n=this.options.width):"landscape"==i||this.options.width<=this.options.skinny_size&&(s=a=50,n=this.options.width-a-s),this._el.content.style.paddingLeft=a+"px",this._el.content.style.paddingRight=s+"px",this._el.content.style.width=n+"px",this.options.height=e||this._el.container.offsetHeight,this._media&&(!this.has.text&&this.has.headline?this._media.updateDisplay(n,this.options.height-this._text.headlineHeight(),i):this.has.text||this.has.headline?this.options.width<=this.options.skinny_size?this._media.updateDisplay(n,this.options.height,i):this._media.updateDisplay(n/2,this.options.height,i):this._media.updateDisplay(n,this.options.height,i)),this._updateBackgroundDisplay()},_updateBackgroundDisplay:function(){this._background_media&&this._background_media._state.loaded&&(this._el.background.style.backgroundImage="url('"+this._background_media.getImageURL(this.options.width,this.options.height)+"')")}}),
/* TL.SlideNav
encapsulate DOM display/events for the
'next' and 'previous' buttons on a slide.
================================================== */
// TODO null out data
TL.SlideNav=TL.Class.extend({includes:[TL.Events,TL.DomMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e,i){
// DOM ELEMENTS
this._el={container:{},content_container:{},icon:{},title:{},description:{}},
// Media Type
this.mediatype={},
// Data
this.data={title:"Navigation",description:"Description",date:"Date"},
//Options
this.options={direction:"previous"},this.animator=null,
// Merge Data and Options
TL.Util.mergeData(this.options,e),TL.Util.mergeData(this.data,t),this._el.container=TL.Dom.create("div","tl-slidenav-"+this.options.direction),TL.Browser.mobile&&this._el.container.setAttribute("ontouchstart"," "),this._initLayout(),this._initEvents(),i&&i.appendChild(this._el.container)},
/* Update Content
================================================== */
update:function(t){var e={title:"",description:"",date:t.getFormattedDate()};t.data.text&&t.data.text.headline&&(e.title=t.data.text.headline),this._update(e)},
/* Color
================================================== */
setColor:function(t){this._el.content_container.className=t?"tl-slidenav-content-container tl-slidenav-inverted":"tl-slidenav-content-container"},
/* Events
================================================== */
_onMouseClick:function(){this.fire("clicked",this.options)},
/* Private Methods
================================================== */
_update:function(t){
// update data
this.data=TL.Util.mergeData(this.data,t),
// Title
this._el.title.innerHTML=TL.Util.unlinkify(this.data.title),
// Date
this._el.description.innerHTML=TL.Util.unlinkify(this.data.date)},_initLayout:function(){
// Create Layout
this._el.content_container=TL.Dom.create("div","tl-slidenav-content-container",this._el.container),this._el.icon=TL.Dom.create("div","tl-slidenav-icon",this._el.content_container),this._el.title=TL.Dom.create("div","tl-slidenav-title",this._el.content_container),this._el.description=TL.Dom.create("div","tl-slidenav-description",this._el.content_container),this._el.icon.innerHTML="&nbsp;",this._update()},_initEvents:function(){TL.DomEvent.addListener(this._el.container,"click",this._onMouseClick,this)}}),
/* StorySlider
is the central class of the API - it is used to create a StorySlider
Events:
nav_next
nav_previous
slideDisplayUpdate
loaded
slideAdded
slideLoaded
slideRemoved
================================================== */
TL.StorySlider=TL.Class.extend({includes:[TL.Events,TL.I18NMixins],
/* Private Methods
================================================== */
initialize:function(t,e,i,n){
// DOM ELEMENTS
this._el={container:{},background:{},slider_container_mask:{},slider_container:{},slider_item_container:{}},this._nav={},this._nav.previous={},this._nav.next={},
// Slide Spacing
this.slide_spacing=0,
// Slides Array
this._slides=[],
// Swipe Object
this._swipable,
// Preload Timer
this.preloadTimer,
// Message
this._message,
// Current Slide
this.current_id="",
// Data Object
this.data={},this.options={id:"",layout:"portrait",width:600,height:600,default_bg_color:{r:255,g:255,b:255},slide_padding_lr:40,// padding on slide of slide
start_at_slide:1,slide_default_fade:"0%",// landscape fade
// animation
duration:1e3,ease:TL.Ease.easeInOutQuint,
// interaction
dragging:!0,trackResize:!0},
// Main element ID
"object"==typeof t?(this._el.container=t,this.options.id=TL.Util.unique_ID(6,"tl")):(this.options.id=t,this._el.container=TL.Dom.get(t)),this._el.container.id||(this._el.container.id=this.options.id),
// Animation Object
this.animator=null,
// Merge Data and Options
TL.Util.mergeData(this.options,i),TL.Util.mergeData(this.data,e),n&&this.init()},init:function(){this._initLayout(),this._initEvents(),this._initData(),this._updateDisplay(),
// Go to initial slide
this.goTo(this.options.start_at_slide),this._onLoaded()},
/* Slides
================================================== */
_addSlide:function(t){t.addTo(this._el.slider_item_container),t.on("added",this._onSlideAdded,this),t.on("background_change",this._onBackgroundChange,this)},_createSlide:function(t,e,i){var n=new TL.Slide(t,this.options,e);this._addSlide(n),i<0?this._slides.push(n):this._slides.splice(i,0,n)},_createSlides:function(t){for(var e=0;e<t.length;e++)""==t[e].unique_id&&(t[e].unique_id=TL.Util.unique_ID(6,"tl-slide")),this._createSlide(t[e],!1,-1)},_removeSlide:function(t){t.removeFrom(this._el.slider_item_container),t.off("added",this._onSlideRemoved,this),t.off("background_change",this._onBackgroundChange)},_destroySlide:function(t){this._removeSlide(this._slides[t]),this._slides.splice(t,1)},_findSlideIndex:function(t){var e=t;return("string"==typeof t||t instanceof String)&&(e=TL.Util.findArrayNumberByUniqueID(t,this._slides,"unique_id")),e},
/* Public
================================================== */
updateDisplay:function(t,e,i,n){this._updateDisplay(t,e,i,n)},
// Create a slide
createSlide:function(t,e){this._createSlide(t,!1,e)},
// Create Many Slides from an array
createSlides:function(t){this._createSlides(t)},
// Destroy slide by index
destroySlide:function(t){this._destroySlide(t)},
// Destroy slide by id
destroySlideId:function(t){this.destroySlide(this._findSlideIndex(t))},
/* Navigation
================================================== */
goTo:function(t,e,i){t=parseInt(t),isNaN(t)&&(t=0);var n=this;this.changeBackground({color_value:"",image:!1}),
// Clear Preloader Timer
this.preloadTimer&&clearTimeout(this.preloadTimer);
// Set Slide Active State
for(var a=0;a<this._slides.length;a++)this._slides[a].setActive(!1);t<this._slides.length&&0<=t&&(this.current_id=this._slides[t].data.unique_id,
// Stop animation
this.animator&&this.animator.stop(),this._swipable&&this._swipable.stopMomentum(),e?(this._el.slider_container.style.left=-this.slide_spacing*t+"px",this._onSlideChange(i)):this.animator=TL.Animate(this._el.slider_container,{left:-this.slide_spacing*t+"px",duration:this.options.duration,easing:this.options.ease,complete:this._onSlideChange(i)}),
// Set Slide Active State
this._slides[t].setActive(!0),
// Update Navigation and Info
this._slides[t+1]?(this.showNav(this._nav.next,!0),this._nav.next.update(this._slides[t+1])):this.showNav(this._nav.next,!1),this._slides[t-1]?(this.showNav(this._nav.previous,!0),this._nav.previous.update(this._slides[t-1])):this.showNav(this._nav.previous,!1),
// Preload Slides
this.preloadTimer=setTimeout(function(){n.preloadSlides(t)},this.options.duration))},goToId:function(t,e,i){this.goTo(this._findSlideIndex(t),e,i)},preloadSlides:function(t){this._slides[t+1]&&(this._slides[t+1].loadMedia(),this._slides[t+1].scrollToTop()),this._slides[t+2]&&(this._slides[t+2].loadMedia(),this._slides[t+2].scrollToTop()),this._slides[t-1]&&(this._slides[t-1].loadMedia(),this._slides[t-1].scrollToTop()),this._slides[t-2]&&(this._slides[t-2].loadMedia(),this._slides[t-2].scrollToTop())},next:function(){var t=this._findSlideIndex(this.current_id);t+1<this._slides.length?this.goTo(t+1):this.goTo(t)},previous:function(){var t=this._findSlideIndex(this.current_id);0<=t-1?this.goTo(t-1):this.goTo(t)},showNav:function(t,e){this.options.width<=500&&TL.Browser.mobile||(e?t.show():t.hide())},changeBackground:function(t){var e={r:256,g:256,b:256},i;t.color_value&&""!=t.color_value?(e=TL.Util.hexToRgb(t.color_value))||(trace("Invalid color value "+t.color_value),e=this.options.default_bg_color):(e=this.options.default_bg_color,t.color_value="rgb("+e.r+" , "+e.g+", "+e.b+")"),i=e.r+","+e.g+","+e.b,this._el.background.style.backgroundImage="none",t.color_value?this._el.background.style.backgroundColor=t.color_value:this._el.background.style.backgroundColor="transparent",e.r<255||e.g<255||e.b<255||t.image?(this._nav.next.setColor(!0),this._nav.previous.setColor(!0)):(this._nav.next.setColor(!1),this._nav.previous.setColor(!1))},
/* Private Methods
================================================== */
// Update Display
_updateDisplay:function(t,e,i,n){var a,s;s=void 0===n?this.options.layout:n,this.options.layout=s,this.slide_spacing=2*this.options.width,this.options.width=t||this._el.container.offsetWidth,this.options.height=e||this._el.container.offsetHeight,
//this._el.container.style.height = this.options.height;
// position navigation
a=this.options.height/2,this._nav.next.setPosition({top:a}),this._nav.previous.setPosition({top:a});
// Position slides
for(var o=0;o<this._slides.length;o++)this._slides[o].updateDisplay(this.options.width,this.options.height,s),this._slides[o].setPosition({left:this.slide_spacing*o,top:0});
// Go to the current slide
this.goToId(this.current_id,!0,!0)},
// Reposition and redraw slides
_updateDrawSlides:function(){for(var t=this.options.layout,e=0;e<this._slides.length;e++)this._slides[e].updateDisplay(this.options.width,this.options.height,t),this._slides[e].setPosition({left:this.slide_spacing*e,top:0});this.goToId(this.current_id,!0,!1)},
/* Init
================================================== */
_initLayout:function(){TL.DomUtil.addClass(this._el.container,"tl-storyslider"),
// Create Layout
this._el.slider_container_mask=TL.Dom.create("div","tl-slider-container-mask",this._el.container),this._el.background=TL.Dom.create("div","tl-slider-background tl-animate",this._el.container),this._el.slider_container=TL.Dom.create("div","tl-slider-container tlanimate",this._el.slider_container_mask),this._el.slider_item_container=TL.Dom.create("div","tl-slider-item-container",this._el.slider_container),
// Update Size
this.options.width=this._el.container.offsetWidth,this.options.height=this._el.container.offsetHeight,
// Create Navigation
this._nav.previous=new TL.SlideNav({title:"Previous",description:"description"},{direction:"previous"}),this._nav.next=new TL.SlideNav({title:"Next",description:"description"},{direction:"next"}),
// add the navigation to the dom
this._nav.next.addTo(this._el.container),this._nav.previous.addTo(this._el.container),this._el.slider_container.style.left="0px",TL.Browser.touch&&(
//this._el.slider_touch_mask = TL.Dom.create('div', 'tl-slider-touch-mask', this._el.slider_container_mask);
this._swipable=new TL.Swipable(this._el.slider_container_mask,this._el.slider_container,{enable:{x:!0,y:!1},snap:!0}),this._swipable.enable(),
// Message
this._message=new TL.Message({},{message_class:"tl-message-full",message_icon_class:"tl-icon-swipe-left"}),this._message.updateMessage(this._("swipe_to_navigate")),this._message.addTo(this._el.container))},_initEvents:function(){this._nav.next.on("clicked",this._onNavigation,this),this._nav.previous.on("clicked",this._onNavigation,this),this._message&&this._message.on("clicked",this._onMessageClick,this),this._swipable&&(this._swipable.on("swipe_left",this._onNavigation,this),this._swipable.on("swipe_right",this._onNavigation,this),this._swipable.on("swipe_nodirection",this._onSwipeNoDirection,this))},_initData:function(){this.data.title&&this._createSlide(this.data.title,!0,-1),this._createSlides(this.data.events)},
/* Events
================================================== */
_onBackgroundChange:function(t){var e=this._findSlideIndex(this.current_id),i=this._slides[e].getBackground();this.changeBackground(t),this.fire("colorchange",i)},_onMessageClick:function(t){this._message.hide()},_onSwipeNoDirection:function(t){this.goToId(this.current_id)},_onNavigation:function(t){"next"==t.direction||"left"==t.direction?this.next():"previous"!=t.direction&&"right"!=t.direction||this.previous(),this.fire("nav_"+t.direction,this.data)},_onSlideAdded:function(t){trace("slideadded"),this.fire("slideAdded",this.data)},_onSlideRemoved:function(t){this.fire("slideRemoved",this.data)},_onSlideChange:function(t){t||this.fire("change",{unique_id:this.current_id})},_onMouseClick:function(t){},_fireMouseEvent:function(t){if(this._loaded){var e=t.type;e="mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,this.hasEventListeners(e)&&("contextmenu"===e&&TL.DomEvent.preventDefault(t),this.fire(e,{latlng:"something",//this.mouseEventToLatLng(e),
layerPoint:"something else"}))}},_onLoaded:function(){this.fire("loaded",this.data)}}),
/* TL.TimeNav
================================================== */
TL.TimeNav=TL.Class.extend({includes:[TL.Events,TL.DomMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e,i,n){
// DOM ELEMENTS
this._el={parent:{},container:{},slider:{},slider_background:{},line:{},marker_container_mask:{},marker_container:{},marker_item_container:{},timeaxis:{},timeaxis_background:{},attribution:{}},this.collapsed=!1,this._el.container="object"==typeof t?t:TL.Dom.get(t),this.config=e,
//Options
this.options={width:600,height:600,duration:1e3,ease:TL.Ease.easeInOutQuint,has_groups:!1,optimal_tick_width:50,scale_factor:2,// How many screen widths wide should the timeline be
marker_padding:5,timenav_height_min:150,// Minimum timenav height
marker_height_min:30,// Minimum Marker Height
marker_width_min:100,// Minimum Marker Width
zoom_sequence:[.5,1,2,3,5,8,13,21,34,55,89]},
// Animation
this.animator=null,
// Ready state
this.ready=!1,
// Markers Array
this._markers=[],
// Eras Array
this._eras=[],this.has_eras=!1,
// Groups Array
this._groups=[],
// Row Height
this._calculated_row_height=100,
// Current Marker
this.current_id="",
// TimeScale
this.timescale={},
// TimeAxis
this.timeaxis={},this.axishelper={},
// Max Rows
this.max_rows=6,
// Animate CSS
this.animate_css=!1,
// Swipe Object
this._swipable,
// Merge Data and Options
TL.Util.mergeData(this.options,i),n&&this.init()},init:function(){this._initLayout(),this._initEvents(),this._initData(),this._updateDisplay(),this._onLoaded()},
/* Public
================================================== */
positionMarkers:function(){this._positionMarkers()},
/* Update Display
================================================== */
updateDisplay:function(t,e,i,n){this._updateDisplay(t,e,i,n)},
/* TimeScale
================================================== */
_getTimeScale:function(){
/* maybe the establishing config values (marker_height_min and max_rows) should be
separated from making a TimeScale object, which happens in another spot in this file with duplicate mapping of properties of this TimeNav into the TimeScale options object? */
// Set Max Rows
var e=0;try{e=parseInt(this.options.marker_height_min)}catch(t){trace("Invalid value for marker_height_min option."),e=30}return 0==e&&(trace("marker_height_min option must not be zero."),e=30),this.max_rows=Math.round((this.options.height-this._el.timeaxis_background.offsetHeight-this.options.marker_padding)/e),this.max_rows<1&&(this.max_rows=1),new TL.TimeScale(this.config,{display_width:this._el.container.offsetWidth,screen_multiplier:this.options.scale_factor,max_rows:this.max_rows})},_updateTimeScale:function(t){this.options.scale_factor=t,this._updateDrawTimeline()},zoomIn:function(){// move the the next "higher" scale factor
var t=TL.Util.findNextGreater(this.options.zoom_sequence,this.options.scale_factor);this.setZoomFactor(t)},zoomOut:function(){// move the the next "lower" scale factor
var t=TL.Util.findNextLesser(this.options.zoom_sequence,this.options.scale_factor);this.setZoomFactor(t)},setZoom:function(t){var e=this.options.zoom_sequence[t];"number"==typeof e?this.setZoomFactor(e):console.warn("Invalid zoom level. Please use an index number between 0 and "+(this.options.zoom_sequence.length-1))},setZoomFactor:function(t){t<=this.options.zoom_sequence[0]?this.fire("zoomtoggle",{zoom:"out",show:!1}):this.fire("zoomtoggle",{zoom:"out",show:!0}),t>=this.options.zoom_sequence[this.options.zoom_sequence.length-1]?this.fire("zoomtoggle",{zoom:"in",show:!1}):this.fire("zoomtoggle",{zoom:"in",show:!0}),0==t&&(console.warn("Zoom factor must be greater than zero. Using 0.1"),t=.1),this.options.scale_factor=t,
//this._updateDrawTimeline(true);
this.goToId(this.current_id,!this._updateDrawTimeline(!0),!0)},
/* Groups
================================================== */
_createGroups:function(){this._groups=[];var t=this.timescale.getGroupLabels();if(t){this.options.has_groups=!0;for(var e=0;e<t.length;e++)this._createGroup(t[e])}},_createGroup:function(t){var e=new TL.TimeGroup(t);this._addGroup(e),this._groups.push(e)},_addGroup:function(t){t.addTo(this._el.container)},_positionGroups:function(){if(this.options.has_groups)for(var t=this.options.height-this._el.timeaxis_background.offsetHeight,e=Math.floor(t/this.timescale.getNumberOfRows()-this.options.marker_padding),i=this.timescale.getGroupLabels(),n=0,a=0;n<this._groups.length;n++){var s=Math.floor(a*(e+this.options.marker_padding)),o=!1;s>t-this.options.marker_padding&&(o=!0),this._groups[n].setRowPosition(s,this._calculated_row_height+this.options.marker_padding/2),this._groups[n].setAlternateRowColor(TL.Util.isEven(n),o),a+=this._groups[n].data.rows}},
/* Markers
================================================== */
_addMarker:function(t){t.addTo(this._el.marker_item_container),t.on("markerclick",this._onMarkerClick,this),t.on("added",this._onMarkerAdded,this)},_createMarker:function(t,e){var i=new TL.TimeMarker(t,this.options);this._addMarker(i),e<0?this._markers.push(i):this._markers.splice(e,0,i)},_createMarkers:function(t){for(var e=0;e<t.length;e++)this._createMarker(t[e],-1)},_removeMarker:function(t){t.removeFrom(this._el.marker_item_container);
//marker.off('added', this._onMarkerRemoved, this);
},_destroyMarker:function(t){this._removeMarker(this._markers[t]),this._markers.splice(t,1)},_positionMarkers:function(t){
// POSITION X
for(var e=0;e<this._markers.length;e++){var i=this.timescale.getPositionInfo(e);t?this._markers[e].setClass("tl-timemarker tl-timemarker-fast"):this._markers[e].setClass("tl-timemarker"),this._markers[e].setPosition({left:i.start}),this._markers[e].setWidth(i.width)}},_calculateMarkerHeight:function(t){return t/this.timescale.getNumberOfRows()-this.options.marker_padding},_calculateRowHeight:function(t){return t/this.timescale.getNumberOfRows()},_calculateAvailableHeight:function(){return this.options.height-this._el.timeaxis_background.offsetHeight-this.options.marker_padding},_calculateMinimumTimeNavHeight:function(){return this.timescale.getNumberOfRows()*this.options.marker_height_min+this._el.timeaxis_background.offsetHeight+this.options.marker_padding},getMinimumHeight:function(){return this._calculateMinimumTimeNavHeight()},_assignRowsToMarkers:function(){var t=this._calculateAvailableHeight(),e=this._calculateMarkerHeight(t);this._positionGroups(),this._calculated_row_height=this._calculateRowHeight(t);for(var i=0;i<this._markers.length;i++){
// Set Height
this._markers[i].setHeight(e);
//Position by Row
var n=this.timescale.getPositionInfo(i).row,a=Math.floor(n*(e+this.options.marker_padding))+this.options.marker_padding,s=t-a+this.options.marker_padding;this._markers[i].setRowPosition(a,s)}},_resetMarkersActive:function(){for(var t=0;t<this._markers.length;t++)this._markers[t].setActive(!1)},_findMarkerIndex:function(t){var e=-1;return("string"==typeof t||t instanceof String)&&(e=TL.Util.findArrayNumberByUniqueID(t,this._markers,"unique_id",e)),e},
/* ERAS
================================================== */
_createEras:function(t){for(var e=0;e<t.length;e++)this._createEra(t[e],-1)},_createEra:function(t,e){var i=new TL.TimeEra(t,this.options);this._addEra(i),e<0?this._eras.push(i):this._eras.splice(e,0,i)},_addEra:function(t){t.addTo(this._el.marker_item_container),t.on("added",this._onEraAdded,this)},_removeEra:function(t){t.removeFrom(this._el.marker_item_container);
//marker.off('added', this._onMarkerRemoved, this);
},_destroyEra:function(t){this._removeEra(this._eras[t]),this._eras.splice(t,1)},_positionEras:function(t){
// POSITION X
for(var e=0,i=0;i<this._eras.length;i++){var n={start:0,end:0,width:0};n.start=this.timescale.getPosition(this._eras[i].data.start_date.getTime()),n.end=this.timescale.getPosition(this._eras[i].data.end_date.getTime()),n.width=n.end-n.start,t?this._eras[i].setClass("tl-timeera tl-timeera-fast"):this._eras[i].setClass("tl-timeera"),this._eras[i].setPosition({left:n.start}),this._eras[i].setWidth(n.width),5<++e&&(e=0),this._eras[i].setColor(e)}},
/* Public
================================================== */
// Create a marker
createMarker:function(t,e){this._createMarker(t,e)},
// Create many markers from an array
createMarkers:function(t){this._createMarkers(t)},
// Destroy marker by index
destroyMarker:function(t){this._destroyMarker(t)},
// Destroy marker by id
destroyMarkerId:function(t){this.destroyMarker(this._findMarkerIndex(t))},
/* Navigation
================================================== */
goTo:function(t,e,i){var n=this,a=this.options.ease,s=this.options.duration,o=t<0?0:t;
// Set Marker active state
this._resetMarkersActive(),0<=t&&t<this._markers.length&&this._markers[t].setActive(!0),
// Stop animation
this.animator&&this.animator.stop(),e?(this._el.slider.className="tl-timenav-slider",this._el.slider.style.left=-this._markers[o].getLeft()+this.options.width/2+"px"):i?(this._el.slider.className="tl-timenav-slider tl-timenav-slider-animate",this.animate_css=!0,this._el.slider.style.left=-this._markers[o].getLeft()+this.options.width/2+"px"):(this._el.slider.className="tl-timenav-slider",this.animator=TL.Animate(this._el.slider,{left:-this._markers[o].getLeft()+this.options.width/2+"px",duration:s,easing:a})),0<=t&&t<this._markers.length?this.current_id=this._markers[t].data.unique_id:this.current_id=""},goToId:function(t,e,i){this.goTo(this._findMarkerIndex(t),e,i)},
/* Events
================================================== */
_onLoaded:function(){this.ready=!0,this.fire("loaded",this.config)},_onMarkerAdded:function(t){this.fire("dateAdded",this.config)},_onEraAdded:function(t){this.fire("eraAdded",this.config)},_onMarkerRemoved:function(t){this.fire("dateRemoved",this.config)},_onMarkerClick:function(t){
// Go to the clicked marker
this.goToId(t.unique_id),this.fire("change",{unique_id:t.unique_id})},_onMouseScroll:function(t){var e=0,i=0,n={right:-(this.timescale.getPixelWidth()-this.options.width/2),left:this.options.width/2};t||(t=window.event),t.originalEvent&&(t=t.originalEvent),
// Webkit and browsers able to differntiate between up/down and left/right scrolling
void 0!==t.wheelDeltaX&&(e=t.wheelDeltaY/6,e=Math.abs(t.wheelDeltaX)>Math.abs(t.wheelDeltaY)?t.wheelDeltaX/6:0),e&&(t.preventDefault&&t.preventDefault(),t.returnValue=!1),(
// Stop from scrolling too far
i=parseInt(this._el.slider.style.left.replace("px",""))+e)>n.left?i=n.left:i<n.right&&(i=n.right),this.animate_css&&(this._el.slider.className="tl-timenav-slider",this.animate_css=!1),this._el.slider.style.left=i+"px"},_onDragMove:function(t){this.animate_css&&(this._el.slider.className="tl-timenav-slider",this.animate_css=!1)},
/* Private Methods
================================================== */
// Update Display
_updateDisplay:function(t,e,i){t&&(this.options.width=t),e&&e!=this.options.height&&(this.options.height=e,this.timescale=this._getTimeScale()),
// Size Markers
this._assignRowsToMarkers(),
// Size swipable area
this._el.slider_background.style.width=this.timescale.getPixelWidth()+this.options.width+"px",this._el.slider_background.style.left=-this.options.width/2+"px",this._el.slider.style.width=this.timescale.getPixelWidth()+this.options.width+"px",
// Update Swipable constraint
this._swipable.updateConstraint({top:!1,bottom:!1,left:this.options.width/2,right:-(this.timescale.getPixelWidth()-this.options.width/2)}),
// Go to the current slide
this.goToId(this.current_id,!0)},_drawTimeline:function(t){this.timescale=this._getTimeScale(),this.timeaxis.drawTicks(this.timescale,this.options.optimal_tick_width),this._positionMarkers(t),this._assignRowsToMarkers(),this._createGroups(),this._positionGroups(),this.has_eras&&this._positionEras(t)},_updateDrawTimeline:function(t){var e=!1;
// Check to see if redraw is needed
if(t){
/* keep this aligned with _getTimeScale or reduce code duplication */
var i=new TL.TimeScale(this.config,{display_width:this._el.container.offsetWidth,screen_multiplier:this.options.scale_factor,max_rows:this.max_rows});this.timescale.getMajorScale()==i.getMajorScale()&&this.timescale.getMinorScale()==i.getMinorScale()&&(e=!0)}else e=!0;
// Perform update or redraw
return e?(this.timescale=this._getTimeScale(),this.timeaxis.positionTicks(this.timescale,this.options.optimal_tick_width),this._positionMarkers(),this._assignRowsToMarkers(),this._positionGroups(),this.has_eras&&this._positionEras(),this._updateDisplay()):this._drawTimeline(!0),e},
/* Init
================================================== */
_initLayout:function(){
// Create Layout
this._el.attribution=TL.Dom.create("div","tl-attribution",this._el.container),this._el.line=TL.Dom.create("div","tl-timenav-line",this._el.container),this._el.slider=TL.Dom.create("div","tl-timenav-slider",this._el.container),this._el.slider_background=TL.Dom.create("div","tl-timenav-slider-background",this._el.slider),this._el.marker_container_mask=TL.Dom.create("div","tl-timenav-container-mask",this._el.slider),this._el.marker_container=TL.Dom.create("div","tl-timenav-container",this._el.marker_container_mask),this._el.marker_item_container=TL.Dom.create("div","tl-timenav-item-container",this._el.marker_container),this._el.timeaxis=TL.Dom.create("div","tl-timeaxis",this._el.slider),this._el.timeaxis_background=TL.Dom.create("div","tl-timeaxis-background",this._el.container),
// Knight Lab Logo
this._el.attribution.innerHTML="<a href='http://timeline.knightlab.com' target='_blank'><span class='tl-knightlab-logo'></span>Timeline JS</a>",
// Time Axis
this.timeaxis=new TL.TimeAxis(this._el.timeaxis,this.options),
// Swipable
this._swipable=new TL.Swipable(this._el.slider_background,this._el.slider,{enable:{x:!0,y:!1},constraint:{top:!1,bottom:!1,left:this.options.width/2,right:!1},snap:!1}),this._swipable.enable()},_initEvents:function(){
// Drag Events
this._swipable.on("dragmove",this._onDragMove,this),
// Scroll Events
TL.DomEvent.addListener(this._el.container,"mousewheel",this._onMouseScroll,this),TL.DomEvent.addListener(this._el.container,"DOMMouseScroll",this._onMouseScroll,this)},_initData:function(){
// Create Markers and then add them
this._createMarkers(this.config.events),this.config.eras&&(this.has_eras=!0,this._createEras(this.config.eras)),this._drawTimeline()}}),
/* TL.TimeMarker
================================================== */
TL.TimeMarker=TL.Class.extend({includes:[TL.Events,TL.DomMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e){
// DOM Elements
this._el={container:{},content_container:{},media_container:{},timespan:{},line_left:{},line_right:{},content:{},text:{},media:{}},
// Components
this._text={},
// State
this._state={loaded:!1},
// Data
this.data={unique_id:"",background:null,date:{year:0,month:0,day:0,hour:0,minute:0,second:0,millisecond:0,thumbnail:"",format:""},text:{headline:"",text:""},media:null},
// Options
this.options={duration:1e3,ease:TL.Ease.easeInSpline,width:600,height:600,marker_width_min:100},
// Actively Displaying
this.active=!1,
// Animation Object
this.animator={},
// End date
this.has_end_date=!1,
// Merge Data and Options
TL.Util.mergeData(this.options,e),TL.Util.mergeData(this.data,t),this._initLayout(),this._initEvents()},
/* Adding, Hiding, Showing etc
================================================== */
show:function(){},hide:function(){},setActive:function(t){this.active=t,this.active&&this.has_end_date?this._el.container.className="tl-timemarker tl-timemarker-with-end tl-timemarker-active":this.active?this._el.container.className="tl-timemarker tl-timemarker-active":this.has_end_date?this._el.container.className="tl-timemarker tl-timemarker-with-end":this._el.container.className="tl-timemarker"},addTo:function(t){t.appendChild(this._el.container)},removeFrom:function(t){t.removeChild(this._el.container)},updateDisplay:function(t,e){this._updateDisplay(t,e)},loadMedia:function(){this._media&&!this._state.loaded&&(this._media.loadMedia(),this._state.loaded=!0)},stopMedia:function(){this._media&&this._state.loaded&&this._media.stopMedia()},getLeft:function(){return this._el.container.style.left.slice(0,-2)},getTime:function(){// TODO does this need to know about the end date?
return this.data.start_date.getTime()},getEndTime:function(){return!!this.data.end_date&&this.data.end_date.getTime()},setHeight:function(t){var e=12,i=1;this._el.content_container.style.height=t+"px",this._el.timespan_content.style.height=t+"px",
// Handle Line height for better display of text
this._el.content.className=t<=30?"tl-timemarker-content tl-timemarker-content-small":"tl-timemarker-content",t<=56?TL.DomUtil.addClass(this._el.content_container,"tl-timemarker-content-container-small"):TL.DomUtil.removeClass(this._el.content_container,"tl-timemarker-content-container-small"),
// Handle number of lines visible vertically
TL.Browser.webkit?((i=Math.floor(t/14))<1&&(i=1),this._text.className="tl-headline",this._text.style.webkitLineClamp=i):(i=t/12,this._text.className=1<i?"tl-headline tl-headline-fadeout":"tl-headline",this._text.style.height=12*i+"px")},setWidth:function(t){this.data.end_date&&(this._el.container.style.width=t+"px",t>this.options.marker_width_min?(this._el.content_container.style.width=t+"px",this._el.content_container.className="tl-timemarker-content-container tl-timemarker-content-container-long"):(this._el.content_container.style.width=this.options.marker_width_min+"px",this._el.content_container.className="tl-timemarker-content-container"))},setClass:function(t){this._el.container.className=t},setRowPosition:function(t,e){this.setPosition({top:t}),this._el.timespan.style.height=e+"px"},
/* Events
================================================== */
_onMarkerClick:function(t){this.fire("markerclick",{unique_id:this.data.unique_id})},
/* Private Methods
================================================== */
_initLayout:function(){
// Thumbnail or Icon
if(
//trace(this.data)
// Create Layout
this._el.container=TL.Dom.create("div","tl-timemarker"),this.data.unique_id&&(this._el.container.id=this.data.unique_id+"-marker"),this.data.end_date&&(this.has_end_date=!0,this._el.container.className="tl-timemarker tl-timemarker-with-end"),this._el.timespan=TL.Dom.create("div","tl-timemarker-timespan",this._el.container),this._el.timespan_content=TL.Dom.create("div","tl-timemarker-timespan-content",this._el.timespan),this._el.content_container=TL.Dom.create("div","tl-timemarker-content-container",this._el.container),this._el.content=TL.Dom.create("div","tl-timemarker-content",this._el.content_container),this._el.line_left=TL.Dom.create("div","tl-timemarker-line-left",this._el.timespan),this._el.line_right=TL.Dom.create("div","tl-timemarker-line-right",this._el.timespan),this.data.media){this._el.media_container=TL.Dom.create("div","tl-timemarker-media-container",this._el.content);
// ugh. needs an overhaul
var t={url:this.data.media.thumbnail},e=this.data.media.thumbnail?TL.MediaType(t,!0):null;if(e){var i=new e.cls(t);i.on("loaded",function(){this._el.media=TL.Dom.create("img","tl-timemarker-media",this._el.media_container),this._el.media.src=i.getImageURL()}.bind(this)),i.loadMedia()}else{var n=TL.MediaType(this.data.media).type;this._el.media=TL.Dom.create("span","tl-icon-"+n,this._el.media_container)}}
// Text
this._el.text=TL.Dom.create("div","tl-timemarker-text",this._el.content),this._text=TL.Dom.create("h2","tl-headline",this._el.text),this.data.text.headline&&""!=this.data.text.headline?this._text.innerHTML=TL.Util.unlinkify(this.data.text.headline):this.data.text.text&&""!=this.data.text.text?this._text.innerHTML=TL.Util.unlinkify(this.data.text.text):this.data.media&&this.data.media.caption&&""!=this.data.media.caption&&(this._text.innerHTML=TL.Util.unlinkify(this.data.media.caption)),
// Fire event that the slide is loaded
this.onLoaded()},_initEvents:function(){TL.DomEvent.addListener(this._el.container,"click",this._onMarkerClick,this)},
// Update Display
_updateDisplay:function(t,e,i){t&&(this.options.width=t),e&&(this.options.height=e)}}),
/* TL.TimeMarker
================================================== */
TL.TimeEra=TL.Class.extend({includes:[TL.Events,TL.DomMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e){
// DOM Elements
this._el={container:{},background:{},content_container:{},content:{},text:{}},
// Components
this._text={},
// State
this._state={loaded:!1},
// Data
this.data={unique_id:"",date:{year:0,month:0,day:0,hour:0,minute:0,second:0,millisecond:0,thumbnail:"",format:""},text:{headline:"",text:""}},
// Options
this.options={duration:1e3,ease:TL.Ease.easeInSpline,width:600,height:600,marker_width_min:100},
// Actively Displaying
this.active=!1,
// Animation Object
this.animator={},
// End date
this.has_end_date=!1,
// Merge Data and Options
TL.Util.mergeData(this.options,e),TL.Util.mergeData(this.data,t),this._initLayout(),this._initEvents()},
/* Adding, Hiding, Showing etc
================================================== */
show:function(){},hide:function(){},setActive:function(t){},addTo:function(t){t.appendChild(this._el.container)},removeFrom:function(t){t.removeChild(this._el.container)},updateDisplay:function(t,e){this._updateDisplay(t,e)},getLeft:function(){return this._el.container.style.left.slice(0,-2)},getTime:function(){// TODO does this need to know about the end date?
return this.data.start_date.getTime()},getEndTime:function(){return!!this.data.end_date&&this.data.end_date.getTime()},setHeight:function(t){var e=12,i=1;this._el.content_container.style.height=t+"px",this._el.content.className="tl-timeera-content",
// Handle number of lines visible vertically
TL.Browser.webkit?((i=Math.floor(t/14))<1&&(i=1),this._text.className="tl-headline",this._text.style.webkitLineClamp=i):(i=t/12,this._text.className=1<i?"tl-headline tl-headline-fadeout":"tl-headline",this._text.style.height=12*i+"px")},setWidth:function(t){this.data.end_date&&(this._el.container.style.width=t+"px",t>this.options.marker_width_min?(this._el.content_container.style.width=t+"px",this._el.content_container.className="tl-timeera-content-container tl-timeera-content-container-long"):(this._el.content_container.style.width=this.options.marker_width_min+"px",this._el.content_container.className="tl-timeera-content-container"))},setClass:function(t){this._el.container.className=t},setRowPosition:function(t,e){this.setPosition({top:t})},setColor:function(t){this._el.container.className="tl-timeera tl-timeera-color"+t},
/* Events
================================================== */
/* Private Methods
================================================== */
_initLayout:function(){
//trace(this.data)
// Create Layout
this._el.container=TL.Dom.create("div","tl-timeera"),this.data.unique_id&&(this._el.container.id=this.data.unique_id+"-era"),this.data.end_date&&(this.has_end_date=!0,this._el.container.className="tl-timeera tl-timeera-with-end"),this._el.content_container=TL.Dom.create("div","tl-timeera-content-container",this._el.container),this._el.background=TL.Dom.create("div","tl-timeera-background",this._el.content_container),this._el.content=TL.Dom.create("div","tl-timeera-content",this._el.content_container),
// Text
this._el.text=TL.Dom.create("div","tl-timeera-text",this._el.content),this._text=TL.Dom.create("h2","tl-headline",this._el.text),this.data.text.headline&&""!=this.data.text.headline&&(this._text.innerHTML=TL.Util.unlinkify(this.data.text.headline)),
// Fire event that the slide is loaded
this.onLoaded()},_initEvents:function(){},
// Update Display
_updateDisplay:function(t,e,i){t&&(this.options.width=t),e&&(this.options.height=e)}}),
/* TL.TimeGroup
================================================== */
TL.TimeGroup=TL.Class.extend({includes:[TL.Events,TL.DomMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t){
// DOM ELEMENTS
this._el={parent:{},container:{},message:{}},
//Options
this.options={width:600,height:600},
// Data
this.data={label:"",rows:1},this._el.container=TL.Dom.create("div","tl-timegroup"),
// Merge Data
TL.Util.mergeData(this.data,t),
// Animation
this.animator={},this._initLayout(),this._initEvents()},
/* Public
================================================== */
/* Update Display
================================================== */
updateDisplay:function(t,e){},setRowPosition:function(t,e){
// trace(n);
// trace(this._el.container)
this.options.height=e*this.data.rows,this.setPosition({top:t}),this._el.container.style.height=this.options.height+"px"},setAlternateRowColor:function(t,e){var i="tl-timegroup";t&&(i+=" tl-timegroup-alternate"),e&&(i+=" tl-timegroup-hidden"),this._el.container.className=i},
/* Events
================================================== */
_onMouseClick:function(){this.fire("clicked",this.options)},
/* Private Methods
================================================== */
_initLayout:function(){
// Create Layout
this._el.message=TL.Dom.create("div","tl-timegroup-message",this._el.container),this._el.message.innerHTML=this.data.label},_initEvents:function(){TL.DomEvent.addListener(this._el.container,"click",this._onMouseClick,this)},
// Update Display
_updateDisplay:function(t,e,i){}}),
/* TL.TimeScale
Strategies for laying out the timenav
make a new one if the slides change
TODOS: deal with clustering
================================================== */
TL.TimeScale=TL.Class.extend({initialize:function(t,e){var i=t.events;this._scale=t.scale,e=TL.Util.mergeData({// establish defaults
display_width:500,screen_multiplier:3,max_rows:null},e),this._display_width=e.display_width,this._screen_multiplier=e.screen_multiplier,this._pixel_width=this._screen_multiplier*this._display_width,this._group_labels=void 0,this._positions=[],this._pixels_per_milli=0,this._earliest=t.getEarliestDate().getTime(),this._latest=t.getLatestDate().getTime(),this._span_in_millis=this._latest-this._earliest,this._span_in_millis<=0&&(this._span_in_millis=this._computeDefaultSpan(t)),this._average=this._span_in_millis/i.length,this._pixels_per_milli=this.getPixelWidth()/this._span_in_millis,this._axis_helper=TL.AxisHelper.getBestHelper(this),this._scaled_padding=1/this.getPixelsPerTick()*(this._display_width/2),this._computePositionInfo(i,e.max_rows)},_computeDefaultSpan:function(t){
// this gets called when all events are at the same instant,
// or maybe when the span_in_millis is > 0 but still below a desired threshold
// TODO: does this need smarts about eras?
if("human"!=t.scale)return 2e5;// what is the right handling for cosmo dates?
for(var e={},i=0;i<t.events.length;i++){var n=t.events[i].start_date.findBestFormat();e[n]=e[n]?e[n]+1:1}for(var i=TL.Date.SCALES.length-1;0<=i;i--)if(e.hasOwnProperty(TL.Date.SCALES[i][0])){var a=TL.Date.SCALES[TL.Date.SCALES.length-1];// default
return TL.Date.SCALES[i+1]&&(a=TL.Date.SCALES[i+1]),a[1]}return 31536e6;// default to a year?
},getGroupLabels:function(){
/*
return an array of objects, one per group, in the order (top to bottom) that the groups are expected to appear. Each object will have two properties:
* label (the string as specified in one or more 'group' properties of events in the configuration)
* rows (the number of rows occupied by events associated with the label. )
*/
return this._group_labels||[]},getScale:function(){return this._scale},getNumberOfRows:function(){return this._number_of_rows},getPixelWidth:function(){return this._pixel_width},getPosition:function(t){
// be careful using millis, as they won't scale to cosmological time.
// however, we're moving to make the arg to this whatever value
// comes from TL.Date.getTime() which could be made smart about that --
// so it may just be about the naming.
return(t-this._earliest)*this._pixels_per_milli},getPositionInfo:function(t){return this._positions[t]},getPixelsPerTick:function(){return this._axis_helper.getPixelsPerTick(this._pixels_per_milli)},getTicks:function(){return{major:this._axis_helper.getMajorTicks(this),minor:this._axis_helper.getMinorTicks(this)}},getDateFromTime:function(t){if("human"==this._scale)return new TL.Date(t);if("cosmological"==this._scale)return new TL.BigDate(new TL.BigYear(t));throw new TL.Error("time_scale_scale_err",this._scale)},getMajorScale:function(){return this._axis_helper.major.name},getMinorScale:function(){return this._axis_helper.minor.name},_assessGroups:function(t){for(var e=[],i=!1,n=0;n<t.length;n++)t[n].group&&(e.indexOf(t[n].group)<0?e.push(t[n].group):i=!0);return e.length&&i&&e.push(""),e},
/* Compute the marker row positions, minimizing the number of
overlaps.
@positions = list of objects from this._positions
@rows_left = number of rows available (assume > 0)
*/
_computeRowInfo:function(t,e){for(var i=[],n=0,a=0;a<t.length;a++){var s=t[a],o=[];
// See if we can add item to an existing row without
// overlapping the previous item in that row
delete s.row;for(var r=0;r<i.length;r++)if(o.push(i[r].end-s.start),o[r]<=0){i[s.row=r]=s;break}
// If we couldn't add to an existing row without overlap...
if(void 0===s.row)if(null===e)
// Make a new row
s.row=i.length,i.push(s);else if(0<e)
// Make a new row
s.row=i.length,i.push(s),e--;else{
// Add to existing row with minimum overlap.
var l=Math.min.apply(null,o),h=o.indexOf(l);s.row=h,s.end>i[h].end&&(i[h]=s),n++}}return{n_rows:i.length,n_overlaps:n}},
/* Compute marker positions. If using groups, this._number_of_rows
will never be less than the number of groups.
@max_rows = total number of available rows
@default_marker_width should be in pixels
*/
_computePositionInfo:function(t,e,i){i=i||100;
// Set start/end/width; enumerate groups
for(var n=[],a=!1,s=0;s<t.length;s++){var o={start:this.getPosition(t[s].start_date.getTime())};if(this._positions.push(o),void 0!==t[s].end_date){var r=this.getPosition(t[s].end_date.getTime());o.width=r-o.start,o.width>i?o.end=o.start+o.width:o.end=o.start+i}else o.width=i,o.end=o.start+i;t[s].group?n.indexOf(t[s].group)<0&&n.push(t[s].group):a=!0}if(n.length){a&&n.push("");
// Init group info
for(var l=[],s=0;s<n.length;s++)l[s]={label:n[s],idx:s,positions:[],n_rows:1,// default
n_overlaps:0};for(var s=0;s<this._positions.length;s++){var o;(o=this._positions[s]).group=n.indexOf(t[s].group||""),o.row=0;for(var h,d=(h=l[o.group]).positions.length-1;0<=d;d--)h.positions[d].end>o.start&&h.n_overlaps++;h.positions.push(o)}// start with 1 row per group
for(var c=n.length;;){
// Count free rows available
var u=Math.max(0,e-c);if(!u)break;// no free rows, nothing to do
// Sort by # overlaps, idx
if(l.sort(function(t,e){return t.n_overlaps>e.n_overlaps?-1:t.n_overlaps<e.n_overlaps?1:t.idx-e.idx}),!l[0].n_overlaps)break;// no overlaps, nothing to do
// Distribute free rows among groups with overlaps
for(var c=0,s=0;s<l.length;s++){var h;if((h=l[s]).n_overlaps&&u){var m=this._computeRowInfo(h.positions,h.n_rows+1);h.n_rows=m.n_rows,// update group info
h.n_overlaps=m.n_overlaps,u--}c+=h.n_rows}}
// Set number of rows
this._number_of_rows=c,
// Set group labels; offset row positions
this._group_labels=[],l.sort(function(t,e){return t.idx-e.idx});for(var s=0,_=0;s<l.length;s++){this._group_labels.push({label:l[s].label,rows:l[s].n_rows});for(var d=0;d<l[s].positions.length;d++){var o;(o=l[s].positions[d]).row+=_}_+=l[s].n_rows}}else{var p=this._computeRowInfo(this._positions,e);this._number_of_rows=p.n_rows}}}),
/* TL.TimeAxis
Display element for showing timescale ticks
================================================== */
TL.TimeAxis=TL.Class.extend({includes:[TL.Events,TL.DomMixins,TL.I18NMixins],_el:{},
/* Constructor
================================================== */
initialize:function(t,e){
// DOM Elements
this._el={container:{},content_container:{},major:{},minor:{}},
// Components
this._text={},
// State
this._state={loaded:!1},
// Data
this.data={},
// Options
this.options={duration:1e3,ease:TL.Ease.easeInSpline,width:600,height:600},
// Actively Displaying
this.active=!1,
// Animation Object
this.animator={},
// Axis Helper
this.axis_helper={},
// Minor tick dom element array
this.minor_ticks=[],
// Minor tick dom element array
this.major_ticks=[],
// Date Format Lookup, map TL.Date.SCALES names to...
this.dateformat_lookup={millisecond:"time_milliseconds",// ...TL.Language.<code>.dateformats
second:"time_short",minute:"time_no_seconds_short",hour:"time_no_minutes_short",day:"full_short",month:"month_short",year:"year",decade:"year",century:"year",millennium:"year",age:"compact",// ...TL.Language.<code>.bigdateformats
epoch:"compact",era:"compact",eon:"compact",eon2:"compact"},
// Main element
this._el.container="object"==typeof t?t:TL.Dom.get(t),
// Merge Data and Options
TL.Util.mergeData(this.options,e),this._initLayout(),this._initEvents()},
/* Adding, Hiding, Showing etc
================================================== */
show:function(){},hide:function(){},addTo:function(t){t.appendChild(this._el.container)},removeFrom:function(t){t.removeChild(this._el.container)},updateDisplay:function(t,e){this._updateDisplay(t,e)},getLeft:function(){return this._el.container.style.left.slice(0,-2)},drawTicks:function(t,e){var i=t.getTicks(),n={minor:{el:this._el.minor,dateformat:this.dateformat_lookup[i.minor.name],ts_ticks:i.minor.ticks,tick_elements:this.minor_ticks},major:{el:this._el.major,dateformat:this.dateformat_lookup[i.major.name],ts_ticks:i.major.ticks,tick_elements:this.major_ticks}};
// FADE OUT
this._el.major.className="tl-timeaxis-major",this._el.minor.className="tl-timeaxis-minor",this._el.major.style.opacity=0,this._el.minor.style.opacity=0,
// CREATE MAJOR TICKS
this.major_ticks=this._createTickElements(i.major.ticks,this._el.major,this.dateformat_lookup[i.major.name]),
// CREATE MINOR TICKS
this.minor_ticks=this._createTickElements(i.minor.ticks,this._el.minor,this.dateformat_lookup[i.minor.name],i.major.ticks),this.positionTicks(t,e,!0),
// FADE IN
this._el.major.className="tl-timeaxis-major tl-animate-opacity tl-timeaxis-animate-opacity",this._el.minor.className="tl-timeaxis-minor tl-animate-opacity tl-timeaxis-animate-opacity",this._el.major.style.opacity=1,this._el.minor.style.opacity=1},_createTickElements:function(t,e,i,n){e.innerHTML="";var a={},s;if(a[new Date(-1,13,-30).getTime()]=!0,n)for(var o=0;o<n.length;o++)a[n[o].getTime()]=!0;for(var r=[],o=0;o<t.length;o++){var l=t[o];if(!(l.getTime()in a)){var h=TL.Dom.create("div","tl-timeaxis-tick",e),d=TL.Dom.create("span","tl-timeaxis-tick-text tl-animate-opacity",h);d.innerHTML=l.getDisplayDate(this.getLanguage(),i),r.push({tick:h,tick_text:d,display_date:l.getDisplayDate(this.getLanguage(),i),date:l})}}return r},positionTicks:function(t,e,i){
// Handle Animation
this._el.minor.className=i?(this._el.major.className="tl-timeaxis-major","tl-timeaxis-minor"):(this._el.major.className="tl-timeaxis-major tl-timeaxis-animate","tl-timeaxis-minor tl-timeaxis-animate"),this._positionTickArray(this.major_ticks,t,e),this._positionTickArray(this.minor_ticks,t,e)},_positionTickArray:function(t,e,i){
// Poition Ticks & Handle density of ticks
if(t[1]&&t[0]){var n,a=1;e.getPosition(t[1].date.getMillisecond())-e.getPosition(t[0].date.getMillisecond())<i&&(a=Math.round(i/e.getPixelsPerTick()));for(var s=1,o=0;o<t.length;o++){var r=t[o];
// Poition Ticks
r.tick.style.left=e.getPosition(r.date.getMillisecond())+"px",r.tick_text.innerHTML=r.display_date,
// Handle density of ticks
r.tick.className=1<a?a<=s?(s=1,r.tick_text.style.opacity=1,"tl-timeaxis-tick"):(s++,r.tick_text.style.opacity=0,"tl-timeaxis-tick tl-timeaxis-tick-hidden"):(r.tick_text.style.opacity=1,"tl-timeaxis-tick")}}},
/* Events
================================================== */
/* Private Methods
================================================== */
_initLayout:function(){this._el.content_container=TL.Dom.create("div","tl-timeaxis-content-container",this._el.container),this._el.major=TL.Dom.create("div","tl-timeaxis-major",this._el.content_container),this._el.minor=TL.Dom.create("div","tl-timeaxis-minor",this._el.content_container),
// Fire event that the slide is loaded
this.onLoaded()},_initEvents:function(){},
// Update Display
_updateDisplay:function(t,e,i){t&&(this.options.width=t),e&&(this.options.height=e)}}),
/* TL.AxisHelper
Strategies for laying out the timenav
markers and time axis
Intended as a private class -- probably only known to TimeScale
================================================== */
TL.AxisHelper=TL.Class.extend({initialize:function(t){if(!t)throw new TL.Error("axis_helper_no_options_err");this.scale=t.scale,this.minor=t.minor,this.major=t.major},getPixelsPerTick:function(t){return t*this.minor.factor},getMajorTicks:function(t){return this._getTicks(t,this.major)},getMinorTicks:function(t){return this._getTicks(t,this.minor)},_getTicks:function(t,e){for(var i=t._scaled_padding*e.factor,n=t._earliest-i,a=t._latest+i,s=[],o=n;o<a;o+=e.factor)s.push(t.getDateFromTime(o).floor(e.name));return{name:e.name,ticks:s}}}),function(s){// add some class-level behavior
var d={},t=function(t,e){d[t]=[];for(var i=0;i<e.length-1;i++){var n=e[i],a=e[i+1];d[t].push(new s({scale:n[3],minor:{name:n[0],factor:n[1]},major:{name:a[0],factor:a[1]}}))}};t("human",TL.Date.SCALES),t("cosmological",TL.BigDate.SCALES),s.HELPERS=d,s.getBestHelper=function(t,e){"number"!=typeof e&&(e=100);var i=t.getScale(),n=d[i];if(!n)throw new TL.Error("axis_helper_scale_err",i);for(var a=null,s=0;s<n.length;s++){var o=n[s],r=o.getPixelsPerTick(t._pixels_per_milli),l,h;if(e<r)return null==a?o:Math.abs(e-r)<Math.abs(e-r)?o:a;a=o}return n[n.length-1];// last resort
}}(TL.AxisHelper),
/* TimelineJS
Designed and built by Zach Wise at KnightLab
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
================================================== */
/*
TODO
*/
/* Required Files
CodeKit Import
https://incident57.com/codekit/
================================================== */
// CORE
// @codekit-prepend "core/TL.js";
// @codekit-prepend "core/TL.Error.js";
// @codekit-prepend "core/TL.Util.js";
// @codekit-prepend "data/TL.Data.js";
// @codekit-prepend "core/TL.Class.js";
// @codekit-prepend "core/TL.Events.js";
// @codekit-prepend "core/TL.Browser.js";
// @codekit-prepend "core/TL.Load.js";
// @codekit-prepend "core/TL.TimelineConfig.js";
// @codekit-prepend "core/TL.ConfigFactory.js";
// LANGUAGE
// @codekit-prepend "language/TL.Language.js";
// @codekit-prepend "language/TL.I18NMixins.js";
// ANIMATION
// @codekit-prepend "animation/TL.Ease.js";
// @codekit-prepend "animation/TL.Animate.js";
// DOM
// @codekit-prepend "dom/TL.Point.js";
// @codekit-prepend "dom/TL.DomMixins.js";
// @codekit-prepend "dom/TL.Dom.js";
// @codekit-prepend "dom/TL.DomUtil.js";
// @codekit-prepend "dom/TL.DomEvent.js";
// @codekit-prepend "dom/TL.StyleSheet.js";
// Date
// @codekit-prepend "date/TL.Date.js";
// @codekit-prepend "date/TL.DateUtil.js";
// UI
// @codekit-prepend "ui/TL.Draggable.js";
// @codekit-prepend "ui/TL.Swipable.js";
// @codekit-prepend "ui/TL.MenuBar.js";
// @codekit-prepend "ui/TL.Message.js";
// MEDIA
// @codekit-prepend "media/TL.MediaType.js";
// @codekit-prepend "media/TL.Media.js";
// MEDIA TYPES
// @codekit-prepend "media/types/TL.Media.Blockquote.js";
// @codekit-prepend "media/types/TL.Media.DailyMotion.js";
// @codekit-prepend "media/types/TL.Media.DocumentCloud.js";
// @codekit-prepend "media/types/TL.Media.Flickr.js";
// @codekit-prepend "media/types/TL.Media.GoogleDoc.js";
// @codekit-prepend "media/types/TL.Media.GooglePlus.js";
// @codekit-prepend "media/types/TL.Media.IFrame.js";
// @codekit-prepend "media/types/TL.Media.Image.js";
// @codekit-prepend "media/types/TL.Media.Imgur.js";
// @codekit-prepend "media/types/TL.Media.Instagram.js";
// @codekit-prepend "media/types/TL.Media.GoogleMap.js";
// @codekit-prepend "media/types/TL.Media.PDF.js";
// @codekit-prepend "media/types/TL.Media.Profile.js";
// @codekit-prepend "media/types/TL.Media.Slider.js";
// @codekit-prepend "media/types/TL.Media.SoundCloud.js";
// @codekit-prepend "media/types/TL.Media.Spotify.js";
// @codekit-prepend "media/types/TL.Media.Storify.js";
// @codekit-prepend "media/types/TL.Media.Text.js";
// @codekit-prepend "media/types/TL.Media.Twitter.js";
// @codekit-prepend "media/types/TL.Media.TwitterEmbed.js";
// @codekit-prepend "media/types/TL.Media.Vimeo.js";
// @codekit-prepend "media/types/TL.Media.Vine.js";
// @codekit-prepend "media/types/TL.Media.Website.js";
// @codekit-prepend "media/types/TL.Media.Wikipedia.js";
// @codekit-prepend "media/types/TL.Media.Wistia.js";
// @codekit-prepend "media/types/TL.Media.YouTube.js";
// @codekit-prepend "media/types/TL.Media.Audio.js";
// @codekit-prepend "media/types/TL.Media.Video.js";
// STORYSLIDER
// @codekit-prepend "slider/TL.Slide.js";
// @codekit-prepend "slider/TL.SlideNav.js";
// @codekit-prepend "slider/TL.StorySlider.js";
// TIMENAV
// @codekit-prepend "timenav/TL.TimeNav.js";
// @codekit-prepend "timenav/TL.TimeMarker.js";
// @codekit-prepend "timenav/TL.TimeEra.js";
// @codekit-prepend "timenav/TL.TimeGroup.js";
// @codekit-prepend "timenav/TL.TimeScale.js";
// @codekit-prepend "timenav/TL.TimeAxis.js";
// @codekit-prepend "timenav/TL.AxisHelper.js";
TL.Timeline=TL.Class.extend({includes:[TL.Events,TL.I18NMixins],
/* Private Methods
================================================== */
initialize:function(t,e,i){var o=this;
// Merge Options
if(i||(i={}),
// Version
this.version="3.2.6",
// Ready
this.ready=!1,
// DOM ELEMENTS
this._el={container:{},storyslider:{},timenav:{},menubar:{}},
// Determine Container Element
this._el.container="object"==typeof t?t:TL.Dom.get(t),
// Slider
this._storyslider={},
// Style Sheet
this._style_sheet=new TL.StyleSheet,
// TimeNav
this._timenav={},
// Menu Bar
this._menubar={},
// Loaded State
this._loaded={storyslider:!1,timenav:!1},
// Data Object
this.config=null,this.options={script_path:"",height:this._el.container.offsetHeight,width:this._el.container.offsetWidth,debug:!1,is_embed:!1,is_full_embed:!1,hash_bookmark:!1,default_bg_color:{r:255,g:255,b:255},scale_factor:2,// How many screen widths wide should the timeline be
layout:"landscape",// portrait or landscape
timenav_position:"bottom",// timeline on top or bottom
optimal_tick_width:60,// optimal distance (in pixels) between ticks on axis
base_class:"tl-timeline",// removing tl-timeline will break all default stylesheets...
timenav_height:null,timenav_height_percentage:25,// Overrides timenav height as a percentage of the screen
timenav_mobile_height_percentage:40,// timenav height as a percentage on mobile devices
timenav_height_min:175,// Minimum timenav height
marker_height_min:30,// Minimum Marker Height
marker_width_min:100,// Minimum Marker Width
marker_padding:5,// Top Bottom Marker Padding
start_at_slide:0,start_at_end:!1,menubar_height:0,skinny_size:650,medium_size:800,relative_date:!1,// Use momentjs to show a relative date from the slide.text.date.created_time field
use_bc:!1,// Use declared suffix on dates earlier than 0
// animation
duration:1e3,ease:TL.Ease.easeInOutQuint,
// interaction
dragging:!0,trackResize:!0,map_type:"stamen:toner-lite",slide_padding_lr:100,// padding on slide of slide
slide_default_fade:"0%",// landscape fade
zoom_sequence:[.5,1,2,3,5,8,13,21,34,55,89],// Array of Fibonacci numbers for TimeNav zoom levels
language:"en",ga_property_id:null,track_events:["back_to_start","nav_next","nav_previous","zoom_in","zoom_out"]},
// Animation Objects
this.animator_timenav=null,this.animator_storyslider=null,this.animator_menubar=null,
// Add message to DOM
this.message=new TL.Message({},{message_class:"tl-message-full"},this._el.container),"string"==typeof i.default_bg_color){var n=TL.Util.hexToRgb(i.default_bg_color);// will clear it out if its invalid
n?i.default_bg_color=n:(delete i.default_bg_color,trace("Invalid default background color. Ignoring."))}TL.Util.mergeData(this.options,i),window.addEventListener("resize",function(t){o.updateDisplay()}),
// Set Debug Mode
TL.debug=this.options.debug,
// Apply base class to container
TL.DomUtil.addClass(this._el.container,"tl-timeline"),this.options.is_embed&&TL.DomUtil.addClass(this._el.container,"tl-timeline-embed"),this.options.is_full_embed&&TL.DomUtil.addClass(this._el.container,"tl-timeline-full-embed"),document.addEventListener("keydown",function(t){var e=t.key,i=o._getSlideIndex(o.current_id),n=o.config.events.length-1,a=o.config.title?n+1:n,s=0;"ArrowLeft"==e?0!=i&&o.goToPrev():"ArrowRight"==e&&i!=a&&o.goToNext()}),
// Use Relative Date Calculations
// NOT YET IMPLEMENTED
this.options.relative_date?"undefined"!=typeof moment?o._loadLanguage(e):TL.Load.js(this.options.script_path+"/library/moment.js",function(){o._loadLanguage(e),trace("LOAD MOMENTJS")}):o._loadLanguage(e)},_translateError:function(t){return t.hasOwnProperty("stack")&&trace(t.stack),t.message_key?this._(t.message_key)+(t.detail?" ["+t.detail+"]":""):t},
/* Load Language
================================================== */
_loadLanguage:function(t){try{this.options.language=new TL.Language(this.options),this._initData(t)}catch(t){this.showMessage(this._translateError(t))}},
/* Navigation
================================================== */
// Goto slide with id
goToId:function(t){this.current_id!=t&&(this.current_id=t,this._timenav.goToId(this.current_id),this._storyslider.goToId(this.current_id,!1,!0),this.fire("change",{unique_id:this.current_id},this))},
// Goto slide n
goTo:function(t){this.config.title?0==t?this.goToId(this.config.title.unique_id):this.goToId(this.config.events[t-1].unique_id):this.goToId(this.config.events[t].unique_id)},
// Goto first slide
goToStart:function(){this.goTo(0)},
// Goto last slide
goToEnd:function(){var t=this.config.events.length-1;this.goTo(this.config.title?t+1:t)},
// Goto previous slide
goToPrev:function(){this.goTo(this._getSlideIndex(this.current_id)-1)},
// Goto next slide
goToNext:function(){this.goTo(this._getSlideIndex(this.current_id)+1)},
/* Event maniupluation
================================================== */
// Add an event
add:function(t){var e=this.config.addEvent(t),i=this._getEventIndex(e),n=this.config.events[i];this._storyslider.createSlide(n,this.config.title?i+1:i),this._storyslider._updateDrawSlides(),this._timenav.createMarker(n,i),this._timenav._updateDrawTimeline(!1),this.fire("added",{unique_id:e})},
// Remove an event
remove:function(t){if(0<=t&&t<this.config.events.length){
// If removing the current, nav to new one first
this.config.events[t].unique_id==this.current_id&&(t<this.config.events.length-1?this.goTo(t+1):this.goTo(t-1));var e=this.config.events.splice(t,1);delete this.config.event_dict[e[0].unique_id],this._storyslider.destroySlide(this.config.title?t+1:t),this._storyslider._updateDrawSlides(),this._timenav.destroyMarker(t),this._timenav._updateDrawTimeline(!1),this.fire("removed",{unique_id:e[0].unique_id})}},removeId:function(t){this.remove(this._getEventIndex(t))},
/* Get slide data
================================================== */
getData:function(t){if(this.config.title){if(0==t)return this.config.title;if(0<t&&t<=this.config.events.length)return this.config.events[t-1]}else if(0<=t&&t<this.config.events.length)return this.config.events[t];return null},getDataById:function(t){return this.getData(this._getSlideIndex(t))},
/* Get slide object
================================================== */
getSlide:function(t){return 0<=t&&t<this._storyslider._slides.length?this._storyslider._slides[t]:null},getSlideById:function(t){return this.getSlide(this._getSlideIndex(t))},getCurrentSlide:function(){return this.getSlideById(this.current_id)},
/* Display
================================================== */
updateDisplay:function(){this.ready&&this._updateDisplay()},
/*
Compute the height of the navigation section of the Timeline, taking into account
the possibility of an explicit height or height percentage, but also honoring the
`timenav_height_min` option value. If `timenav_height` is specified it takes precedence over `timenav_height_percentage` but in either case, if the resultant pixel height is less than `options.timenav_height_min` then the value of `options.timenav_height_min` will be returned. (A minor adjustment is made to the returned value to account for marker padding.)
Arguments:
@timenav_height (optional): an integer value for the desired height in pixels
@timenav_height_percentage (optional): an integer between 1 and 100
*/
_calculateTimeNavHeight:function(t,e){var i=0;return t?i=t:(this.options.timenav_height_percentage||e)&&(i=e?Math.round(this.options.height/100*e):Math.round(this.options.height/100*this.options.timenav_height_percentage)),
// Set new minimum based on how many rows needed
this._timenav.ready&&this.options.timenav_height_min<this._timenav.getMinimumHeight()&&(this.options.timenav_height_min=this._timenav.getMinimumHeight()),
// If height is less than minimum set it to minimum
i<this.options.timenav_height_min&&(i=this.options.timenav_height_min),i-=2*this.options.marker_padding},
/* Private Methods
================================================== */
// Update View
_updateDisplay:function(t,e,i){var n=this.options.duration,a=this.options.base_class,s=0,o=this;i&&(n=i),
// Update width and height
this.options.width=this._el.container.offsetWidth,this.options.height=this._el.container.offsetHeight,
// Check if skinny
this.options.width<=this.options.skinny_size?(a+=" tl-skinny",this.options.layout="portrait"):(this.options.width<=this.options.medium_size&&(a+=" tl-medium"),this.options.layout="landscape"),
// Detect Mobile and Update Orientation on Touch devices
TL.Browser.touch&&(this.options.layout=TL.Browser.orientation()),TL.Browser.mobile?(a+=" tl-mobile",
// Set TimeNav Height
this.options.timenav_height=this._calculateTimeNavHeight(t,this.options.timenav_mobile_height_percentage)):
// Set TimeNav Height
this.options.timenav_height=this._calculateTimeNavHeight(t),
// LAYOUT
"portrait"==this.options.layout?
// Portrait
a+=" tl-layout-portrait":
// Landscape
a+=" tl-layout-landscape",
// Set StorySlider Height
this.options.storyslider_height=this.options.height-this.options.timenav_height,
// Positon Menu
s="top"==this.options.timenav_position?Math.ceil(this.options.timenav_height)/2-this._el.menubar.offsetHeight/2-19.5:Math.round(this.options.storyslider_height+1+Math.ceil(this.options.timenav_height)/2-this._el.menubar.offsetHeight/2-17.5),e?(
// Animate TimeNav
/*
if (this.animator_timenav) {
this.animator_timenav.stop();
}
this.animator_timenav = TL.Animate(this._el.timenav, {
height: (this.options.timenav_height) + "px",
duration: duration/4,
easing: TL.Ease.easeOutStrong,
complete: function () {
//self._map.updateDisplay(self.options.width, self.options.timenav_height, animate, d, self.options.menubar_height);
}
});
*/
this._el.timenav.style.height=Math.ceil(this.options.timenav_height)+"px",
// Animate StorySlider
this.animator_storyslider&&this.animator_storyslider.stop(),this.animator_storyslider=TL.Animate(this._el.storyslider,{height:this.options.storyslider_height+"px",duration:n/2,easing:TL.Ease.easeOutStrong}),
// Animate Menubar
this.animator_menubar&&this.animator_menubar.stop(),this.animator_menubar=TL.Animate(this._el.menubar,{top:s+"px",duration:n/2,easing:TL.Ease.easeOutStrong})):(
// TimeNav
this._el.timenav.style.height=Math.ceil(this.options.timenav_height)+"px",
// StorySlider
this._el.storyslider.style.height=this.options.storyslider_height+"px",
// Menubar
this._el.menubar.style.top=s+"px"),this.message&&this.message.updateDisplay(this.options.width,this.options.height),
// Update Component Displays
this._timenav.updateDisplay(this.options.width,this.options.timenav_height,e),this._storyslider.updateDisplay(this.options.width,this.options.storyslider_height,e,this.options.layout),"rtl"==this.options.language.direction&&(a+=" tl-rtl"),
// Apply class
this._el.container.className=a},
// Update hashbookmark in the url bar
_updateHashBookmark:function(t){var e="#"+t.toString();"file:"!=window.location.protocol&&window.history.replaceState(null,"Browsing TimelineJS",e),this.fire("hash_updated",{unique_id:this.current_id,hashbookmark:"#"+t.toString()},this)},
/* Init
================================================== */
// Initialize the data
_initData:function(t){var e=this;if("string"==typeof t){var e=this;TL.ConfigFactory.makeConfig(t,function(t){e.setConfig(t)})}else TL.TimelineConfig==t.constructor?this.setConfig(t):this.setConfig(new TL.TimelineConfig(t))},setConfig:function(t){if(this.config=t,this.config.validate(),this._validateOptions(),this.config.isValid())try{this._onDataLoaded()}catch(t){this.showMessage("<strong>"+this._("error")+":</strong> "+this._translateError(t))}else{for(var e=[],i=0,n=this.config.getErrors();i<n.length;i++)e.push(this._translateError(n[i]));this.showMessage("<strong>"+this._("error")+":</strong> "+e.join("<br>"))}},_validateOptions:function(){for(
// assumes that this.options and this.config have been set.
var t=["timenav_height","timenav_height_min","marker_height_min","marker_width_min","marker_padding","start_at_slide","slide_padding_lr"],e=0;e<t.length;e++){var i=t[e],n=this.options[i];valid=!0,"number"==typeof n?valid=n==parseInt(n):"string"==typeof n&&(valid=n.match(/^\s*(\-?\d+)?\s*$/)),valid||this.config.logError({message_key:"invalid_integer_option",detail:i})}},
// Initialize the layout
_initLayout:function(){var t=this;this.message.removeFrom(this._el.container),this._el.container.innerHTML="",
// Create Layout
"top"==this.options.timenav_position?(this._el.timenav=TL.Dom.create("div","tl-timenav",this._el.container),this._el.storyslider=TL.Dom.create("div","tl-storyslider",this._el.container)):(this._el.storyslider=TL.Dom.create("div","tl-storyslider",this._el.container),this._el.timenav=TL.Dom.create("div","tl-timenav",this._el.container)),this._el.menubar=TL.Dom.create("div","tl-menubar",this._el.container),
// Initial Default Layout
this.options.width=this._el.container.offsetWidth,this.options.height=this._el.container.offsetHeight,
// this._el.storyslider.style.top = "1px";
// Set TimeNav Height
this.options.timenav_height=this._calculateTimeNavHeight(this.options.timenav_height),
// Create TimeNav
this._timenav=new TL.TimeNav(this._el.timenav,this.config,this.options),this._timenav.on("loaded",this._onTimeNavLoaded,this),this._timenav.on("update_timenav_min",this._updateTimeNavHeightMin,this),this._timenav.options.height=this.options.timenav_height,this._timenav.init(),
// intial_zoom cannot be applied before the timenav has been created
this.options.initial_zoom&&
// at this point, this.options refers to the merged set of options
this.setZoom(this.options.initial_zoom),
// Create StorySlider
this._storyslider=new TL.StorySlider(this._el.storyslider,this.config,this.options),this._storyslider.on("loaded",this._onStorySliderLoaded,this),this._storyslider.init(),
// Create Menu Bar
this._menubar=new TL.MenuBar(this._el.menubar,this._el.container,this.options),
// LAYOUT
"portrait"==this.options.layout?this.options.storyslider_height=this.options.height-this.options.timenav_height-1:this.options.storyslider_height=this.options.height-1,
// Update Display
this._updateDisplay(this._timenav.options.height,!0,2e3)},
/* Depends upon _initLayout because these events are on things the layout initializes */
_initEvents:function(){
// TimeNav Events
this._timenav.on("change",this._onTimeNavChange,this),this._timenav.on("zoomtoggle",this._onZoomToggle,this),
// StorySlider Events
this._storyslider.on("change",this._onSlideChange,this),this._storyslider.on("colorchange",this._onColorChange,this),this._storyslider.on("nav_next",this._onStorySliderNext,this),this._storyslider.on("nav_previous",this._onStorySliderPrevious,this),
// Menubar Events
this._menubar.on("zoom_in",this._onZoomIn,this),this._menubar.on("zoom_out",this._onZoomOut,this),this._menubar.on("back_to_start",this._onBackToStart,this)},
/* Analytics
================================================== */
_initGoogleAnalytics:function(){var t,e,i,n,a,s,o;t=window,e=document,i="script",n="//www.google-analytics.com/analytics.js",a="ga",t.GoogleAnalyticsObject=a,t.ga=t.ga||function(){(t.ga.q=t.ga.q||[]).push(arguments)},t.ga.l=1*new Date,s=e.createElement(i),o=e.getElementsByTagName(i)[0],s.async=1,s.src=n,o.parentNode.insertBefore(s,o),ga("create",this.options.ga_property_id,"auto"),ga("set","anonymizeIp",!0)},_initAnalytics:function(){if(null!==this.options.ga_property_id){this._initGoogleAnalytics(),ga("send","pageview");var t=this.options.track_events;for(i=0;i<t.length;i++){var e=t[i];this.addEventListener(e,function(t){ga("send","event",t.type,"clicked")})}}},_onZoomToggle:function(t){"in"==t.zoom?this._menubar.toogleZoomIn(t.show):"out"==t.zoom&&this._menubar.toogleZoomOut(t.show)},
/* Get index of event by id
================================================== */
_getEventIndex:function(t){for(var e=0;e<this.config.events.length;e++)if(t==this.config.events[e].unique_id)return e;return-1},
/* Get index of slide by id
================================================== */
_getSlideIndex:function(t){if(this.config.title&&this.config.title.unique_id==t)return 0;for(var e=0;e<this.config.events.length;e++)if(t==this.config.events[e].unique_id)return this.config.title?e+1:e;return-1},
/* Events
================================================== */
_onDataLoaded:function(t){this.fire("dataloaded"),this._initLayout(),this._initEvents(),this._initAnalytics(),this.message&&this.message.hide(),this.ready=!0},showMessage:function(t){this.message?this.message.updateMessage(t):(trace("No message display available."),trace(t))},_onColorChange:function(t){this.fire("color_change",{unique_id:this.current_id},this),t.color||t.image},_onSlideChange:function(t){this.current_id!=t.unique_id&&(this.current_id=t.unique_id,this._timenav.goToId(this.current_id),this._onChange(t))},_onTimeNavChange:function(t){this.current_id!=t.unique_id&&(this.current_id=t.unique_id,this._storyslider.goToId(this.current_id),this._onChange(t))},_onChange:function(t){this.fire("change",{unique_id:this.current_id},this),this.options.hash_bookmark&&this.current_id&&this._updateHashBookmark(this.current_id)},_onBackToStart:function(t){this._storyslider.goTo(0),this.fire("back_to_start",{unique_id:this.current_id},this)},
/**
* Zoom in and zoom out should be part of the public API.
*/
zoomIn:function(){this._timenav.zoomIn()},zoomOut:function(){this._timenav.zoomOut()},setZoom:function(t){this._timenav.setZoom(t)},_onZoomIn:function(t){this._timenav.zoomIn(),this.fire("zoom_in",{zoom_level:this._timenav.options.scale_factor},this)},_onZoomOut:function(t){this._timenav.zoomOut(),this.fire("zoom_out",{zoom_level:this._timenav.options.scale_factor},this)},_onTimeNavLoaded:function(){this._loaded.timenav=!0,this._onLoaded()},_onStorySliderLoaded:function(){this._loaded.storyslider=!0,this._onLoaded()},_onStorySliderNext:function(t){this.fire("nav_next",t)},_onStorySliderPrevious:function(t){this.fire("nav_previous",t)},_onLoaded:function(){this._loaded.storyslider&&this._loaded.timenav&&(this.fire("loaded",this.config),
// Go to proper slide
this.options.hash_bookmark&&""!=window.location.hash?this.goToId(window.location.hash.replace("#","")):(TL.Util.isTrue(this.options.start_at_end)||this.options.start_at_slide>this.config.events.length?this.goToEnd():this.goTo(this.options.start_at_slide),this.options.hash_bookmark&&this._updateHashBookmark(this.current_id)))}}),TL.Timeline.source_path=function(){var t=document.getElementsByTagName("script"),e=t[t.length-1].src;return e.substr(0,e.lastIndexOf("/"))}();