src/pyams_media/skin/resources/flowplayer/flowplayer.js
changeset 0 fd39db613f8b
child 30 a84ca4335d44
equal deleted inserted replaced
-1:000000000000 0:fd39db613f8b
       
     1 /*!
       
     2 
       
     3    Flowplayer v6.0.3 (Thursday, 23. July 2015 09:32PM) | flowplayer.org/license
       
     4 
       
     5 */
       
     6 /*! (C) WebReflection Mit Style License */
       
     7 (function(e){function m(e,t,n,r){for(var i,s=n.slice(),o=b(t,e),u=0,a=s.length;u<a;u++){handler=s[u],typeof handler=="object"&&typeof handler.handleEvent=="function"?handler.handleEvent(o):handler.call(e,o);if(o.stoppedImmediatePropagation)break}return i=!o.stoppedPropagation,r&&i&&e.parentNode?e.parentNode.dispatchEvent(o):!o.defaultPrevented}function g(e,t){return{configurable:!0,get:e,set:t}}function y(e,t,n){var r=a(t||e,n);o(e,"textContent",g(function(){return r.get.call(this)},function(e){r.set.call(this,e)}))}function b(e,t){return e.currentTarget=t,e.eventPhase=e.target===e.currentTarget?2:3,e}function w(e,t){var n=e.length;while(n--&&e[n]!==t);return n}function E(){if(this.tagName==="BR")return"\n";var e=this.firstChild,t=[];while(e)e.nodeType!==8&&e.nodeType!==7&&t.push(e.textContent),e=e.nextSibling;return t.join("")}function S(e){return e.nodeType!==9&&document.documentElement.contains(e)}function x(e){var t=document.createEvent("Event");t.initEvent("input",!0,!0),(e.srcElement||e.fromElement||document).dispatchEvent(t)}function T(e){!n&&p.test(document.readyState)&&(n=!n,document.detachEvent(r,T),e=document.createEvent("Event"),e.initEvent(i,!0,!0),document.dispatchEvent(e))}function N(e){var t;while(t=this.lastChild)this.removeChild(t);e!=null&&this.appendChild(document.createTextNode(e))}function C(t,n){return n||(n=e.event),n.target||(n.target=n.srcElement||n.fromElement||document),n.timeStamp||(n.timeStamp=(new Date).getTime()),n}if(document.createEvent)return;var t=!0,n=!1,r="onreadystatechange",i="DOMContentLoaded",s="__IE8__"+Math.random(),o=Object.defineProperty||function(e,t,n){e[t]=n.value},u=Object.defineProperties||function(t,n){for(var r in n)if(f.call(n,r))try{o(t,r,n[r])}catch(i){e.console&&console.log(r+" failed on object:",t,i.message)}},a=Object.getOwnPropertyDescriptor,f=Object.prototype.hasOwnProperty,l=e.Element.prototype,c=e.Text.prototype,h=/^[a-z]+$/,p=/loaded|complete/,d={},v=document.createElement("div");y(e.HTMLCommentElement.prototype,l,"nodeValue"),y(e.HTMLScriptElement.prototype,null,"text"),y(c,null,"nodeValue"),y(e.HTMLTitleElement.prototype,null,"text"),o(e.HTMLStyleElement.prototype,"textContent",function(e){return g(function(){return e.get.call(this.styleSheet)},function(t){e.set.call(this.styleSheet,t)})}(a(e.CSSStyleSheet.prototype,"cssText"))),u(l,{textContent:{get:E,set:N},firstElementChild:{get:function(){for(var e=this.childNodes||[],t=0,n=e.length;t<n;t++)if(e[t].nodeType==1)return e[t]}},lastElementChild:{get:function(){for(var e=this.childNodes||[],t=e.length;t--;)if(e[t].nodeType==1)return e[t]}},oninput:{get:function(){return this._oninput||null},set:function(e){this._oninput&&(this.removeEventListener("input",this._oninput),this._oninput=e,e&&this.addEventListener("input",e))}},previousElementSibling:{get:function(){var e=this.previousSibling;while(e&&e.nodeType!=1)e=e.previousSibling;return e}},nextElementSibling:{get:function(){var e=this.nextSibling;while(e&&e.nodeType!=1)e=e.nextSibling;return e}},childElementCount:{get:function(){for(var e=0,t=this.childNodes||[],n=t.length;n--;e+=t[n].nodeType==1);return e}},addEventListener:{value:function(e,t,n){var r=this,i="on"+e,u=r[s]||o(r,s,{value:{}})[s],a=u[i]||(u[i]={}),l=a.h||(a.h=[]),c;if(!f.call(a,"w")){a.w=function(e){return e[s]||m(r,C(r,e),l,!1)};if(!f.call(d,i))if(h.test(e))try{c=document.createEventObject(),c[s]=!0,r.nodeType!=9&&r.parentNode==null&&v.appendChild(r),r.fireEvent(i,c),d[i]=!0}catch(c){d[i]=!1;while(v.hasChildNodes())v.removeChild(v.firstChild)}else d[i]=!1;(a.n=d[i])&&r.attachEvent(i,a.w)}w(l,t)<0&&l[n?"unshift":"push"](t),e==="input"&&r.attachEvent("onkeyup",x)}},dispatchEvent:{value:function(e){var t=this,n="on"+e.type,r=t[s],i=r&&r[n],o=!!i,u;return e.target||(e.target=t),o?i.n?t.fireEvent(n,e):m(t,e,i.h,!0):(u=t.parentNode)?u.dispatchEvent(e):!0,!e.defaultPrevented}},removeEventListener:{value:function(e,t,n){var r=this,i="on"+e,o=r[s],u=o&&o[i],a=u&&u.h,f=a?w(a,t):-1;-1<f&&a.splice(f,1)}}}),u(c,{addEventListener:{value:l.addEventListener},dispatchEvent:{value:l.dispatchEvent},removeEventListener:{value:l.removeEventListener}}),u(e.XMLHttpRequest.prototype,{addEventListener:{value:function(e,t,n){var r=this,i="on"+e,u=r[s]||o(r,s,{value:{}})[s],a=u[i]||(u[i]={}),f=a.h||(a.h=[]);w(f,t)<0&&(r[i]||(r[i]=function(){var t=document.createEvent("Event");t.initEvent(e,!0,!0),r.dispatchEvent(t)}),f[n?"unshift":"push"](t))}},dispatchEvent:{value:function(e){var t=this,n="on"+e.type,r=t[s],i=r&&r[n],o=!!i;return o&&(i.n?t.fireEvent(n,e):m(t,e,i.h,!0))}},removeEventListener:{value:l.removeEventListener}}),u(e.Event.prototype,{bubbles:{value:!0,writable:!0},cancelable:{value:!0,writable:!0},preventDefault:{value:function(){this.cancelable&&(this.defaultPrevented=!0,this.returnValue=!1)}},stopPropagation:{value:function(){this.stoppedPropagation=!0,this.cancelBubble=!0}},stopImmediatePropagation:{value:function(){this.stoppedImmediatePropagation=!0,this.stopPropagation()}},initEvent:{value:function(e,t,n){this.type=e,this.bubbles=!!t,this.cancelable=!!n,this.bubbles||this.stopPropagation()}}}),u(e.HTMLDocument.prototype,{defaultView:{get:function(){return this.parentWindow}},textContent:{get:function(){return this.nodeType===11?E.call(this):null},set:function(e){this.nodeType===11&&N.call(this,e)}},addEventListener:{value:function(n,s,o){var u=this;l.addEventListener.call(u,n,s,o),t&&n===i&&!p.test(u.readyState)&&(t=!1,u.attachEvent(r,T),e==top&&function a(e){try{u.documentElement.doScroll("left"),T()}catch(t){setTimeout(a,50)}}())}},dispatchEvent:{value:l.dispatchEvent},removeEventListener:{value:l.removeEventListener},createEvent:{value:function(e){var t;if(e!=="Event")throw new Error("unsupported "+e);return t=document.createEventObject(),t.timeStamp=(new Date).getTime(),t}}}),u(e.Window.prototype,{getComputedStyle:{value:function(){function i(e){this._=e}function s(){}var e=/^(?:[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/,t=/^(top|right|bottom|left)$/,n=/\-([a-z])/g,r=function(e,t){return t.toUpperCase()};return i.prototype.getPropertyValue=function(i){var s=this._,o=s.style,u=s.currentStyle,a=s.runtimeStyle,f,l,c;return i=(i==="float"?"style-float":i).replace(n,r),f=u?u[i]:o[i],e.test(f)&&!t.test(i)&&(l=o.left,c=a&&a.left,c&&(a.left=u.left),o.left=i==="fontSize"?"1em":f,f=o.pixelLeft+"px",o.left=l,c&&(a.left=c)),f==null?f:f+""||"auto"},s.prototype.getPropertyValue=function(){return null},function(e,t){return t?new s(e):new i(e)}}()},addEventListener:{value:function(t,n,r){var i=e,o="on"+t,u;i[o]||(i[o]=function(e){return m(i,C(i,e),u,!1)}),u=i[o][s]||(i[o][s]=[]),w(u,n)<0&&u[r?"unshift":"push"](n)}},dispatchEvent:{value:function(t){var n=e["on"+t.type];return n?n.call(e,t)!==!1&&!t.defaultPrevented:!0}},removeEventListener:{value:function(t,n,r){var i="on"+t,o=(e[i]||Object)[s],u=o?w(o,n):-1;-1<u&&o.splice(u,1)}}})})(this);
       
     8 !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.flowplayer=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
       
     9 'use strict';
       
    10 var common = module.exports = {},
       
    11     ClassList = _dereq_('class-list'),
       
    12     $ = window.jQuery,
       
    13     punycode = _dereq_('punycode'),
       
    14     computedStyle = _dereq_('computed-style');
       
    15 
       
    16 common.noop = function() {};
       
    17 common.identity = function(i) { return i; };
       
    18 
       
    19 common.removeNode = function(el) {
       
    20   if (!el || !el.parentNode) return;
       
    21   el.parentNode.removeChild(el);
       
    22 };
       
    23 
       
    24 common.find = function(query, ctx) {
       
    25   if ($) return $(query, ctx).toArray();
       
    26   ctx = ctx || document;
       
    27   return Array.prototype.map.call(ctx.querySelectorAll(query), function(el) { return el; });
       
    28 };
       
    29 
       
    30 common.text = function(el, txt) {
       
    31   el[('innerText' in el) ? 'innerText' : 'textContent'] = txt;
       
    32 };
       
    33 
       
    34 common.findDirect = function(query, ctx) {
       
    35   return common.find(query, ctx).filter(function(node) {
       
    36     return node.parentNode === ctx;
       
    37   });
       
    38 };
       
    39 
       
    40 common.hasClass = function(el, kls) {
       
    41   return ClassList(el).contains(kls);
       
    42 };
       
    43 
       
    44 
       
    45 common.css = function(el, property, value) {
       
    46   if (typeof property === 'object') {
       
    47     return Object.keys(property).forEach(function(key) {
       
    48       common.css(el, key, property[key]);
       
    49     });
       
    50   }
       
    51   if (typeof value !== 'undefined') {
       
    52     if (value === '') return el ? el.style.removeProperty(property)  : undefined;
       
    53     return el ? el.style.setProperty(property, value) : undefined;
       
    54   }
       
    55   return el ? computedStyle(el, property) : undefined;
       
    56 };
       
    57 
       
    58 common.createElement = function(tag, attributes, innerHTML) {
       
    59   try {
       
    60     var el = document.createElement(tag);
       
    61     for (var key in attributes) {
       
    62       if (!attributes.hasOwnProperty(key)) continue;
       
    63       if (key === 'css') {
       
    64         common.css(el, attributes[key]);
       
    65       } else {
       
    66         common.attr(el, key, attributes[key]);
       
    67       }
       
    68     }
       
    69     el.innerHTML = innerHTML || '';
       
    70     return el;
       
    71   } catch (e) {
       
    72     if (!$) throw e;
       
    73     return $('<' + tag + '>' + innerHTML + '</' + tag + '>').attr(attributes)[0];
       
    74   }
       
    75 };
       
    76 
       
    77 common.toggleClass = function(el, cls, flag) {
       
    78   if (!el) return;
       
    79   var classes = ClassList(el);
       
    80   if (typeof flag === 'undefined') classes.toggle(cls);
       
    81   else if (flag) classes.add(cls);
       
    82   else if (!flag) classes.remove(cls);
       
    83 };
       
    84 
       
    85 common.addClass = function(el, cls) {
       
    86   return common.toggleClass(el, cls, true);
       
    87 };
       
    88 
       
    89 common.removeClass = function(el, cls) {
       
    90   return common.toggleClass(el, cls, false);
       
    91 };
       
    92 
       
    93 common.append = function(par, child) {
       
    94   par.appendChild(child);
       
    95   return par;
       
    96 };
       
    97 
       
    98 common.appendTo = function(child, par) {
       
    99   common.append(par, child);
       
   100   return child;
       
   101 };
       
   102 
       
   103 common.prepend = function(par, child) {
       
   104   par.insertBefore(child, par.firstChild);
       
   105 };
       
   106 
       
   107 
       
   108 // Inserts `el` after `child` that is child of `par`
       
   109 common.insertAfter = function(par, child, el) {
       
   110   if (child == common.lastChild(par)) par.appendChild(el);
       
   111   var childIndex = Array.prototype.indexOf.call(par.children, child);
       
   112   par.insertBefore(el, par.children[childIndex + 1]);
       
   113 };
       
   114 
       
   115 common.html = function(elms, val) {
       
   116   elms = elms.length ? elms : [elms];
       
   117   elms.forEach(function(elm) {
       
   118     elm.innerHTML = val;
       
   119   });
       
   120 };
       
   121 
       
   122 
       
   123 common.attr = function(el, key, val) {
       
   124   if (key === 'class') key = 'className';
       
   125   if (common.hasOwnOrPrototypeProperty(el, key)) {
       
   126     try {
       
   127       el[key] = val;
       
   128     } catch (e) { // Most likely IE not letting set property
       
   129       if ($) {
       
   130         $(el).attr(key, val);
       
   131       } else {
       
   132         throw e;
       
   133       }
       
   134     }
       
   135   } else {
       
   136     if (val === false) {
       
   137       el.removeAttribute(key);
       
   138     } else {
       
   139       el.setAttribute(key, val);
       
   140     }
       
   141   }
       
   142   return el;
       
   143 };
       
   144 
       
   145 common.prop = function(el, key, val) {
       
   146   if (typeof val === 'undefined') {
       
   147     return el && el[key];
       
   148   }
       
   149   el[key] = val;
       
   150 };
       
   151 
       
   152 common.offset = function(el) {
       
   153   var ret = el.getBoundingClientRect();
       
   154   if (el.offsetWidth / el.offsetHeight > el.clientWidth / el.clientHeight) { // https://github.com/flowplayer/flowplayer/issues/757
       
   155     ret = {
       
   156       left: ret.left * 100,
       
   157       right: ret.right * 100,
       
   158       top: ret.top * 100,
       
   159       bottom: ret.bottom * 100,
       
   160       width: ret.width * 100,
       
   161       height: ret.height * 100
       
   162     };
       
   163   }
       
   164   return ret;
       
   165 };
       
   166 
       
   167 common.width = function(el, val) {
       
   168   /*jshint -W093 */
       
   169   if (val) return el.style.width = (''+val).replace(/px$/, '') + 'px';
       
   170   var ret = common.offset(el).width;
       
   171   return typeof ret === 'undefined' ? el.offsetWidth : ret;
       
   172 };
       
   173 
       
   174 common.height = function(el, val) {
       
   175   /*jshint -W093 */
       
   176   if (val) return el.style.height = (''+val).replace(/px$/, '') + 'px';
       
   177   var ret = common.offset(el).height;
       
   178   return typeof ret === 'undefined' ? el.offsetHeight : ret;
       
   179 };
       
   180 
       
   181 common.lastChild = function(el) {
       
   182   return el.children[el.children.length - 1];
       
   183 };
       
   184 
       
   185 common.hasParent = function(el, parentSelector) {
       
   186   var parent = el.parentElement;
       
   187   while (parent) {
       
   188     if (common.matches(parent, parentSelector)) return true;
       
   189     parent = parent.parentElement;
       
   190   }
       
   191   return false;
       
   192 };
       
   193 
       
   194 common.createAbsoluteUrl = function(url) {
       
   195   return common.createElement('a', {href: url}).href; // This won't work on IE7
       
   196 };
       
   197 
       
   198 common.xhrGet = function(url, successCb, errorCb) {
       
   199   var xhr = new XMLHttpRequest();
       
   200   xhr.onreadystatechange = function() {
       
   201     if (this.readyState !== 4) return;
       
   202     if (this.status >= 400) return errorCb();
       
   203     successCb(this.responseText);
       
   204   };
       
   205   xhr.open('get', url, true);
       
   206   xhr.send();
       
   207 };
       
   208 
       
   209 common.pick = function(obj, props) {
       
   210   var ret = {};
       
   211   props.forEach(function(prop) {
       
   212     if (obj.hasOwnProperty(prop)) ret[prop] = obj[prop];
       
   213   });
       
   214   return ret;
       
   215 };
       
   216 
       
   217 common.hostname = function(host) {
       
   218   return punycode.toUnicode(host || window.location.hostname);
       
   219 };
       
   220 
       
   221 //Hacks
       
   222 common.browser = {
       
   223   webkit: 'WebkitAppearance' in document.documentElement.style
       
   224 };
       
   225 
       
   226 common.getPrototype = function(el) {
       
   227   /* jshint proto:true */
       
   228   if (!Object.getPrototypeOf) return el.__proto__;
       
   229   return Object.getPrototypeOf(el);
       
   230 };
       
   231 
       
   232 common.hasOwnOrPrototypeProperty = function(obj, prop) {
       
   233   var o = obj;
       
   234   while (o) {
       
   235     if (Object.prototype.hasOwnProperty.call(o, prop)) return true;
       
   236     o = common.getPrototype(o);
       
   237   }
       
   238   return false;
       
   239 };
       
   240 
       
   241 
       
   242 // Polyfill for Element.matches
       
   243 // adapted from https://developer.mozilla.org/en/docs/Web/API/Element/matches
       
   244 common.matches = function(elem, selector) {
       
   245   var proto = Element.prototype,
       
   246       fn = proto.matches ||
       
   247           proto.matchesSelector ||
       
   248           proto.mozMatchesSelector ||
       
   249           proto.msMatchesSelector ||
       
   250           proto.oMatchesSelector ||
       
   251           proto.webkitMatchesSelector ||
       
   252           function (selector) {
       
   253             var element = this,
       
   254                 matches = (element.document || element.ownerDocument).querySelectorAll(selector),
       
   255                 i = 0;
       
   256             while (matches[i] && matches[i] !== element) {
       
   257               i++;
       
   258             }
       
   259 
       
   260             return matches[i] ? true : false;
       
   261       };
       
   262   return fn.call(elem, selector);
       
   263 };
       
   264 
       
   265 
       
   266 // Polyfill for CSSStyleDeclaration
       
   267 // from https://github.com/shawnbot/aight
       
   268 (function(CSSSDProto) {
       
   269 
       
   270   function getAttribute(property) {
       
   271     return property.replace(/-[a-z]/g, function(bit) {
       
   272       return bit[1].toUpperCase();
       
   273     });
       
   274   }
       
   275 
       
   276   // patch CSSStyleDeclaration.prototype using IE8's methods
       
   277   if (typeof CSSSDProto.setAttribute !== "undefined") {
       
   278     CSSSDProto.setProperty = function(property, value) {
       
   279       return this.setAttribute(getAttribute(property), String(value) /*, important */ );
       
   280     };
       
   281     CSSSDProto.getPropertyValue = function(property) {
       
   282       return this.getAttribute(getAttribute(property)) || null;
       
   283     };
       
   284     CSSSDProto.removeProperty = function(property) {
       
   285       var value = this.getPropertyValue(property);
       
   286       this.removeAttribute(getAttribute(property));
       
   287       return value;
       
   288     };
       
   289   }
       
   290 
       
   291 })(window.CSSStyleDeclaration.prototype);
       
   292 
       
   293 },{"class-list":22,"computed-style":24,"punycode":21}],2:[function(_dereq_,module,exports){
       
   294 /* global __flash_unloadHandler:true,__flash_savedUnloadHandler:true */
       
   295 'use strict';
       
   296 var common = _dereq_('../common');
       
   297 
       
   298 // movie required in opts
       
   299 module.exports = function embed(swf, flashvars, wmode, bgColor) {
       
   300    wmode = wmode || "opaque";
       
   301 
       
   302    var id = "obj" + ("" + Math.random()).slice(2, 15),
       
   303        tag = '<object class="fp-engine" id="' + id+ '" name="' + id + '" ',
       
   304        msie = navigator.userAgent.indexOf('MSIE') > -1;
       
   305 
       
   306    tag += msie ? 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">' :
       
   307       ' data="' + swf  + '" type="application/x-shockwave-flash">';
       
   308 
       
   309    var opts = {
       
   310       width: "100%",
       
   311       height: "100%",
       
   312       allowscriptaccess: "always",
       
   313       wmode: wmode,
       
   314       quality: "high",
       
   315       flashvars: "",
       
   316 
       
   317       // https://github.com/flowplayer/flowplayer/issues/13#issuecomment-9369919
       
   318       movie: swf + (msie ? "?" + id : ""),
       
   319       name: id
       
   320    };
       
   321 
       
   322    if (wmode !== 'transparent') opts.bgcolor = bgColor || '#333333';
       
   323 
       
   324    // flashvars
       
   325    Object.keys(flashvars).forEach(function(key) {
       
   326       opts.flashvars += key + "=" + flashvars[key] + "&";
       
   327    });
       
   328 
       
   329    // parameters
       
   330    Object.keys(opts).forEach(function(key) {
       
   331       tag += '<param name="' + key + '" value="'+ opts[key] +'"/>';
       
   332    });
       
   333 
       
   334    tag += "</object>";
       
   335    var el = common.createElement('div', {}, tag);
       
   336    return common.find('object', el);
       
   337 
       
   338 };
       
   339 
       
   340 
       
   341 // Flash is buggy allover
       
   342 if (window.attachEvent) {
       
   343    window.attachEvent("onbeforeunload", function() {
       
   344       __flash_savedUnloadHandler = __flash_unloadHandler = function() {};
       
   345    });
       
   346 }
       
   347 
       
   348 
       
   349 },{"../common":1}],3:[function(_dereq_,module,exports){
       
   350 'use strict';
       
   351 var flowplayer = _dereq_('../flowplayer'),
       
   352     common = _dereq_('../common'),
       
   353     embed = _dereq_('./embed'),
       
   354     extend = _dereq_('extend-object'),
       
   355     bean = _dereq_('bean'),
       
   356     engineImpl;
       
   357 
       
   358 engineImpl = function flashEngine(player, root) {
       
   359 
       
   360    var conf = player.conf,
       
   361       video = player.video,
       
   362       loadVideo,
       
   363       callbackId,
       
   364       objectTag,
       
   365       api;
       
   366 
       
   367    var win = window;
       
   368 
       
   369    var engine = {
       
   370       engineName: engineImpl.engineName,
       
   371 
       
   372       pick: function(sources) {
       
   373 
       
   374          if (flowplayer.support.flashVideo) {
       
   375             var selectedSource;
       
   376             for (var i = 0, source; i < sources.length; i++) {
       
   377                source = sources[i];
       
   378                if (/mp4|flv|flash/i.test(source.type)) selectedSource = source;
       
   379                if (player.conf.swfHls && /mpegurl/i.test(source.type)) selectedSource = source;
       
   380                if (selectedSource && !/mp4/i.test(selectedSource.type)) return selectedSource;
       
   381                // Did not find any source or source was video/mp4, let's try find more
       
   382             }
       
   383             return selectedSource; // Accept the fact we don't have anything or just an MP4
       
   384          }
       
   385       },
       
   386 
       
   387       load: function(video) {
       
   388          loadVideo = video;
       
   389 
       
   390          function escapeURL(url) {
       
   391             return url.replace(/&amp;/g, '%26').replace(/&/g, '%26').replace(/=/g, '%3D');
       
   392          }
       
   393 
       
   394          var html5Tag = common.findDirect('video', root)[0] || common.find('.fp-player > video', root)[0],
       
   395             url = escapeURL(video.src),
       
   396             is_absolute = /^https?:/.test(url);
       
   397 
       
   398          var removeTag = function() {
       
   399             common.removeNode(html5Tag);
       
   400          };
       
   401          var hasSupportedSource = function(sources) {
       
   402             return sources.some(function(src) {
       
   403                return !!html5Tag.canPlayType(src.type);
       
   404             });
       
   405          };
       
   406          if (flowplayer.support.video &&
       
   407             common.prop(html5Tag, 'autoplay') &&
       
   408             hasSupportedSource(video.sources)) bean.one(html5Tag, 'timeupdate', removeTag);
       
   409          else removeTag();
       
   410 
       
   411          // convert to absolute
       
   412          var rtmp = video.rtmp || conf.rtmp;
       
   413          if (!is_absolute && !rtmp) url = common.createAbsoluteUrl(url);
       
   414 
       
   415          if (api && isHLS(video) && api.data !== conf.swfHls) engine.unload();
       
   416 
       
   417          if (api) {
       
   418             ['live', 'preload', 'loop'].forEach(function(prop) {
       
   419               if (!video.hasOwnProperty(prop)) return;
       
   420               api.__set(prop, video[prop]);
       
   421             });
       
   422             Object.keys(video.flashls || {}).forEach(function(key) {
       
   423               api.__set('hls_' + key, video.flashls[key]);
       
   424             });
       
   425             var providerChangeNeeded = false;
       
   426             if (!is_absolute && rtmp) api.__set('rtmp', rtmp.url || rtmp);
       
   427             else {
       
   428               var oldRtmp = api.__get('rtmp');
       
   429               providerChangeNeeded = !!oldRtmp;
       
   430               api.__set('rtmp', null);
       
   431             }
       
   432             api.__play(url, providerChangeNeeded || video.rtmp && video.rtmp !== conf.rtmp);
       
   433 
       
   434          } else {
       
   435 
       
   436             callbackId = "fpCallback" + ("" + Math.random()).slice(3, 15);
       
   437 
       
   438             var opts = {
       
   439                hostname: conf.embedded ? common.hostname(conf.hostname) : common.hostname(location.hostname),
       
   440                url: url,
       
   441                callback: callbackId
       
   442             };
       
   443             if (root.getAttribute('data-origin')) {
       
   444                opts.origin = root.getAttribute('data-origin');
       
   445             }
       
   446 
       
   447             // optional conf
       
   448             ['proxy', 'key', 'autoplay', 'preload', 'subscribe', 'live', 'loop', 'debug', 'splash', 'poster', 'rtmpt'].forEach(function(key) {
       
   449               if (conf.hasOwnProperty(key)) opts[key] = conf[key];
       
   450               if (video.hasOwnProperty(key)) opts[key] = video[key];
       
   451               if ((conf.rtmp || {}).hasOwnProperty(key)) opts[key] = (conf.rtmp || {})[key];
       
   452               if ((video.rtmp || {}).hasOwnProperty(key)) opts[key] = (video.rtmp || {})[key];
       
   453             });
       
   454             if (conf.rtmp) opts.rtmp = conf.rtmp.url || conf.rtmp;
       
   455             if (video.rtmp) opts.rtmp = video.rtmp.url || video.rtmp;
       
   456             Object.keys(video.flashls || {}).forEach(function(key) {
       
   457               var val = video.flashls[key];
       
   458               opts['hls_' + key] = val;
       
   459             });
       
   460             // bufferTime might be 0
       
   461             if (conf.bufferTime !== undefined) opts.bufferTime = conf.bufferTime;
       
   462 
       
   463             if (is_absolute) delete opts.rtmp;
       
   464 
       
   465             // issues #376
       
   466             if (opts.rtmp) {
       
   467                opts.rtmp = escapeURL(opts.rtmp);
       
   468             }
       
   469 
       
   470             // issue #733
       
   471             var bgColor = common.css(root, 'background-color') ||'', bg;
       
   472             if (bgColor.indexOf('rgb') === 0) {
       
   473               bg = toHex(bgColor);
       
   474             } else if (bgColor.indexOf('#') === 0) {
       
   475               bg = toLongHex(bgColor);
       
   476             }
       
   477 
       
   478             // issues #387
       
   479             opts.initialVolume = player.volumeLevel;
       
   480 
       
   481             var swfUrl = isHLS(video) ? conf.swfHls : conf.swf;
       
   482 
       
   483             api = embed(swfUrl, opts, conf.wmode, bg)[0];
       
   484 
       
   485             var container = common.find('.fp-player', root)[0];
       
   486 
       
   487             common.prepend(container, api);
       
   488 
       
   489             // throw error if no loading occurs
       
   490             setTimeout(function() {
       
   491                try {
       
   492                   if (!api.PercentLoaded()) {
       
   493                      return player.trigger("error", [player, { code: 7, url: conf.swf }]);
       
   494                   }
       
   495                } catch (e) {}
       
   496             }, 5000);
       
   497 
       
   498             // detect disabled flash
       
   499             setTimeout(function() {
       
   500               if (typeof api.PercentLoaded === 'undefined') {
       
   501                 player.trigger('flashdisabled', [player]);
       
   502               }
       
   503             }, 1000);
       
   504 
       
   505             api.pollInterval = setInterval(function () {
       
   506                if (!api) return;
       
   507                var status = api.__status ? api.__status() : null;
       
   508 
       
   509                if (!status) return;
       
   510 
       
   511                if (player.playing && status.time && status.time !== player.video.time) player.trigger("progress", [player, status.time]);
       
   512 
       
   513                video.buffer = status.buffer / video.bytes * video.duration;
       
   514                player.trigger("buffer", [player, video.buffer]);
       
   515                if (!video.buffered && status.time > 0) {
       
   516                   video.buffered = true;
       
   517                   player.trigger("buffered", [player]);
       
   518                }
       
   519 
       
   520             }, 250);
       
   521 
       
   522             // listen
       
   523             window[callbackId] = function(type, arg) {
       
   524                var video = loadVideo;
       
   525 
       
   526                if (conf.debug) {
       
   527                  if (type.indexOf('debug') === 0 && arg && arg.length) {
       
   528                    console.log.apply(console, ['-- ' + type].concat(arg));
       
   529                  }
       
   530                  else console.log("--", type, arg);
       
   531                }
       
   532 
       
   533                var event = {
       
   534                  type: type
       
   535                };
       
   536 
       
   537                switch (type) {
       
   538 
       
   539                   // RTMP sends a lot of finish events in vain
       
   540                   // case "finish": if (conf.rtmp) return;
       
   541                   case "ready": arg = extend(video, arg); break;
       
   542                   case "click": event.flash = true; break;
       
   543                   case "keydown": event.which = arg; break;
       
   544                   case "seek": video.time = arg; break;
       
   545                   case "status":
       
   546                      player.trigger("progress", [player, arg.time]);
       
   547 
       
   548                      if (arg.buffer < video.bytes && !video.buffered) {
       
   549                         video.buffer = arg.buffer / video.bytes * video.duration;
       
   550                         player.trigger("buffer", video.buffer);
       
   551                      } else if (!video.buffered) {
       
   552                         video.buffered = true;
       
   553                         player.trigger("buffered");
       
   554                      }
       
   555 
       
   556                      break;
       
   557                }
       
   558                if (type === 'click' || type === 'keydown') {
       
   559                  event.target = root;
       
   560                  bean.fire(root, type, [event]);
       
   561                }
       
   562                else if (type != 'buffered' && type !== 'unload') {
       
   563                   // add some delay so that player is truly ready after an event
       
   564                   setTimeout(function() { player.trigger(event, [player, arg]); }, 1);
       
   565                } else if (type === 'unload') {
       
   566                  player.trigger(event, [player, arg]);
       
   567                }
       
   568 
       
   569             };
       
   570 
       
   571          }
       
   572 
       
   573       },
       
   574 
       
   575       // not supported yet
       
   576       speed: common.noop,
       
   577 
       
   578 
       
   579       unload: function() {
       
   580          if (api && api.__unload) api.__unload();
       
   581          try {
       
   582            if (callbackId && window[callbackId])delete window[callbackId];
       
   583          } catch (e) {}
       
   584          common.find("object", root).forEach(common.removeNode);
       
   585          api = 0;
       
   586          player.off('.flashengine');
       
   587          clearInterval(api.pollInterval);
       
   588       }
       
   589 
       
   590    };
       
   591 
       
   592    ['pause','resume','seek','volume'].forEach(function(name) {
       
   593 
       
   594       engine[name] = function(arg) {
       
   595          try {
       
   596            if (player.ready) {
       
   597 
       
   598               if (name == 'seek' && player.video.time && !player.paused) {
       
   599                  player.trigger("beforeseek");
       
   600               }
       
   601 
       
   602               if (arg === undefined) {
       
   603                  api["__" + name]();
       
   604 
       
   605               } else {
       
   606                  api["__" + name](arg);
       
   607               }
       
   608 
       
   609            }
       
   610          } catch (e) {
       
   611            if (typeof api["__" + name] === 'undefined') { //flash lost it's methods
       
   612              return player.trigger('flashdisabled', [player]);
       
   613            }
       
   614            throw e;
       
   615          }
       
   616       };
       
   617 
       
   618    });
       
   619 
       
   620    function toHex(bg) {
       
   621      function hex(x) {
       
   622        return ("0" + parseInt(x).toString(16)).slice(-2);
       
   623      }
       
   624 
       
   625      bg = bg.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
       
   626      if (!bg) return;
       
   627 
       
   628      return '#' + hex(bg[1]) + hex(bg[2]) + hex(bg[3]);
       
   629    }
       
   630 
       
   631    function toLongHex(bg) {
       
   632      if (bg.length === 7) return bg;
       
   633      var a = bg.split('').slice(1);
       
   634      return '#' + a.map(function(i) {
       
   635        return i + i;
       
   636      }).join('');
       
   637    }
       
   638 
       
   639    function isHLS(video) {
       
   640      return /application\/x-mpegurl/i.test(video.type);
       
   641    }
       
   642 
       
   643    return engine;
       
   644 
       
   645 };
       
   646 
       
   647 
       
   648 engineImpl.engineName = 'flash';
       
   649 engineImpl.canPlay = function(type, conf) {
       
   650   return flowplayer.support.flashVideo && /video\/(mp4|flash|flv)/i.test(type) || flowplayer.support.flashVideo && conf.swfHls && /mpegurl/i.test(type);
       
   651 };
       
   652 flowplayer.engines.push(engineImpl);
       
   653 
       
   654 },{"../common":1,"../flowplayer":18,"./embed":2,"bean":20,"extend-object":26}],4:[function(_dereq_,module,exports){
       
   655 'use strict';
       
   656 var flowplayer = _dereq_('../flowplayer'),
       
   657     bean = _dereq_('bean'),
       
   658     ClassList = _dereq_('class-list'),
       
   659     extend = _dereq_('extend-object'),
       
   660     common = _dereq_('../common');
       
   661 var VIDEO = document.createElement('video');
       
   662 
       
   663 // HTML5 --> Flowplayer event
       
   664 var EVENTS = {
       
   665 
       
   666    // fired
       
   667    ended: 'finish',
       
   668    pause: 'pause',
       
   669    play: 'resume',
       
   670    progress: 'buffer',
       
   671    timeupdate: 'progress',
       
   672    volumechange: 'volume',
       
   673    ratechange: 'speed',
       
   674    //seeking: 'beforeseek',
       
   675    seeked: 'seek',
       
   676    // abort: 'resume',
       
   677 
       
   678    // not fired
       
   679    loadeddata: 'ready',
       
   680    // loadedmetadata: 0,
       
   681    // canplay: 0,
       
   682 
       
   683    // error events
       
   684    // load: 0,
       
   685    // emptied: 0,
       
   686    // empty: 0,
       
   687    error: 'error',
       
   688    dataunavailable: 'error',
       
   689    webkitendfullscreen: !flowplayer.support.inlineVideo && 'unload'
       
   690 
       
   691 };
       
   692 
       
   693 function round(val, per) {
       
   694    per = per || 100;
       
   695    return Math.round(val * per) / per;
       
   696 }
       
   697 
       
   698 function getType(type) {
       
   699    return /mpegurl/i.test(type) ? "application/x-mpegurl" : type;
       
   700 }
       
   701 
       
   702 function canPlay(type) {
       
   703    if (!/^(video|application)/i.test(type))
       
   704       type = getType(type);
       
   705    return !!VIDEO.canPlayType(type).replace("no", '');
       
   706 }
       
   707 
       
   708 function findFromSourcesByType(sources, type) {
       
   709    var arr = sources.filter(function(s) {
       
   710       return s.type === type;
       
   711    });
       
   712    return arr.length ? arr[0] : null;
       
   713 }
       
   714 
       
   715 var videoTagCache;
       
   716 var createVideoTag = function(video, autoplay, preload, useCache) {
       
   717   if (typeof autoplay === 'undefined') autoplay = true;
       
   718   if (typeof preload === 'undefined') preload = 'none';
       
   719   if (typeof useCache === 'undefined') useCache = true;
       
   720   if (useCache && videoTagCache) {
       
   721     videoTagCache.type = getType(video.type);
       
   722     videoTagCache.src = video.src;
       
   723     return videoTagCache;
       
   724   }
       
   725   var el  = document.createElement('video');
       
   726   el.src = video.src;
       
   727   el.type = getType(video.type);
       
   728   el.className = 'fp-engine';
       
   729   el.autoplay = autoplay ? 'autoplay' : false;
       
   730   el.preload = preload;
       
   731   el.setAttribute('x-webkit-airplay', 'allow');
       
   732   if (useCache) videoTagCache = el;
       
   733   return el;
       
   734 };
       
   735 
       
   736 var engine;
       
   737 
       
   738 engine = function(player, root) {
       
   739 
       
   740   var api = common.findDirect('video', root)[0] || common.find('.fp-player > video', root)[0],
       
   741       support = flowplayer.support,
       
   742       track = common.find("track", api)[0],
       
   743       conf = player.conf,
       
   744       self,
       
   745       timer,
       
   746       volumeLevel;
       
   747    /*jshint -W093 */
       
   748    return self = {
       
   749       engineName: engine.engineName,
       
   750 
       
   751       pick: function(sources) {
       
   752          if (support.video) {
       
   753             if (conf.videoTypePreference) {
       
   754                var mp4source = findFromSourcesByType(sources, conf.videoTypePreference);
       
   755                if (mp4source) return mp4source;
       
   756             }
       
   757 
       
   758             for (var i = 0, source; i < sources.length; i++) {
       
   759                if (canPlay(sources[i].type)) return sources[i];
       
   760             }
       
   761          }
       
   762       },
       
   763 
       
   764       load: function(video) {
       
   765          var created = false, container = common.find('.fp-player', root)[0], reload = false;
       
   766          if (conf.splash && !api) {
       
   767            api = createVideoTag(video);
       
   768            common.prepend(container, api);
       
   769            created = true;
       
   770          } else if (!api) {
       
   771            api = createVideoTag(video, !!video.autoplay || !!conf.autoplay, conf.clip.preload || 'metadata', false);
       
   772            common.prepend(container, api);
       
   773            created = true;
       
   774          } else {
       
   775            ClassList(api).add('fp-engine');
       
   776            common.find('source,track', api).forEach(common.removeNode);
       
   777            if (!player.conf.nativesubtitles) common.attr(api, 'crossorigin', false);
       
   778            reload = api.src === video.src;
       
   779          }
       
   780          if (!support.inlineVideo) {
       
   781            common.css(api, {
       
   782              position: 'absolute',
       
   783              top: '-9999em'
       
   784            });
       
   785          }
       
   786          //TODO subtitles support
       
   787 
       
   788          // IE does not fire delegated timeupdate events
       
   789          bean.off(api, 'timeupdate', common.noop);
       
   790          bean.on(api, 'timeupdate', common.noop);
       
   791 
       
   792          common.prop(api, 'loop', !!(video.loop || conf.loop));
       
   793 
       
   794          if (typeof volumeLevel !== 'undefined') {
       
   795            api.volume = volumeLevel;
       
   796          }
       
   797 
       
   798          if (player.video.src && video.src != player.video.src || video.index) common.attr(api, 'autoplay', 'autoplay');
       
   799          api.src = video.src;
       
   800          api.type = video.type;
       
   801 
       
   802          listen(api, common.find("source", api).concat(api), video);
       
   803 
       
   804          // iPad (+others?) demands load()
       
   805          if (conf.clip.preload != 'none' && video.type != "mpegurl" || !support.zeropreload || !support.dataload) api.load();
       
   806          if (created || reload) api.load();
       
   807          if (api.paused && (video.autoplay || conf.autoplay)) api.play();
       
   808       },
       
   809 
       
   810       pause: function() {
       
   811          api.pause();
       
   812       },
       
   813 
       
   814       resume: function() {
       
   815          api.play();
       
   816       },
       
   817 
       
   818       speed: function(val) {
       
   819          api.playbackRate = val;
       
   820       },
       
   821 
       
   822       seek: function(time) {
       
   823          try {
       
   824             var pausedState = player.paused;
       
   825             api.currentTime = time;
       
   826             if (pausedState) api.pause();
       
   827          } catch (ignored) {}
       
   828       },
       
   829 
       
   830       volume: function(level) {
       
   831          volumeLevel = level;
       
   832          if (api) {
       
   833             api.volume = level;
       
   834          }
       
   835       },
       
   836 
       
   837       unload: function() {
       
   838          common.find('video.fp-engine', root).forEach(common.removeNode);
       
   839          if (!support.cachedVideoTag) videoTagCache = null;
       
   840          timer = clearInterval(timer);
       
   841          api = 0;
       
   842       }
       
   843 
       
   844    };
       
   845 
       
   846    function listen(api, sources, video) {
       
   847       // listen only once
       
   848       var instanceId = root.getAttribute('data-flowplayer-instance-id');
       
   849 
       
   850       if (api.listeners && api.listeners.hasOwnProperty(instanceId)) {
       
   851         api.listeners[instanceId] = video;
       
   852         return;
       
   853       }
       
   854       (api.listeners || (api.listeners = {}))[instanceId] = video;
       
   855 
       
   856       bean.on(sources, 'error', function(e) {
       
   857          try {
       
   858             if (canPlay(e.target.getAttribute('type'))) {
       
   859                player.trigger("error", [player, { code: 4, video: extend(video, {src: api.src, url: api.src}) }]);
       
   860             }
       
   861          } catch (er) {
       
   862             // Most likely: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
       
   863          }
       
   864       });
       
   865 
       
   866       player.on('shutdown', function() {
       
   867         bean.off(sources);
       
   868       });
       
   869 
       
   870       Object.keys(EVENTS).forEach(function(type) {
       
   871         var flow = EVENTS[type];
       
   872         if (!flow) return;
       
   873         root.addEventListener(type, function(e) {
       
   874           video = api.listeners[instanceId];
       
   875           if (!e.target || !ClassList(e.target).contains('fp-engine')) return;
       
   876 
       
   877             if (conf.debug && !/progress/.test(flow)) console.log(type, "->", flow, e);
       
   878 
       
   879             // no events if player not ready
       
   880             if (!player.ready && !/ready|error/.test(flow) || !flow || !common.find('video', root).length) { return; }
       
   881 
       
   882             var arg, vtype;
       
   883 
       
   884             if (flow === 'unload') { //Call player unload
       
   885               player.unload();
       
   886               return;
       
   887             }
       
   888 
       
   889             var triggerEvent = function() {
       
   890               player.trigger(flow, [player, arg]);
       
   891             };
       
   892 
       
   893             switch (flow) {
       
   894 
       
   895                case "ready":
       
   896 
       
   897                   arg = extend(video, {
       
   898                      duration: api.duration,
       
   899                      width: api.videoWidth,
       
   900                      height: api.videoHeight,
       
   901                      url: api.currentSrc,
       
   902                      src: api.currentSrc
       
   903                   });
       
   904 
       
   905                   try {
       
   906                      arg.seekable = !conf.live && /mpegurl/i.test(video ? (video.type || '') : '') && api.duration || api.seekable && api.seekable.end(null);
       
   907 
       
   908                   } catch (ignored) {}
       
   909 
       
   910                   // buffer
       
   911                   timer = timer || setInterval(function() {
       
   912 
       
   913                      try {
       
   914                         arg.buffer = api.buffered.end(null);
       
   915 
       
   916                      } catch (ignored) {}
       
   917 
       
   918                      if (arg.buffer) {
       
   919                         if (round(arg.buffer, 1000) < round(arg.duration, 1000) && !arg.buffered) {
       
   920                            player.trigger("buffer", e);
       
   921 
       
   922                         } else if (!arg.buffered) {
       
   923                            arg.buffered = true;
       
   924                            player.trigger("buffer", e).trigger("buffered", e);
       
   925                            clearInterval(timer);
       
   926                            timer = 0;
       
   927                         }
       
   928                      }
       
   929 
       
   930                   }, 250);
       
   931 
       
   932                   if (!conf.live && !arg.duration && !support.hlsDuration && type === "loadeddata") {
       
   933                      var durationChanged = function() {
       
   934                         arg.duration = api.duration;
       
   935                         try {
       
   936                            arg.seekable = api.seekable && api.seekable.end(null);
       
   937 
       
   938                         } catch (ignored) {}
       
   939                         triggerEvent();
       
   940                         api.removeEventListener('durationchange', durationChanged);
       
   941                         ClassList(root).remove('is-live');
       
   942                      };
       
   943                      api.addEventListener('durationchange', durationChanged);
       
   944 
       
   945                      // Ugly hack to handle broken Android devices
       
   946                      var timeUpdated = function() {
       
   947                        if (!player.ready && !api.duration) { // No duration even though the video already plays
       
   948                          arg.duration = 0;
       
   949                          ClassList(root).add('is-live'); // Make UI believe it's live
       
   950                          triggerEvent();
       
   951                        }
       
   952                        api.removeEventListener('timeupdate', timeUpdated);
       
   953                      };
       
   954                      api.addEventListener('timeupdate', timeUpdated);
       
   955                      return;
       
   956                   }
       
   957 
       
   958                   break;
       
   959 
       
   960                case "progress": case "seek":
       
   961 
       
   962                   var dur = player.video.duration;
       
   963 
       
   964                   if (api.currentTime > 0 || player.live) {
       
   965                      arg = Math.max(api.currentTime, 0);
       
   966 
       
   967                   } else if (flow == 'progress') {
       
   968                      return;
       
   969                   }
       
   970                   break;
       
   971 
       
   972 
       
   973                case "speed":
       
   974                   arg = round(api.playbackRate);
       
   975                   break;
       
   976 
       
   977                case "volume":
       
   978                   arg = round(api.volume);
       
   979                   break;
       
   980 
       
   981                case "error":
       
   982                   try {
       
   983                      arg = (e.srcElement || e.originalTarget).error;
       
   984                      arg.video = extend(video, {src: api.src, url: api.src});
       
   985                   } catch (er) {
       
   986                      // Most likely https://bugzilla.mozilla.org/show_bug.cgi?id=208427
       
   987                      return;
       
   988                   }
       
   989             }
       
   990 
       
   991             triggerEvent();
       
   992 
       
   993 
       
   994          }, true);
       
   995 
       
   996       });
       
   997 
       
   998    }
       
   999 
       
  1000 };
       
  1001 
       
  1002 
       
  1003 engine.canPlay = function(type) {
       
  1004   return flowplayer.support.video && canPlay(type);
       
  1005 };
       
  1006 
       
  1007 engine.engineName = 'html5';
       
  1008 
       
  1009 flowplayer.engines.push(engine);
       
  1010 
       
  1011 },{"../common":1,"../flowplayer":18,"bean":20,"class-list":22,"extend-object":26}],5:[function(_dereq_,module,exports){
       
  1012 'use strict';
       
  1013 /* global _gat */
       
  1014 var flowplayer = _dereq_('../flowplayer'),
       
  1015     TYPE_RE = _dereq_('./resolve').TYPE_RE,
       
  1016     scriptjs = _dereq_('scriptjs'),
       
  1017     bean = _dereq_('bean');
       
  1018 flowplayer(function(player, root) {
       
  1019 
       
  1020    var id = player.conf.analytics, time = 0, last = 0, timer;
       
  1021 
       
  1022    if (id) {
       
  1023 
       
  1024       // load Analytics script if needed
       
  1025       if (typeof _gat == 'undefined') scriptjs("//google-analytics.com/ga.js");
       
  1026 
       
  1027       var getTracker = function() {
       
  1028         var tracker = _gat._getTracker(id);
       
  1029         tracker._setAllowLinker(true);
       
  1030         return tracker;
       
  1031       };
       
  1032 
       
  1033       var  track = function track(e, api, video) {
       
  1034 
       
  1035          video = video || player.video;
       
  1036 
       
  1037          if (time && typeof _gat != 'undefined') {
       
  1038             var tracker = getTracker();
       
  1039 
       
  1040 
       
  1041             // http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html
       
  1042             tracker._trackEvent(
       
  1043                "Video / Seconds played",
       
  1044                player.engine.engineName + "/" + video.type,
       
  1045                video.title || root.getAttribute("title") || video.src.split("/").slice(-1)[0].replace(TYPE_RE, ''),
       
  1046                Math.round(time / 1000)
       
  1047             );
       
  1048             time = 0;
       
  1049             if (timer) {
       
  1050               clearTimeout(timer);
       
  1051               timer = null;
       
  1052             }
       
  1053          }
       
  1054 
       
  1055       };
       
  1056 
       
  1057       player.bind("load unload", track).bind("progress", function() {
       
  1058 
       
  1059          if (!player.seeking) {
       
  1060             time += last ? (+new Date() - last) : 0;
       
  1061             last = +new Date();
       
  1062          }
       
  1063 
       
  1064          if (!timer) {
       
  1065            timer = setTimeout(function() {
       
  1066              timer = null;
       
  1067              var tracker = getTracker();
       
  1068              tracker._trackEvent('Flowplayer heartbeat', 'Heartbeat', '', 0, true);
       
  1069            }, 10*60*1000); // heartbeat every 10 minutes
       
  1070          }
       
  1071 
       
  1072       }).bind("pause", function() {
       
  1073          last = 0;
       
  1074       });
       
  1075 
       
  1076       player.bind('shutdown', function() {
       
  1077         bean.off(window, 'unload', track);
       
  1078       });
       
  1079 
       
  1080       bean.on(window, 'unload', track);
       
  1081 
       
  1082    }
       
  1083 
       
  1084 });
       
  1085 
       
  1086 },{"../flowplayer":18,"./resolve":13,"bean":20,"scriptjs":29}],6:[function(_dereq_,module,exports){
       
  1087 'use strict';
       
  1088 var flowplayer = _dereq_('../flowplayer'),
       
  1089     ClassList = _dereq_('class-list'),
       
  1090     common = _dereq_('../common'),
       
  1091     bean = _dereq_('bean');
       
  1092 
       
  1093 flowplayer(function(player, root) {
       
  1094 
       
  1095    var CUE_RE = / ?cue\d+ ?/;
       
  1096 
       
  1097    var lastTime = 0, cuepointsDisabled = false;
       
  1098 
       
  1099    function setClass(index) {
       
  1100       root.className = root.className.replace(CUE_RE, " ");
       
  1101       if (index >= 0) ClassList(root).add('cue' + index);
       
  1102    }
       
  1103 
       
  1104    var segments = {}, lastFiredSegment = -0.125;
       
  1105 
       
  1106    var fire = function(cue) {
       
  1107      var idx = player.cuepoints.indexOf(cue);
       
  1108      if (!isNaN(cue)) cue = { time: cue };
       
  1109      cue.index = idx;
       
  1110      setClass(idx);
       
  1111      player.trigger('cuepoint', [player, cue]);
       
  1112    };
       
  1113 
       
  1114    player.on("progress", function(e, api, time) {
       
  1115      if (cuepointsDisabled) return;
       
  1116       var segment = segmentForCue(time);
       
  1117       while (lastFiredSegment < segment) {
       
  1118         lastFiredSegment += 0.125;
       
  1119         if (!segments[lastFiredSegment]) continue;
       
  1120         segments[lastFiredSegment].forEach(fire);
       
  1121       }
       
  1122 
       
  1123    }).on("unload", setClass)
       
  1124    .on('beforeseek', function() {
       
  1125      cuepointsDisabled = true;
       
  1126    }).on("seek", function(ev, api, time) {
       
  1127      setClass();
       
  1128      lastFiredSegment = segmentForCue(time || 0) - 0.125;
       
  1129      cuepointsDisabled = false;
       
  1130      if (!time && segments[0]) segments[0].forEach(fire);
       
  1131    }).on('ready', function(e, api, video) {
       
  1132      lastFiredSegment = -0.125;
       
  1133      var cues = video.cuepoints || player.conf.cuepoints || [];
       
  1134      player.setCuepoints(cues);
       
  1135    }).on('finish', function() {
       
  1136      lastFiredSegment = -0.125;
       
  1137    });
       
  1138    if (player.conf.generate_cuepoints) {
       
  1139 
       
  1140       player.bind("load", function() {
       
  1141 
       
  1142          // clean up cuepoint elements of previous playlist items
       
  1143          common.find('.fp-cuepoint', root).forEach(common.removeNode);
       
  1144 
       
  1145       });
       
  1146    }
       
  1147 
       
  1148    /**
       
  1149     * API
       
  1150     */
       
  1151    player.setCuepoints = function(cues) {
       
  1152      player.cuepoints = [];
       
  1153      segments = {};
       
  1154      cues.forEach(player.addCuepoint);
       
  1155      return player;
       
  1156    };
       
  1157    player.addCuepoint = function(cue) {
       
  1158      if (!player.cuepoints) player.cuepoints = [];
       
  1159      var segment = segmentForCue(cue);
       
  1160      if (!segments[segment]) segments[segment] = [];
       
  1161      segments[segment].push(cue);
       
  1162      player.cuepoints.push(cue);
       
  1163 
       
  1164     if (player.conf.generate_cuepoints && cue.visible !== false) {
       
  1165        var duration = player.video.duration,
       
  1166            timeline = common.find('.fp-timeline', root)[0];
       
  1167         common.css(timeline, "overflow", "visible");
       
  1168 
       
  1169         var time = cue.time || cue;
       
  1170         if (time < 0) time = duration + cue;
       
  1171 
       
  1172         var el = common.createElement('a', {className: 'fp-cuepoint fp-cuepoint' + (player.cuepoints.length - 1)});
       
  1173         common.css(el, "left", (time / duration * 100) + "%");
       
  1174 
       
  1175         timeline.appendChild(el);
       
  1176         bean.on(el, 'mousedown', function(e) {
       
  1177           e.preventDefault();
       
  1178           player.seek(time);
       
  1179 
       
  1180           // preventDefault() doesn't work
       
  1181           return false;
       
  1182         });
       
  1183     }
       
  1184     return player;
       
  1185    };
       
  1186 
       
  1187    player.removeCuepoint = function(cue) {
       
  1188      var idx = player.cuepoints.indexOf(cue),
       
  1189          segment = segmentForCue(cue);
       
  1190      if (idx === -1) return;
       
  1191      player.cuepoints = player.cuepoints.slice(0, idx).concat(player.cuepoints.slice(idx+1));
       
  1192 
       
  1193      var sIdx = segments[segment].indexOf(cue);
       
  1194      if (sIdx === -1) return;
       
  1195      segments[segment] = segments[segment].slice(0, sIdx).concat(segments[segment].slice(sIdx+1));
       
  1196      return player;
       
  1197    };
       
  1198 
       
  1199    function segmentForCue(cue) {
       
  1200      var time = cue && !isNaN(cue.time) ? cue.time : cue;
       
  1201      if (time < 0) time = player.video.duration + time;
       
  1202      return Math.round(time/0.125)*0.125;
       
  1203    }
       
  1204 
       
  1205 });
       
  1206 
       
  1207 },{"../common":1,"../flowplayer":18,"bean":20,"class-list":22}],7:[function(_dereq_,module,exports){
       
  1208 'use strict';
       
  1209 var flowplayer = _dereq_('../flowplayer'),
       
  1210     bean = _dereq_('bean'),
       
  1211     common = _dereq_('../common'),
       
  1212     isObject = _dereq_('is-object'),
       
  1213     extend = _dereq_('extend-object'),
       
  1214     ClassList = _dereq_('class-list');
       
  1215 
       
  1216 
       
  1217 
       
  1218 flowplayer(function(player, root) {
       
  1219 
       
  1220    // no embedding
       
  1221    if (player.conf.embed === false) return;
       
  1222 
       
  1223    var conf = player.conf,
       
  1224       ui = common.find('.fp-ui', root)[0],
       
  1225       trigger = common.createElement('a', { "class": "fp-embed", title: 'Copy to your site'}),
       
  1226       target = common.createElement('div',{ 'class': 'fp-embed-code'}, '<label>Paste this HTML code on your site to embed.</label><textarea></textarea>'),
       
  1227       area = common.find("textarea", target)[0];
       
  1228 
       
  1229    ui.appendChild(trigger);
       
  1230    ui.appendChild(target);
       
  1231 
       
  1232    player.embedCode = function() {
       
  1233      var embedConf = player.conf.embed || {},
       
  1234          video = player.video;
       
  1235 
       
  1236      if (embedConf.iframe) {
       
  1237        var src = player.conf.embed.iframe,
       
  1238            width = embedConf.width || video.width || common.width(root),
       
  1239            height = embedConf.height || video.height || common.height(root);
       
  1240        return '<iframe src="' + player.conf.embed.iframe + '" frameBorder="0" allowfullscreen width="' + width + '" height="' + height + '"></iframe>';
       
  1241      }
       
  1242      var props = ['ratio', 'rtmp', 'live', 'bufferTime', 'origin', 'analytics', 'key', 'subscribe', 'swf', 'swfHls', 'embed', 'adaptiveRatio', 'logo'];
       
  1243      if (embedConf.playlist) props.push('playlist');
       
  1244      var c = common.pick(player.conf, props);
       
  1245      if (c.logo) c.logo = common.createElement('img', {src: c.logo}).src;
       
  1246      if (!embedConf.playlist || !player.conf.playlist.length) c.clip =  extend({}, player.conf.clip, common.pick(player.video, ['sources']));
       
  1247      var script = "var w=window,d=document,e;w._fpes||(w._fpes=[],w.addEventListener(\"load\",function(){var s=d.createElement(\"script\");s.src=\"//embed.flowplayer.org/6.0.3/embed.min.js\",d.body.appendChild(s)})),e=[].slice.call(d.getElementsByTagName(\"script\"),-1)[0].parentNode,w._fpes.push({e:e,l:\"$library\",c:$conf});\n".replace('$conf', JSON.stringify(c)).replace('$library', embedConf.library || '');
       
  1248 
       
  1249      return '<a href="$href">Watch video!\n<script>$script</script></a>'.replace('$href', player.conf.origin || window.location.href).replace('$script', script);
       
  1250 
       
  1251    };
       
  1252    fptip(root, ".fp-embed", "is-embedding");
       
  1253 
       
  1254    bean.on(root, 'click', '.fp-embed-code textarea',  function() {
       
  1255       area.select();
       
  1256    });
       
  1257 
       
  1258    bean.on(root, 'click', '.fp-embed', function() {
       
  1259       area.textContent = player.embedCode().replace(/(\r\n|\n|\r)/gm,"");
       
  1260       area.focus();
       
  1261       area.select();
       
  1262    });
       
  1263 
       
  1264 });
       
  1265 
       
  1266 var fptip = function(root, trigger, active) {
       
  1267 
       
  1268   function close() {
       
  1269     rootClasses.remove(active);
       
  1270     bean.off(document, '.st');
       
  1271   }
       
  1272 
       
  1273   var rootClasses = ClassList(root);
       
  1274 
       
  1275   bean.on(root, 'click', trigger || 'a', function(e) {
       
  1276     e.preventDefault();
       
  1277 
       
  1278     rootClasses.toggle(active);
       
  1279 
       
  1280     if (rootClasses.contains(active)) {
       
  1281 
       
  1282       bean.on(document, 'keydown.st', function(e) {
       
  1283         if (e.which == 27) close();
       
  1284       });
       
  1285       bean.on(document, 'click.st', function(e) {
       
  1286         if (!common.hasParent(e.target, '.' + active)) close();
       
  1287       });
       
  1288     }
       
  1289   });
       
  1290 };
       
  1291 
       
  1292 
       
  1293 },{"../common":1,"../flowplayer":18,"bean":20,"class-list":22,"extend-object":26,"is-object":28}],8:[function(_dereq_,module,exports){
       
  1294 'use strict';
       
  1295 /* global jQuery */
       
  1296 /**
       
  1297  * Mimimal jQuery-like event emitter implementation
       
  1298  */
       
  1299 module.exports = function(obj, elem) {
       
  1300   if (!elem) elem = document.createElement('div'); //In this case we always want to trigger (Custom)Events on dom element
       
  1301   var handlers = {}, eventArguments = {};
       
  1302 
       
  1303   var listenEvent = function(type, hndlr, disposable) {
       
  1304     var actualEvent = type.split('.')[0]; //Strip namespace
       
  1305     var internalHandler = function(ev) {
       
  1306       if (disposable) {
       
  1307         elem.removeEventListener(actualEvent, internalHandler);
       
  1308         handlers[type].splice(handlers[type].indexOf(internalHandler), 1);
       
  1309       }
       
  1310       var args = [ev].concat(eventArguments[ev.timeStamp + ev.type] || []);
       
  1311       if (hndlr) hndlr.apply(undefined, args);
       
  1312     };
       
  1313     elem.addEventListener(actualEvent, internalHandler);
       
  1314 
       
  1315     //Store handlers for unbinding
       
  1316     if (!handlers[type]) handlers[type] = [];
       
  1317     handlers[type].push(internalHandler);
       
  1318   };
       
  1319 
       
  1320   obj.on = obj.bind = function(typ, hndlr) {
       
  1321     var types = typ.split(' ');
       
  1322     types.forEach(function(type) {
       
  1323       listenEvent(type, hndlr);
       
  1324     });
       
  1325     return obj; //for chaining
       
  1326   };
       
  1327 
       
  1328   obj.one = function(typ, hndlr) {
       
  1329     var types = typ.split(' ');
       
  1330     types.forEach(function(type) {
       
  1331       listenEvent(type, hndlr, true);
       
  1332     });
       
  1333     return obj;
       
  1334   };
       
  1335 
       
  1336   // Function to check if all items in toBeContained array are in the containing array
       
  1337   var containsAll = function(containing, toBeContained) {
       
  1338     return toBeContained.filter(function(i) {
       
  1339       return containing.indexOf(i) === -1;
       
  1340     }).length === 0;
       
  1341   };
       
  1342 
       
  1343 
       
  1344   obj.off = obj.unbind = function(typ) {
       
  1345     var types = typ.split(' ');
       
  1346     types.forEach(function(type) {
       
  1347       var typeNameSpaces = type.split('.').slice(1),
       
  1348           actualType = type.split('.')[0];
       
  1349       Object.keys(handlers).filter(function(t) {
       
  1350         var handlerNamespaces = t.split('.').slice(1);
       
  1351         return (!actualType || t.indexOf(actualType) === 0) && containsAll(handlerNamespaces, typeNameSpaces);
       
  1352       }).forEach(function(t) {
       
  1353         var registererHandlers = handlers[t],
       
  1354             actualEvent = t.split('.')[0];
       
  1355         registererHandlers.forEach(function(hndlr) {
       
  1356           elem.removeEventListener(actualEvent, hndlr);
       
  1357           registererHandlers.splice(registererHandlers.indexOf(hndlr), 1);
       
  1358         });
       
  1359       });
       
  1360     });
       
  1361     return obj;
       
  1362   };
       
  1363 
       
  1364   obj.trigger = function(typ, args, returnEvent) {
       
  1365     if (!typ) return;
       
  1366     args = (args || []).length ? args || [] : [args];
       
  1367     var event = document.createEvent('Event'), typStr;
       
  1368     typStr = typ.type || typ;
       
  1369     event.initEvent(typStr, false, true);
       
  1370     eventArguments[event.timeStamp + event.type] = args;
       
  1371     elem.dispatchEvent(event);
       
  1372     return returnEvent ? event : obj;
       
  1373   };
       
  1374 };
       
  1375 
       
  1376 
       
  1377 module.exports.EVENTS = [
       
  1378   'beforeseek',
       
  1379   'disable',
       
  1380   'error',
       
  1381   'finish',
       
  1382   'fullscreen',
       
  1383   'fullscreen-exit',
       
  1384   'load',
       
  1385   'mute',
       
  1386   'pause',
       
  1387   'progress',
       
  1388   'ready',
       
  1389   'resume',
       
  1390   'seek',
       
  1391   'speed',
       
  1392   'stop',
       
  1393   'unload',
       
  1394   'volume',
       
  1395   'boot',
       
  1396   'shutdown'
       
  1397 ];
       
  1398 
       
  1399 },{}],9:[function(_dereq_,module,exports){
       
  1400 'use strict';
       
  1401 var flowplayer = _dereq_('../flowplayer'),
       
  1402     bean = _dereq_('bean'),
       
  1403     ClassList = _dereq_('class-list'),
       
  1404     extend = _dereq_('extend-object'),
       
  1405     common = _dereq_('../common'),
       
  1406    VENDOR = flowplayer.support.browser.mozilla ? "moz": "webkit",
       
  1407    FS_ENTER = "fullscreen",
       
  1408    FS_EXIT = "fullscreen-exit",
       
  1409    FULL_PLAYER,
       
  1410    FS_SUPPORT = flowplayer.support.fullscreen,
       
  1411    FS_NATIVE_SUPPORT = typeof document.exitFullscreen == 'function',
       
  1412    ua = navigator.userAgent.toLowerCase(),
       
  1413    IS_SAFARI = /(safari)[ \/]([\w.]+)/.exec(ua) && !/(chrome)[ \/]([\w.]+)/.exec(ua);
       
  1414 
       
  1415 
       
  1416 // esc button
       
  1417 bean.on(document, "fullscreenchange.ffscr webkitfullscreenchange.ffscr mozfullscreenchange.ffscr MSFullscreenChange.ffscr", function(e) {
       
  1418   var el = document.webkitCurrentFullScreenElement || document.mozFullScreenElement || document.fullscreenElement || document.msFullscreenElement || e.target;
       
  1419   if (!FULL_PLAYER && (!el.parentNode || !el.parentNode.getAttribute('data-flowplayer-instance-id'))) return;
       
  1420   var player = FULL_PLAYER || flowplayer(el.parentNode);
       
  1421   if (el && !FULL_PLAYER) {
       
  1422      FULL_PLAYER = player.trigger(FS_ENTER, [el]);
       
  1423   } else {
       
  1424      FULL_PLAYER.trigger(FS_EXIT, [FULL_PLAYER]);
       
  1425      FULL_PLAYER = null;
       
  1426   }
       
  1427  });
       
  1428 
       
  1429 flowplayer(function(player, root) {
       
  1430 
       
  1431    var wrapper = common.createElement('div', {className: 'fp-player'});
       
  1432    Array.prototype.map.call(root.children, common.identity).forEach(function(el) {
       
  1433      if (common.matches(el, '.fp-ratio,script')) return;
       
  1434      wrapper.appendChild(el);
       
  1435    });
       
  1436    root.appendChild(wrapper);
       
  1437 
       
  1438    if (!player.conf.fullscreen) return;
       
  1439 
       
  1440    var win = window,
       
  1441       scrollY,
       
  1442       scrollX,
       
  1443       rootClasses = ClassList(root);
       
  1444 
       
  1445    player.isFullscreen = false;
       
  1446 
       
  1447    player.fullscreen = function(flag) {
       
  1448 
       
  1449       if (player.disabled) return;
       
  1450 
       
  1451       if (flag === undefined) flag = !player.isFullscreen;
       
  1452 
       
  1453       if (flag) {
       
  1454         scrollY = win.scrollY;
       
  1455         scrollX = win.scrollX;
       
  1456       }
       
  1457 
       
  1458       if (FS_SUPPORT) {
       
  1459 
       
  1460          if (flag) {
       
  1461             ['requestFullScreen', 'webkitRequestFullScreen', 'mozRequestFullScreen', 'msRequestFullscreen'].forEach(function(fName) {
       
  1462                if (typeof wrapper[fName] === 'function') {
       
  1463                   wrapper[fName](Element.ALLOW_KEYBOARD_INPUT);
       
  1464                   if (IS_SAFARI && !document.webkitCurrentFullScreenElement && !document.mozFullScreenElement) { // Element.ALLOW_KEYBOARD_INPUT not allowed
       
  1465                      wrapper[fName]();
       
  1466                   }
       
  1467                   return false;
       
  1468                }
       
  1469             });
       
  1470 
       
  1471          } else {
       
  1472             ['exitFullscreen', 'webkitCancelFullScreen', 'mozCancelFullScreen', 'msExitFullscreen'].forEach(function(fName) {
       
  1473               if (typeof document[fName] === 'function') {
       
  1474                 document[fName]();
       
  1475                 return false;
       
  1476               }
       
  1477             });
       
  1478          }
       
  1479 
       
  1480       } else {
       
  1481          player.trigger(flag ? FS_ENTER : FS_EXIT, [player]);
       
  1482       }
       
  1483 
       
  1484       return player;
       
  1485    };
       
  1486 
       
  1487    var lastClick;
       
  1488 
       
  1489    player.on("mousedown.fs", function() {
       
  1490       if (+new Date() - lastClick < 150 && player.ready) player.fullscreen();
       
  1491       lastClick = +new Date();
       
  1492    });
       
  1493 
       
  1494    player.on(FS_ENTER, function(e) {
       
  1495       rootClasses.add("is-fullscreen");
       
  1496       if (!FS_SUPPORT) common.css(root, 'position', 'fixed');
       
  1497       player.isFullscreen = true;
       
  1498 
       
  1499    }).on(FS_EXIT, function(e) {
       
  1500       var oldOpacity;
       
  1501       if (!FS_SUPPORT && player.engine === "html5") {
       
  1502         oldOpacity = root.css('opacity') || '';
       
  1503         common.css(root, 'opacity', 0);
       
  1504       }
       
  1505       if (!FS_SUPPORT) common.css(root, 'position', '');
       
  1506       rootClasses.remove("is-fullscreen");
       
  1507       if (!FS_SUPPORT && player.engine === "html5") setTimeout(function() { root.css('opacity', oldOpacity); });
       
  1508       player.isFullscreen = false;
       
  1509       win.scrollTo(scrollX, scrollY);
       
  1510    }).on('unload', function() {
       
  1511      if (player.isFullscreen) player.fullscreen();
       
  1512    });
       
  1513 
       
  1514    player.on('shutdown', function() {
       
  1515      bean.off(document, '.ffscr');
       
  1516      FULL_PLAYER = null;
       
  1517    });
       
  1518 
       
  1519 });
       
  1520 
       
  1521 },{"../common":1,"../flowplayer":18,"bean":20,"class-list":22,"extend-object":26}],10:[function(_dereq_,module,exports){
       
  1522 'use strict';
       
  1523 var flowplayer = _dereq_('../flowplayer'),
       
  1524     bean = _dereq_('bean'),
       
  1525     focused,
       
  1526     focusedRoot,
       
  1527     IS_HELP = "is-help",
       
  1528     common = _dereq_('../common'),
       
  1529     ClassList = _dereq_('class-list');
       
  1530 
       
  1531  // keyboard. single global listener
       
  1532 bean.on(document, "keydown.fp", function(e) {
       
  1533 
       
  1534    var el = focused,
       
  1535       metaKeyPressed = e.ctrlKey || e.metaKey || e.altKey,
       
  1536       key = e.which,
       
  1537       conf = el && el.conf,
       
  1538       focusedRootClasses = focusedRoot && ClassList(focusedRoot);
       
  1539 
       
  1540    if (!el || !conf.keyboard || el.disabled) return;
       
  1541 
       
  1542    // help dialog (shift key not truly required)
       
  1543    if ([63, 187, 191].indexOf(key) != -1) {
       
  1544       focusedRootClasses.toggle(IS_HELP);
       
  1545       return false;
       
  1546    }
       
  1547 
       
  1548    // close help / unload
       
  1549    if (key == 27 && focusedRootClasses.contains(IS_HELP)) {
       
  1550       focusedRootClasses.toggle(IS_HELP);
       
  1551       return false;
       
  1552    }
       
  1553 
       
  1554    if (!metaKeyPressed && el.ready) {
       
  1555 
       
  1556       e.preventDefault();
       
  1557 
       
  1558       // slow motion / fast forward
       
  1559       if (e.shiftKey) {
       
  1560          if (key == 39) el.speed(true);
       
  1561          else if (key == 37) el.speed(false);
       
  1562          return;
       
  1563       }
       
  1564 
       
  1565       // 1, 2, 3, 4 ..
       
  1566       if (key < 58 && key > 47) return el.seekTo(key - 48);
       
  1567 
       
  1568       switch (key) {
       
  1569          case 38: case 75: el.volume(el.volumeLevel + 0.15); break;        // volume up
       
  1570          case 40: case 74: el.volume(el.volumeLevel - 0.15); break;        // volume down
       
  1571          case 39: case 76: el.seeking = true; el.seek(true); break;        // forward
       
  1572          case 37: case 72: el.seeking = true; el.seek(false); break;       // backward
       
  1573          case 190: el.seekTo(); break;                                     // to last seek position
       
  1574          case 32: el.toggle(); break;                                      // spacebar
       
  1575          case 70: if(conf.fullscreen) el.fullscreen(); break;               // toggle fullscreen
       
  1576          case 77: el.mute(); break;                                        // mute
       
  1577          case 81: el.unload(); break;                                      // unload/stop
       
  1578       }
       
  1579 
       
  1580    }
       
  1581 
       
  1582 });
       
  1583 
       
  1584 flowplayer(function(api, root) {
       
  1585 
       
  1586    // no keyboard configured
       
  1587    if (!api.conf.keyboard) return;
       
  1588 
       
  1589    // hover
       
  1590    bean.on(root, "mouseenter mouseleave", function(e) {
       
  1591       focused = !api.disabled && e.type == 'mouseover' ? api : 0;
       
  1592       if (focused) focusedRoot = root;
       
  1593    });
       
  1594 
       
  1595    var speedhelp = flowplayer.support.video && api.conf.engine !== "flash" &&
       
  1596       !!document.createElement('video').playbackRate ?
       
  1597       '<p><em>shift</em> + <em>&#8592;</em><em>&#8594;</em>slower / faster</p>' : '';
       
  1598 
       
  1599    // TODO: add to player-layout.html
       
  1600    root.appendChild(common.createElement('div', { className: 'fp-help' }, '\
       
  1601          <a class="fp-close"></a>\
       
  1602          <div class="fp-help-section fp-help-basics">\
       
  1603             <p><em>space</em>play / pause</p>\
       
  1604             <p><em>q</em>unload | stop</p>\
       
  1605             <p><em>f</em>fullscreen</p>' + speedhelp + '\
       
  1606          </div>\
       
  1607          <div class="fp-help-section">\
       
  1608             <p><em>&#8593;</em><em>&#8595;</em>volume</p>\
       
  1609             <p><em>m</em>mute</p>\
       
  1610          </div>\
       
  1611          <div class="fp-help-section">\
       
  1612             <p><em>&#8592;</em><em>&#8594;</em>seek</p>\
       
  1613             <p><em>&nbsp;. </em>seek to previous\
       
  1614             </p><p><em>1</em><em>2</em>&hellip; <em>6</em> seek to 10%, 20% &hellip; 60% </p>\
       
  1615          </div>\
       
  1616    '));
       
  1617 
       
  1618    if (api.conf.tooltip) {
       
  1619      var ui = common.find('.fp-ui', root)[0];
       
  1620      ui.setAttribute('title', 'Hit ? for help');
       
  1621      bean.one(root, "mouseout.tip", '.fp-ui', function() {
       
  1622        ui.removeAttribute('title');
       
  1623      });
       
  1624    }
       
  1625 
       
  1626    bean.on(root, 'click', '.fp-close', function() {
       
  1627      ClassList(root).toggle(IS_HELP);
       
  1628    });
       
  1629 
       
  1630    api.bind('shutdown', function() {
       
  1631      if (focusedRoot == root) focusedRoot = null;
       
  1632    });
       
  1633 
       
  1634 });
       
  1635 
       
  1636 
       
  1637 },{"../common":1,"../flowplayer":18,"bean":20,"class-list":22}],11:[function(_dereq_,module,exports){
       
  1638 'use strict';
       
  1639 var flowplayer = _dereq_('../flowplayer'),
       
  1640     isIeMobile = /IEMobile/.test(window.navigator.userAgent),
       
  1641     ClassList = _dereq_('class-list'),
       
  1642     common = _dereq_('../common'),
       
  1643     bean = _dereq_('bean'),
       
  1644     format = _dereq_('./ui').format,
       
  1645     UA = window.navigator.userAgent;
       
  1646 if (flowplayer.support.touch || isIeMobile) {
       
  1647 
       
  1648    flowplayer(function(player, root) {
       
  1649       var isAndroid = /Android/.test(UA) && !/Firefox/.test(UA) && !/Opera/.test(UA),
       
  1650           isSilk = /Silk/.test(UA),
       
  1651           androidVer = isAndroid ? parseFloat(/Android\ (\d\.\d)/.exec(UA)[1], 10) : 0,
       
  1652           rootClasses = ClassList(root);
       
  1653 
       
  1654       // custom load for android
       
  1655       if (isAndroid && !isIeMobile) {
       
  1656          if (!/Chrome/.test(UA) && androidVer < 4) {
       
  1657             var originalLoad = player.load;
       
  1658             player.load = function(video, callback) {
       
  1659                var ret = originalLoad.apply(player, arguments);
       
  1660                player.trigger('ready', [player, player.video]);
       
  1661                return ret;
       
  1662             };
       
  1663          }
       
  1664          var timer, currentTime = 0;
       
  1665          var resumeTimer = function(api) {
       
  1666            timer = setInterval(function() {
       
  1667              api.video.time = ++currentTime;
       
  1668              api.trigger('progress', [api, currentTime]);
       
  1669            }, 1000);
       
  1670          };
       
  1671          player.bind('ready pause unload', function() {
       
  1672            if (timer) {
       
  1673              clearInterval(timer);
       
  1674              timer = null;
       
  1675            }
       
  1676          });
       
  1677          player.bind('ready', function() {
       
  1678            currentTime = 0;
       
  1679          });
       
  1680          player.bind('resume', function(ev, api) {
       
  1681            if (!api.live) return;
       
  1682            if (currentTime) { return resumeTimer(api); }
       
  1683            player.one('progress', function(ev, api, t) {
       
  1684              if (t === 0) { // https://github.com/flowplayer/flowplayer/issues/727
       
  1685                resumeTimer(api);
       
  1686              }
       
  1687            });
       
  1688          });
       
  1689       }
       
  1690 
       
  1691       // hide volume
       
  1692       if (!flowplayer.support.volume) {
       
  1693          rootClasses.add("no-volume");
       
  1694          rootClasses.add("no-mute");
       
  1695       }
       
  1696       rootClasses.add("is-touch");
       
  1697       if (player.sliders && player.sliders.timeline) player.sliders.timeline.disableAnimation();
       
  1698 
       
  1699       if (!flowplayer.support.inlineVideo || player.conf.native_fullscreen) player.conf.nativesubtitles = true;
       
  1700 
       
  1701       // fake mouseover effect with click
       
  1702       var hasMoved = false;
       
  1703       bean.on(root, 'touchmove', function() {
       
  1704         hasMoved = true;
       
  1705       });
       
  1706       bean.on(root, 'touchend click', function(e) {
       
  1707         if (hasMoved) { //not intentional, most likely scrolling
       
  1708           hasMoved = false;
       
  1709           return;
       
  1710         }
       
  1711 
       
  1712         if (player.playing && !rootClasses.contains("is-mouseover")) {
       
  1713           rootClasses.add("is-mouseover");
       
  1714           rootClasses.remove("is-mouseout");
       
  1715           e.preventDefault();
       
  1716           e.stopPropagation();
       
  1717           return;
       
  1718         }
       
  1719 
       
  1720         if (!player.playing && !player.splash && rootClasses.contains('is-mouseout') && !rootClasses.contains('is-mouseover')) {
       
  1721           setTimeout(function() {
       
  1722             if (!player.playing && !player.splash) {
       
  1723               player.resume();
       
  1724             }
       
  1725           }, 400);
       
  1726         }
       
  1727 
       
  1728 
       
  1729       });
       
  1730 
       
  1731       // native fullscreen
       
  1732       if (player.conf.native_fullscreen && typeof document.createElement('video').webkitEnterFullScreen === 'function') {
       
  1733          player.fullscreen = function() {
       
  1734             var video = common.find('video.fp-engine', root)[0];
       
  1735             video.webkitEnterFullScreen();
       
  1736             bean.one(video, 'webkitendfullscreen', function() {
       
  1737               common.prop(video, 'controls', true);
       
  1738               common.prop(video, 'controls', false);
       
  1739             });
       
  1740          };
       
  1741       }
       
  1742 
       
  1743 
       
  1744       // Android browser gives video.duration == 1 until second 'timeupdate' event
       
  1745       if (isAndroid || isSilk) player.bind("ready", function() {
       
  1746 
       
  1747          var video = common.find('video.fp-engine', root)[0];
       
  1748          bean.one(video, 'canplay', function() {
       
  1749             video.play();
       
  1750          });
       
  1751          video.play();
       
  1752 
       
  1753          player.bind("progress.dur", function() {
       
  1754 
       
  1755             var duration = video.duration;
       
  1756 
       
  1757             if (duration !== 1) {
       
  1758                player.video.duration = duration;
       
  1759                common.find(".fp-duration", root)[0].innerHTML = format(duration);
       
  1760                player.unbind("progress.dur");
       
  1761             }
       
  1762          });
       
  1763       });
       
  1764 
       
  1765 
       
  1766    });
       
  1767 
       
  1768 }
       
  1769 
       
  1770 
       
  1771 },{"../common":1,"../flowplayer":18,"./ui":17,"bean":20,"class-list":22}],12:[function(_dereq_,module,exports){
       
  1772 'use strict';
       
  1773 var flowplayer = _dereq_('../flowplayer'),
       
  1774     extend = _dereq_('extend-object'),
       
  1775     bean = _dereq_('bean'),
       
  1776     ClassList = _dereq_('class-list'),
       
  1777     common = _dereq_('../common'),
       
  1778     Resolve = _dereq_('./resolve'),
       
  1779     resolver = new Resolve(),
       
  1780     $ = window.jQuery,
       
  1781     externalRe = /^#/;
       
  1782 flowplayer(function(player, root) {
       
  1783 
       
  1784    var conf = extend({ active: 'is-active', advance: true, query: ".fp-playlist a" }, player.conf),
       
  1785       klass = conf.active, rootClasses = ClassList(root);
       
  1786 
       
  1787    // getters
       
  1788    function els() {
       
  1789      return common.find(conf.query, queryRoot());
       
  1790    }
       
  1791 
       
  1792    function queryRoot() {
       
  1793      if (externalRe.test(conf.query)) return;
       
  1794      return root;
       
  1795    }
       
  1796 
       
  1797    function active() {
       
  1798       return common.find(conf.query + "." + klass, queryRoot());
       
  1799    }
       
  1800 
       
  1801 
       
  1802    player.play = function(i) {
       
  1803       if (i === undefined) return player.resume();
       
  1804       if (typeof i === 'number' && !player.conf.playlist[i]) return player;
       
  1805       else if (typeof i != 'number') return player.load.apply(null, arguments);
       
  1806       var arg = extend({index: i}, player.conf.playlist[i]);
       
  1807       if (i === player.video.index) return player.load(arg, function() { player.resume(); });
       
  1808       player.off('resume.fromfirst'); // Don't start from beginning if clip explicitely chosen
       
  1809       player.load(arg, function() {
       
  1810         player.video.index = i;
       
  1811       });
       
  1812       return player;
       
  1813    };
       
  1814 
       
  1815    player.next = function(e) {
       
  1816       if (e) e.preventDefault();
       
  1817       var current = player.video.index;
       
  1818       if (current != -1) {
       
  1819          current = current === player.conf.playlist.length - 1 ? 0 : current + 1;
       
  1820          player.play(current);
       
  1821       }
       
  1822       return player;
       
  1823    };
       
  1824 
       
  1825    player.prev = function(e) {
       
  1826       if (e) e.preventDefault();
       
  1827       var current = player.video.index;
       
  1828       if (current != -1) {
       
  1829          current = current === 0 ? player.conf.playlist.length - 1 : current - 1;
       
  1830          player.play(current);
       
  1831       }
       
  1832       return player;
       
  1833    };
       
  1834 
       
  1835    player.setPlaylist = function(items) {
       
  1836      player.conf.playlist = items;
       
  1837      delete player.video.index;
       
  1838      generatePlaylist();
       
  1839      return player;
       
  1840    };
       
  1841 
       
  1842    player.addPlaylistItem = function(item) {
       
  1843      return player.setPlaylist(player.conf.playlist.concat([item]));
       
  1844    };
       
  1845 
       
  1846    player.removePlaylistItem = function(idx) {
       
  1847      var pl = player.conf.playlist;
       
  1848      return player.setPlaylist(pl.slice(0, idx).concat(pl.slice(idx+1)));
       
  1849    };
       
  1850 
       
  1851    bean.on(root, 'click', '.fp-next', player.next);
       
  1852    bean.on(root, 'click', '.fp-prev', player.prev);
       
  1853 
       
  1854    if (conf.advance) {
       
  1855       player.off("finish.pl").on("finish.pl", function(e, player) {
       
  1856          // clip looping
       
  1857          if (player.video.loop) return player.seek(0, function() { player.resume(); });
       
  1858          // next clip is found or loop
       
  1859          var next = player.video.index >= 0 ? player.video.index + 1 : undefined;
       
  1860          if (next < player.conf.playlist.length || conf.loop) {
       
  1861             next = next === player.conf.playlist.length ? 0 : next;
       
  1862             rootClasses.remove('is-finished');
       
  1863             setTimeout(function() { // Let other finish callbacks fire first
       
  1864                player.play(next);
       
  1865             });
       
  1866 
       
  1867          // stop to last clip, play button starts from 1:st clip
       
  1868          } else {
       
  1869 
       
  1870             // If we have multiple items in playlist, start from first
       
  1871             if (player.conf.playlist.length > 1) player.one("resume.fromfirst", function() {
       
  1872                player.play(0);
       
  1873                return false;
       
  1874             });
       
  1875          }
       
  1876       });
       
  1877    }
       
  1878 
       
  1879    function generatePlaylist() {
       
  1880       var plEl = common.find('.fp-playlist', root)[0];
       
  1881       if (!plEl) {
       
  1882          plEl = common.createElement('div', {className: 'fp-playlist'});
       
  1883          var cntrls = common.find('.fp-next,.fp-prev', root);
       
  1884          if (!cntrls.length) common.insertAfter(root, common.find('video', root)[0], plEl);
       
  1885          else cntrls[0].parentElement.insertBefore(plEl, cntrls[0]);
       
  1886       }
       
  1887       plEl.innerHTML = '';
       
  1888       if (player.conf.playlist[0].length) { // FP5 style playlist
       
  1889         player.conf.playlist = player.conf.playlist.map(function(itm) {
       
  1890           if (typeof itm === 'string') {
       
  1891             var type = itm.split(Resolve.TYPE_RE)[1];
       
  1892             return {
       
  1893               sources: [{
       
  1894                 type: type.toLowerCase() === 'm3u8' ? 'application/x-mpegurl' : 'video/' + type,
       
  1895                 src: itm
       
  1896               }]
       
  1897             };
       
  1898           }
       
  1899           return {
       
  1900             sources: itm.map(function(src) {
       
  1901               var s = {};
       
  1902               Object.keys(src).forEach(function(k) {
       
  1903                 s.type = /mpegurl/i.test(k) ? 'application/x-mpegurl' : 'video/' + k;
       
  1904                 s.src = src[k];
       
  1905               });
       
  1906               return s;
       
  1907             })
       
  1908           };
       
  1909         });
       
  1910       }
       
  1911       player.conf.playlist.forEach(function(item, i) {
       
  1912          var href = item.sources[0].src;
       
  1913          plEl.appendChild(common.createElement('a', {
       
  1914             href: href,
       
  1915             'data-index': i
       
  1916          }));
       
  1917       });
       
  1918    }
       
  1919 
       
  1920    var playlistInitialized = false;
       
  1921    if (player.conf.playlist.length) { // playlist configured by javascript, generate playlist
       
  1922       playlistInitialized = true;
       
  1923       generatePlaylist();
       
  1924       if (!player.conf.clip || !player.conf.clip.sources.length) player.conf.clip = player.conf.playlist[0];
       
  1925    }
       
  1926 
       
  1927    if (els().length && !playlistInitialized) { //generate playlist from existing elements
       
  1928        player.conf.playlist = [];
       
  1929        els().forEach(function(el) {
       
  1930           var src = el.href;
       
  1931           el.setAttribute('data-index', player.conf.playlist.length);
       
  1932           var itm = resolver.resolve(src, player.conf.clip.sources);
       
  1933           if ($) {
       
  1934             extend(itm, $(el).data());
       
  1935           }
       
  1936           player.conf.playlist.push(itm);
       
  1937        });
       
  1938     }
       
  1939 
       
  1940     /* click -> play */
       
  1941     bean.on(externalRe.test(conf.query) ? document : root, "click", conf.query, function(e) {
       
  1942        e.preventDefault();
       
  1943        var el = e.currentTarget;
       
  1944        var toPlay = Number(el.getAttribute('data-index'));
       
  1945        if (toPlay != -1) {
       
  1946           player.play(toPlay);
       
  1947        }
       
  1948     });
       
  1949 
       
  1950     // highlight
       
  1951     player.on("load", function(e, api, video) {
       
  1952        if (!player.conf.playlist.length) return;
       
  1953        var prev = active()[0],
       
  1954           prevIndex = prev && prev.getAttribute('data-index'),
       
  1955           index = video.index = video.index || player.video.index || 0,
       
  1956           el = common.find(conf.query +'[data-index="' + index + '"]', queryRoot())[0],
       
  1957           is_last = index == player.conf.playlist.length - 1;
       
  1958        if (prev) ClassList(prev).remove(klass);
       
  1959        if (el) ClassList(el).add(klass);
       
  1960        // index
       
  1961        rootClasses.remove("video" + prevIndex);
       
  1962        rootClasses.add("video" + index);
       
  1963        common.toggleClass(root, "last-video", is_last);
       
  1964 
       
  1965        // video properties
       
  1966        video.index = api.video.index = index;
       
  1967        video.is_last = api.video.is_last = is_last;
       
  1968 
       
  1969     // without namespace callback called only once. unknown rason.
       
  1970     }).on("unload.pl", function() {
       
  1971        if (!player.conf.playlist.length) return;
       
  1972        active().forEach(function(el) {
       
  1973          ClassList(el).toggle(klass);
       
  1974        });
       
  1975        player.conf.playlist.forEach(function(itm, i) {
       
  1976          rootClasses.remove('video' + i);
       
  1977        });
       
  1978     });
       
  1979 
       
  1980    if (player.conf.playlist.length) {
       
  1981       // disable single clip looping
       
  1982       player.conf.loop = false;
       
  1983    }
       
  1984 
       
  1985 
       
  1986 });
       
  1987 
       
  1988 },{"../common":1,"../flowplayer":18,"./resolve":13,"bean":20,"class-list":22,"extend-object":26}],13:[function(_dereq_,module,exports){
       
  1989 'use strict';
       
  1990 var TYPE_RE = /\.(\w{3,4})(\?.*)?$/i,
       
  1991     extend = _dereq_('extend-object');
       
  1992 
       
  1993 function parseSource(el) {
       
  1994 
       
  1995    var src = el.attr("src"),
       
  1996       type = el.attr("type") || "",
       
  1997       suffix = src.split(TYPE_RE)[1];
       
  1998    type = type.toLowerCase();
       
  1999    return extend(el.data(), { src: src, suffix: suffix || type, type: type || suffix });
       
  2000 }
       
  2001 
       
  2002 function getType(typ) {
       
  2003   if (/mpegurl/i.test(typ)) return 'application/x-mpegurl';
       
  2004   return 'video/' + typ;
       
  2005 }
       
  2006 
       
  2007 /* Resolves video object from initial configuration and from load() method */
       
  2008 module.exports = function URLResolver() {
       
  2009   var self = this;
       
  2010 
       
  2011   self.sourcesFromVideoTag = function(videoTag, $) {
       
  2012     /* global $ */
       
  2013     var sources = [];
       
  2014     // initial sources
       
  2015     $("source", videoTag).each(function() {
       
  2016       sources.push(parseSource($(this)));
       
  2017     });
       
  2018 
       
  2019     if (!sources.length && videoTag.length) sources.push(parseSource(videoTag));
       
  2020 
       
  2021     return sources;
       
  2022   };
       
  2023 
       
  2024 
       
  2025   self.resolve = function(video, sources) {
       
  2026     if (!video) return { sources: sources };
       
  2027 
       
  2028     if (typeof video == 'string') {
       
  2029       video = { src: video, sources: [] };
       
  2030       video.sources = (sources || []).map(function(source) {
       
  2031         var suffix = source.src.split(TYPE_RE)[1];
       
  2032         return {type: source.type, src: video.src.replace(TYPE_RE, '.' + suffix + "$2")};
       
  2033       });
       
  2034     }
       
  2035 
       
  2036     if (video instanceof Array) {
       
  2037       video = {
       
  2038         sources: video.map(function(src) {
       
  2039           if (src.type && src.src) return src;
       
  2040           return Object.keys(src).reduce(function(m, typ) {
       
  2041             return extend(m, {
       
  2042               type: getType(typ),
       
  2043               src: src[typ]
       
  2044             });
       
  2045           }, {});
       
  2046         })
       
  2047       };
       
  2048     }
       
  2049 
       
  2050     return video;
       
  2051   };
       
  2052 };
       
  2053 
       
  2054 module.exports.TYPE_RE = TYPE_RE;
       
  2055 
       
  2056 },{"extend-object":26}],14:[function(_dereq_,module,exports){
       
  2057 'use strict';
       
  2058 // skip IE policies
       
  2059 // document.ondragstart = function () { return false; };
       
  2060 //
       
  2061 var ClassList = _dereq_('class-list'),
       
  2062     bean = _dereq_('bean'),
       
  2063     common = _dereq_('../common');
       
  2064 
       
  2065 
       
  2066 // execute function every <delay> ms
       
  2067 var throttle = function(fn, delay) {
       
  2068    var locked;
       
  2069 
       
  2070    return function () {
       
  2071       if (!locked) {
       
  2072          fn.apply(this, arguments);
       
  2073          locked = 1;
       
  2074          setTimeout(function () { locked = 0; }, delay);
       
  2075       }
       
  2076    };
       
  2077 };
       
  2078 
       
  2079 
       
  2080 var slider = function(root, rtl) {
       
  2081   var IS_IPAD = /iPad/.test(navigator.userAgent) && !/CriOS/.test(navigator.userAgent);
       
  2082 
       
  2083   var progress = common.lastChild(root),
       
  2084       rootClasses = ClassList(root),
       
  2085       progressClasses = ClassList(progress),
       
  2086       disabled,
       
  2087       offset,
       
  2088       width,
       
  2089       height,
       
  2090       vertical,
       
  2091       size,
       
  2092       maxValue,
       
  2093       max,
       
  2094       skipAnimation = false,
       
  2095 
       
  2096       /* private */
       
  2097       calc = function() {
       
  2098          offset = common.offset(root);
       
  2099          width = common.width(root);
       
  2100          height = common.height(root);
       
  2101 
       
  2102          /* exit from fullscreen can mess this up.*/
       
  2103          // vertical = height > width;
       
  2104 
       
  2105          size = vertical ? height : width;
       
  2106          max = toDelta(maxValue);
       
  2107       },
       
  2108 
       
  2109       fire = function(value) {
       
  2110          if (!disabled && value != api.value && (!maxValue || value < maxValue)) {
       
  2111             bean.fire(root, 'slide', [ value ]);
       
  2112             api.value = value;
       
  2113          }
       
  2114       },
       
  2115 
       
  2116       mousemove = function(e) {
       
  2117          var pageX = e.pageX || e.clientX;
       
  2118          if (!pageX && e.originalEvent && e.originalEvent.touches && e.originalEvent.touches.length) {
       
  2119             pageX = e.originalEvent.touches[0].pageX;
       
  2120          }
       
  2121          var delta = vertical ? e.pageY - offset.top : pageX - offset.left;
       
  2122          delta = Math.max(0, Math.min(max || size, delta));
       
  2123 
       
  2124          var value = delta / size;
       
  2125          if (vertical) value = 1 - value;
       
  2126          if (rtl) value = 1 - value;
       
  2127          return move(value, 0, true);
       
  2128       },
       
  2129 
       
  2130       move = function(value, speed) {
       
  2131          if (speed === undefined) { speed = 0; }
       
  2132          if (value > 1) value = 1;
       
  2133 
       
  2134          var to = (Math.round(value * 1000) / 10) + "%";
       
  2135 
       
  2136          if (!maxValue || value <= maxValue) {
       
  2137            progressClasses.remove('animated');
       
  2138             if (skipAnimation) {
       
  2139               progressClasses.remove('animated');
       
  2140             } else {
       
  2141               progressClasses.add('animated');
       
  2142               common.css(progress, 'transition-duration', (speed || 0) + 'ms');
       
  2143             }
       
  2144             common.css(progress, 'width', to);
       
  2145          }
       
  2146 
       
  2147          return value;
       
  2148       },
       
  2149 
       
  2150       toDelta = function(value) {
       
  2151          return Math.max(0, Math.min(size, vertical ? (1 - value) * height : value * width));
       
  2152       },
       
  2153 
       
  2154       /* public */
       
  2155       api = {
       
  2156 
       
  2157          max: function(value) {
       
  2158             maxValue = value;
       
  2159          },
       
  2160 
       
  2161          disable: function(flag) {
       
  2162             disabled = flag;
       
  2163          },
       
  2164 
       
  2165          slide: function(value, speed, fireEvent) {
       
  2166             calc();
       
  2167             if (fireEvent) fire(value);
       
  2168             move(value, speed);
       
  2169          },
       
  2170 
       
  2171          // Should animation be handled via css
       
  2172          disableAnimation: function(value, alsoCssAnimations) {
       
  2173             skipAnimation = value !== false;
       
  2174             common.toggleClass(root, 'no-animation', !!alsoCssAnimations);
       
  2175          }
       
  2176 
       
  2177       };
       
  2178 
       
  2179   calc();
       
  2180 
       
  2181   // bound dragging into document
       
  2182   bean.on(root, 'mousedown.sld touchstart', function(e) {
       
  2183     e.preventDefault();
       
  2184 
       
  2185     if (!disabled) {
       
  2186       // begin --> recalculate. allows dynamic resizing of the slider
       
  2187       var delayedFire = throttle(fire, 100);
       
  2188       calc();
       
  2189       api.dragging = true;
       
  2190       rootClasses.add('is-dragging');
       
  2191       fire(mousemove(e));
       
  2192 
       
  2193       bean.on(document, 'mousemove.sld touchmove.sld', function(e) {
       
  2194         e.preventDefault();
       
  2195         delayedFire(mousemove(e));
       
  2196 
       
  2197       });
       
  2198       bean.one(document, 'mouseup touchend', function() {
       
  2199          api.dragging = false;
       
  2200          rootClasses.remove('is-dragging');
       
  2201          bean.off(document, 'mousemove.sld touchmove.sld');
       
  2202       });
       
  2203 
       
  2204      }
       
  2205 
       
  2206   });
       
  2207   return api;
       
  2208 };
       
  2209 
       
  2210 module.exports = slider;
       
  2211 
       
  2212 },{"../common":1,"bean":20,"class-list":22}],15:[function(_dereq_,module,exports){
       
  2213 'use strict';
       
  2214 var flowplayer = _dereq_('../flowplayer'),
       
  2215     common = _dereq_('../common'),
       
  2216     bean = _dereq_('bean'),
       
  2217     ClassList = _dereq_('class-list');
       
  2218 
       
  2219 flowplayer.defaults.subtitleParser = function(txt) {
       
  2220   var TIMECODE_RE = /^(([0-9]{2}:){1,2}[0-9]{2}[,.][0-9]{3}) --\> (([0-9]{2}:){1,2}[0-9]{2}[,.][0-9]{3})(.*)/;
       
  2221 
       
  2222   function seconds(timecode) {
       
  2223      var els = timecode.split(':');
       
  2224      if (els.length == 2) els.unshift(0);
       
  2225      return els[0] * 60 * 60 + els[1] * 60 + parseFloat(els[2].replace(',','.'));
       
  2226   }
       
  2227 
       
  2228   var entries = [];
       
  2229   for (var i = 0, lines = txt.split("\n"), len = lines.length, entry = {}, title, timecode, text, cue; i < len; i++) {
       
  2230     timecode = TIMECODE_RE.exec(lines[i]);
       
  2231 
       
  2232     if (timecode) {
       
  2233 
       
  2234       // title
       
  2235       title = lines[i - 1];
       
  2236 
       
  2237       // text
       
  2238       text = "<p>" + lines[++i] + "</p><br/>";
       
  2239       while (typeof lines[++i] === 'string' && lines[i].trim() && i < lines.length) text +=  "<p>" + lines[i] + "</p><br/>";
       
  2240 
       
  2241       // entry
       
  2242       entry = {
       
  2243         title: title,
       
  2244         startTime: seconds(timecode[1]),
       
  2245         endTime: seconds(timecode[3]),
       
  2246         text: text
       
  2247       };
       
  2248       entries.push(entry);
       
  2249     }
       
  2250   }
       
  2251   return entries;
       
  2252 };
       
  2253 
       
  2254 flowplayer(function(p, root) {
       
  2255   var wrapClasses, currentPoint, wrap,
       
  2256       rootClasses = ClassList(root),
       
  2257       subtitleControl;
       
  2258 
       
  2259   var createSubtitleControl = function() {
       
  2260     subtitleControl = common.createElement('a', {className: 'fp-menu'});
       
  2261     var menu = common.createElement('ul', {className: 'fp-dropdown fp-dropup'});
       
  2262     menu.appendChild(common.createElement('li', {'data-subtitle-index': -1}, 'No subtitles'));
       
  2263     (p.video.subtitles || []).forEach(function(st, i) {
       
  2264       var srcLang = st.srclang || 'en',
       
  2265           label = st.label || 'Default (' + srcLang + ')';
       
  2266       var item = common.createElement('li', {'data-subtitle-index': i}, label);
       
  2267       menu.appendChild(item);
       
  2268     });
       
  2269     subtitleControl.appendChild(menu);
       
  2270     common.find('.fp-controls', root)[0].appendChild(subtitleControl);
       
  2271     return subtitleControl;
       
  2272   };
       
  2273 
       
  2274   bean.on(root, 'click', '.fp-menu', function(ev) {
       
  2275     ClassList(subtitleControl).toggle('dropdown-open');
       
  2276   });
       
  2277 
       
  2278   bean.on(root, 'click', '.fp-menu li[data-subtitle-index]', function(ev) {
       
  2279     var idx = ev.target.getAttribute('data-subtitle-index');
       
  2280     if (idx === '-1') return p.disableSubtitles();
       
  2281     p.loadSubtitles(idx);
       
  2282   });
       
  2283 
       
  2284   var createUIElements = function() {
       
  2285     var playerEl = common.find('.fp-player', root)[0];
       
  2286     wrap = common.find('.fp-subtitle', root)[0];
       
  2287     wrap = wrap || common.appendTo(common.createElement('div', {'class': 'fp-subtitle'}), playerEl);
       
  2288     Array.prototype.forEach.call(wrap.children, common.removeNode);
       
  2289     wrapClasses = ClassList(wrap);
       
  2290     common.find('.fp-menu', root).forEach(common.removeNode);
       
  2291     createSubtitleControl();
       
  2292   };
       
  2293 
       
  2294 
       
  2295   p.on('ready',  function(ev, player, video) {
       
  2296     var conf = player.conf;
       
  2297     if (flowplayer.support.subtitles && conf.nativesubtitles && player.engine.engineName == 'html5') {
       
  2298       var setMode = function(mode) {
       
  2299         var tracks = common.find('video', root)[0].textTracks;
       
  2300         if (!tracks.length) return;
       
  2301         tracks[0].mode = mode;
       
  2302       };
       
  2303       if (!video.subtitles || !video.subtitles.length) return;
       
  2304       var videoTag = common.find('video.fp-engine', root)[0];
       
  2305       video.subtitles.forEach(function(st) {
       
  2306         videoTag.appendChild(common.createElement('track', {
       
  2307           kind: 'subtitles',
       
  2308           srclang: st.srclang || 'en',
       
  2309           label: st.label || 'en',
       
  2310           src: st.src,
       
  2311           'default': st['default']
       
  2312         }));
       
  2313       });
       
  2314       setMode('disabled');
       
  2315       setMode('showing');
       
  2316       return;
       
  2317     }
       
  2318 
       
  2319     player.subtitles = [];
       
  2320 
       
  2321     createUIElements();
       
  2322 
       
  2323     rootClasses.remove('has-menu');
       
  2324 
       
  2325     p.disableSubtitles();
       
  2326 
       
  2327     if (!video.subtitles || !video.subtitles.length) return;
       
  2328 
       
  2329     rootClasses.add('has-menu');
       
  2330     var defaultSubtitle = video.subtitles.filter(function(one) {
       
  2331       return one['default'];
       
  2332     })[0];
       
  2333     if (defaultSubtitle) player.loadSubtitles(video.subtitles.indexOf(defaultSubtitle));
       
  2334   });
       
  2335 
       
  2336   p.bind("cuepoint", function(e, api, cue) {
       
  2337     if (cue.subtitle) {
       
  2338        currentPoint = cue.index;
       
  2339        common.html(wrap, cue.subtitle.text);
       
  2340        wrapClasses.add('fp-active');
       
  2341     } else if (cue.subtitleEnd) {
       
  2342        wrapClasses.remove('fp-active');
       
  2343        currentPoint = cue.index;
       
  2344     }
       
  2345   });
       
  2346 
       
  2347   p.bind("seek", function(e, api, time) {
       
  2348     // Clear future subtitles if seeking backwards
       
  2349     if (currentPoint && p.cuepoints[currentPoint] && p.cuepoints[currentPoint].time > time) {
       
  2350        wrapClasses.remove('fp-active');
       
  2351        currentPoint = null;
       
  2352     }
       
  2353     (p.cuepoints || []).forEach(function(cue) {
       
  2354       var entry = cue.subtitle;
       
  2355       //Trigger cuepoint if start time before seek position and end time nonexistent or in the future
       
  2356       if (entry && currentPoint != cue.index) {
       
  2357         if (time >= cue.time && (!entry.endTime || time <= entry.endTime)) p.trigger("cuepoint", [p, cue]);
       
  2358       } // Also handle cuepoints that act as the removal trigger
       
  2359       else if (cue.subtitleEnd && time >= cue.time && cue.index == currentPoint + 1) p.trigger("cuepoint", [p, cue]);
       
  2360     });
       
  2361 
       
  2362   });
       
  2363 
       
  2364   var setActiveSubtitleClass = function(idx) {
       
  2365     common.toggleClass(common.find('li.active', root)[0], 'active');
       
  2366     common.toggleClass(common.find('li[data-subtitle-index="' + idx + '"]', root)[0], 'active');
       
  2367   };
       
  2368 
       
  2369   p.disableSubtitles = function() {
       
  2370     p.subtitles = [];
       
  2371     (p.cuepoints || []).forEach(function(c) {
       
  2372       if (c.subtitle || c.subtitleEnd) p.removeCuepoint(c);
       
  2373     });
       
  2374     if (wrap) Array.prototype.forEach.call(wrap.children, common.removeNode);
       
  2375     setActiveSubtitleClass(-1);
       
  2376     return p;
       
  2377   };
       
  2378 
       
  2379   p.loadSubtitles = function(i) {
       
  2380     //First remove possible old subtitles
       
  2381     p.disableSubtitles();
       
  2382 
       
  2383     var st = p.video.subtitles[i];
       
  2384 
       
  2385     var url = st.src;
       
  2386     if (!url) return;
       
  2387     setActiveSubtitleClass(i);
       
  2388     common.xhrGet(url, function(txt) {
       
  2389       var entries = p.conf.subtitleParser(txt);
       
  2390       entries.forEach(function(entry) {
       
  2391         var cue = { time: entry.startTime, subtitle: entry, visible: false };
       
  2392         p.subtitles.push(entry);
       
  2393         p.addCuepoint(cue);
       
  2394         p.addCuepoint({ time: entry.endTime, subtitleEnd: entry.title, visible: false });
       
  2395 
       
  2396         // initial cuepoint
       
  2397         if (entry.startTime === 0 && !p.video.time) {
       
  2398           p.trigger("cuepoint", [p, cue]);
       
  2399         }
       
  2400       });
       
  2401     }, function() {
       
  2402       p.trigger("error", {code: 8, url: url });
       
  2403       return false;
       
  2404     });
       
  2405     return p;
       
  2406   };
       
  2407 });
       
  2408 
       
  2409 
       
  2410 },{"../common":1,"../flowplayer":18,"bean":20,"class-list":22}],16:[function(_dereq_,module,exports){
       
  2411 'use strict';
       
  2412 /* global ActiveXObject */
       
  2413 var flowplayer = _dereq_('../flowplayer'),
       
  2414     extend = _dereq_('extend-object');
       
  2415 (function() {
       
  2416 
       
  2417    var parseIpadVersion = function(UA) {
       
  2418       var e = /Version\/(\d\.\d)/.exec(UA);
       
  2419       if (e && e.length > 1) {
       
  2420          return parseFloat(e[1], 10);
       
  2421       }
       
  2422       return 0;
       
  2423    };
       
  2424 
       
  2425    var createVideoTag = function() {
       
  2426      var videoTag = document.createElement('video');
       
  2427      videoTag.loop = true;
       
  2428      videoTag.autoplay = true;
       
  2429      videoTag.preload = true;
       
  2430      return videoTag;
       
  2431    };
       
  2432 
       
  2433     var b = {},
       
  2434       ua = navigator.userAgent.toLowerCase(),
       
  2435       match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
       
  2436       /(safari)[ \/]([\w.]+)/.exec(ua) ||
       
  2437       /(webkit)[ \/]([\w.]+)/.exec(ua) ||
       
  2438       /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
       
  2439       /(msie) ([\w.]+)/.exec(ua) ||
       
  2440       ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
       
  2441 
       
  2442    if (match[1]) {
       
  2443       b[match[1]] = true;
       
  2444       b.version = match[2] || "0";
       
  2445    }
       
  2446 
       
  2447    var video = createVideoTag(),
       
  2448       UA = navigator.userAgent,
       
  2449       IS_IE = b.msie || /Trident\/7/.test(UA),
       
  2450       IS_IPAD = /iPad|MeeGo/.test(UA) && !/CriOS/.test(UA),
       
  2451       IS_IPAD_CHROME = /iPad/.test(UA) && /CriOS/.test(UA),
       
  2452       IS_IPHONE = /iP(hone|od)/i.test(UA) && !/iPad/.test(UA) && !/IEMobile/i.test(UA),
       
  2453       IS_ANDROID = /Android/.test(UA) && !/Firefox/.test(UA),
       
  2454       IS_ANDROID_FIREFOX = /Android/.test(UA) && /Firefox/.test(UA),
       
  2455       IS_SILK = /Silk/.test(UA),
       
  2456       IS_WP = /IEMobile/.test(UA),
       
  2457       WP_VER = IS_WP ? parseFloat(/Windows\ Phone\ (\d+\.\d+)/.exec(UA)[1], 10) : 0,
       
  2458       IE_MOBILE_VER = IS_WP ? parseFloat(/IEMobile\/(\d+\.\d+)/.exec(UA)[1], 10) : 0,
       
  2459       IPAD_VER = IS_IPAD ? parseIpadVersion(UA) : 0,
       
  2460       ANDROID_VER = IS_ANDROID ? parseFloat(/Android\ (\d\.\d)/.exec(UA)[1], 10) : 0,
       
  2461       s = extend(flowplayer.support, {
       
  2462 
       
  2463         browser: b,
       
  2464         subtitles: !!video.addTextTrack,
       
  2465         fullscreen: typeof document.webkitCancelFullScreen == 'function' && !/Mac OS X 10_5.+Version\/5\.0\.\d Safari/.test(UA) ||
       
  2466               document.mozFullScreenEnabled ||
       
  2467               typeof document.exitFullscreen == 'function' ||
       
  2468               typeof document.msExitFullscreen == 'function',
       
  2469         inlineBlock: !(IS_IE && b.version < 8),
       
  2470         touch: ('ontouchstart' in window),
       
  2471         dataload: !IS_IPAD && !IS_IPHONE && !IS_WP,
       
  2472         zeropreload: !IS_IE && !IS_ANDROID, // IE supports only preload=metadata
       
  2473         volume: !IS_IPAD && !IS_ANDROID && !IS_IPHONE && !IS_SILK && !IS_IPAD_CHROME,
       
  2474         cachedVideoTag: !IS_IPAD && !IS_IPHONE && !IS_IPAD_CHROME && !IS_WP,
       
  2475         firstframe: !IS_IPHONE && !IS_IPAD && !IS_ANDROID && !IS_SILK && !IS_IPAD_CHROME && !IS_WP && !IS_ANDROID_FIREFOX,
       
  2476         inlineVideo: !IS_IPHONE && (!IS_WP || (WP_VER >= 8.1 && IE_MOBILE_VER >= 11)) && (!IS_ANDROID || ANDROID_VER >= 3),
       
  2477         hlsDuration: !IS_ANDROID && (!b.safari || IS_IPAD || IS_IPHONE || IS_IPAD_CHROME),
       
  2478         seekable: !IS_IPAD && !IS_IPAD_CHROME
       
  2479     });
       
  2480 
       
  2481    // flashVideo
       
  2482    try {
       
  2483       var plugin = navigator.plugins["Shockwave Flash"],
       
  2484           ver = IS_IE ? new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable('$version') : plugin.description;
       
  2485       if (!IS_IE && !plugin[0].enabledPlugin) s.flashVideo = false;
       
  2486       else {
       
  2487 
       
  2488          ver = ver.split(/\D+/);
       
  2489          if (ver.length && !ver[0]) ver = ver.slice(1);
       
  2490 
       
  2491          s.flashVideo = ver[0] > 9 || ver[0] == 9 && ver[3] >= 115;
       
  2492       }
       
  2493 
       
  2494    } catch (ignored) {}
       
  2495    try {
       
  2496       s.video = !!video.canPlayType;
       
  2497       if (s.video) video.canPlayType('video/mp4');
       
  2498    } catch (e) {
       
  2499       s.video = false;
       
  2500    }
       
  2501 
       
  2502    // animation
       
  2503    s.animation = (function() {
       
  2504       var vendors = ['','Webkit','Moz','O','ms','Khtml'], el = document.createElement('p');
       
  2505 
       
  2506       for (var i = 0; i < vendors.length; i++) {
       
  2507          if (typeof el.style[vendors[i] + 'AnimationName'] !== 'undefined') return true;
       
  2508       }
       
  2509    })();
       
  2510 
       
  2511 
       
  2512 
       
  2513 })();
       
  2514 
       
  2515 
       
  2516 },{"../flowplayer":18,"extend-object":26}],17:[function(_dereq_,module,exports){
       
  2517 'use strict';
       
  2518 var flowplayer = _dereq_('../flowplayer'),
       
  2519     common = _dereq_('../common'),
       
  2520     ClassList = _dereq_('class-list'),
       
  2521     bean = _dereq_('bean'),
       
  2522     slider = _dereq_('./slider');
       
  2523 
       
  2524 function zeropad(val) {
       
  2525    val = parseInt(val, 10);
       
  2526    return val >= 10 ? val : "0" + val;
       
  2527 }
       
  2528 
       
  2529 // display seconds in hh:mm:ss format
       
  2530 function format(sec) {
       
  2531 
       
  2532    sec = sec || 0;
       
  2533 
       
  2534    var h = Math.floor(sec / 3600),
       
  2535        min = Math.floor(sec / 60);
       
  2536 
       
  2537    sec = sec - (min * 60);
       
  2538 
       
  2539    if (h >= 1) {
       
  2540       min -= h * 60;
       
  2541       return h + ":" + zeropad(min) + ":" + zeropad(sec);
       
  2542    }
       
  2543 
       
  2544    return zeropad(min) + ":" + zeropad(sec);
       
  2545 }
       
  2546 
       
  2547 flowplayer(function(api, root) {
       
  2548 
       
  2549    var conf = api.conf,
       
  2550       support = flowplayer.support,
       
  2551       hovertimer,
       
  2552       rootClasses = ClassList(root);
       
  2553    common.find('.fp-ratio,.fp-ui', root).forEach(common.removeNode);
       
  2554    rootClasses.add('flowplayer');
       
  2555    root.appendChild(common.createElement('div', {className: 'fp-ratio'}));
       
  2556    var ui = common.createElement('div', {className: 'fp-ui'}, '\
       
  2557          <div class="waiting"><em></em><em></em><em></em></div>\
       
  2558          <a class="fullscreen"></a>\
       
  2559          <a class="unload"></a>\
       
  2560          <p class="speed"></p>\
       
  2561          <div class="controls">\
       
  2562             <a class="play"></a>\
       
  2563             <div class="timeline">\
       
  2564                <div class="buffer"></div>\
       
  2565                <div class="progress"></div>\
       
  2566             </div>\
       
  2567             <div class="timeline-tooltip fp-tooltip"></div>\
       
  2568             <div class="volume">\
       
  2569                <a class="mute"></a>\
       
  2570                <div class="volumeslider">\
       
  2571                   <div class="volumelevel"></div>\
       
  2572                </div>\
       
  2573             </div>\
       
  2574          </div>\
       
  2575          <div class="time">\
       
  2576             <em class="elapsed">00:00</em>\
       
  2577             <em class="remaining"></em>\
       
  2578             <em class="duration">00:00</em>\
       
  2579          </div>\
       
  2580          <div class="message"><h2></h2><p></p></div>'.replace(/class="/g, 'class="fp-'));
       
  2581    root.appendChild(ui);
       
  2582    function find(klass) {
       
  2583      return common.find(".fp-" + klass, root)[0];
       
  2584    }
       
  2585 
       
  2586    // widgets
       
  2587    var progress = find("progress"),
       
  2588       buffer = find("buffer"),
       
  2589       elapsed = find("elapsed"),
       
  2590       remaining = find("remaining"),
       
  2591       waiting = find("waiting"),
       
  2592       ratio = find("ratio"),
       
  2593       speed = find("speed"),
       
  2594       speedClasses = ClassList(speed),
       
  2595       durationEl = find("duration"),
       
  2596       controls = find('controls'),
       
  2597       timelineTooltip = find('timeline-tooltip'),
       
  2598       origRatio = common.css(ratio, 'padding-top'),
       
  2599 
       
  2600       // sliders
       
  2601       timeline = find("timeline"),
       
  2602       timelineApi = slider(timeline, api.rtl),
       
  2603 
       
  2604       volume = find("volume"),
       
  2605       fullscreen = find("fullscreen"),
       
  2606       volumeSlider = find("volumeslider"),
       
  2607       volumeApi = slider(volumeSlider, api.rtl),
       
  2608       noToggle = rootClasses.contains('fixed-controls') || rootClasses.contains('no-toggle');
       
  2609 
       
  2610    timelineApi.disableAnimation(rootClasses.contains('is-touch'));
       
  2611    api.sliders = api.sliders || {};
       
  2612    api.sliders.timeline = timelineApi;
       
  2613    api.sliders.volume = volumeApi;
       
  2614 
       
  2615    // aspect ratio
       
  2616    function setRatio(val) {
       
  2617      common.css(ratio, 'padding-top', val * 100 + "%");
       
  2618      if (!support.inlineBlock) common.height(common.find('object', root)[0], common.height(root));
       
  2619    }
       
  2620 
       
  2621    function hover(flag) {
       
  2622      if (flag) {
       
  2623        rootClasses.add('is-mouseover');
       
  2624        rootClasses.remove('is-mouseout');
       
  2625      } else {
       
  2626        rootClasses.add('is-mouseout');
       
  2627        rootClasses.remove('is-mouseover');
       
  2628      }
       
  2629    }
       
  2630 
       
  2631    // loading...
       
  2632    if (!support.animation) common.html(waiting, "<p>loading &hellip;</p>");
       
  2633 
       
  2634    if (conf.ratio) setRatio(conf.ratio);
       
  2635 
       
  2636    // no fullscreen in IFRAME
       
  2637    try {
       
  2638       if (!conf.fullscreen) common.removeNode(fullscreen);
       
  2639 
       
  2640    } catch (e) {
       
  2641       common.removeNode(fullscreen);
       
  2642    }
       
  2643 
       
  2644    api.on("ready", function(ev, api, video) {
       
  2645 
       
  2646       var duration = api.video.duration;
       
  2647 
       
  2648       timelineApi.disable(api.disabled || !duration);
       
  2649 
       
  2650       if (conf.adaptiveRatio && !isNaN(video.height / video.width)) setRatio(video.height / video.width, true);
       
  2651 
       
  2652       // initial time & volume
       
  2653       common.html([durationEl, remaining], format(duration));
       
  2654 
       
  2655       // do we need additional space for showing hour
       
  2656       common.toggleClass(root, 'is-long', duration >= 3600);
       
  2657       volumeApi.slide(api.volumeLevel);
       
  2658 
       
  2659       if (api.engine.engineName === 'flash') timelineApi.disableAnimation(true, true);
       
  2660       else timelineApi.disableAnimation(false);
       
  2661       common.find('.fp-title', ui).forEach(common.removeNode);
       
  2662       if (video.title) {
       
  2663         common.prepend(ui, common.createElement('div', {
       
  2664           className: 'fp-title'
       
  2665         }, video.title));
       
  2666       }
       
  2667 
       
  2668 
       
  2669    }).on("unload", function() {
       
  2670      if (!origRatio) common.css(ratio, "paddingTop", "");
       
  2671      timelineApi.slide(0);
       
  2672 
       
  2673    // buffer
       
  2674    }).on("buffer", function() {
       
  2675       var video = api.video,
       
  2676          max = video.buffer / video.duration;
       
  2677 
       
  2678       if (!video.seekable && support.seekable) timelineApi.max(max);
       
  2679       if (max < 1) common.css(buffer, "width", (max * 100) + "%");
       
  2680       else common.css(buffer, 'width', '100%');
       
  2681 
       
  2682    }).on("speed", function(e, api, val) {
       
  2683      common.text(speed, val + "x");
       
  2684      speedClasses.add('fp-hilite');
       
  2685      setTimeout(function() { speedClasses.remove('fp-hilite'); }, 1000);
       
  2686 
       
  2687    }).on("buffered", function() {
       
  2688      common.css(buffer, 'width', '100%');
       
  2689       timelineApi.max(1);
       
  2690 
       
  2691    // progress
       
  2692    }).on("progress", function() {
       
  2693 
       
  2694       var time = api.video.time,
       
  2695          duration = api.video.duration;
       
  2696 
       
  2697       if (!timelineApi.dragging) {
       
  2698         timelineApi.slide(time / duration, api.seeking ? 0 : 250);
       
  2699       }
       
  2700 
       
  2701       common.html(elapsed, format(time));
       
  2702       common.html(remaining, '-' + format(duration - time));
       
  2703 
       
  2704    }).on("finish resume seek", function(e) {
       
  2705       common.toggleClass(root, "is-finished", e.type == "finish");
       
  2706 
       
  2707    }).on("stop", function() {
       
  2708       common.html(elapsed, format(0));
       
  2709       timelineApi.slide(0, 100);
       
  2710 
       
  2711    }).on("finish", function() {
       
  2712       common.html(elapsed, format(api.video.duration));
       
  2713       timelineApi.slide(1, 100);
       
  2714       rootClasses.remove('is-seeking');
       
  2715 
       
  2716    // misc
       
  2717    }).on("beforeseek", function() {
       
  2718       //TODO FIXME
       
  2719       //progress.stop();
       
  2720 
       
  2721    }).on("volume", function() {
       
  2722       volumeApi.slide(api.volumeLevel);
       
  2723 
       
  2724 
       
  2725    }).on("disable", function() {
       
  2726       var flag = api.disabled;
       
  2727       timelineApi.disable(flag);
       
  2728       volumeApi.disable(flag);
       
  2729       common.toggleClass(root, 'is-disabled', api.disabled);
       
  2730 
       
  2731    }).on("mute", function(e, api, flag) {
       
  2732       common.toggleClass(root, 'is-muted', flag);
       
  2733 
       
  2734    }).on("error", function(e, api, error) {
       
  2735       common.removeClass(root, 'is-loading');
       
  2736       common.addClass(root, 'is-error');
       
  2737       if (error) {
       
  2738          error.message = conf.errors[error.code];
       
  2739          api.error = true;
       
  2740 
       
  2741          var el = common.find('.fp-message', root)[0],
       
  2742              video = error.video || api.video;
       
  2743          common.find('h2', el)[0].innerHTML = (api.engine && api.engine.engineName || 'html5') + ": " + error.message;
       
  2744          common.find('p', el)[0].innerHTML = error.url || video.url || video.src || conf.errorUrls[error.code];
       
  2745          api.off("mouseenter click");
       
  2746          rootClasses.remove('is-mouseover');
       
  2747       }
       
  2748 
       
  2749 
       
  2750    // hover
       
  2751    });
       
  2752    //Interaction events
       
  2753    bean.on(root, "mouseenter mouseleave", function(e) {
       
  2754      if (noToggle) return;
       
  2755 
       
  2756       var is_over = e.type == "mouseover",
       
  2757          lastMove;
       
  2758 
       
  2759       // is-mouseover/out
       
  2760       hover(is_over);
       
  2761 
       
  2762       if (is_over) {
       
  2763 
       
  2764          var reg = function() {
       
  2765             hover(true);
       
  2766             lastMove = new Date();
       
  2767          };
       
  2768          api.on("pause.x volume.x", reg);
       
  2769          bean.on(root, 'mousemove.x', reg);
       
  2770 
       
  2771          hovertimer = setInterval(function() {
       
  2772             if (new Date() - lastMove > conf.mouseoutTimeout) {
       
  2773                hover(false);
       
  2774                lastMove = new Date();
       
  2775             }
       
  2776          }, 100);
       
  2777 
       
  2778       } else {
       
  2779          bean.off(root, 'mousemove.x');
       
  2780          api.off("pause.x volume.x");
       
  2781          clearInterval(hovertimer);
       
  2782       }
       
  2783 
       
  2784 
       
  2785    // allow dragging over the player edge
       
  2786    });
       
  2787    bean.on(root, "mouseleave", function() {
       
  2788 
       
  2789      if (timelineApi.dragging || volumeApi.dragging) {
       
  2790        rootClasses.add('is-mouseover');
       
  2791        rootClasses.remove('is-mouseout');
       
  2792      }
       
  2793 
       
  2794    // click
       
  2795    });
       
  2796    bean.on(root, "click.player", function(e) {
       
  2797      if (api.disabled) return;
       
  2798      var kls = ClassList(e.target);
       
  2799       if (kls.contains('fp-ui') || kls.contains('fp-engine') || e.flash) {
       
  2800          if (e.preventDefault) e.preventDefault();
       
  2801          return api.toggle();
       
  2802       }
       
  2803    });
       
  2804 
       
  2805    bean.on(root, 'mousemove', '.fp-timeline', function(ev) {
       
  2806      var x = ev.pageX || ev.clientX,
       
  2807          delta = x - common.offset(timeline).left,
       
  2808          percentage = delta / common.width(timeline),
       
  2809          seconds = percentage * api.video.duration;
       
  2810      if (percentage < 0) return;
       
  2811      common.html(timelineTooltip, format(seconds));
       
  2812      common.css(timelineTooltip, 'left', (x - common.offset(controls).left - common.width(timelineTooltip) / 2) + 'px');
       
  2813    });
       
  2814 
       
  2815    bean.on(root, 'contextmenu', function(ev) {
       
  2816       var o = common.offset(common.find('.fp-player', root)[0]),
       
  2817           w = window,
       
  2818           left = ev.clientX - o.left,
       
  2819           t = ev.clientY - (o.top + w.scrollY);
       
  2820       var menu = common.find('.fp-context-menu', root)[0];
       
  2821       if (!menu) return;
       
  2822       ev.preventDefault();
       
  2823       common.css(menu,
       
  2824       {left: left + 'px',
       
  2825          top: t + 'px',
       
  2826          display: 'block'
       
  2827       });
       
  2828       bean.on(root, 'click', '.fp-context-menu', function(ev) {
       
  2829          ev.stopPropagation();
       
  2830       });
       
  2831       bean.on(document, 'click.outsidemenu', function(ev) {
       
  2832          common.css(menu, 'display', 'none');
       
  2833          bean.off(document, 'click.outsidemenu');
       
  2834       });
       
  2835    });
       
  2836    api.on('flashdisabled', function() {
       
  2837      rootClasses.add('is-flash-disabled');
       
  2838      api.one('ready', function() {
       
  2839        rootClasses.remove('is-flash-disabled');
       
  2840        common.find('.fp-flash-disabled', root).forEach(common.removeNode);
       
  2841      });
       
  2842      root.appendChild(common.createElement('div', {className: "fp-flash-disabled"}, 'Adobe Flash is disabled for this page, click player area to enable'));
       
  2843    });
       
  2844 
       
  2845    // poster -> background image
       
  2846    if (conf.poster) common.css(root, 'background-image', "url(" + conf.poster + ")");
       
  2847 
       
  2848    var bc = common.css(root, 'background-color'),
       
  2849       has_bg = common.css(root, 'background-image') != "none" || bc && bc != "rgba(0, 0, 0, 0)" && bc != "transparent";
       
  2850 
       
  2851    // is-poster class
       
  2852    if (has_bg && !conf.splash && !conf.autoplay) {
       
  2853 
       
  2854       api.on("ready stop", function() {
       
  2855          rootClasses.add("is-poster");
       
  2856          api.one("progress", function() {
       
  2857             rootClasses.remove("is-poster");
       
  2858          });
       
  2859       });
       
  2860 
       
  2861    }
       
  2862 
       
  2863    if (typeof conf.splash === 'string') {
       
  2864      common.css(root, 'background-image', "url('" + conf.splash + "')");
       
  2865    }
       
  2866 
       
  2867    // default background color if not present
       
  2868    if (!has_bg && api.forcedSplash) {
       
  2869       common.css(root, "background-color", "#555");
       
  2870    }
       
  2871 
       
  2872    bean.on(root, 'click', '.fp-toggle, .fp-play', function() {
       
  2873      if (api.disabled) return;
       
  2874      api.toggle();
       
  2875    });
       
  2876 
       
  2877    /* controlbar elements */
       
  2878    bean.on(root, 'click', '.fp-mute', function() { api.mute(); });
       
  2879    bean.on(root, 'click', '.fp-fullscreen', function() { api.fullscreen(); });
       
  2880    bean.on(root, 'click', '.fp-unload', function() { api.unload(); });
       
  2881 
       
  2882    bean.on(timeline, 'slide', function(val) {
       
  2883      api.seeking = true;
       
  2884      api.seek(val * api.video.duration);
       
  2885    });
       
  2886 
       
  2887    bean.on(volumeSlider, 'slide', function(val) {
       
  2888       api.volume(val);
       
  2889    });
       
  2890 
       
  2891    // times
       
  2892 
       
  2893    var time = find('time');
       
  2894    bean.on(root, 'click', '.fp-time', function() {
       
  2895      ClassList(time).toggle('is-inverted');
       
  2896    });
       
  2897 
       
  2898    hover(noToggle);
       
  2899 
       
  2900    api.on('shutdown', function() {
       
  2901      bean.off(timeline);
       
  2902      bean.off(volumeSlider);
       
  2903    });
       
  2904 
       
  2905 });
       
  2906 
       
  2907 
       
  2908 module.exports.format = format;
       
  2909 
       
  2910 },{"../common":1,"../flowplayer":18,"./slider":14,"bean":20,"class-list":22}],18:[function(_dereq_,module,exports){
       
  2911 'use strict';
       
  2912 var extend = _dereq_('extend-object'),
       
  2913     isFunction = _dereq_('is-function'),
       
  2914     ClassList = _dereq_('class-list'),
       
  2915     bean = _dereq_('bean'),
       
  2916     common = _dereq_('./common'),
       
  2917     events = _dereq_('./ext/events');
       
  2918 
       
  2919 var instances = [],
       
  2920    extensions = [],
       
  2921    UA = window.navigator.userAgent;
       
  2922 
       
  2923 
       
  2924 var oldHandler = window.onbeforeunload;
       
  2925 window.onbeforeunload = function(ev) {
       
  2926   instances.forEach(function(api) {
       
  2927     if (api.conf.splash) {
       
  2928       api.unload();
       
  2929     } else {
       
  2930       api.bind("error", function () {
       
  2931         common.find('.flowplayer.is-error .fp-message').forEach(common.removeNode);
       
  2932       });
       
  2933     }
       
  2934   });
       
  2935   if (oldHandler) return oldHandler(ev);
       
  2936 };
       
  2937 
       
  2938 var supportLocalStorage = false;
       
  2939 try {
       
  2940   if (typeof window.localStorage == "object") {
       
  2941     window.localStorage.flowplayerTestStorage = "test";
       
  2942     supportLocalStorage = true;
       
  2943   }
       
  2944 } catch (ignored) {}
       
  2945 
       
  2946 var isSafari = /Safari/.exec(navigator.userAgent) && !/Chrome/.exec(navigator.userAgent),
       
  2947     m = /(\d+\.\d+) Safari/.exec(navigator.userAgent),
       
  2948     safariVersion = m ? Number(m[1]) : 100;
       
  2949 
       
  2950 /* flowplayer()  */
       
  2951 var flowplayer = module.exports = function(fn, opts, callback) {
       
  2952   if (isFunction(fn)) return extensions.push(fn);
       
  2953   if (typeof fn == 'number' || typeof fn === 'undefined') return instances[fn || 0];
       
  2954   if (fn.nodeType) { // Is an element
       
  2955     if (fn.getAttribute('data-flowplayer-instance-id') !== null) { // Already flowplayer instance
       
  2956       return instances[fn.getAttribute('data-flowplayer-instance-id')];
       
  2957     }
       
  2958     if (!opts) return; // Can't initialize without data
       
  2959     return initializePlayer(fn, opts, callback);
       
  2960   }
       
  2961   if (fn.jquery) return flowplayer(fn[0], opts, callback);
       
  2962   if (typeof fn === 'string') {
       
  2963     var el = common.find(fn)[0];
       
  2964     return el && flowplayer(el, opts, callback);
       
  2965   }
       
  2966 };
       
  2967 
       
  2968 extend(flowplayer, {
       
  2969 
       
  2970    version: '6.0.3',
       
  2971 
       
  2972    engines: [],
       
  2973 
       
  2974    conf: {},
       
  2975 
       
  2976    set: function(key, value) {
       
  2977       if (typeof key === 'string') flowplayer.conf[key] = value;
       
  2978       else extend(flowplayer.conf, key);
       
  2979    },
       
  2980 
       
  2981    support: {},
       
  2982 
       
  2983    defaults: {
       
  2984 
       
  2985       debug: supportLocalStorage ? !!localStorage.flowplayerDebug : false,
       
  2986 
       
  2987       // true = forced playback
       
  2988       disabled: false,
       
  2989 
       
  2990       fullscreen: window == window.top,
       
  2991 
       
  2992       // keyboard shortcuts
       
  2993       keyboard: true,
       
  2994 
       
  2995       // default aspect ratio
       
  2996       ratio: 9 / 16,
       
  2997 
       
  2998       adaptiveRatio: false,
       
  2999 
       
  3000       rtmp: 0,
       
  3001 
       
  3002       proxy: 'best',
       
  3003 
       
  3004       splash: false,
       
  3005 
       
  3006       live: false,
       
  3007 
       
  3008       swf: "//releases.flowplayer.org/6.0.3/flowplayer.swf",
       
  3009       swfHls: "//releases.flowplayer.org/6.0.3/flowplayerhls.swf",
       
  3010 
       
  3011       speeds: [0.25, 0.5, 1, 1.5, 2],
       
  3012 
       
  3013       tooltip: true,
       
  3014 
       
  3015       mouseoutTimeout: 5000,
       
  3016 
       
  3017       // initial volume level
       
  3018       volume: !supportLocalStorage ? 1 : localStorage.muted == "true" ? 0 : !isNaN(localStorage.volume) ? localStorage.volume || 1 : 1,
       
  3019 
       
  3020       // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#error-codes
       
  3021       errors: [
       
  3022 
       
  3023          // video exceptions
       
  3024          '',
       
  3025          'Video loading aborted',
       
  3026          'Network error',
       
  3027          'Video not properly encoded',
       
  3028          'Video file not found',
       
  3029 
       
  3030          // player exceptions
       
  3031          'Unsupported video',
       
  3032          'Skin not found',
       
  3033          'SWF file not found',
       
  3034          'Subtitles not found',
       
  3035          'Invalid RTMP URL',
       
  3036          'Unsupported video format. Try installing Adobe Flash.'
       
  3037       ],
       
  3038       errorUrls: ['','','','','','','','','','',
       
  3039          'http://get.adobe.com/flashplayer/'
       
  3040       ],
       
  3041       playlist: [],
       
  3042 
       
  3043       hlsFix: isSafari && safariVersion < 8
       
  3044 
       
  3045    },
       
  3046    // Expose utilities for plugins
       
  3047    bean: bean,
       
  3048    common: common,
       
  3049    extend: extend
       
  3050 
       
  3051 
       
  3052 
       
  3053 });
       
  3054 
       
  3055 // keep track of players
       
  3056 var playerCount = 0;
       
  3057 
       
  3058 var URLResolver = _dereq_('./ext/resolve');
       
  3059 
       
  3060 
       
  3061 
       
  3062 if (typeof window.jQuery !== 'undefined') {
       
  3063   var $ = window.jQuery;
       
  3064   // auto-install (any video tag with parent .flowplayer)
       
  3065   $(function() {
       
  3066      if (typeof $.fn.flowplayer == 'function') {
       
  3067         $('.flowplayer:has(video,script[type="application/json"])').flowplayer();
       
  3068      }
       
  3069   });
       
  3070 
       
  3071   // jQuery plugin
       
  3072   var videoTagConfig = function(videoTag) {
       
  3073     if (!videoTag.length) return {};
       
  3074     var clip = videoTag.data() || {}, conf = {};
       
  3075     $.each(['autoplay', 'loop', 'preload', 'poster'], function(i, key) {
       
  3076       var val = videoTag.attr(key);
       
  3077       if (val !== undefined && ['autoplay', 'poster'].indexOf(key) !== -1) conf[key] = val ? val : true;
       
  3078       else if (val !== undefined) clip[key] = val ? val : true;
       
  3079     });
       
  3080     clip.subtitles = videoTag.find('track').map(function() {
       
  3081       var tr = $(this);
       
  3082       return {
       
  3083         src: tr.attr('src'),
       
  3084         kind: tr.attr('kind'),
       
  3085         label: tr.attr('label'),
       
  3086         srclang: tr.attr('srclang'),
       
  3087         'default': tr.prop('default')
       
  3088       };
       
  3089     }).get();
       
  3090 
       
  3091     clip.sources = (new URLResolver()).sourcesFromVideoTag(videoTag, $);
       
  3092     return extend(conf, {clip: clip});
       
  3093   };
       
  3094   $.fn.flowplayer = function(opts, callback) {
       
  3095     return this.each(function() {
       
  3096       if (typeof opts == 'string') opts = { swf: opts };
       
  3097       if (isFunction(opts)) { callback = opts; opts = {}; }
       
  3098       var root = $(this),
       
  3099           scriptConf = root.find('script[type="application/json"]'),
       
  3100           confObject = scriptConf.length ? JSON.parse(scriptConf.text()) : videoTagConfig(root.find('video')),
       
  3101           conf = $.extend({}, opts || {}, confObject, root.data());
       
  3102       var api = initializePlayer(this, conf, callback);
       
  3103       events.EVENTS.forEach(function(evName) {
       
  3104         api.on(evName + '.jquery', function(ev) {
       
  3105           root.trigger.call(root, ev.type, ev.detail && ev.detail.args);
       
  3106         });
       
  3107       });
       
  3108       root.data('flowplayer', api);
       
  3109     });
       
  3110   };
       
  3111 }
       
  3112 
       
  3113 function initializePlayer(element, opts, callback) {
       
  3114   if (opts && opts.embed) opts.embed = extend({}, flowplayer.defaults.embed, opts.embed);
       
  3115 
       
  3116   var root = element,
       
  3117       rootClasses = ClassList(root),
       
  3118       conf = extend({}, flowplayer.defaults, flowplayer.conf, opts),
       
  3119       storage = {},
       
  3120       lastSeekPosition,
       
  3121       engine,
       
  3122       url,
       
  3123       urlResolver = new URLResolver();
       
  3124 
       
  3125       rootClasses.add('is-loading');
       
  3126 
       
  3127       try {
       
  3128          storage = supportLocalStorage ? window.localStorage : storage;
       
  3129       } catch(e) {}
       
  3130 
       
  3131       var isRTL = (root.currentStyle && root.currentStyle.direction === 'rtl') ||
       
  3132         (window.getComputedStyle && window.getComputedStyle(root, null) !== null && window.getComputedStyle(root, null).getPropertyValue('direction') === 'rtl');
       
  3133 
       
  3134       if (isRTL) rootClasses.add('is-rtl');
       
  3135 
       
  3136       /*** API ***/
       
  3137       var api = {
       
  3138 
       
  3139          // properties
       
  3140          conf: conf,
       
  3141          currentSpeed: 1,
       
  3142          volumeLevel: conf.muted ? 0 : typeof conf.volume === "undefined" ? storage.volume * 1 : conf.volume,
       
  3143          video: {},
       
  3144 
       
  3145          // states
       
  3146          disabled: false,
       
  3147          finished: false,
       
  3148          loading: false,
       
  3149          muted: storage.muted == "true" || conf.muted,
       
  3150          paused: false,
       
  3151          playing: false,
       
  3152          ready: false,
       
  3153          splash: false,
       
  3154          rtl: isRTL,
       
  3155 
       
  3156          // methods
       
  3157          load: function(video, callback) {
       
  3158 
       
  3159             if (api.error || api.loading) return;
       
  3160             api.video = {};
       
  3161 
       
  3162             api.finished = false;
       
  3163 
       
  3164             video = video || conf.clip;
       
  3165 
       
  3166             // resolve URL
       
  3167             video = extend({}, urlResolver.resolve(video, conf.clip.sources));
       
  3168             if (api.playing || api.engine) video.autoplay = true;
       
  3169             var engineImpl = selectEngine(video);
       
  3170             if (!engineImpl) return api.trigger("error", [api, { code: flowplayer.support.flashVideo ? 5 : 10 }]);
       
  3171             if (!engineImpl.engineName) throw new Error('engineName property of factory should be exposed');
       
  3172             if (!api.engine || engineImpl.engineName !== api.engine.engineName) {
       
  3173               api.ready = false;
       
  3174               if (api.engine) {
       
  3175                 api.engine.unload();
       
  3176                 api.conf.autoplay = true;
       
  3177               }
       
  3178               engine = api.engine = engineImpl(api, root);
       
  3179               api.one('ready', function() {
       
  3180                 engine.volume(api.volumeLevel);
       
  3181               });
       
  3182             }
       
  3183 
       
  3184             extend(video, engine.pick(video.sources.filter(function(source) { // Filter out sources explicitely configured for some other engine
       
  3185               if (!source.engine) return true;
       
  3186               return source.engine === engine.engineName;
       
  3187             })));
       
  3188 
       
  3189             if (video.src) {
       
  3190                video.src = common.createElement('a', {href: video.src}).href;
       
  3191                var e = api.trigger('load', [api, video, engine], true);
       
  3192                if (!e.defaultPrevented) {
       
  3193                   engine.load(video);
       
  3194 
       
  3195                   // callback
       
  3196                   if (isFunction(video)) callback = video;
       
  3197                   if (callback) api.one("ready", callback);
       
  3198                } else {
       
  3199                   api.loading = false;
       
  3200                }
       
  3201             }
       
  3202 
       
  3203             return api;
       
  3204          },
       
  3205 
       
  3206          pause: function(fn) {
       
  3207             if (api.ready && !api.seeking && !api.loading) {
       
  3208                engine.pause();
       
  3209                api.one("pause", fn);
       
  3210             }
       
  3211             return api;
       
  3212          },
       
  3213 
       
  3214          resume: function() {
       
  3215 
       
  3216             if (api.ready && api.paused) {
       
  3217                engine.resume();
       
  3218 
       
  3219                // Firefox (+others?) does not fire "resume" after finish
       
  3220                if (api.finished) {
       
  3221                   api.trigger("resume", [api]);
       
  3222                   api.finished = false;
       
  3223                }
       
  3224             }
       
  3225 
       
  3226             return api;
       
  3227          },
       
  3228 
       
  3229          toggle: function() {
       
  3230             return api.ready ? api.paused ? api.resume() : api.pause() : api.load();
       
  3231          },
       
  3232 
       
  3233          /*
       
  3234             seek(1.4)   -> 1.4s time
       
  3235             seek(true)  -> 10% forward
       
  3236             seek(false) -> 10% backward
       
  3237          */
       
  3238          seek: function(time, callback) {
       
  3239             if (api.ready && !api.live) {
       
  3240 
       
  3241                if (typeof time == "boolean") {
       
  3242                   var delta = api.video.duration * 0.1;
       
  3243                   time = api.video.time + (time ? delta : -delta);
       
  3244                }
       
  3245                time = lastSeekPosition = Math.min(Math.max(time, 0), api.video.duration).toFixed(1);
       
  3246                var ev = api.trigger('beforeseek', [api, time], true);
       
  3247                if (!ev.defaultPrevented) {
       
  3248                   engine.seek(time);
       
  3249                   if (isFunction(callback)) api.one("seek", callback);
       
  3250                } else {
       
  3251                   api.seeking = false;
       
  3252                   common.toggleClass(root, 'is-seeking', api.seeking); // remove loading indicator
       
  3253                }
       
  3254             }
       
  3255             return api;
       
  3256          },
       
  3257 
       
  3258          /*
       
  3259             seekTo(1) -> 10%
       
  3260             seekTo(2) -> 20%
       
  3261             seekTo(3) -> 30%
       
  3262             ...
       
  3263             seekTo()  -> last position
       
  3264          */
       
  3265          seekTo: function(position, fn) {
       
  3266             var time = position === undefined ? lastSeekPosition : api.video.duration * 0.1 * position;
       
  3267             return api.seek(time, fn);
       
  3268          },
       
  3269 
       
  3270          mute: function(flag, skipStore) {
       
  3271            if (flag === undefined) flag = !api.muted;
       
  3272            if (!skipStore) {
       
  3273              storage.muted = api.muted = flag;
       
  3274              storage.volume = !isNaN(storage.volume) ? storage.volume : conf.volume; // make sure storage has volume
       
  3275            }
       
  3276            api.volume(flag ? 0 : storage.volume, true);
       
  3277            api.trigger("mute", [api, flag]);
       
  3278            return api;
       
  3279          },
       
  3280 
       
  3281          volume: function(level, skipStore) {
       
  3282             if (api.ready) {
       
  3283               level = Math.min(Math.max(level, 0), 1);
       
  3284               if (!skipStore) storage.volume = level;
       
  3285               engine.volume(level);
       
  3286             }
       
  3287 
       
  3288             return api;
       
  3289          },
       
  3290 
       
  3291          speed: function(val, callback) {
       
  3292 
       
  3293             if (api.ready) {
       
  3294 
       
  3295                // increase / decrease
       
  3296                if (typeof val == "boolean") {
       
  3297                   val = conf.speeds[conf.speeds.indexOf(api.currentSpeed) + (val ? 1 : -1)] || api.currentSpeed;
       
  3298                }
       
  3299 
       
  3300                engine.speed(val);
       
  3301                if (callback) root.one("speed", callback);
       
  3302             }
       
  3303 
       
  3304             return api;
       
  3305          },
       
  3306 
       
  3307 
       
  3308          stop: function() {
       
  3309             if (api.ready) {
       
  3310                api.pause();
       
  3311                api.seek(0, function() {
       
  3312                   api.trigger("stop");
       
  3313                });
       
  3314             }
       
  3315             return api;
       
  3316          },
       
  3317 
       
  3318          unload: function() {
       
  3319             if (!rootClasses.contains("is-embedding")) {
       
  3320 
       
  3321                if (conf.splash) {
       
  3322                   api.trigger("unload", [api]);
       
  3323                   if (engine) engine.unload();
       
  3324                } else {
       
  3325                   api.stop();
       
  3326                }
       
  3327             }
       
  3328             return api;
       
  3329          },
       
  3330 
       
  3331          shutdown: function() {
       
  3332            api.unload();
       
  3333            api.trigger('shutdown', [api]);
       
  3334            bean.off(root);
       
  3335            delete instances[root.getAttribute('data-flowplayer-instance-id')];
       
  3336          },
       
  3337 
       
  3338          disable: function(flag) {
       
  3339             if (flag === undefined) flag = !api.disabled;
       
  3340 
       
  3341             if (flag != api.disabled) {
       
  3342                api.disabled = flag;
       
  3343                api.trigger("disable", flag);
       
  3344             }
       
  3345             return api;
       
  3346          }
       
  3347 
       
  3348       };
       
  3349 
       
  3350       api.conf = extend(api.conf, conf);
       
  3351 
       
  3352       /* event binding / unbinding */
       
  3353       events(api);
       
  3354 
       
  3355       var selectEngine = function(clip) {
       
  3356         var engine;
       
  3357         var engines = flowplayer.engines;
       
  3358         if (conf.engine) {
       
  3359           var eng = engines.filter(function(e) { return e.engineName === conf.engine; })[0];
       
  3360           if (eng && clip.sources.some(function(source) {
       
  3361             if (source.engine && source.engine !== eng.engineName) return false;
       
  3362             return eng.canPlay(source.type, api.conf);
       
  3363           })) return eng;
       
  3364         }
       
  3365         if (conf.enginePreference) engines = flowplayer.engines.filter(function(one) { return conf.enginePreference.indexOf(one.engineName) > -1; }).sort(function(a, b) {
       
  3366           return conf.enginePreference.indexOf(a.engineName) - conf.enginePreference.indexOf(b.engineName);
       
  3367         });
       
  3368         clip.sources.some(function(source) {
       
  3369           var eng = engines.filter(function(engine) {
       
  3370             if (source.engine && source.engine !== engine.engineName) return false;
       
  3371             return engine.canPlay(source.type, api.conf);
       
  3372           }).shift();
       
  3373           if (eng) engine = eng;
       
  3374           return !!eng;
       
  3375         });
       
  3376         return engine;
       
  3377       };
       
  3378 
       
  3379       /*** Behaviour ***/
       
  3380       if (!root.getAttribute('data-flowplayer-instance-id')) { // Only bind once
       
  3381          root.setAttribute('data-flowplayer-instance-id', playerCount++);
       
  3382 
       
  3383 
       
  3384          api.on('boot', function() {
       
  3385 
       
  3386             // splash
       
  3387             if (conf.splash || rootClasses.contains("is-splash") || !flowplayer.support.firstframe) {
       
  3388                api.forcedSplash = !conf.splash && !rootClasses.contains("is-splash");
       
  3389                api.splash = conf.autoplay = true;
       
  3390                if (!conf.splash) conf.splash = true;
       
  3391                rootClasses.add("is-splash");
       
  3392             }
       
  3393 
       
  3394             if (conf.splash) common.find('video', root).forEach(common.removeNode);
       
  3395 
       
  3396             if (conf.live || rootClasses.contains('is-live')) {
       
  3397                api.live = conf.live = true;
       
  3398                rootClasses.add('is-live');
       
  3399             }
       
  3400 
       
  3401             // extensions
       
  3402             extensions.forEach(function(e) {
       
  3403                e(api, root);
       
  3404             });
       
  3405 
       
  3406             // instances
       
  3407             instances.push(api);
       
  3408 
       
  3409             // start
       
  3410             if (conf.splash) api.unload(); else api.load();
       
  3411 
       
  3412             // disabled
       
  3413             if (conf.disabled) api.disable();
       
  3414 
       
  3415             // initial callback
       
  3416             api.one("ready", callback);
       
  3417 
       
  3418 
       
  3419          }).on("load", function(e, api, video) {
       
  3420 
       
  3421             // unload others
       
  3422             if (conf.splash) {
       
  3423               common.find('.flowplayer.is-ready,.flowplayer.is-loading').forEach(function(el) {
       
  3424                 var playerId = el.getAttribute('data-flowplayer-instance-id');
       
  3425                 if (playerId === root.getAttribute('data-flowplayer-instance-id')) return;
       
  3426                 var a = instances[Number(playerId)];
       
  3427                 if (a && a.conf.splash) a.unload();
       
  3428               });
       
  3429 
       
  3430             }
       
  3431 
       
  3432             // loading
       
  3433             rootClasses.add("is-loading");
       
  3434             api.loading = true;
       
  3435 
       
  3436             if (typeof video.live !== 'undefined') {
       
  3437               common.toggleClass(root, 'is-live', video.live);
       
  3438               api.live = video.live;
       
  3439             }
       
  3440 
       
  3441 
       
  3442          }).on("ready", function(e, api, video) {
       
  3443             video.time = 0;
       
  3444             api.video = video;
       
  3445 
       
  3446             rootClasses.remove("is-loading");
       
  3447             api.loading = false;
       
  3448 
       
  3449             // saved state
       
  3450             if (api.muted) api.mute(true, true);
       
  3451             else api.volume(api.volumeLevel);
       
  3452 
       
  3453             // see https://github.com/flowplayer/flowplayer/issues/479
       
  3454 
       
  3455             var hlsFix = api.conf.hlsFix && /mpegurl/i.exec(video.type);
       
  3456             common.toggleClass(root, 'hls-fix', !!hlsFix);
       
  3457 
       
  3458          }).on("unload", function(e) {
       
  3459             rootClasses.remove("is-loading");
       
  3460             api.loading = false;
       
  3461 
       
  3462 
       
  3463          }).on("ready unload", function(e) {
       
  3464            var is_ready = e.type == "ready";
       
  3465            common.toggleClass(root, 'is-splash', !is_ready);
       
  3466            common.toggleClass(root, 'is-ready', is_ready);
       
  3467            api.ready = is_ready;
       
  3468            api.splash = !is_ready;
       
  3469 
       
  3470 
       
  3471          }).on("progress", function(e, api, time) {
       
  3472             api.video.time = time;
       
  3473 
       
  3474 
       
  3475          }).on("speed", function(e, api, val) {
       
  3476             api.currentSpeed = val;
       
  3477 
       
  3478          }).on("volume", function(e, api, level) {
       
  3479             api.volumeLevel = Math.round(level * 100) / 100;
       
  3480             if (!api.muted) storage.volume = level;
       
  3481             else if (level) api.mute(false);
       
  3482 
       
  3483 
       
  3484          }).on("beforeseek seek", function(e) {
       
  3485             api.seeking = e.type == "beforeseek";
       
  3486             common.toggleClass(root, 'is-seeking', api.seeking);
       
  3487 
       
  3488          }).on("ready pause resume unload finish stop", function(e, _api, video) {
       
  3489 
       
  3490             // PAUSED: pause / finish
       
  3491             api.paused = /pause|finish|unload|stop/.test(e.type);
       
  3492             api.paused = api.paused || e.type === 'ready' && !conf.autoplay && !api.playing;
       
  3493 
       
  3494             // the opposite
       
  3495             api.playing = !api.paused;
       
  3496 
       
  3497             // CSS classes
       
  3498             common.toggleClass(root, 'is-paused', api.paused);
       
  3499             common.toggleClass(root, 'is-playing', api.playing);
       
  3500 
       
  3501             // sanity check
       
  3502             if (!api.load.ed) api.pause();
       
  3503 
       
  3504          }).on("finish", function(e) {
       
  3505             api.finished = true;
       
  3506 
       
  3507          }).on("error", function() {
       
  3508          });
       
  3509       }
       
  3510 
       
  3511       // boot
       
  3512       api.trigger('boot', [api, root]);
       
  3513   return api;
       
  3514 }
       
  3515 
       
  3516 },{"./common":1,"./ext/events":8,"./ext/resolve":13,"bean":20,"class-list":22,"extend-object":26,"is-function":27}],19:[function(_dereq_,module,exports){
       
  3517 //Flowplayer with extensions
       
  3518 
       
  3519 _dereq_('es5-shim');
       
  3520 
       
  3521 var flowplayer = module.exports = _dereq_('./flowplayer');
       
  3522 //
       
  3523 
       
  3524 //Support needed before engines
       
  3525 _dereq_('./ext/support');
       
  3526 
       
  3527 //Engines
       
  3528 _dereq_('./engine/embed');
       
  3529 _dereq_('./engine/html5');
       
  3530 _dereq_('./engine/flash');
       
  3531 
       
  3532 //Extensions
       
  3533 //require('./ext/slider'); //TODO enable
       
  3534 _dereq_('./ext/ui');
       
  3535 _dereq_('./ext/keyboard');
       
  3536 _dereq_('./ext/playlist');
       
  3537 _dereq_('./ext/cuepoint');
       
  3538 _dereq_('./ext/subtitle');
       
  3539 _dereq_('./ext/analytics');
       
  3540 _dereq_('./ext/embed');
       
  3541 //Have to add fullscreen last
       
  3542 _dereq_('./ext/fullscreen');
       
  3543 
       
  3544 _dereq_('./ext/mobile');
       
  3545 flowplayer(function(e,o){function a(e){var o=document.createElement("a");return o.href=e,t.hostname(o.hostname)}var n=function(e,o){var a=e.className.split(" ");-1===a.indexOf(o)&&(e.className+=" "+o)},r=function(e){return"none"!==window.getComputedStyle(e).display},l=e.conf,t=flowplayer.common,i=t.createElement,d=l.swf.indexOf("flowplayer.org")&&l.e&&o.getAttribute("data-origin"),s=d?a(d):t.hostname(),p=(document,l.key);"file:"==location.protocol&&(s="localhost"),e.load.ed=1,l.hostname=s,l.origin=d||location.href,d&&n(o,"is-embedded"),"string"==typeof p&&(p=p.split(/,\s*/));var f=function(e,a){var n=i("a",{href:a,className:"fp-brand"});n.innerHTML=e,t.find(".fp-controls",o)[0].appendChild(n)};if(p&&"function"==typeof key_check&&key_check(p,s)){if(l.logo){var c=i("a",{href:d,className:"fp-logo"});l.embed&&l.embed.popup&&(c.target="_blank");var h=i("img",{src:l.logo});c.appendChild(h),o.appendChild(c)}l.brand&&d||l.brand&&l.brand.showOnOrigin?f(l.brand.text||l.brand,d||location.href):t.addClass(o,"no-brand")}else{f("flowplayer","http://flowplayer.org");var c=i("a",{href:"http://flowplayer.org"});o.appendChild(c);var y=i("div",{className:"fp-context-menu"},'<ul><li class="copyright">&copy; 2015</li><li><a href="http://flowplayer.org">About Flowplayer</a></li><li><a href="http://flowplayer.org/license">GPL based license</a></li></ul>'),u=window.location.href.indexOf("localhost"),m=t.find(".fp-player",o)[0];7!==u&&(m||o).appendChild(y),e.on("pause resume finish unload ready",function(e,a){t.removeClass(o,"no-brand");var n=-1;if(a.video.src)for(var l=[["org","flowplayer","drive"],["org","flowplayer","my"]],i=0;i<l.length&&(n=a.video.src.indexOf("://"+l[i].reverse().join(".")),-1===n);i++);if((4===n||5===n)&&t.addClass(o,"no-brand"),/pause|resume/.test(e.type)&&"flash"!=a.engine.engineName&&4!=n&&5!=n){var d={display:"block",position:"absolute",left:"16px",bottom:"46px",zIndex:99999,width:"100px",height:"20px",backgroundImage:"url("+[".png","logo","/",".net",".cloudfront","d32wqyuo10o653","//"].reverse().join("")+")"};for(var s in d)d.hasOwnProperty(s)&&(c.style[s]=d[s]);a.load.ed=r(c)&&(7===u||y.parentNode==o||y.parentNode==m)&&!t.hasClass(o,"no-brand"),a.load.ed||a.pause()}else c.style.display="none"})}});
       
  3546 
       
  3547 
       
  3548 },{"./engine/embed":2,"./engine/flash":3,"./engine/html5":4,"./ext/analytics":5,"./ext/cuepoint":6,"./ext/embed":7,"./ext/fullscreen":9,"./ext/keyboard":10,"./ext/mobile":11,"./ext/playlist":12,"./ext/subtitle":15,"./ext/support":16,"./ext/ui":17,"./flowplayer":18,"es5-shim":25}],20:[function(_dereq_,module,exports){
       
  3549 /*!
       
  3550   * Bean - copyright (c) Jacob Thornton 2011-2012
       
  3551   * https://github.com/fat/bean
       
  3552   * MIT license
       
  3553   */
       
  3554 (function (name, context, definition) {
       
  3555   if (typeof module != 'undefined' && module.exports) module.exports = definition()
       
  3556   else if (typeof define == 'function' && define.amd) define(definition)
       
  3557   else context[name] = definition()
       
  3558 })('bean', this, function (name, context) {
       
  3559   name    = name    || 'bean'
       
  3560   context = context || this
       
  3561 
       
  3562   var win            = window
       
  3563     , old            = context[name]
       
  3564     , namespaceRegex = /[^\.]*(?=\..*)\.|.*/
       
  3565     , nameRegex      = /\..*/
       
  3566     , addEvent       = 'addEventListener'
       
  3567     , removeEvent    = 'removeEventListener'
       
  3568     , doc            = document || {}
       
  3569     , root           = doc.documentElement || {}
       
  3570     , W3C_MODEL      = root[addEvent]
       
  3571     , eventSupport   = W3C_MODEL ? addEvent : 'attachEvent'
       
  3572     , ONE            = {} // singleton for quick matching making add() do one()
       
  3573 
       
  3574     , slice          = Array.prototype.slice
       
  3575     , str2arr        = function (s, d) { return s.split(d || ' ') }
       
  3576     , isString       = function (o) { return typeof o == 'string' }
       
  3577     , isFunction     = function (o) { return typeof o == 'function' }
       
  3578 
       
  3579       // events that we consider to be 'native', anything not in this list will
       
  3580       // be treated as a custom event
       
  3581     , standardNativeEvents =
       
  3582         'click dblclick mouseup mousedown contextmenu '                  + // mouse buttons
       
  3583         'mousewheel mousemultiwheel DOMMouseScroll '                     + // mouse wheel
       
  3584         'mouseover mouseout mousemove selectstart selectend '            + // mouse movement
       
  3585         'keydown keypress keyup '                                        + // keyboard
       
  3586         'orientationchange '                                             + // mobile
       
  3587         'focus blur change reset select submit '                         + // form elements
       
  3588         'load unload beforeunload resize move DOMContentLoaded '         + // window
       
  3589         'readystatechange message '                                      + // window
       
  3590         'error abort scroll '                                              // misc
       
  3591       // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event
       
  3592       // that doesn't actually exist, so make sure we only do these on newer browsers
       
  3593     , w3cNativeEvents =
       
  3594         'show '                                                          + // mouse buttons
       
  3595         'input invalid '                                                 + // form elements
       
  3596         'touchstart touchmove touchend touchcancel '                     + // touch
       
  3597         'gesturestart gesturechange gestureend '                         + // gesture
       
  3598         'textinput '                                                     + // TextEvent
       
  3599         'readystatechange pageshow pagehide popstate '                   + // window
       
  3600         'hashchange offline online '                                     + // window
       
  3601         'afterprint beforeprint '                                        + // printing
       
  3602         'dragstart dragenter dragover dragleave drag drop dragend '      + // dnd
       
  3603         'loadstart progress suspend emptied stalled loadmetadata '       + // media
       
  3604         'loadeddata canplay canplaythrough playing waiting seeking '     + // media
       
  3605         'seeked ended durationchange timeupdate play pause ratechange '  + // media
       
  3606         'volumechange cuechange '                                        + // media
       
  3607         'checking noupdate downloading cached updateready obsolete '       // appcache
       
  3608 
       
  3609       // convert to a hash for quick lookups
       
  3610     , nativeEvents = (function (hash, events, i) {
       
  3611         for (i = 0; i < events.length; i++) events[i] && (hash[events[i]] = 1)
       
  3612         return hash
       
  3613       }({}, str2arr(standardNativeEvents + (W3C_MODEL ? w3cNativeEvents : ''))))
       
  3614 
       
  3615       // custom events are events that we *fake*, they are not provided natively but
       
  3616       // we can use native events to generate them
       
  3617     , customEvents = (function () {
       
  3618         var isAncestor = 'compareDocumentPosition' in root
       
  3619               ? function (element, container) {
       
  3620                   return container.compareDocumentPosition && (container.compareDocumentPosition(element) & 16) === 16
       
  3621                 }
       
  3622               : 'contains' in root
       
  3623                 ? function (element, container) {
       
  3624                     container = container.nodeType === 9 || container === window ? root : container
       
  3625                     return container !== element && container.contains(element)
       
  3626                   }
       
  3627                 : function (element, container) {
       
  3628                     while (element = element.parentNode) if (element === container) return 1
       
  3629                     return 0
       
  3630                   }
       
  3631           , check = function (event) {
       
  3632               var related = event.relatedTarget
       
  3633               return !related
       
  3634                 ? related == null
       
  3635                 : (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString())
       
  3636                     && !isAncestor(related, this))
       
  3637             }
       
  3638 
       
  3639         return {
       
  3640             mouseenter: { base: 'mouseover', condition: check }
       
  3641           , mouseleave: { base: 'mouseout', condition: check }
       
  3642           , mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
       
  3643         }
       
  3644       }())
       
  3645 
       
  3646       // we provide a consistent Event object across browsers by taking the actual DOM
       
  3647       // event object and generating a new one from its properties.
       
  3648     , Event = (function () {
       
  3649             // a whitelist of properties (for different event types) tells us what to check for and copy
       
  3650         var commonProps  = str2arr('altKey attrChange attrName bubbles cancelable ctrlKey currentTarget ' +
       
  3651               'detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey '  +
       
  3652               'srcElement target timeStamp type view which propertyName')
       
  3653           , mouseProps   = commonProps.concat(str2arr('button buttons clientX clientY dataTransfer '      +
       
  3654               'fromElement offsetX offsetY pageX pageY screenX screenY toElement'))
       
  3655           , mouseWheelProps = mouseProps.concat(str2arr('wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ ' +
       
  3656               'axis')) // 'axis' is FF specific
       
  3657           , keyProps     = commonProps.concat(str2arr('char charCode key keyCode keyIdentifier '          +
       
  3658               'keyLocation location'))
       
  3659           , textProps    = commonProps.concat(str2arr('data'))
       
  3660           , touchProps   = commonProps.concat(str2arr('touches targetTouches changedTouches scale rotation'))
       
  3661           , messageProps = commonProps.concat(str2arr('data origin source'))
       
  3662           , stateProps   = commonProps.concat(str2arr('state'))
       
  3663           , overOutRegex = /over|out/
       
  3664             // some event types need special handling and some need special properties, do that all here
       
  3665           , typeFixers   = [
       
  3666                 { // key events
       
  3667                     reg: /key/i
       
  3668                   , fix: function (event, newEvent) {
       
  3669                       newEvent.keyCode = event.keyCode || event.which
       
  3670                       return keyProps
       
  3671                     }
       
  3672                 }
       
  3673               , { // mouse events
       
  3674                     reg: /click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i
       
  3675                   , fix: function (event, newEvent, type) {
       
  3676                       newEvent.rightClick = event.which === 3 || event.button === 2
       
  3677                       newEvent.pos = { x: 0, y: 0 }
       
  3678                       if (event.pageX || event.pageY) {
       
  3679                         newEvent.clientX = event.pageX
       
  3680                         newEvent.clientY = event.pageY
       
  3681                       } else if (event.clientX || event.clientY) {
       
  3682                         newEvent.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
       
  3683                         newEvent.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
       
  3684                       }
       
  3685                       if (overOutRegex.test(type)) {
       
  3686                         newEvent.relatedTarget = event.relatedTarget
       
  3687                           || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']
       
  3688                       }
       
  3689                       return mouseProps
       
  3690                     }
       
  3691                 }
       
  3692               , { // mouse wheel events
       
  3693                     reg: /mouse.*(wheel|scroll)/i
       
  3694                   , fix: function () { return mouseWheelProps }
       
  3695                 }
       
  3696               , { // TextEvent
       
  3697                     reg: /^text/i
       
  3698                   , fix: function () { return textProps }
       
  3699                 }
       
  3700               , { // touch and gesture events
       
  3701                     reg: /^touch|^gesture/i
       
  3702                   , fix: function () { return touchProps }
       
  3703                 }
       
  3704               , { // message events
       
  3705                     reg: /^message$/i
       
  3706                   , fix: function () { return messageProps }
       
  3707                 }
       
  3708               , { // popstate events
       
  3709                     reg: /^popstate$/i
       
  3710                   , fix: function () { return stateProps }
       
  3711                 }
       
  3712               , { // everything else
       
  3713                     reg: /.*/
       
  3714                   , fix: function () { return commonProps }
       
  3715                 }
       
  3716             ]
       
  3717           , typeFixerMap = {} // used to map event types to fixer functions (above), a basic cache mechanism
       
  3718 
       
  3719           , Event = function (event, element, isNative) {
       
  3720               if (!arguments.length) return
       
  3721               event = event || ((element.ownerDocument || element.document || element).parentWindow || win).event
       
  3722               this.originalEvent = event
       
  3723               this.isNative       = isNative
       
  3724               this.isBean         = true
       
  3725 
       
  3726               if (!event) return
       
  3727 
       
  3728               var type   = event.type
       
  3729                 , target = event.target || event.srcElement
       
  3730                 , i, l, p, props, fixer
       
  3731 
       
  3732               this.target = target && target.nodeType === 3 ? target.parentNode : target
       
  3733 
       
  3734               if (isNative) { // we only need basic augmentation on custom events, the rest expensive & pointless
       
  3735                 fixer = typeFixerMap[type]
       
  3736                 if (!fixer) { // haven't encountered this event type before, map a fixer function for it
       
  3737                   for (i = 0, l = typeFixers.length; i < l; i++) {
       
  3738                     if (typeFixers[i].reg.test(type)) { // guaranteed to match at least one, last is .*
       
  3739                       typeFixerMap[type] = fixer = typeFixers[i].fix
       
  3740                       break
       
  3741                     }
       
  3742                   }
       
  3743                 }
       
  3744 
       
  3745                 props = fixer(event, this, type)
       
  3746                 for (i = props.length; i--;) {
       
  3747                   if (!((p = props[i]) in this) && p in event) this[p] = event[p]
       
  3748                 }
       
  3749               }
       
  3750             }
       
  3751 
       
  3752         // preventDefault() and stopPropagation() are a consistent interface to those functions
       
  3753         // on the DOM, stop() is an alias for both of them together
       
  3754         Event.prototype.preventDefault = function () {
       
  3755           if (this.originalEvent.preventDefault) this.originalEvent.preventDefault()
       
  3756           else this.originalEvent.returnValue = false
       
  3757         }
       
  3758         Event.prototype.stopPropagation = function () {
       
  3759           if (this.originalEvent.stopPropagation) this.originalEvent.stopPropagation()
       
  3760           else this.originalEvent.cancelBubble = true
       
  3761         }
       
  3762         Event.prototype.stop = function () {
       
  3763           this.preventDefault()
       
  3764           this.stopPropagation()
       
  3765           this.stopped = true
       
  3766         }
       
  3767         // stopImmediatePropagation() has to be handled internally because we manage the event list for
       
  3768         // each element
       
  3769         // note that originalElement may be a Bean#Event object in some situations
       
  3770         Event.prototype.stopImmediatePropagation = function () {
       
  3771           if (this.originalEvent.stopImmediatePropagation) this.originalEvent.stopImmediatePropagation()
       
  3772           this.isImmediatePropagationStopped = function () { return true }
       
  3773         }
       
  3774         Event.prototype.isImmediatePropagationStopped = function () {
       
  3775           return this.originalEvent.isImmediatePropagationStopped && this.originalEvent.isImmediatePropagationStopped()
       
  3776         }
       
  3777         Event.prototype.clone = function (currentTarget) {
       
  3778           //TODO: this is ripe for optimisation, new events are *expensive*
       
  3779           // improving this will speed up delegated events
       
  3780           var ne = new Event(this, this.element, this.isNative)
       
  3781           ne.currentTarget = currentTarget
       
  3782           return ne
       
  3783         }
       
  3784 
       
  3785         return Event
       
  3786       }())
       
  3787 
       
  3788       // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both
       
  3789     , targetElement = function (element, isNative) {
       
  3790         return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element
       
  3791       }
       
  3792 
       
  3793       /**
       
  3794         * Bean maintains an internal registry for event listeners. We don't touch elements, objects
       
  3795         * or functions to identify them, instead we store everything in the registry.
       
  3796         * Each event listener has a RegEntry object, we have one 'registry' for the whole instance.
       
  3797         */
       
  3798     , RegEntry = (function () {
       
  3799         // each handler is wrapped so we can handle delegation and custom events
       
  3800         var wrappedHandler = function (element, fn, condition, args) {
       
  3801             var call = function (event, eargs) {
       
  3802                   return fn.apply(element, args ? slice.call(eargs, event ? 0 : 1).concat(args) : eargs)
       
  3803                 }
       
  3804               , findTarget = function (event, eventElement) {
       
  3805                   return fn.__beanDel ? fn.__beanDel.ft(event.target, element) : eventElement
       
  3806                 }
       
  3807               , handler = condition
       
  3808                   ? function (event) {
       
  3809                       var target = findTarget(event, this) // deleated event
       
  3810                       if (condition.apply(target, arguments)) {
       
  3811                         if (event) event.currentTarget = target
       
  3812                         return call(event, arguments)
       
  3813                       }
       
  3814                     }
       
  3815                   : function (event) {
       
  3816                       if (fn.__beanDel) event = event.clone(findTarget(event)) // delegated event, fix the fix
       
  3817                       return call(event, arguments)
       
  3818                     }
       
  3819             handler.__beanDel = fn.__beanDel
       
  3820             return handler
       
  3821           }
       
  3822 
       
  3823         , RegEntry = function (element, type, handler, original, namespaces, args, root) {
       
  3824             var customType     = customEvents[type]
       
  3825               , isNative
       
  3826 
       
  3827             if (type == 'unload') {
       
  3828               // self clean-up
       
  3829               handler = once(removeListener, element, type, handler, original)
       
  3830             }
       
  3831 
       
  3832             if (customType) {
       
  3833               if (customType.condition) {
       
  3834                 handler = wrappedHandler(element, handler, customType.condition, args)
       
  3835               }
       
  3836               type = customType.base || type
       
  3837             }
       
  3838 
       
  3839             this.isNative      = isNative = nativeEvents[type] && !!element[eventSupport]
       
  3840             this.customType    = !W3C_MODEL && !isNative && type
       
  3841             this.element       = element
       
  3842             this.type          = type
       
  3843             this.original      = original
       
  3844             this.namespaces    = namespaces
       
  3845             this.eventType     = W3C_MODEL || isNative ? type : 'propertychange'
       
  3846             this.target        = targetElement(element, isNative)
       
  3847             this[eventSupport] = !!this.target[eventSupport]
       
  3848             this.root          = root
       
  3849             this.handler       = wrappedHandler(element, handler, null, args)
       
  3850           }
       
  3851 
       
  3852         // given a list of namespaces, is our entry in any of them?
       
  3853         RegEntry.prototype.inNamespaces = function (checkNamespaces) {
       
  3854           var i, j, c = 0
       
  3855           if (!checkNamespaces) return true
       
  3856           if (!this.namespaces) return false
       
  3857           for (i = checkNamespaces.length; i--;) {
       
  3858             for (j = this.namespaces.length; j--;) {
       
  3859               if (checkNamespaces[i] == this.namespaces[j]) c++
       
  3860             }
       
  3861           }
       
  3862           return checkNamespaces.length === c
       
  3863         }
       
  3864 
       
  3865         // match by element, original fn (opt), handler fn (opt)
       
  3866         RegEntry.prototype.matches = function (checkElement, checkOriginal, checkHandler) {
       
  3867           return this.element === checkElement &&
       
  3868             (!checkOriginal || this.original === checkOriginal) &&
       
  3869             (!checkHandler || this.handler === checkHandler)
       
  3870         }
       
  3871 
       
  3872         return RegEntry
       
  3873       }())
       
  3874 
       
  3875     , registry = (function () {
       
  3876         // our map stores arrays by event type, just because it's better than storing
       
  3877         // everything in a single array.
       
  3878         // uses '$' as a prefix for the keys for safety and 'r' as a special prefix for
       
  3879         // rootListeners so we can look them up fast
       
  3880         var map = {}
       
  3881 
       
  3882           // generic functional search of our registry for matching listeners,
       
  3883           // `fn` returns false to break out of the loop
       
  3884           , forAll = function (element, type, original, handler, root, fn) {
       
  3885               var pfx = root ? 'r' : '$'
       
  3886               if (!type || type == '*') {
       
  3887                 // search the whole registry
       
  3888                 for (var t in map) {
       
  3889                   if (t.charAt(0) == pfx) {
       
  3890                     forAll(element, t.substr(1), original, handler, root, fn)
       
  3891                   }
       
  3892                 }
       
  3893               } else {
       
  3894                 var i = 0, l, list = map[pfx + type], all = element == '*'
       
  3895                 if (!list) return
       
  3896                 for (l = list.length; i < l; i++) {
       
  3897                   if ((all || list[i].matches(element, original, handler)) && !fn(list[i], list, i, type)) return
       
  3898                 }
       
  3899               }
       
  3900             }
       
  3901 
       
  3902           , has = function (element, type, original, root) {
       
  3903               // we're not using forAll here simply because it's a bit slower and this
       
  3904               // needs to be fast
       
  3905               var i, list = map[(root ? 'r' : '$') + type]
       
  3906               if (list) {
       
  3907                 for (i = list.length; i--;) {
       
  3908                   if (!list[i].root && list[i].matches(element, original, null)) return true
       
  3909                 }
       
  3910               }
       
  3911               return false
       
  3912             }
       
  3913 
       
  3914           , get = function (element, type, original, root) {
       
  3915               var entries = []
       
  3916               forAll(element, type, original, null, root, function (entry) {
       
  3917                 return entries.push(entry)
       
  3918               })
       
  3919               return entries
       
  3920             }
       
  3921 
       
  3922           , put = function (entry) {
       
  3923               var has = !entry.root && !this.has(entry.element, entry.type, null, false)
       
  3924                 , key = (entry.root ? 'r' : '$') + entry.type
       
  3925               ;(map[key] || (map[key] = [])).push(entry)
       
  3926               return has
       
  3927             }
       
  3928 
       
  3929           , del = function (entry) {
       
  3930               forAll(entry.element, entry.type, null, entry.handler, entry.root, function (entry, list, i) {
       
  3931                 list.splice(i, 1)
       
  3932                 entry.removed = true
       
  3933                 if (list.length === 0) delete map[(entry.root ? 'r' : '$') + entry.type]
       
  3934                 return false
       
  3935               })
       
  3936             }
       
  3937 
       
  3938             // dump all entries, used for onunload
       
  3939           , entries = function () {
       
  3940               var t, entries = []
       
  3941               for (t in map) {
       
  3942                 if (t.charAt(0) == '$') entries = entries.concat(map[t])
       
  3943               }
       
  3944               return entries
       
  3945             }
       
  3946 
       
  3947         return { has: has, get: get, put: put, del: del, entries: entries }
       
  3948       }())
       
  3949 
       
  3950       // we need a selector engine for delegated events, use querySelectorAll if it exists
       
  3951       // but for older browsers we need Qwery, Sizzle or similar
       
  3952     , selectorEngine
       
  3953     , setSelectorEngine = function (e) {
       
  3954         if (!arguments.length) {
       
  3955           selectorEngine = doc.querySelectorAll
       
  3956             ? function (s, r) {
       
  3957                 return r.querySelectorAll(s)
       
  3958               }
       
  3959             : function () {
       
  3960                 throw new Error('Bean: No selector engine installed') // eeek
       
  3961               }
       
  3962         } else {
       
  3963           selectorEngine = e
       
  3964         }
       
  3965       }
       
  3966 
       
  3967       // we attach this listener to each DOM event that we need to listen to, only once
       
  3968       // per event type per DOM element
       
  3969     , rootListener = function (event, type) {
       
  3970         if (!W3C_MODEL && type && event && event.propertyName != '_on' + type) return
       
  3971 
       
  3972         var listeners = registry.get(this, type || event.type, null, false)
       
  3973           , l = listeners.length
       
  3974           , i = 0
       
  3975 
       
  3976         event = new Event(event, this, true)
       
  3977         if (type) event.type = type
       
  3978 
       
  3979         // iterate through all handlers registered for this type, calling them unless they have
       
  3980         // been removed by a previous handler or stopImmediatePropagation() has been called
       
  3981         for (; i < l && !event.isImmediatePropagationStopped(); i++) {
       
  3982           if (!listeners[i].removed) listeners[i].handler.call(this, event)
       
  3983         }
       
  3984       }
       
  3985 
       
  3986       // add and remove listeners to DOM elements
       
  3987     , listener = W3C_MODEL
       
  3988         ? function (element, type, add) {
       
  3989             // new browsers
       
  3990             element[add ? addEvent : removeEvent](type, rootListener, false)
       
  3991           }
       
  3992         : function (element, type, add, custom) {
       
  3993             // IE8 and below, use attachEvent/detachEvent and we have to piggy-back propertychange events
       
  3994             // to simulate event bubbling etc.
       
  3995             var entry
       
  3996             if (add) {
       
  3997               registry.put(entry = new RegEntry(
       
  3998                   element
       
  3999                 , custom || type
       
  4000                 , function (event) { // handler
       
  4001                     rootListener.call(element, event, custom)
       
  4002                   }
       
  4003                 , rootListener
       
  4004                 , null
       
  4005                 , null
       
  4006                 , true // is root
       
  4007               ))
       
  4008               if (custom && element['_on' + custom] == null) element['_on' + custom] = 0
       
  4009               entry.target.attachEvent('on' + entry.eventType, entry.handler)
       
  4010             } else {
       
  4011               entry = registry.get(element, custom || type, rootListener, true)[0]
       
  4012               if (entry) {
       
  4013                 entry.target.detachEvent('on' + entry.eventType, entry.handler)
       
  4014                 registry.del(entry)
       
  4015               }
       
  4016             }
       
  4017           }
       
  4018 
       
  4019     , once = function (rm, element, type, fn, originalFn) {
       
  4020         // wrap the handler in a handler that does a remove as well
       
  4021         return function () {
       
  4022           fn.apply(this, arguments)
       
  4023           rm(element, type, originalFn)
       
  4024         }
       
  4025       }
       
  4026 
       
  4027     , removeListener = function (element, orgType, handler, namespaces) {
       
  4028         var type     = orgType && orgType.replace(nameRegex, '')
       
  4029           , handlers = registry.get(element, type, null, false)
       
  4030           , removed  = {}
       
  4031           , i, l
       
  4032 
       
  4033         for (i = 0, l = handlers.length; i < l; i++) {
       
  4034           if ((!handler || handlers[i].original === handler) && handlers[i].inNamespaces(namespaces)) {
       
  4035             // TODO: this is problematic, we have a registry.get() and registry.del() that
       
  4036             // both do registry searches so we waste cycles doing this. Needs to be rolled into
       
  4037             // a single registry.forAll(fn) that removes while finding, but the catch is that
       
  4038             // we'll be splicing the arrays that we're iterating over. Needs extra tests to
       
  4039             // make sure we don't screw it up. @rvagg
       
  4040             registry.del(handlers[i])
       
  4041             if (!removed[handlers[i].eventType] && handlers[i][eventSupport])
       
  4042               removed[handlers[i].eventType] = { t: handlers[i].eventType, c: handlers[i].type }
       
  4043           }
       
  4044         }
       
  4045         // check each type/element for removed listeners and remove the rootListener where it's no longer needed
       
  4046         for (i in removed) {
       
  4047           if (!registry.has(element, removed[i].t, null, false)) {
       
  4048             // last listener of this type, remove the rootListener
       
  4049             listener(element, removed[i].t, false, removed[i].c)
       
  4050           }
       
  4051         }
       
  4052       }
       
  4053 
       
  4054       // set up a delegate helper using the given selector, wrap the handler function
       
  4055     , delegate = function (selector, fn) {
       
  4056         //TODO: findTarget (therefore $) is called twice, once for match and once for
       
  4057         // setting e.currentTarget, fix this so it's only needed once
       
  4058         var findTarget = function (target, root) {
       
  4059               var i, array = isString(selector) ? selectorEngine(selector, root) : selector
       
  4060               for (; target && target !== root; target = target.parentNode) {
       
  4061                 for (i = array.length; i--;) {
       
  4062                   if (array[i] === target) return target
       
  4063                 }
       
  4064               }
       
  4065             }
       
  4066           , handler = function (e) {
       
  4067               var match = findTarget(e.target, this)
       
  4068               if (match) fn.apply(match, arguments)
       
  4069             }
       
  4070 
       
  4071         // __beanDel isn't pleasant but it's a private function, not exposed outside of Bean
       
  4072         handler.__beanDel = {
       
  4073             ft       : findTarget // attach it here for customEvents to use too
       
  4074           , selector : selector
       
  4075         }
       
  4076         return handler
       
  4077       }
       
  4078 
       
  4079     , fireListener = W3C_MODEL ? function (isNative, type, element) {
       
  4080         // modern browsers, do a proper dispatchEvent()
       
  4081         var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents')
       
  4082         evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1)
       
  4083         element.dispatchEvent(evt)
       
  4084       } : function (isNative, type, element) {
       
  4085         // old browser use onpropertychange, just increment a custom property to trigger the event
       
  4086         element = targetElement(element, isNative)
       
  4087         isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++
       
  4088       }
       
  4089 
       
  4090       /**
       
  4091         * Public API: off(), on(), add(), (remove()), one(), fire(), clone()
       
  4092         */
       
  4093 
       
  4094       /**
       
  4095         * off(element[, eventType(s)[, handler ]])
       
  4096         */
       
  4097     , off = function (element, typeSpec, fn) {
       
  4098         var isTypeStr = isString(typeSpec)
       
  4099           , k, type, namespaces, i
       
  4100 
       
  4101         if (isTypeStr && typeSpec.indexOf(' ') > 0) {
       
  4102           // off(el, 't1 t2 t3', fn) or off(el, 't1 t2 t3')
       
  4103           typeSpec = str2arr(typeSpec)
       
  4104           for (i = typeSpec.length; i--;)
       
  4105             off(element, typeSpec[i], fn)
       
  4106           return element
       
  4107         }
       
  4108 
       
  4109         type = isTypeStr && typeSpec.replace(nameRegex, '')
       
  4110         if (type && customEvents[type]) type = customEvents[type].base
       
  4111 
       
  4112         if (!typeSpec || isTypeStr) {
       
  4113           // off(el) or off(el, t1.ns) or off(el, .ns) or off(el, .ns1.ns2.ns3)
       
  4114           if (namespaces = isTypeStr && typeSpec.replace(namespaceRegex, '')) namespaces = str2arr(namespaces, '.')
       
  4115           removeListener(element, type, fn, namespaces)
       
  4116         } else if (isFunction(typeSpec)) {
       
  4117           // off(el, fn)
       
  4118           removeListener(element, null, typeSpec)
       
  4119         } else {
       
  4120           // off(el, { t1: fn1, t2, fn2 })
       
  4121           for (k in typeSpec) {
       
  4122             if (typeSpec.hasOwnProperty(k)) off(element, k, typeSpec[k])
       
  4123           }
       
  4124         }
       
  4125 
       
  4126         return element
       
  4127       }
       
  4128 
       
  4129       /**
       
  4130         * on(element, eventType(s)[, selector], handler[, args ])
       
  4131         */
       
  4132     , on = function(element, events, selector, fn) {
       
  4133         var originalFn, type, types, i, args, entry, first
       
  4134 
       
  4135         //TODO: the undefined check means you can't pass an 'args' argument, fix this perhaps?
       
  4136         if (selector === undefined && typeof events == 'object') {
       
  4137           //TODO: this can't handle delegated events
       
  4138           for (type in events) {
       
  4139             if (events.hasOwnProperty(type)) {
       
  4140               on.call(this, element, type, events[type])
       
  4141             }
       
  4142           }
       
  4143           return
       
  4144         }
       
  4145 
       
  4146         if (!isFunction(selector)) {
       
  4147           // delegated event
       
  4148           originalFn = fn
       
  4149           args       = slice.call(arguments, 4)
       
  4150           fn         = delegate(selector, originalFn, selectorEngine)
       
  4151         } else {
       
  4152           args       = slice.call(arguments, 3)
       
  4153           fn         = originalFn = selector
       
  4154         }
       
  4155 
       
  4156         types = str2arr(events)
       
  4157 
       
  4158         // special case for one(), wrap in a self-removing handler
       
  4159         if (this === ONE) {
       
  4160           fn = once(off, element, events, fn, originalFn)
       
  4161         }
       
  4162 
       
  4163         for (i = types.length; i--;) {
       
  4164           // add new handler to the registry and check if it's the first for this element/type
       
  4165           first = registry.put(entry = new RegEntry(
       
  4166               element
       
  4167             , types[i].replace(nameRegex, '') // event type
       
  4168             , fn
       
  4169             , originalFn
       
  4170             , str2arr(types[i].replace(namespaceRegex, ''), '.') // namespaces
       
  4171             , args
       
  4172             , false // not root
       
  4173           ))
       
  4174           if (entry[eventSupport] && first) {
       
  4175             // first event of this type on this element, add root listener
       
  4176             listener(element, entry.eventType, true, entry.customType)
       
  4177           }
       
  4178         }
       
  4179 
       
  4180         return element
       
  4181       }
       
  4182 
       
  4183       /**
       
  4184         * add(element[, selector], eventType(s), handler[, args ])
       
  4185         *
       
  4186         * Deprecated: kept (for now) for backward-compatibility
       
  4187         */
       
  4188     , add = function (element, events, fn, delfn) {
       
  4189         return on.apply(
       
  4190             null
       
  4191           , !isString(fn)
       
  4192               ? slice.call(arguments)
       
  4193               : [ element, fn, events, delfn ].concat(arguments.length > 3 ? slice.call(arguments, 5) : [])
       
  4194         )
       
  4195       }
       
  4196 
       
  4197       /**
       
  4198         * one(element, eventType(s)[, selector], handler[, args ])
       
  4199         */
       
  4200     , one = function () {
       
  4201         return on.apply(ONE, arguments)
       
  4202       }
       
  4203 
       
  4204       /**
       
  4205         * fire(element, eventType(s)[, args ])
       
  4206         *
       
  4207         * The optional 'args' argument must be an array, if no 'args' argument is provided
       
  4208         * then we can use the browser's DOM event system, otherwise we trigger handlers manually
       
  4209         */
       
  4210     , fire = function (element, type, args) {
       
  4211         var types = str2arr(type)
       
  4212           , i, j, l, names, handlers
       
  4213 
       
  4214         for (i = types.length; i--;) {
       
  4215           type = types[i].replace(nameRegex, '')
       
  4216           if (names = types[i].replace(namespaceRegex, '')) names = str2arr(names, '.')
       
  4217           if (!names && !args && element[eventSupport]) {
       
  4218             fireListener(nativeEvents[type], type, element)
       
  4219           } else {
       
  4220             // non-native event, either because of a namespace, arguments or a non DOM element
       
  4221             // iterate over all listeners and manually 'fire'
       
  4222             handlers = registry.get(element, type, null, false)
       
  4223             args = [false].concat(args)
       
  4224             for (j = 0, l = handlers.length; j < l; j++) {
       
  4225               if (handlers[j].inNamespaces(names)) {
       
  4226                 handlers[j].handler.apply(element, args)
       
  4227               }
       
  4228             }
       
  4229           }
       
  4230         }
       
  4231         return element
       
  4232       }
       
  4233 
       
  4234       /**
       
  4235         * clone(dstElement, srcElement[, eventType ])
       
  4236         *
       
  4237         * TODO: perhaps for consistency we should allow the same flexibility in type specifiers?
       
  4238         */
       
  4239     , clone = function (element, from, type) {
       
  4240         var handlers = registry.get(from, type, null, false)
       
  4241           , l = handlers.length
       
  4242           , i = 0
       
  4243           , args, beanDel
       
  4244 
       
  4245         for (; i < l; i++) {
       
  4246           if (handlers[i].original) {
       
  4247             args = [ element, handlers[i].type ]
       
  4248             if (beanDel = handlers[i].handler.__beanDel) args.push(beanDel.selector)
       
  4249             args.push(handlers[i].original)
       
  4250             on.apply(null, args)
       
  4251           }
       
  4252         }
       
  4253         return element
       
  4254       }
       
  4255 
       
  4256     , bean = {
       
  4257           'on'                : on
       
  4258         , 'add'               : add
       
  4259         , 'one'               : one
       
  4260         , 'off'               : off
       
  4261         , 'remove'            : off
       
  4262         , 'clone'             : clone
       
  4263         , 'fire'              : fire
       
  4264         , 'Event'             : Event
       
  4265         , 'setSelectorEngine' : setSelectorEngine
       
  4266         , 'noConflict'        : function () {
       
  4267             context[name] = old
       
  4268             return this
       
  4269           }
       
  4270       }
       
  4271 
       
  4272   // for IE, clean up on unload to avoid leaks
       
  4273   if (win.attachEvent) {
       
  4274     var cleanup = function () {
       
  4275       var i, entries = registry.entries()
       
  4276       for (i in entries) {
       
  4277         if (entries[i].type && entries[i].type !== 'unload') off(entries[i].element, entries[i].type)
       
  4278       }
       
  4279       win.detachEvent('onunload', cleanup)
       
  4280       win.CollectGarbage && win.CollectGarbage()
       
  4281     }
       
  4282     win.attachEvent('onunload', cleanup)
       
  4283   }
       
  4284 
       
  4285   // initialize selector engine to internal default (qSA or throw Error)
       
  4286   setSelectorEngine()
       
  4287 
       
  4288   return bean
       
  4289 });
       
  4290 
       
  4291 },{}],21:[function(_dereq_,module,exports){
       
  4292 (function (global){
       
  4293 /*! http://mths.be/punycode v1.2.4 by @mathias */
       
  4294 ;(function(root) {
       
  4295 
       
  4296 	/** Detect free variables */
       
  4297 	var freeExports = typeof exports == 'object' && exports;
       
  4298 	var freeModule = typeof module == 'object' && module &&
       
  4299 		module.exports == freeExports && module;
       
  4300 	var freeGlobal = typeof global == 'object' && global;
       
  4301 	if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
       
  4302 		root = freeGlobal;
       
  4303 	}
       
  4304 
       
  4305 	/**
       
  4306 	 * The `punycode` object.
       
  4307 	 * @name punycode
       
  4308 	 * @type Object
       
  4309 	 */
       
  4310 	var punycode,
       
  4311 
       
  4312 	/** Highest positive signed 32-bit float value */
       
  4313 	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
       
  4314 
       
  4315 	/** Bootstring parameters */
       
  4316 	base = 36,
       
  4317 	tMin = 1,
       
  4318 	tMax = 26,
       
  4319 	skew = 38,
       
  4320 	damp = 700,
       
  4321 	initialBias = 72,
       
  4322 	initialN = 128, // 0x80
       
  4323 	delimiter = '-', // '\x2D'
       
  4324 
       
  4325 	/** Regular expressions */
       
  4326 	regexPunycode = /^xn--/,
       
  4327 	regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
       
  4328 	regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
       
  4329 
       
  4330 	/** Error messages */
       
  4331 	errors = {
       
  4332 		'overflow': 'Overflow: input needs wider integers to process',
       
  4333 		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
       
  4334 		'invalid-input': 'Invalid input'
       
  4335 	},
       
  4336 
       
  4337 	/** Convenience shortcuts */
       
  4338 	baseMinusTMin = base - tMin,
       
  4339 	floor = Math.floor,
       
  4340 	stringFromCharCode = String.fromCharCode,
       
  4341 
       
  4342 	/** Temporary variable */
       
  4343 	key;
       
  4344 
       
  4345 	/*--------------------------------------------------------------------------*/
       
  4346 
       
  4347 	/**
       
  4348 	 * A generic error utility function.
       
  4349 	 * @private
       
  4350 	 * @param {String} type The error type.
       
  4351 	 * @returns {Error} Throws a `RangeError` with the applicable error message.
       
  4352 	 */
       
  4353 	function error(type) {
       
  4354 		throw RangeError(errors[type]);
       
  4355 	}
       
  4356 
       
  4357 	/**
       
  4358 	 * A generic `Array#map` utility function.
       
  4359 	 * @private
       
  4360 	 * @param {Array} array The array to iterate over.
       
  4361 	 * @param {Function} callback The function that gets called for every array
       
  4362 	 * item.
       
  4363 	 * @returns {Array} A new array of values returned by the callback function.
       
  4364 	 */
       
  4365 	function map(array, fn) {
       
  4366 		var length = array.length;
       
  4367 		while (length--) {
       
  4368 			array[length] = fn(array[length]);
       
  4369 		}
       
  4370 		return array;
       
  4371 	}
       
  4372 
       
  4373 	/**
       
  4374 	 * A simple `Array#map`-like wrapper to work with domain name strings.
       
  4375 	 * @private
       
  4376 	 * @param {String} domain The domain name.
       
  4377 	 * @param {Function} callback The function that gets called for every
       
  4378 	 * character.
       
  4379 	 * @returns {Array} A new string of characters returned by the callback
       
  4380 	 * function.
       
  4381 	 */
       
  4382 	function mapDomain(string, fn) {
       
  4383 		return map(string.split(regexSeparators), fn).join('.');
       
  4384 	}
       
  4385 
       
  4386 	/**
       
  4387 	 * Creates an array containing the numeric code points of each Unicode
       
  4388 	 * character in the string. While JavaScript uses UCS-2 internally,
       
  4389 	 * this function will convert a pair of surrogate halves (each of which
       
  4390 	 * UCS-2 exposes as separate characters) into a single code point,
       
  4391 	 * matching UTF-16.
       
  4392 	 * @see `punycode.ucs2.encode`
       
  4393 	 * @see <http://mathiasbynens.be/notes/javascript-encoding>
       
  4394 	 * @memberOf punycode.ucs2
       
  4395 	 * @name decode
       
  4396 	 * @param {String} string The Unicode input string (UCS-2).
       
  4397 	 * @returns {Array} The new array of code points.
       
  4398 	 */
       
  4399 	function ucs2decode(string) {
       
  4400 		var output = [],
       
  4401 		    counter = 0,
       
  4402 		    length = string.length,
       
  4403 		    value,
       
  4404 		    extra;
       
  4405 		while (counter < length) {
       
  4406 			value = string.charCodeAt(counter++);
       
  4407 			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
       
  4408 				// high surrogate, and there is a next character
       
  4409 				extra = string.charCodeAt(counter++);
       
  4410 				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
       
  4411 					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
       
  4412 				} else {
       
  4413 					// unmatched surrogate; only append this code unit, in case the next
       
  4414 					// code unit is the high surrogate of a surrogate pair
       
  4415 					output.push(value);
       
  4416 					counter--;
       
  4417 				}
       
  4418 			} else {
       
  4419 				output.push(value);
       
  4420 			}
       
  4421 		}
       
  4422 		return output;
       
  4423 	}
       
  4424 
       
  4425 	/**
       
  4426 	 * Creates a string based on an array of numeric code points.
       
  4427 	 * @see `punycode.ucs2.decode`
       
  4428 	 * @memberOf punycode.ucs2
       
  4429 	 * @name encode
       
  4430 	 * @param {Array} codePoints The array of numeric code points.
       
  4431 	 * @returns {String} The new Unicode string (UCS-2).
       
  4432 	 */
       
  4433 	function ucs2encode(array) {
       
  4434 		return map(array, function(value) {
       
  4435 			var output = '';
       
  4436 			if (value > 0xFFFF) {
       
  4437 				value -= 0x10000;
       
  4438 				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
       
  4439 				value = 0xDC00 | value & 0x3FF;
       
  4440 			}
       
  4441 			output += stringFromCharCode(value);
       
  4442 			return output;
       
  4443 		}).join('');
       
  4444 	}
       
  4445 
       
  4446 	/**
       
  4447 	 * Converts a basic code point into a digit/integer.
       
  4448 	 * @see `digitToBasic()`
       
  4449 	 * @private
       
  4450 	 * @param {Number} codePoint The basic numeric code point value.
       
  4451 	 * @returns {Number} The numeric value of a basic code point (for use in
       
  4452 	 * representing integers) in the range `0` to `base - 1`, or `base` if
       
  4453 	 * the code point does not represent a value.
       
  4454 	 */
       
  4455 	function basicToDigit(codePoint) {
       
  4456 		if (codePoint - 48 < 10) {
       
  4457 			return codePoint - 22;
       
  4458 		}
       
  4459 		if (codePoint - 65 < 26) {
       
  4460 			return codePoint - 65;
       
  4461 		}
       
  4462 		if (codePoint - 97 < 26) {
       
  4463 			return codePoint - 97;
       
  4464 		}
       
  4465 		return base;
       
  4466 	}
       
  4467 
       
  4468 	/**
       
  4469 	 * Converts a digit/integer into a basic code point.
       
  4470 	 * @see `basicToDigit()`
       
  4471 	 * @private
       
  4472 	 * @param {Number} digit The numeric value of a basic code point.
       
  4473 	 * @returns {Number} The basic code point whose value (when used for
       
  4474 	 * representing integers) is `digit`, which needs to be in the range
       
  4475 	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
       
  4476 	 * used; else, the lowercase form is used. The behavior is undefined
       
  4477 	 * if `flag` is non-zero and `digit` has no uppercase form.
       
  4478 	 */
       
  4479 	function digitToBasic(digit, flag) {
       
  4480 		//  0..25 map to ASCII a..z or A..Z
       
  4481 		// 26..35 map to ASCII 0..9
       
  4482 		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
       
  4483 	}
       
  4484 
       
  4485 	/**
       
  4486 	 * Bias adaptation function as per section 3.4 of RFC 3492.
       
  4487 	 * http://tools.ietf.org/html/rfc3492#section-3.4
       
  4488 	 * @private
       
  4489 	 */
       
  4490 	function adapt(delta, numPoints, firstTime) {
       
  4491 		var k = 0;
       
  4492 		delta = firstTime ? floor(delta / damp) : delta >> 1;
       
  4493 		delta += floor(delta / numPoints);
       
  4494 		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
       
  4495 			delta = floor(delta / baseMinusTMin);
       
  4496 		}
       
  4497 		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
       
  4498 	}
       
  4499 
       
  4500 	/**
       
  4501 	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
       
  4502 	 * symbols.
       
  4503 	 * @memberOf punycode
       
  4504 	 * @param {String} input The Punycode string of ASCII-only symbols.
       
  4505 	 * @returns {String} The resulting string of Unicode symbols.
       
  4506 	 */
       
  4507 	function decode(input) {
       
  4508 		// Don't use UCS-2
       
  4509 		var output = [],
       
  4510 		    inputLength = input.length,
       
  4511 		    out,
       
  4512 		    i = 0,
       
  4513 		    n = initialN,
       
  4514 		    bias = initialBias,
       
  4515 		    basic,
       
  4516 		    j,
       
  4517 		    index,
       
  4518 		    oldi,
       
  4519 		    w,
       
  4520 		    k,
       
  4521 		    digit,
       
  4522 		    t,
       
  4523 		    /** Cached calculation results */
       
  4524 		    baseMinusT;
       
  4525 
       
  4526 		// Handle the basic code points: let `basic` be the number of input code
       
  4527 		// points before the last delimiter, or `0` if there is none, then copy
       
  4528 		// the first basic code points to the output.
       
  4529 
       
  4530 		basic = input.lastIndexOf(delimiter);
       
  4531 		if (basic < 0) {
       
  4532 			basic = 0;
       
  4533 		}
       
  4534 
       
  4535 		for (j = 0; j < basic; ++j) {
       
  4536 			// if it's not a basic code point
       
  4537 			if (input.charCodeAt(j) >= 0x80) {
       
  4538 				error('not-basic');
       
  4539 			}
       
  4540 			output.push(input.charCodeAt(j));
       
  4541 		}
       
  4542 
       
  4543 		// Main decoding loop: start just after the last delimiter if any basic code
       
  4544 		// points were copied; start at the beginning otherwise.
       
  4545 
       
  4546 		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
       
  4547 
       
  4548 			// `index` is the index of the next character to be consumed.
       
  4549 			// Decode a generalized variable-length integer into `delta`,
       
  4550 			// which gets added to `i`. The overflow checking is easier
       
  4551 			// if we increase `i` as we go, then subtract off its starting
       
  4552 			// value at the end to obtain `delta`.
       
  4553 			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
       
  4554 
       
  4555 				if (index >= inputLength) {
       
  4556 					error('invalid-input');
       
  4557 				}
       
  4558 
       
  4559 				digit = basicToDigit(input.charCodeAt(index++));
       
  4560 
       
  4561 				if (digit >= base || digit > floor((maxInt - i) / w)) {
       
  4562 					error('overflow');
       
  4563 				}
       
  4564 
       
  4565 				i += digit * w;
       
  4566 				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
       
  4567 
       
  4568 				if (digit < t) {
       
  4569 					break;
       
  4570 				}
       
  4571 
       
  4572 				baseMinusT = base - t;
       
  4573 				if (w > floor(maxInt / baseMinusT)) {
       
  4574 					error('overflow');
       
  4575 				}
       
  4576 
       
  4577 				w *= baseMinusT;
       
  4578 
       
  4579 			}
       
  4580 
       
  4581 			out = output.length + 1;
       
  4582 			bias = adapt(i - oldi, out, oldi == 0);
       
  4583 
       
  4584 			// `i` was supposed to wrap around from `out` to `0`,
       
  4585 			// incrementing `n` each time, so we'll fix that now:
       
  4586 			if (floor(i / out) > maxInt - n) {
       
  4587 				error('overflow');
       
  4588 			}
       
  4589 
       
  4590 			n += floor(i / out);
       
  4591 			i %= out;
       
  4592 
       
  4593 			// Insert `n` at position `i` of the output
       
  4594 			output.splice(i++, 0, n);
       
  4595 
       
  4596 		}
       
  4597 
       
  4598 		return ucs2encode(output);
       
  4599 	}
       
  4600 
       
  4601 	/**
       
  4602 	 * Converts a string of Unicode symbols to a Punycode string of ASCII-only
       
  4603 	 * symbols.
       
  4604 	 * @memberOf punycode
       
  4605 	 * @param {String} input The string of Unicode symbols.
       
  4606 	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
       
  4607 	 */
       
  4608 	function encode(input) {
       
  4609 		var n,
       
  4610 		    delta,
       
  4611 		    handledCPCount,
       
  4612 		    basicLength,
       
  4613 		    bias,
       
  4614 		    j,
       
  4615 		    m,
       
  4616 		    q,
       
  4617 		    k,
       
  4618 		    t,
       
  4619 		    currentValue,
       
  4620 		    output = [],
       
  4621 		    /** `inputLength` will hold the number of code points in `input`. */
       
  4622 		    inputLength,
       
  4623 		    /** Cached calculation results */
       
  4624 		    handledCPCountPlusOne,
       
  4625 		    baseMinusT,
       
  4626 		    qMinusT;
       
  4627 
       
  4628 		// Convert the input in UCS-2 to Unicode
       
  4629 		input = ucs2decode(input);
       
  4630 
       
  4631 		// Cache the length
       
  4632 		inputLength = input.length;
       
  4633 
       
  4634 		// Initialize the state
       
  4635 		n = initialN;
       
  4636 		delta = 0;
       
  4637 		bias = initialBias;
       
  4638 
       
  4639 		// Handle the basic code points
       
  4640 		for (j = 0; j < inputLength; ++j) {
       
  4641 			currentValue = input[j];
       
  4642 			if (currentValue < 0x80) {
       
  4643 				output.push(stringFromCharCode(currentValue));
       
  4644 			}
       
  4645 		}
       
  4646 
       
  4647 		handledCPCount = basicLength = output.length;
       
  4648 
       
  4649 		// `handledCPCount` is the number of code points that have been handled;
       
  4650 		// `basicLength` is the number of basic code points.
       
  4651 
       
  4652 		// Finish the basic string - if it is not empty - with a delimiter
       
  4653 		if (basicLength) {
       
  4654 			output.push(delimiter);
       
  4655 		}
       
  4656 
       
  4657 		// Main encoding loop:
       
  4658 		while (handledCPCount < inputLength) {
       
  4659 
       
  4660 			// All non-basic code points < n have been handled already. Find the next
       
  4661 			// larger one:
       
  4662 			for (m = maxInt, j = 0; j < inputLength; ++j) {
       
  4663 				currentValue = input[j];
       
  4664 				if (currentValue >= n && currentValue < m) {
       
  4665 					m = currentValue;
       
  4666 				}
       
  4667 			}
       
  4668 
       
  4669 			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
       
  4670 			// but guard against overflow
       
  4671 			handledCPCountPlusOne = handledCPCount + 1;
       
  4672 			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
       
  4673 				error('overflow');
       
  4674 			}
       
  4675 
       
  4676 			delta += (m - n) * handledCPCountPlusOne;
       
  4677 			n = m;
       
  4678 
       
  4679 			for (j = 0; j < inputLength; ++j) {
       
  4680 				currentValue = input[j];
       
  4681 
       
  4682 				if (currentValue < n && ++delta > maxInt) {
       
  4683 					error('overflow');
       
  4684 				}
       
  4685 
       
  4686 				if (currentValue == n) {
       
  4687 					// Represent delta as a generalized variable-length integer
       
  4688 					for (q = delta, k = base; /* no condition */; k += base) {
       
  4689 						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
       
  4690 						if (q < t) {
       
  4691 							break;
       
  4692 						}
       
  4693 						qMinusT = q - t;
       
  4694 						baseMinusT = base - t;
       
  4695 						output.push(
       
  4696 							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
       
  4697 						);
       
  4698 						q = floor(qMinusT / baseMinusT);
       
  4699 					}
       
  4700 
       
  4701 					output.push(stringFromCharCode(digitToBasic(q, 0)));
       
  4702 					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
       
  4703 					delta = 0;
       
  4704 					++handledCPCount;
       
  4705 				}
       
  4706 			}
       
  4707 
       
  4708 			++delta;
       
  4709 			++n;
       
  4710 
       
  4711 		}
       
  4712 		return output.join('');
       
  4713 	}
       
  4714 
       
  4715 	/**
       
  4716 	 * Converts a Punycode string representing a domain name to Unicode. Only the
       
  4717 	 * Punycoded parts of the domain name will be converted, i.e. it doesn't
       
  4718 	 * matter if you call it on a string that has already been converted to
       
  4719 	 * Unicode.
       
  4720 	 * @memberOf punycode
       
  4721 	 * @param {String} domain The Punycode domain name to convert to Unicode.
       
  4722 	 * @returns {String} The Unicode representation of the given Punycode
       
  4723 	 * string.
       
  4724 	 */
       
  4725 	function toUnicode(domain) {
       
  4726 		return mapDomain(domain, function(string) {
       
  4727 			return regexPunycode.test(string)
       
  4728 				? decode(string.slice(4).toLowerCase())
       
  4729 				: string;
       
  4730 		});
       
  4731 	}
       
  4732 
       
  4733 	/**
       
  4734 	 * Converts a Unicode string representing a domain name to Punycode. Only the
       
  4735 	 * non-ASCII parts of the domain name will be converted, i.e. it doesn't
       
  4736 	 * matter if you call it with a domain that's already in ASCII.
       
  4737 	 * @memberOf punycode
       
  4738 	 * @param {String} domain The domain name to convert, as a Unicode string.
       
  4739 	 * @returns {String} The Punycode representation of the given domain name.
       
  4740 	 */
       
  4741 	function toASCII(domain) {
       
  4742 		return mapDomain(domain, function(string) {
       
  4743 			return regexNonASCII.test(string)
       
  4744 				? 'xn--' + encode(string)
       
  4745 				: string;
       
  4746 		});
       
  4747 	}
       
  4748 
       
  4749 	/*--------------------------------------------------------------------------*/
       
  4750 
       
  4751 	/** Define the public API */
       
  4752 	punycode = {
       
  4753 		/**
       
  4754 		 * A string representing the current Punycode.js version number.
       
  4755 		 * @memberOf punycode
       
  4756 		 * @type String
       
  4757 		 */
       
  4758 		'version': '1.2.4',
       
  4759 		/**
       
  4760 		 * An object of methods to convert from JavaScript's internal character
       
  4761 		 * representation (UCS-2) to Unicode code points, and back.
       
  4762 		 * @see <http://mathiasbynens.be/notes/javascript-encoding>
       
  4763 		 * @memberOf punycode
       
  4764 		 * @type Object
       
  4765 		 */
       
  4766 		'ucs2': {
       
  4767 			'decode': ucs2decode,
       
  4768 			'encode': ucs2encode
       
  4769 		},
       
  4770 		'decode': decode,
       
  4771 		'encode': encode,
       
  4772 		'toASCII': toASCII,
       
  4773 		'toUnicode': toUnicode
       
  4774 	};
       
  4775 
       
  4776 	/** Expose `punycode` */
       
  4777 	// Some AMD build optimizers, like r.js, check for specific condition patterns
       
  4778 	// like the following:
       
  4779 	if (
       
  4780 		typeof define == 'function' &&
       
  4781 		typeof define.amd == 'object' &&
       
  4782 		define.amd
       
  4783 	) {
       
  4784 		define('punycode', function() {
       
  4785 			return punycode;
       
  4786 		});
       
  4787 	} else if (freeExports && !freeExports.nodeType) {
       
  4788 		if (freeModule) { // in Node.js or RingoJS v0.8.0+
       
  4789 			freeModule.exports = punycode;
       
  4790 		} else { // in Narwhal or RingoJS v0.7.0-
       
  4791 			for (key in punycode) {
       
  4792 				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
       
  4793 			}
       
  4794 		}
       
  4795 	} else { // in Rhino or a web browser
       
  4796 		root.punycode = punycode;
       
  4797 	}
       
  4798 
       
  4799 }(this));
       
  4800 
       
  4801 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
       
  4802 },{}],22:[function(_dereq_,module,exports){
       
  4803 // contains, add, remove, toggle
       
  4804 var indexof = _dereq_('indexof')
       
  4805 
       
  4806 module.exports = ClassList
       
  4807 
       
  4808 function ClassList(elem) {
       
  4809     var cl = elem.classList
       
  4810 
       
  4811     if (cl) {
       
  4812         return cl
       
  4813     }
       
  4814 
       
  4815     var classList = {
       
  4816         add: add
       
  4817         , remove: remove
       
  4818         , contains: contains
       
  4819         , toggle: toggle
       
  4820         , toString: $toString
       
  4821         , length: 0
       
  4822         , item: item
       
  4823     }
       
  4824 
       
  4825     return classList
       
  4826 
       
  4827     function add(token) {
       
  4828         var list = getTokens()
       
  4829         if (indexof(list, token) > -1) {
       
  4830             return
       
  4831         }
       
  4832         list.push(token)
       
  4833         setTokens(list)
       
  4834     }
       
  4835 
       
  4836     function remove(token) {
       
  4837         var list = getTokens()
       
  4838             , index = indexof(list, token)
       
  4839 
       
  4840         if (index === -1) {
       
  4841             return
       
  4842         }
       
  4843 
       
  4844         list.splice(index, 1)
       
  4845         setTokens(list)
       
  4846     }
       
  4847 
       
  4848     function contains(token) {
       
  4849         return indexof(getTokens(), token) > -1
       
  4850     }
       
  4851 
       
  4852     function toggle(token) {
       
  4853         if (contains(token)) {
       
  4854             remove(token)
       
  4855             return false
       
  4856         } else {
       
  4857             add(token)
       
  4858             return true
       
  4859         }
       
  4860     }
       
  4861 
       
  4862     function $toString() {
       
  4863         return elem.className
       
  4864     }
       
  4865 
       
  4866     function item(index) {
       
  4867         var tokens = getTokens()
       
  4868         return tokens[index] || null
       
  4869     }
       
  4870 
       
  4871     function getTokens() {
       
  4872         var className = elem.className
       
  4873 
       
  4874         return filter(className.split(" "), isTruthy)
       
  4875     }
       
  4876 
       
  4877     function setTokens(list) {
       
  4878         var length = list.length
       
  4879 
       
  4880         elem.className = list.join(" ")
       
  4881         classList.length = length
       
  4882 
       
  4883         for (var i = 0; i < list.length; i++) {
       
  4884             classList[i] = list[i]
       
  4885         }
       
  4886 
       
  4887         delete list[length]
       
  4888     }
       
  4889 }
       
  4890 
       
  4891 function filter (arr, fn) {
       
  4892     var ret = []
       
  4893     for (var i = 0; i < arr.length; i++) {
       
  4894         if (fn(arr[i])) ret.push(arr[i])
       
  4895     }
       
  4896     return ret
       
  4897 }
       
  4898 
       
  4899 function isTruthy(value) {
       
  4900     return !!value
       
  4901 }
       
  4902 
       
  4903 },{"indexof":23}],23:[function(_dereq_,module,exports){
       
  4904 
       
  4905 var indexOf = [].indexOf;
       
  4906 
       
  4907 module.exports = function(arr, obj){
       
  4908   if (indexOf) return arr.indexOf(obj);
       
  4909   for (var i = 0; i < arr.length; ++i) {
       
  4910     if (arr[i] === obj) return i;
       
  4911   }
       
  4912   return -1;
       
  4913 };
       
  4914 },{}],24:[function(_dereq_,module,exports){
       
  4915 // DEV: We don't use var but favor parameters since these play nicer with minification
       
  4916 function computedStyle(el, prop, getComputedStyle, style) {
       
  4917   getComputedStyle = window.getComputedStyle;
       
  4918   style =
       
  4919       // If we have getComputedStyle
       
  4920       getComputedStyle ?
       
  4921         // Query it
       
  4922         // TODO: From CSS-Query notes, we might need (node, null) for FF
       
  4923         getComputedStyle(el) :
       
  4924 
       
  4925       // Otherwise, we are in IE and use currentStyle
       
  4926         el.currentStyle;
       
  4927   if (style) {
       
  4928     return style
       
  4929     [
       
  4930       // Switch to camelCase for CSSOM
       
  4931       // DEV: Grabbed from jQuery
       
  4932       // https://github.com/jquery/jquery/blob/1.9-stable/src/css.js#L191-L194
       
  4933       // https://github.com/jquery/jquery/blob/1.9-stable/src/core.js#L593-L597
       
  4934       prop.replace(/-(\w)/gi, function (word, letter) {
       
  4935         return letter.toUpperCase();
       
  4936       })
       
  4937     ];
       
  4938   }
       
  4939 }
       
  4940 
       
  4941 module.exports = computedStyle;
       
  4942 
       
  4943 },{}],25:[function(_dereq_,module,exports){
       
  4944 /*!
       
  4945  * https://github.com/es-shims/es5-shim
       
  4946  * @license es5-shim Copyright 2009-2015 by contributors, MIT License
       
  4947  * see https://github.com/es-shims/es5-shim/blob/master/LICENSE
       
  4948  */
       
  4949 
       
  4950 // vim: ts=4 sts=4 sw=4 expandtab
       
  4951 
       
  4952 // Add semicolon to prevent IIFE from being passed as argument to concatenated code.
       
  4953 ;
       
  4954 
       
  4955 // UMD (Universal Module Definition)
       
  4956 // see https://github.com/umdjs/umd/blob/master/returnExports.js
       
  4957 (function (root, factory) {
       
  4958     'use strict';
       
  4959 
       
  4960     /* global define, exports, module */
       
  4961     if (typeof define === 'function' && define.amd) {
       
  4962         // AMD. Register as an anonymous module.
       
  4963         define(factory);
       
  4964     } else if (typeof exports === 'object') {
       
  4965         // Node. Does not work with strict CommonJS, but
       
  4966         // only CommonJS-like enviroments that support module.exports,
       
  4967         // like Node.
       
  4968         module.exports = factory();
       
  4969     } else {
       
  4970         // Browser globals (root is window)
       
  4971         root.returnExports = factory();
       
  4972     }
       
  4973 }(this, function () {
       
  4974 
       
  4975 /**
       
  4976  * Brings an environment as close to ECMAScript 5 compliance
       
  4977  * as is possible with the facilities of erstwhile engines.
       
  4978  *
       
  4979  * Annotated ES5: http://es5.github.com/ (specific links below)
       
  4980  * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
       
  4981  * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
       
  4982  */
       
  4983 
       
  4984 // Shortcut to an often accessed properties, in order to avoid multiple
       
  4985 // dereference that costs universally. This also holds a reference to known-good
       
  4986 // functions.
       
  4987 var $Array = Array;
       
  4988 var ArrayPrototype = $Array.prototype;
       
  4989 var $Object = Object;
       
  4990 var ObjectPrototype = $Object.prototype;
       
  4991 var FunctionPrototype = Function.prototype;
       
  4992 var $String = String;
       
  4993 var StringPrototype = $String.prototype;
       
  4994 var $Number = Number;
       
  4995 var NumberPrototype = $Number.prototype;
       
  4996 var array_slice = ArrayPrototype.slice;
       
  4997 var array_splice = ArrayPrototype.splice;
       
  4998 var array_push = ArrayPrototype.push;
       
  4999 var array_unshift = ArrayPrototype.unshift;
       
  5000 var array_concat = ArrayPrototype.concat;
       
  5001 var call = FunctionPrototype.call;
       
  5002 var max = Math.max;
       
  5003 var min = Math.min;
       
  5004 
       
  5005 // Having a toString local variable name breaks in Opera so use to_string.
       
  5006 var to_string = ObjectPrototype.toString;
       
  5007 
       
  5008 var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
       
  5009 var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
       
  5010 var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; };
       
  5011 var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; };
       
  5012 
       
  5013 /* inlined from http://npmjs.com/define-properties */
       
  5014 var defineProperties = (function (has) {
       
  5015   var supportsDescriptors = $Object.defineProperty && (function () {
       
  5016       try {
       
  5017           var obj = {};
       
  5018           $Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
       
  5019           for (var _ in obj) { return false; }
       
  5020           return obj.x === obj;
       
  5021       } catch (e) { /* this is ES3 */
       
  5022           return false;
       
  5023       }
       
  5024   }());
       
  5025 
       
  5026   // Define configurable, writable and non-enumerable props
       
  5027   // if they don't exist.
       
  5028   var defineProperty;
       
  5029   if (supportsDescriptors) {
       
  5030       defineProperty = function (object, name, method, forceAssign) {
       
  5031           if (!forceAssign && (name in object)) { return; }
       
  5032           $Object.defineProperty(object, name, {
       
  5033               configurable: true,
       
  5034               enumerable: false,
       
  5035               writable: true,
       
  5036               value: method
       
  5037           });
       
  5038       };
       
  5039   } else {
       
  5040       defineProperty = function (object, name, method, forceAssign) {
       
  5041           if (!forceAssign && (name in object)) { return; }
       
  5042           object[name] = method;
       
  5043       };
       
  5044   }
       
  5045   return function defineProperties(object, map, forceAssign) {
       
  5046       for (var name in map) {
       
  5047           if (has.call(map, name)) {
       
  5048             defineProperty(object, name, map[name], forceAssign);
       
  5049           }
       
  5050       }
       
  5051   };
       
  5052 }(ObjectPrototype.hasOwnProperty));
       
  5053 
       
  5054 //
       
  5055 // Util
       
  5056 // ======
       
  5057 //
       
  5058 
       
  5059 /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */
       
  5060 var isPrimitive = function isPrimitive(input) {
       
  5061     var type = typeof input;
       
  5062     return input === null || (type !== 'object' && type !== 'function');
       
  5063 };
       
  5064 
       
  5065 var ES = {
       
  5066     // ES5 9.4
       
  5067     // http://es5.github.com/#x9.4
       
  5068     // http://jsperf.com/to-integer
       
  5069     /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */
       
  5070     ToInteger: function ToInteger(num) {
       
  5071         var n = +num;
       
  5072         if (n !== n) { // isNaN
       
  5073             n = 0;
       
  5074         } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
       
  5075             n = (n > 0 || -1) * Math.floor(Math.abs(n));
       
  5076         }
       
  5077         return n;
       
  5078     },
       
  5079 
       
  5080     /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */
       
  5081     ToPrimitive: function ToPrimitive(input) {
       
  5082         var val, valueOf, toStr;
       
  5083         if (isPrimitive(input)) {
       
  5084             return input;
       
  5085         }
       
  5086         valueOf = input.valueOf;
       
  5087         if (isCallable(valueOf)) {
       
  5088             val = valueOf.call(input);
       
  5089             if (isPrimitive(val)) {
       
  5090                 return val;
       
  5091             }
       
  5092         }
       
  5093         toStr = input.toString;
       
  5094         if (isCallable(toStr)) {
       
  5095             val = toStr.call(input);
       
  5096             if (isPrimitive(val)) {
       
  5097                 return val;
       
  5098             }
       
  5099         }
       
  5100         throw new TypeError();
       
  5101     },
       
  5102 
       
  5103     // ES5 9.9
       
  5104     // http://es5.github.com/#x9.9
       
  5105     /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
       
  5106     ToObject: function (o) {
       
  5107         /* jshint eqnull: true */
       
  5108         if (o == null) { // this matches both null and undefined
       
  5109             throw new TypeError("can't convert " + o + ' to object');
       
  5110         }
       
  5111         return $Object(o);
       
  5112     },
       
  5113 
       
  5114     /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */
       
  5115     ToUint32: function ToUint32(x) {
       
  5116         return x >>> 0;
       
  5117     }
       
  5118 };
       
  5119 
       
  5120 //
       
  5121 // Function
       
  5122 // ========
       
  5123 //
       
  5124 
       
  5125 // ES-5 15.3.4.5
       
  5126 // http://es5.github.com/#x15.3.4.5
       
  5127 
       
  5128 var Empty = function Empty() {};
       
  5129 
       
  5130 defineProperties(FunctionPrototype, {
       
  5131     bind: function bind(that) { // .length is 1
       
  5132         // 1. Let Target be the this value.
       
  5133         var target = this;
       
  5134         // 2. If IsCallable(Target) is false, throw a TypeError exception.
       
  5135         if (!isCallable(target)) {
       
  5136             throw new TypeError('Function.prototype.bind called on incompatible ' + target);
       
  5137         }
       
  5138         // 3. Let A be a new (possibly empty) internal list of all of the
       
  5139         //   argument values provided after thisArg (arg1, arg2 etc), in order.
       
  5140         // XXX slicedArgs will stand in for "A" if used
       
  5141         var args = array_slice.call(arguments, 1); // for normal call
       
  5142         // 4. Let F be a new native ECMAScript object.
       
  5143         // 11. Set the [[Prototype]] internal property of F to the standard
       
  5144         //   built-in Function prototype object as specified in 15.3.3.1.
       
  5145         // 12. Set the [[Call]] internal property of F as described in
       
  5146         //   15.3.4.5.1.
       
  5147         // 13. Set the [[Construct]] internal property of F as described in
       
  5148         //   15.3.4.5.2.
       
  5149         // 14. Set the [[HasInstance]] internal property of F as described in
       
  5150         //   15.3.4.5.3.
       
  5151         var bound;
       
  5152         var binder = function () {
       
  5153 
       
  5154             if (this instanceof bound) {
       
  5155                 // 15.3.4.5.2 [[Construct]]
       
  5156                 // When the [[Construct]] internal method of a function object,
       
  5157                 // F that was created using the bind function is called with a
       
  5158                 // list of arguments ExtraArgs, the following steps are taken:
       
  5159                 // 1. Let target be the value of F's [[TargetFunction]]
       
  5160                 //   internal property.
       
  5161                 // 2. If target has no [[Construct]] internal method, a
       
  5162                 //   TypeError exception is thrown.
       
  5163                 // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
       
  5164                 //   property.
       
  5165                 // 4. Let args be a new list containing the same values as the
       
  5166                 //   list boundArgs in the same order followed by the same
       
  5167                 //   values as the list ExtraArgs in the same order.
       
  5168                 // 5. Return the result of calling the [[Construct]] internal
       
  5169                 //   method of target providing args as the arguments.
       
  5170 
       
  5171                 var result = target.apply(
       
  5172                     this,
       
  5173                     array_concat.call(args, array_slice.call(arguments))
       
  5174                 );
       
  5175                 if ($Object(result) === result) {
       
  5176                     return result;
       
  5177                 }
       
  5178                 return this;
       
  5179 
       
  5180             } else {
       
  5181                 // 15.3.4.5.1 [[Call]]
       
  5182                 // When the [[Call]] internal method of a function object, F,
       
  5183                 // which was created using the bind function is called with a
       
  5184                 // this value and a list of arguments ExtraArgs, the following
       
  5185                 // steps are taken:
       
  5186                 // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
       
  5187                 //   property.
       
  5188                 // 2. Let boundThis be the value of F's [[BoundThis]] internal
       
  5189                 //   property.
       
  5190                 // 3. Let target be the value of F's [[TargetFunction]] internal
       
  5191                 //   property.
       
  5192                 // 4. Let args be a new list containing the same values as the
       
  5193                 //   list boundArgs in the same order followed by the same
       
  5194                 //   values as the list ExtraArgs in the same order.
       
  5195                 // 5. Return the result of calling the [[Call]] internal method
       
  5196                 //   of target providing boundThis as the this value and
       
  5197                 //   providing args as the arguments.
       
  5198 
       
  5199                 // equiv: target.call(this, ...boundArgs, ...args)
       
  5200                 return target.apply(
       
  5201                     that,
       
  5202                     array_concat.call(args, array_slice.call(arguments))
       
  5203                 );
       
  5204 
       
  5205             }
       
  5206 
       
  5207         };
       
  5208 
       
  5209         // 15. If the [[Class]] internal property of Target is "Function", then
       
  5210         //     a. Let L be the length property of Target minus the length of A.
       
  5211         //     b. Set the length own property of F to either 0 or L, whichever is
       
  5212         //       larger.
       
  5213         // 16. Else set the length own property of F to 0.
       
  5214 
       
  5215         var boundLength = max(0, target.length - args.length);
       
  5216 
       
  5217         // 17. Set the attributes of the length own property of F to the values
       
  5218         //   specified in 15.3.5.1.
       
  5219         var boundArgs = [];
       
  5220         for (var i = 0; i < boundLength; i++) {
       
  5221             array_push.call(boundArgs, '$' + i);
       
  5222         }
       
  5223 
       
  5224         // XXX Build a dynamic function with desired amount of arguments is the only
       
  5225         // way to set the length property of a function.
       
  5226         // In environments where Content Security Policies enabled (Chrome extensions,
       
  5227         // for ex.) all use of eval or Function costructor throws an exception.
       
  5228         // However in all of these environments Function.prototype.bind exists
       
  5229         // and so this code will never be executed.
       
  5230         bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
       
  5231 
       
  5232         if (target.prototype) {
       
  5233             Empty.prototype = target.prototype;
       
  5234             bound.prototype = new Empty();
       
  5235             // Clean up dangling references.
       
  5236             Empty.prototype = null;
       
  5237         }
       
  5238 
       
  5239         // TODO
       
  5240         // 18. Set the [[Extensible]] internal property of F to true.
       
  5241 
       
  5242         // TODO
       
  5243         // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
       
  5244         // 20. Call the [[DefineOwnProperty]] internal method of F with
       
  5245         //   arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
       
  5246         //   thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
       
  5247         //   false.
       
  5248         // 21. Call the [[DefineOwnProperty]] internal method of F with
       
  5249         //   arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
       
  5250         //   [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
       
  5251         //   and false.
       
  5252 
       
  5253         // TODO
       
  5254         // NOTE Function objects created using Function.prototype.bind do not
       
  5255         // have a prototype property or the [[Code]], [[FormalParameters]], and
       
  5256         // [[Scope]] internal properties.
       
  5257         // XXX can't delete prototype in pure-js.
       
  5258 
       
  5259         // 22. Return F.
       
  5260         return bound;
       
  5261     }
       
  5262 });
       
  5263 
       
  5264 // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
       
  5265 // us it in defining shortcuts.
       
  5266 var owns = call.bind(ObjectPrototype.hasOwnProperty);
       
  5267 var toStr = call.bind(ObjectPrototype.toString);
       
  5268 var strSlice = call.bind(StringPrototype.slice);
       
  5269 var strSplit = call.bind(StringPrototype.split);
       
  5270 
       
  5271 //
       
  5272 // Array
       
  5273 // =====
       
  5274 //
       
  5275 
       
  5276 var isArray = $Array.isArray || function isArray(obj) {
       
  5277     return toStr(obj) === '[object Array]';
       
  5278 };
       
  5279 
       
  5280 // ES5 15.4.4.12
       
  5281 // http://es5.github.com/#x15.4.4.13
       
  5282 // Return len+argCount.
       
  5283 // [bugfix, ielt8]
       
  5284 // IE < 8 bug: [].unshift(0) === undefined but should be "1"
       
  5285 var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
       
  5286 defineProperties(ArrayPrototype, {
       
  5287     unshift: function () {
       
  5288         array_unshift.apply(this, arguments);
       
  5289         return this.length;
       
  5290     }
       
  5291 }, hasUnshiftReturnValueBug);
       
  5292 
       
  5293 // ES5 15.4.3.2
       
  5294 // http://es5.github.com/#x15.4.3.2
       
  5295 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
       
  5296 defineProperties($Array, { isArray: isArray });
       
  5297 
       
  5298 // The IsCallable() check in the Array functions
       
  5299 // has been replaced with a strict check on the
       
  5300 // internal class of the object to trap cases where
       
  5301 // the provided function was actually a regular
       
  5302 // expression literal, which in V8 and
       
  5303 // JavaScriptCore is a typeof "function".  Only in
       
  5304 // V8 are regular expression literals permitted as
       
  5305 // reduce parameters, so it is desirable in the
       
  5306 // general case for the shim to match the more
       
  5307 // strict and common behavior of rejecting regular
       
  5308 // expressions.
       
  5309 
       
  5310 // ES5 15.4.4.18
       
  5311 // http://es5.github.com/#x15.4.4.18
       
  5312 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
       
  5313 
       
  5314 // Check failure of by-index access of string characters (IE < 9)
       
  5315 // and failure of `0 in boxedString` (Rhino)
       
  5316 var boxedString = $Object('a');
       
  5317 var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
       
  5318 
       
  5319 var properlyBoxesContext = function properlyBoxed(method) {
       
  5320     // Check node 0.6.21 bug where third parameter is not boxed
       
  5321     var properlyBoxesNonStrict = true;
       
  5322     var properlyBoxesStrict = true;
       
  5323     if (method) {
       
  5324         method.call('foo', function (_, __, context) {
       
  5325             if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
       
  5326         });
       
  5327 
       
  5328         method.call([1], function () {
       
  5329             'use strict';
       
  5330 
       
  5331             properlyBoxesStrict = typeof this === 'string';
       
  5332         }, 'x');
       
  5333     }
       
  5334     return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
       
  5335 };
       
  5336 
       
  5337 defineProperties(ArrayPrototype, {
       
  5338     forEach: function forEach(callbackfn /*, thisArg*/) {
       
  5339         var object = ES.ToObject(this);
       
  5340         var self = splitString && isString(this) ? strSplit(this, '') : object;
       
  5341         var i = -1;
       
  5342         var length = self.length >>> 0;
       
  5343         var T;
       
  5344         if (arguments.length > 1) {
       
  5345           T = arguments[1];
       
  5346         }
       
  5347 
       
  5348         // If no callback function or if callback is not a callable function
       
  5349         if (!isCallable(callbackfn)) {
       
  5350             throw new TypeError('Array.prototype.forEach callback must be a function');
       
  5351         }
       
  5352 
       
  5353         while (++i < length) {
       
  5354             if (i in self) {
       
  5355                 // Invoke the callback function with call, passing arguments:
       
  5356                 // context, property value, property key, thisArg object
       
  5357                 if (typeof T !== 'undefined') {
       
  5358                     callbackfn.call(T, self[i], i, object);
       
  5359                 } else {
       
  5360                     callbackfn(self[i], i, object);
       
  5361                 }
       
  5362             }
       
  5363         }
       
  5364     }
       
  5365 }, !properlyBoxesContext(ArrayPrototype.forEach));
       
  5366 
       
  5367 // ES5 15.4.4.19
       
  5368 // http://es5.github.com/#x15.4.4.19
       
  5369 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
       
  5370 defineProperties(ArrayPrototype, {
       
  5371     map: function map(callbackfn/*, thisArg*/) {
       
  5372         var object = ES.ToObject(this);
       
  5373         var self = splitString && isString(this) ? strSplit(this, '') : object;
       
  5374         var length = self.length >>> 0;
       
  5375         var result = $Array(length);
       
  5376         var T;
       
  5377         if (arguments.length > 1) {
       
  5378             T = arguments[1];
       
  5379         }
       
  5380 
       
  5381         // If no callback function or if callback is not a callable function
       
  5382         if (!isCallable(callbackfn)) {
       
  5383             throw new TypeError('Array.prototype.map callback must be a function');
       
  5384         }
       
  5385 
       
  5386         for (var i = 0; i < length; i++) {
       
  5387             if (i in self) {
       
  5388                 if (typeof T !== 'undefined') {
       
  5389                     result[i] = callbackfn.call(T, self[i], i, object);
       
  5390                 } else {
       
  5391                     result[i] = callbackfn(self[i], i, object);
       
  5392                 }
       
  5393             }
       
  5394         }
       
  5395         return result;
       
  5396     }
       
  5397 }, !properlyBoxesContext(ArrayPrototype.map));
       
  5398 
       
  5399 // ES5 15.4.4.20
       
  5400 // http://es5.github.com/#x15.4.4.20
       
  5401 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
       
  5402 defineProperties(ArrayPrototype, {
       
  5403     filter: function filter(callbackfn /*, thisArg*/) {
       
  5404         var object = ES.ToObject(this);
       
  5405         var self = splitString && isString(this) ? strSplit(this, '') : object;
       
  5406         var length = self.length >>> 0;
       
  5407         var result = [];
       
  5408         var value;
       
  5409         var T;
       
  5410         if (arguments.length > 1) {
       
  5411             T = arguments[1];
       
  5412         }
       
  5413 
       
  5414         // If no callback function or if callback is not a callable function
       
  5415         if (!isCallable(callbackfn)) {
       
  5416             throw new TypeError('Array.prototype.filter callback must be a function');
       
  5417         }
       
  5418 
       
  5419         for (var i = 0; i < length; i++) {
       
  5420             if (i in self) {
       
  5421                 value = self[i];
       
  5422                 if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
       
  5423                     array_push.call(result, value);
       
  5424                 }
       
  5425             }
       
  5426         }
       
  5427         return result;
       
  5428     }
       
  5429 }, !properlyBoxesContext(ArrayPrototype.filter));
       
  5430 
       
  5431 // ES5 15.4.4.16
       
  5432 // http://es5.github.com/#x15.4.4.16
       
  5433 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
       
  5434 defineProperties(ArrayPrototype, {
       
  5435     every: function every(callbackfn /*, thisArg*/) {
       
  5436         var object = ES.ToObject(this);
       
  5437         var self = splitString && isString(this) ? strSplit(this, '') : object;
       
  5438         var length = self.length >>> 0;
       
  5439         var T;
       
  5440         if (arguments.length > 1) {
       
  5441             T = arguments[1];
       
  5442         }
       
  5443 
       
  5444         // If no callback function or if callback is not a callable function
       
  5445         if (!isCallable(callbackfn)) {
       
  5446             throw new TypeError('Array.prototype.every callback must be a function');
       
  5447         }
       
  5448 
       
  5449         for (var i = 0; i < length; i++) {
       
  5450             if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
       
  5451                 return false;
       
  5452             }
       
  5453         }
       
  5454         return true;
       
  5455     }
       
  5456 }, !properlyBoxesContext(ArrayPrototype.every));
       
  5457 
       
  5458 // ES5 15.4.4.17
       
  5459 // http://es5.github.com/#x15.4.4.17
       
  5460 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
       
  5461 defineProperties(ArrayPrototype, {
       
  5462     some: function some(callbackfn/*, thisArg */) {
       
  5463         var object = ES.ToObject(this);
       
  5464         var self = splitString && isString(this) ? strSplit(this, '') : object;
       
  5465         var length = self.length >>> 0;
       
  5466         var T;
       
  5467         if (arguments.length > 1) {
       
  5468             T = arguments[1];
       
  5469         }
       
  5470 
       
  5471         // If no callback function or if callback is not a callable function
       
  5472         if (!isCallable(callbackfn)) {
       
  5473             throw new TypeError('Array.prototype.some callback must be a function');
       
  5474         }
       
  5475 
       
  5476         for (var i = 0; i < length; i++) {
       
  5477             if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
       
  5478                 return true;
       
  5479             }
       
  5480         }
       
  5481         return false;
       
  5482     }
       
  5483 }, !properlyBoxesContext(ArrayPrototype.some));
       
  5484 
       
  5485 // ES5 15.4.4.21
       
  5486 // http://es5.github.com/#x15.4.4.21
       
  5487 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
       
  5488 var reduceCoercesToObject = false;
       
  5489 if (ArrayPrototype.reduce) {
       
  5490     reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
       
  5491 }
       
  5492 defineProperties(ArrayPrototype, {
       
  5493     reduce: function reduce(callbackfn /*, initialValue*/) {
       
  5494         var object = ES.ToObject(this);
       
  5495         var self = splitString && isString(this) ? strSplit(this, '') : object;
       
  5496         var length = self.length >>> 0;
       
  5497 
       
  5498         // If no callback function or if callback is not a callable function
       
  5499         if (!isCallable(callbackfn)) {
       
  5500             throw new TypeError('Array.prototype.reduce callback must be a function');
       
  5501         }
       
  5502 
       
  5503         // no value to return if no initial value and an empty array
       
  5504         if (length === 0 && arguments.length === 1) {
       
  5505             throw new TypeError('reduce of empty array with no initial value');
       
  5506         }
       
  5507 
       
  5508         var i = 0;
       
  5509         var result;
       
  5510         if (arguments.length >= 2) {
       
  5511             result = arguments[1];
       
  5512         } else {
       
  5513             do {
       
  5514                 if (i in self) {
       
  5515                     result = self[i++];
       
  5516                     break;
       
  5517                 }
       
  5518 
       
  5519                 // if array contains no values, no initial value to return
       
  5520                 if (++i >= length) {
       
  5521                     throw new TypeError('reduce of empty array with no initial value');
       
  5522                 }
       
  5523             } while (true);
       
  5524         }
       
  5525 
       
  5526         for (; i < length; i++) {
       
  5527             if (i in self) {
       
  5528                 result = callbackfn(result, self[i], i, object);
       
  5529             }
       
  5530         }
       
  5531 
       
  5532         return result;
       
  5533     }
       
  5534 }, !reduceCoercesToObject);
       
  5535 
       
  5536 // ES5 15.4.4.22
       
  5537 // http://es5.github.com/#x15.4.4.22
       
  5538 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
       
  5539 var reduceRightCoercesToObject = false;
       
  5540 if (ArrayPrototype.reduceRight) {
       
  5541     reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';
       
  5542 }
       
  5543 defineProperties(ArrayPrototype, {
       
  5544     reduceRight: function reduceRight(callbackfn/*, initial*/) {
       
  5545         var object = ES.ToObject(this);
       
  5546         var self = splitString && isString(this) ? strSplit(this, '') : object;
       
  5547         var length = self.length >>> 0;
       
  5548 
       
  5549         // If no callback function or if callback is not a callable function
       
  5550         if (!isCallable(callbackfn)) {
       
  5551             throw new TypeError('Array.prototype.reduceRight callback must be a function');
       
  5552         }
       
  5553 
       
  5554         // no value to return if no initial value, empty array
       
  5555         if (length === 0 && arguments.length === 1) {
       
  5556             throw new TypeError('reduceRight of empty array with no initial value');
       
  5557         }
       
  5558 
       
  5559         var result;
       
  5560         var i = length - 1;
       
  5561         if (arguments.length >= 2) {
       
  5562             result = arguments[1];
       
  5563         } else {
       
  5564             do {
       
  5565                 if (i in self) {
       
  5566                     result = self[i--];
       
  5567                     break;
       
  5568                 }
       
  5569 
       
  5570                 // if array contains no values, no initial value to return
       
  5571                 if (--i < 0) {
       
  5572                     throw new TypeError('reduceRight of empty array with no initial value');
       
  5573                 }
       
  5574             } while (true);
       
  5575         }
       
  5576 
       
  5577         if (i < 0) {
       
  5578             return result;
       
  5579         }
       
  5580 
       
  5581         do {
       
  5582             if (i in self) {
       
  5583                 result = callbackfn(result, self[i], i, object);
       
  5584             }
       
  5585         } while (i--);
       
  5586 
       
  5587         return result;
       
  5588     }
       
  5589 }, !reduceRightCoercesToObject);
       
  5590 
       
  5591 // ES5 15.4.4.14
       
  5592 // http://es5.github.com/#x15.4.4.14
       
  5593 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
       
  5594 var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
       
  5595 defineProperties(ArrayPrototype, {
       
  5596     indexOf: function indexOf(searchElement /*, fromIndex */) {
       
  5597         var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
       
  5598         var length = self.length >>> 0;
       
  5599 
       
  5600         if (length === 0) {
       
  5601             return -1;
       
  5602         }
       
  5603 
       
  5604         var i = 0;
       
  5605         if (arguments.length > 1) {
       
  5606             i = ES.ToInteger(arguments[1]);
       
  5607         }
       
  5608 
       
  5609         // handle negative indices
       
  5610         i = i >= 0 ? i : max(0, length + i);
       
  5611         for (; i < length; i++) {
       
  5612             if (i in self && self[i] === searchElement) {
       
  5613                 return i;
       
  5614             }
       
  5615         }
       
  5616         return -1;
       
  5617     }
       
  5618 }, hasFirefox2IndexOfBug);
       
  5619 
       
  5620 // ES5 15.4.4.15
       
  5621 // http://es5.github.com/#x15.4.4.15
       
  5622 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
       
  5623 var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
       
  5624 defineProperties(ArrayPrototype, {
       
  5625     lastIndexOf: function lastIndexOf(searchElement /*, fromIndex */) {
       
  5626         var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
       
  5627         var length = self.length >>> 0;
       
  5628 
       
  5629         if (length === 0) {
       
  5630             return -1;
       
  5631         }
       
  5632         var i = length - 1;
       
  5633         if (arguments.length > 1) {
       
  5634             i = min(i, ES.ToInteger(arguments[1]));
       
  5635         }
       
  5636         // handle negative indices
       
  5637         i = i >= 0 ? i : length - Math.abs(i);
       
  5638         for (; i >= 0; i--) {
       
  5639             if (i in self && searchElement === self[i]) {
       
  5640                 return i;
       
  5641             }
       
  5642         }
       
  5643         return -1;
       
  5644     }
       
  5645 }, hasFirefox2LastIndexOfBug);
       
  5646 
       
  5647 // ES5 15.4.4.12
       
  5648 // http://es5.github.com/#x15.4.4.12
       
  5649 var spliceNoopReturnsEmptyArray = (function () {
       
  5650     var a = [1, 2];
       
  5651     var result = a.splice();
       
  5652     return a.length === 2 && isArray(result) && result.length === 0;
       
  5653 }());
       
  5654 defineProperties(ArrayPrototype, {
       
  5655     // Safari 5.0 bug where .splice() returns undefined
       
  5656     splice: function splice(start, deleteCount) {
       
  5657         if (arguments.length === 0) {
       
  5658             return [];
       
  5659         } else {
       
  5660             return array_splice.apply(this, arguments);
       
  5661         }
       
  5662     }
       
  5663 }, !spliceNoopReturnsEmptyArray);
       
  5664 
       
  5665 var spliceWorksWithEmptyObject = (function () {
       
  5666     var obj = {};
       
  5667     ArrayPrototype.splice.call(obj, 0, 0, 1);
       
  5668     return obj.length === 1;
       
  5669 }());
       
  5670 defineProperties(ArrayPrototype, {
       
  5671     splice: function splice(start, deleteCount) {
       
  5672         if (arguments.length === 0) { return []; }
       
  5673         var args = arguments;
       
  5674         this.length = max(ES.ToInteger(this.length), 0);
       
  5675         if (arguments.length > 0 && typeof deleteCount !== 'number') {
       
  5676             args = array_slice.call(arguments);
       
  5677             if (args.length < 2) {
       
  5678                 array_push.call(args, this.length - start);
       
  5679             } else {
       
  5680                 args[1] = ES.ToInteger(deleteCount);
       
  5681             }
       
  5682         }
       
  5683         return array_splice.apply(this, args);
       
  5684     }
       
  5685 }, !spliceWorksWithEmptyObject);
       
  5686 var spliceWorksWithLargeSparseArrays = (function () {
       
  5687     // Per https://github.com/es-shims/es5-shim/issues/295
       
  5688     // Safari 7/8 breaks with sparse arrays of size 1e5 or greater
       
  5689     var arr = new $Array(1e5);
       
  5690     // note: the index MUST be 8 or larger or the test will false pass
       
  5691     arr[8] = 'x';
       
  5692     arr.splice(1, 1);
       
  5693     // note: this test must be defined *after* the indexOf shim
       
  5694     // per https://github.com/es-shims/es5-shim/issues/313
       
  5695     return arr.indexOf('x') === 7;
       
  5696 }());
       
  5697 var spliceWorksWithSmallSparseArrays = (function () {
       
  5698     // Per https://github.com/es-shims/es5-shim/issues/295
       
  5699     // Opera 12.15 breaks on this, no idea why.
       
  5700     var n = 256;
       
  5701     var arr = [];
       
  5702     arr[n] = 'a';
       
  5703     arr.splice(n + 1, 0, 'b');
       
  5704     return arr[n] === 'a';
       
  5705 }());
       
  5706 defineProperties(ArrayPrototype, {
       
  5707     splice: function splice(start, deleteCount) {
       
  5708         var O = ES.ToObject(this);
       
  5709         var A = [];
       
  5710         var len = ES.ToUint32(O.length);
       
  5711         var relativeStart = ES.ToInteger(start);
       
  5712         var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len);
       
  5713         var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart);
       
  5714 
       
  5715         var k = 0;
       
  5716         var from;
       
  5717         while (k < actualDeleteCount) {
       
  5718             from = $String(actualStart + k);
       
  5719             if (owns(O, from)) {
       
  5720                 A[k] = O[from];
       
  5721             }
       
  5722             k += 1;
       
  5723         }
       
  5724 
       
  5725         var items = array_slice.call(arguments, 2);
       
  5726         var itemCount = items.length;
       
  5727         var to;
       
  5728         if (itemCount < actualDeleteCount) {
       
  5729             k = actualStart;
       
  5730             while (k < (len - actualDeleteCount)) {
       
  5731                 from = $String(k + actualDeleteCount);
       
  5732                 to = $String(k + itemCount);
       
  5733                 if (owns(O, from)) {
       
  5734                     O[to] = O[from];
       
  5735                 } else {
       
  5736                     delete O[to];
       
  5737                 }
       
  5738                 k += 1;
       
  5739             }
       
  5740             k = len;
       
  5741             while (k > (len - actualDeleteCount + itemCount)) {
       
  5742                 delete O[k - 1];
       
  5743                 k -= 1;
       
  5744             }
       
  5745         } else if (itemCount > actualDeleteCount) {
       
  5746             k = len - actualDeleteCount;
       
  5747             while (k > actualStart) {
       
  5748                 from = $String(k + actualDeleteCount - 1);
       
  5749                 to = $String(k + itemCount - 1);
       
  5750                 if (owns(O, from)) {
       
  5751                     O[to] = O[from];
       
  5752                 } else {
       
  5753                     delete O[to];
       
  5754                 }
       
  5755                 k -= 1;
       
  5756             }
       
  5757         }
       
  5758         k = actualStart;
       
  5759         for (var i = 0; i < items.length; ++i) {
       
  5760             O[k] = items[i];
       
  5761             k += 1;
       
  5762         }
       
  5763         O.length = len - actualDeleteCount + itemCount;
       
  5764 
       
  5765         return A;
       
  5766     }
       
  5767 }, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays);
       
  5768 
       
  5769 //
       
  5770 // Object
       
  5771 // ======
       
  5772 //
       
  5773 
       
  5774 // ES5 15.2.3.14
       
  5775 // http://es5.github.com/#x15.2.3.14
       
  5776 
       
  5777 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
       
  5778 var hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString');
       
  5779 var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');
       
  5780 var hasStringEnumBug = !owns('x', '0');
       
  5781 var equalsConstructorPrototype = function (o) {
       
  5782     var ctor = o.constructor;
       
  5783     return ctor && ctor.prototype === o;
       
  5784 };
       
  5785 var blacklistedKeys = {
       
  5786     $window: true,
       
  5787     $console: true,
       
  5788     $parent: true,
       
  5789     $self: true,
       
  5790     $frames: true,
       
  5791     $frameElement: true,
       
  5792     $webkitIndexedDB: true,
       
  5793     $webkitStorageInfo: true
       
  5794 };
       
  5795 var hasAutomationEqualityBug = (function () {
       
  5796     /* globals window */
       
  5797     if (typeof window === 'undefined') { return false; }
       
  5798     for (var k in window) {
       
  5799         if (!blacklistedKeys['$' + k] && owns(window, k) && window[k] !== null && typeof window[k] === 'object') {
       
  5800             try {
       
  5801                 equalsConstructorPrototype(window[k]);
       
  5802             } catch (e) {
       
  5803                 return true;
       
  5804             }
       
  5805         }
       
  5806     }
       
  5807     return false;
       
  5808 }());
       
  5809 var equalsConstructorPrototypeIfNotBuggy = function (object) {
       
  5810     if (typeof window === 'undefined' || !hasAutomationEqualityBug) { return equalsConstructorPrototype(object); }
       
  5811     try {
       
  5812         return equalsConstructorPrototype(object);
       
  5813     } catch (e) {
       
  5814         return false;
       
  5815     }
       
  5816 };
       
  5817 var dontEnums = [
       
  5818     'toString',
       
  5819     'toLocaleString',
       
  5820     'valueOf',
       
  5821     'hasOwnProperty',
       
  5822     'isPrototypeOf',
       
  5823     'propertyIsEnumerable',
       
  5824     'constructor'
       
  5825 ];
       
  5826 var dontEnumsLength = dontEnums.length;
       
  5827 
       
  5828 var isArguments = function isArguments(value) {
       
  5829     var str = toStr(value);
       
  5830     var isArgs = str === '[object Arguments]';
       
  5831     if (!isArgs) {
       
  5832         isArgs = !isArray(value) &&
       
  5833           value !== null &&
       
  5834           typeof value === 'object' &&
       
  5835           typeof value.length === 'number' &&
       
  5836           value.length >= 0 &&
       
  5837           isCallable(value.callee);
       
  5838     }
       
  5839     return isArgs;
       
  5840 };
       
  5841 
       
  5842 defineProperties($Object, {
       
  5843     keys: function keys(object) {
       
  5844         var isFn = isCallable(object);
       
  5845         var isArgs = isArguments(object);
       
  5846         var isObject = object !== null && typeof object === 'object';
       
  5847         var isStr = isObject && isString(object);
       
  5848 
       
  5849         if (!isObject && !isFn && !isArgs) {
       
  5850             throw new TypeError('Object.keys called on a non-object');
       
  5851         }
       
  5852 
       
  5853         var theKeys = [];
       
  5854         var skipProto = hasProtoEnumBug && isFn;
       
  5855         if ((isStr && hasStringEnumBug) || isArgs) {
       
  5856             for (var i = 0; i < object.length; ++i) {
       
  5857                 array_push.call(theKeys, $String(i));
       
  5858             }
       
  5859         }
       
  5860 
       
  5861         if (!isArgs) {
       
  5862             for (var name in object) {
       
  5863                 if (!(skipProto && name === 'prototype') && owns(object, name)) {
       
  5864                     array_push.call(theKeys, $String(name));
       
  5865                 }
       
  5866             }
       
  5867         }
       
  5868 
       
  5869         if (hasDontEnumBug) {
       
  5870             var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
       
  5871             for (var j = 0; j < dontEnumsLength; j++) {
       
  5872                 var dontEnum = dontEnums[j];
       
  5873                 if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
       
  5874                     array_push.call(theKeys, dontEnum);
       
  5875                 }
       
  5876             }
       
  5877         }
       
  5878         return theKeys;
       
  5879     }
       
  5880 });
       
  5881 
       
  5882 var keysWorksWithArguments = $Object.keys && (function () {
       
  5883     // Safari 5.0 bug
       
  5884     return $Object.keys(arguments).length === 2;
       
  5885 }(1, 2));
       
  5886 var originalKeys = $Object.keys;
       
  5887 defineProperties($Object, {
       
  5888     keys: function keys(object) {
       
  5889         if (isArguments(object)) {
       
  5890             return originalKeys(array_slice.call(object));
       
  5891         } else {
       
  5892             return originalKeys(object);
       
  5893         }
       
  5894     }
       
  5895 }, !keysWorksWithArguments);
       
  5896 
       
  5897 //
       
  5898 // Date
       
  5899 // ====
       
  5900 //
       
  5901 
       
  5902 // ES5 15.9.5.43
       
  5903 // http://es5.github.com/#x15.9.5.43
       
  5904 // This function returns a String value represent the instance in time
       
  5905 // represented by this Date object. The format of the String is the Date Time
       
  5906 // string format defined in 15.9.1.15. All fields are present in the String.
       
  5907 // The time zone is always UTC, denoted by the suffix Z. If the time value of
       
  5908 // this object is not a finite Number a RangeError exception is thrown.
       
  5909 var negativeDate = -62198755200000;
       
  5910 var negativeYearString = '-000001';
       
  5911 var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
       
  5912 var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';
       
  5913 
       
  5914 defineProperties(Date.prototype, {
       
  5915     toISOString: function toISOString() {
       
  5916         var result, length, value, year, month;
       
  5917         if (!isFinite(this)) {
       
  5918             throw new RangeError('Date.prototype.toISOString called on non-finite value.');
       
  5919         }
       
  5920 
       
  5921         year = this.getUTCFullYear();
       
  5922 
       
  5923         month = this.getUTCMonth();
       
  5924         // see https://github.com/es-shims/es5-shim/issues/111
       
  5925         year += Math.floor(month / 12);
       
  5926         month = (month % 12 + 12) % 12;
       
  5927 
       
  5928         // the date time string format is specified in 15.9.1.15.
       
  5929         result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
       
  5930         year = (
       
  5931             (year < 0 ? '-' : (year > 9999 ? '+' : '')) +
       
  5932             strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6)
       
  5933         );
       
  5934 
       
  5935         length = result.length;
       
  5936         while (length--) {
       
  5937             value = result[length];
       
  5938             // pad months, days, hours, minutes, and seconds to have two
       
  5939             // digits.
       
  5940             if (value < 10) {
       
  5941                 result[length] = '0' + value;
       
  5942             }
       
  5943         }
       
  5944         // pad milliseconds to have three digits.
       
  5945         return (
       
  5946             year + '-' + array_slice.call(result, 0, 2).join('-') +
       
  5947             'T' + array_slice.call(result, 2).join(':') + '.' +
       
  5948             strSlice('000' + this.getUTCMilliseconds(), -3) + 'Z'
       
  5949         );
       
  5950     }
       
  5951 }, hasNegativeDateBug || hasSafari51DateBug);
       
  5952 
       
  5953 // ES5 15.9.5.44
       
  5954 // http://es5.github.com/#x15.9.5.44
       
  5955 // This function provides a String representation of a Date object for use by
       
  5956 // JSON.stringify (15.12.3).
       
  5957 var dateToJSONIsSupported = (function () {
       
  5958     try {
       
  5959         return Date.prototype.toJSON &&
       
  5960             new Date(NaN).toJSON() === null &&
       
  5961             new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
       
  5962             Date.prototype.toJSON.call({ // generic
       
  5963                 toISOString: function () { return true; }
       
  5964             });
       
  5965     } catch (e) {
       
  5966         return false;
       
  5967     }
       
  5968 }());
       
  5969 if (!dateToJSONIsSupported) {
       
  5970     Date.prototype.toJSON = function toJSON(key) {
       
  5971         // When the toJSON method is called with argument key, the following
       
  5972         // steps are taken:
       
  5973 
       
  5974         // 1.  Let O be the result of calling ToObject, giving it the this
       
  5975         // value as its argument.
       
  5976         // 2. Let tv be ES.ToPrimitive(O, hint Number).
       
  5977         var O = $Object(this);
       
  5978         var tv = ES.ToPrimitive(O);
       
  5979         // 3. If tv is a Number and is not finite, return null.
       
  5980         if (typeof tv === 'number' && !isFinite(tv)) {
       
  5981             return null;
       
  5982         }
       
  5983         // 4. Let toISO be the result of calling the [[Get]] internal method of
       
  5984         // O with argument "toISOString".
       
  5985         var toISO = O.toISOString;
       
  5986         // 5. If IsCallable(toISO) is false, throw a TypeError exception.
       
  5987         if (!isCallable(toISO)) {
       
  5988             throw new TypeError('toISOString property is not callable');
       
  5989         }
       
  5990         // 6. Return the result of calling the [[Call]] internal method of
       
  5991         //  toISO with O as the this value and an empty argument list.
       
  5992         return toISO.call(O);
       
  5993 
       
  5994         // NOTE 1 The argument is ignored.
       
  5995 
       
  5996         // NOTE 2 The toJSON function is intentionally generic; it does not
       
  5997         // require that its this value be a Date object. Therefore, it can be
       
  5998         // transferred to other kinds of objects for use as a method. However,
       
  5999         // it does require that any such object have a toISOString method. An
       
  6000         // object is free to use the argument key to filter its
       
  6001         // stringification.
       
  6002     };
       
  6003 }
       
  6004 
       
  6005 // ES5 15.9.4.2
       
  6006 // http://es5.github.com/#x15.9.4.2
       
  6007 // based on work shared by Daniel Friesen (dantman)
       
  6008 // http://gist.github.com/303249
       
  6009 var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;
       
  6010 var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')) || !isNaN(Date.parse('2012-12-31T23:59:60.000Z'));
       
  6011 var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));
       
  6012 if (!Date.parse || doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
       
  6013     // XXX global assignment won't work in embeddings that use
       
  6014     // an alternate object for the context.
       
  6015     /* global Date: true */
       
  6016     /* eslint-disable no-undef */
       
  6017     Date = (function (NativeDate) {
       
  6018     /* eslint-enable no-undef */
       
  6019         // Date.length === 7
       
  6020         var DateShim = function Date(Y, M, D, h, m, s, ms) {
       
  6021             var length = arguments.length;
       
  6022             var date;
       
  6023             if (this instanceof NativeDate) {
       
  6024                 date = length === 1 && $String(Y) === Y ? // isString(Y)
       
  6025                     // We explicitly pass it through parse:
       
  6026                     new NativeDate(DateShim.parse(Y)) :
       
  6027                     // We have to manually make calls depending on argument
       
  6028                     // length here
       
  6029                     length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
       
  6030                     length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
       
  6031                     length >= 5 ? new NativeDate(Y, M, D, h, m) :
       
  6032                     length >= 4 ? new NativeDate(Y, M, D, h) :
       
  6033                     length >= 3 ? new NativeDate(Y, M, D) :
       
  6034                     length >= 2 ? new NativeDate(Y, M) :
       
  6035                     length >= 1 ? new NativeDate(Y) :
       
  6036                                   new NativeDate();
       
  6037             } else {
       
  6038                 date = NativeDate.apply(this, arguments);
       
  6039             }
       
  6040             // Prevent mixups with unfixed Date object
       
  6041             defineProperties(date, { constructor: DateShim }, true);
       
  6042             return date;
       
  6043         };
       
  6044 
       
  6045         // 15.9.1.15 Date Time String Format.
       
  6046         var isoDateExpression = new RegExp('^' +
       
  6047             '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign +
       
  6048                                       // 6-digit extended year
       
  6049             '(?:-(\\d{2})' + // optional month capture
       
  6050             '(?:-(\\d{2})' + // optional day capture
       
  6051             '(?:' + // capture hours:minutes:seconds.milliseconds
       
  6052                 'T(\\d{2})' + // hours capture
       
  6053                 ':(\\d{2})' + // minutes capture
       
  6054                 '(?:' + // optional :seconds.milliseconds
       
  6055                     ':(\\d{2})' + // seconds capture
       
  6056                     '(?:(\\.\\d{1,}))?' + // milliseconds capture
       
  6057                 ')?' +
       
  6058             '(' + // capture UTC offset component
       
  6059                 'Z|' + // UTC capture
       
  6060                 '(?:' + // offset specifier +/-hours:minutes
       
  6061                     '([-+])' + // sign capture
       
  6062                     '(\\d{2})' + // hours offset capture
       
  6063                     ':(\\d{2})' + // minutes offset capture
       
  6064                 ')' +
       
  6065             ')?)?)?)?' +
       
  6066         '$');
       
  6067 
       
  6068         var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
       
  6069 
       
  6070         var dayFromMonth = function dayFromMonth(year, month) {
       
  6071             var t = month > 1 ? 1 : 0;
       
  6072             return (
       
  6073                 months[month] +
       
  6074                 Math.floor((year - 1969 + t) / 4) -
       
  6075                 Math.floor((year - 1901 + t) / 100) +
       
  6076                 Math.floor((year - 1601 + t) / 400) +
       
  6077                 365 * (year - 1970)
       
  6078             );
       
  6079         };
       
  6080 
       
  6081         var toUTC = function toUTC(t) {
       
  6082             return $Number(new NativeDate(1970, 0, 1, 0, 0, 0, t));
       
  6083         };
       
  6084 
       
  6085         // Copy any custom methods a 3rd party library may have added
       
  6086         for (var key in NativeDate) {
       
  6087             if (owns(NativeDate, key)) {
       
  6088                 DateShim[key] = NativeDate[key];
       
  6089             }
       
  6090         }
       
  6091 
       
  6092         // Copy "native" methods explicitly; they may be non-enumerable
       
  6093         defineProperties(DateShim, {
       
  6094             now: NativeDate.now,
       
  6095             UTC: NativeDate.UTC
       
  6096         }, true);
       
  6097         DateShim.prototype = NativeDate.prototype;
       
  6098         defineProperties(DateShim.prototype, {
       
  6099             constructor: DateShim
       
  6100         }, true);
       
  6101 
       
  6102         // Upgrade Date.parse to handle simplified ISO 8601 strings
       
  6103         var parseShim = function parse(string) {
       
  6104             var match = isoDateExpression.exec(string);
       
  6105             if (match) {
       
  6106                 // parse months, days, hours, minutes, seconds, and milliseconds
       
  6107                 // provide default values if necessary
       
  6108                 // parse the UTC offset component
       
  6109                 var year = $Number(match[1]),
       
  6110                     month = $Number(match[2] || 1) - 1,
       
  6111                     day = $Number(match[3] || 1) - 1,
       
  6112                     hour = $Number(match[4] || 0),
       
  6113                     minute = $Number(match[5] || 0),
       
  6114                     second = $Number(match[6] || 0),
       
  6115                     millisecond = Math.floor($Number(match[7] || 0) * 1000),
       
  6116                     // When time zone is missed, local offset should be used
       
  6117                     // (ES 5.1 bug)
       
  6118                     // see https://bugs.ecmascript.org/show_bug.cgi?id=112
       
  6119                     isLocalTime = Boolean(match[4] && !match[8]),
       
  6120                     signOffset = match[9] === '-' ? 1 : -1,
       
  6121                     hourOffset = $Number(match[10] || 0),
       
  6122                     minuteOffset = $Number(match[11] || 0),
       
  6123                     result;
       
  6124                 if (
       
  6125                     hour < (
       
  6126                         minute > 0 || second > 0 || millisecond > 0 ?
       
  6127                         24 : 25
       
  6128                     ) &&
       
  6129                     minute < 60 && second < 60 && millisecond < 1000 &&
       
  6130                     month > -1 && month < 12 && hourOffset < 24 &&
       
  6131                     minuteOffset < 60 && // detect invalid offsets
       
  6132                     day > -1 &&
       
  6133                     day < (
       
  6134                         dayFromMonth(year, month + 1) -
       
  6135                         dayFromMonth(year, month)
       
  6136                     )
       
  6137                 ) {
       
  6138                     result = (
       
  6139                         (dayFromMonth(year, month) + day) * 24 +
       
  6140                         hour +
       
  6141                         hourOffset * signOffset
       
  6142                     ) * 60;
       
  6143                     result = (
       
  6144                         (result + minute + minuteOffset * signOffset) * 60 +
       
  6145                         second
       
  6146                     ) * 1000 + millisecond;
       
  6147                     if (isLocalTime) {
       
  6148                         result = toUTC(result);
       
  6149                     }
       
  6150                     if (-8.64e15 <= result && result <= 8.64e15) {
       
  6151                         return result;
       
  6152                     }
       
  6153                 }
       
  6154                 return NaN;
       
  6155             }
       
  6156             return NativeDate.parse.apply(this, arguments);
       
  6157         };
       
  6158         defineProperties(DateShim, { parse: parseShim });
       
  6159 
       
  6160         return DateShim;
       
  6161     }(Date));
       
  6162     /* global Date: false */
       
  6163 }
       
  6164 
       
  6165 // ES5 15.9.4.4
       
  6166 // http://es5.github.com/#x15.9.4.4
       
  6167 if (!Date.now) {
       
  6168     Date.now = function now() {
       
  6169         return new Date().getTime();
       
  6170     };
       
  6171 }
       
  6172 
       
  6173 //
       
  6174 // Number
       
  6175 // ======
       
  6176 //
       
  6177 
       
  6178 // ES5.1 15.7.4.5
       
  6179 // http://es5.github.com/#x15.7.4.5
       
  6180 var hasToFixedBugs = NumberPrototype.toFixed && (
       
  6181   (0.00008).toFixed(3) !== '0.000' ||
       
  6182   (0.9).toFixed(0) !== '1' ||
       
  6183   (1.255).toFixed(2) !== '1.25' ||
       
  6184   (1000000000000000128).toFixed(0) !== '1000000000000000128'
       
  6185 );
       
  6186 
       
  6187 var toFixedHelpers = {
       
  6188   base: 1e7,
       
  6189   size: 6,
       
  6190   data: [0, 0, 0, 0, 0, 0],
       
  6191   multiply: function multiply(n, c) {
       
  6192       var i = -1;
       
  6193       var c2 = c;
       
  6194       while (++i < toFixedHelpers.size) {
       
  6195           c2 += n * toFixedHelpers.data[i];
       
  6196           toFixedHelpers.data[i] = c2 % toFixedHelpers.base;
       
  6197           c2 = Math.floor(c2 / toFixedHelpers.base);
       
  6198       }
       
  6199   },
       
  6200   divide: function divide(n) {
       
  6201       var i = toFixedHelpers.size, c = 0;
       
  6202       while (--i >= 0) {
       
  6203           c += toFixedHelpers.data[i];
       
  6204           toFixedHelpers.data[i] = Math.floor(c / n);
       
  6205           c = (c % n) * toFixedHelpers.base;
       
  6206       }
       
  6207   },
       
  6208   numToString: function numToString() {
       
  6209       var i = toFixedHelpers.size;
       
  6210       var s = '';
       
  6211       while (--i >= 0) {
       
  6212           if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {
       
  6213               var t = $String(toFixedHelpers.data[i]);
       
  6214               if (s === '') {
       
  6215                   s = t;
       
  6216               } else {
       
  6217                   s += strSlice('0000000', 0, 7 - t.length) + t;
       
  6218               }
       
  6219           }
       
  6220       }
       
  6221       return s;
       
  6222   },
       
  6223   pow: function pow(x, n, acc) {
       
  6224       return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
       
  6225   },
       
  6226   log: function log(x) {
       
  6227       var n = 0;
       
  6228       var x2 = x;
       
  6229       while (x2 >= 4096) {
       
  6230           n += 12;
       
  6231           x2 /= 4096;
       
  6232       }
       
  6233       while (x2 >= 2) {
       
  6234           n += 1;
       
  6235           x2 /= 2;
       
  6236       }
       
  6237       return n;
       
  6238   }
       
  6239 };
       
  6240 
       
  6241 defineProperties(NumberPrototype, {
       
  6242     toFixed: function toFixed(fractionDigits) {
       
  6243         var f, x, s, m, e, z, j, k;
       
  6244 
       
  6245         // Test for NaN and round fractionDigits down
       
  6246         f = $Number(fractionDigits);
       
  6247         f = f !== f ? 0 : Math.floor(f);
       
  6248 
       
  6249         if (f < 0 || f > 20) {
       
  6250             throw new RangeError('Number.toFixed called with invalid number of decimals');
       
  6251         }
       
  6252 
       
  6253         x = $Number(this);
       
  6254 
       
  6255         // Test for NaN
       
  6256         if (x !== x) {
       
  6257             return 'NaN';
       
  6258         }
       
  6259 
       
  6260         // If it is too big or small, return the string value of the number
       
  6261         if (x <= -1e21 || x >= 1e21) {
       
  6262             return $String(x);
       
  6263         }
       
  6264 
       
  6265         s = '';
       
  6266 
       
  6267         if (x < 0) {
       
  6268             s = '-';
       
  6269             x = -x;
       
  6270         }
       
  6271 
       
  6272         m = '0';
       
  6273 
       
  6274         if (x > 1e-21) {
       
  6275             // 1e-21 < x < 1e21
       
  6276             // -70 < log2(x) < 70
       
  6277             e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
       
  6278             z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
       
  6279             z *= 0x10000000000000; // Math.pow(2, 52);
       
  6280             e = 52 - e;
       
  6281 
       
  6282             // -18 < e < 122
       
  6283             // x = z / 2 ^ e
       
  6284             if (e > 0) {
       
  6285                 toFixedHelpers.multiply(0, z);
       
  6286                 j = f;
       
  6287 
       
  6288                 while (j >= 7) {
       
  6289                     toFixedHelpers.multiply(1e7, 0);
       
  6290                     j -= 7;
       
  6291                 }
       
  6292 
       
  6293                 toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
       
  6294                 j = e - 1;
       
  6295 
       
  6296                 while (j >= 23) {
       
  6297                     toFixedHelpers.divide(1 << 23);
       
  6298                     j -= 23;
       
  6299                 }
       
  6300 
       
  6301                 toFixedHelpers.divide(1 << j);
       
  6302                 toFixedHelpers.multiply(1, 1);
       
  6303                 toFixedHelpers.divide(2);
       
  6304                 m = toFixedHelpers.numToString();
       
  6305             } else {
       
  6306                 toFixedHelpers.multiply(0, z);
       
  6307                 toFixedHelpers.multiply(1 << (-e), 0);
       
  6308                 m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);
       
  6309             }
       
  6310         }
       
  6311 
       
  6312         if (f > 0) {
       
  6313             k = m.length;
       
  6314 
       
  6315             if (k <= f) {
       
  6316                 m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;
       
  6317             } else {
       
  6318                 m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);
       
  6319             }
       
  6320         } else {
       
  6321             m = s + m;
       
  6322         }
       
  6323 
       
  6324         return m;
       
  6325     }
       
  6326 }, hasToFixedBugs);
       
  6327 
       
  6328 //
       
  6329 // String
       
  6330 // ======
       
  6331 //
       
  6332 
       
  6333 // ES5 15.5.4.14
       
  6334 // http://es5.github.com/#x15.5.4.14
       
  6335 
       
  6336 // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
       
  6337 // Many browsers do not split properly with regular expressions or they
       
  6338 // do not perform the split correctly under obscure conditions.
       
  6339 // See http://blog.stevenlevithan.com/archives/cross-browser-split
       
  6340 // I've tested in many browsers and this seems to cover the deviant ones:
       
  6341 //    'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
       
  6342 //    '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
       
  6343 //    'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
       
  6344 //       [undefined, "t", undefined, "e", ...]
       
  6345 //    ''.split(/.?/) should be [], not [""]
       
  6346 //    '.'.split(/()()/) should be ["."], not ["", "", "."]
       
  6347 
       
  6348 if (
       
  6349     'ab'.split(/(?:ab)*/).length !== 2 ||
       
  6350     '.'.split(/(.?)(.?)/).length !== 4 ||
       
  6351     'tesst'.split(/(s)*/)[1] === 't' ||
       
  6352     'test'.split(/(?:)/, -1).length !== 4 ||
       
  6353     ''.split(/.?/).length ||
       
  6354     '.'.split(/()()/).length > 1
       
  6355 ) {
       
  6356     (function () {
       
  6357         var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group
       
  6358 
       
  6359         StringPrototype.split = function (separator, limit) {
       
  6360             var string = this;
       
  6361             if (typeof separator === 'undefined' && limit === 0) {
       
  6362                 return [];
       
  6363             }
       
  6364 
       
  6365             // If `separator` is not a regex, use native split
       
  6366             if (!isRegex(separator)) {
       
  6367                 return strSplit(this, separator, limit);
       
  6368             }
       
  6369 
       
  6370             var output = [];
       
  6371             var flags = (separator.ignoreCase ? 'i' : '') +
       
  6372                         (separator.multiline ? 'm' : '') +
       
  6373                         (separator.unicode ? 'u' : '') + // in ES6
       
  6374                         (separator.sticky ? 'y' : ''), // Firefox 3+ and ES6
       
  6375                 lastLastIndex = 0,
       
  6376                 // Make `global` and avoid `lastIndex` issues by working with a copy
       
  6377                 separator2, match, lastIndex, lastLength;
       
  6378             var separatorCopy = new RegExp(separator.source, flags + 'g');
       
  6379             string += ''; // Type-convert
       
  6380             if (!compliantExecNpcg) {
       
  6381                 // Doesn't need flags gy, but they don't hurt
       
  6382                 separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
       
  6383             }
       
  6384             /* Values for `limit`, per the spec:
       
  6385              * If undefined: 4294967295 // Math.pow(2, 32) - 1
       
  6386              * If 0, Infinity, or NaN: 0
       
  6387              * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
       
  6388              * If negative number: 4294967296 - Math.floor(Math.abs(limit))
       
  6389              * If other: Type-convert, then use the above rules
       
  6390              */
       
  6391             var splitLimit = typeof limit === 'undefined' ?
       
  6392                 -1 >>> 0 : // Math.pow(2, 32) - 1
       
  6393                 ES.ToUint32(limit);
       
  6394             match = separatorCopy.exec(string);
       
  6395             while (match) {
       
  6396                 // `separatorCopy.lastIndex` is not reliable cross-browser
       
  6397                 lastIndex = match.index + match[0].length;
       
  6398                 if (lastIndex > lastLastIndex) {
       
  6399                     array_push.call(output, strSlice(string, lastLastIndex, match.index));
       
  6400                     // Fix browsers whose `exec` methods don't consistently return `undefined` for
       
  6401                     // nonparticipating capturing groups
       
  6402                     if (!compliantExecNpcg && match.length > 1) {
       
  6403                         /* eslint-disable no-loop-func */
       
  6404                         match[0].replace(separator2, function () {
       
  6405                             for (var i = 1; i < arguments.length - 2; i++) {
       
  6406                                 if (typeof arguments[i] === 'undefined') {
       
  6407                                     match[i] = void 0;
       
  6408                                 }
       
  6409                             }
       
  6410                         });
       
  6411                         /* eslint-enable no-loop-func */
       
  6412                     }
       
  6413                     if (match.length > 1 && match.index < string.length) {
       
  6414                         array_push.apply(output, array_slice.call(match, 1));
       
  6415                     }
       
  6416                     lastLength = match[0].length;
       
  6417                     lastLastIndex = lastIndex;
       
  6418                     if (output.length >= splitLimit) {
       
  6419                         break;
       
  6420                     }
       
  6421                 }
       
  6422                 if (separatorCopy.lastIndex === match.index) {
       
  6423                     separatorCopy.lastIndex++; // Avoid an infinite loop
       
  6424                 }
       
  6425                 match = separatorCopy.exec(string);
       
  6426             }
       
  6427             if (lastLastIndex === string.length) {
       
  6428                 if (lastLength || !separatorCopy.test('')) {
       
  6429                     array_push.call(output, '');
       
  6430                 }
       
  6431             } else {
       
  6432                 array_push.call(output, strSlice(string, lastLastIndex));
       
  6433             }
       
  6434             return output.length > splitLimit ? strSlice(output, 0, splitLimit) : output;
       
  6435         };
       
  6436     }());
       
  6437 
       
  6438 // [bugfix, chrome]
       
  6439 // If separator is undefined, then the result array contains just one String,
       
  6440 // which is the this value (converted to a String). If limit is not undefined,
       
  6441 // then the output array is truncated so that it contains no more than limit
       
  6442 // elements.
       
  6443 // "0".split(undefined, 0) -> []
       
  6444 } else if ('0'.split(void 0, 0).length) {
       
  6445     StringPrototype.split = function split(separator, limit) {
       
  6446         if (typeof separator === 'undefined' && limit === 0) { return []; }
       
  6447         return strSplit(this, separator, limit);
       
  6448     };
       
  6449 }
       
  6450 
       
  6451 var str_replace = StringPrototype.replace;
       
  6452 var replaceReportsGroupsCorrectly = (function () {
       
  6453     var groups = [];
       
  6454     'x'.replace(/x(.)?/g, function (match, group) {
       
  6455         array_push.call(groups, group);
       
  6456     });
       
  6457     return groups.length === 1 && typeof groups[0] === 'undefined';
       
  6458 }());
       
  6459 
       
  6460 if (!replaceReportsGroupsCorrectly) {
       
  6461     StringPrototype.replace = function replace(searchValue, replaceValue) {
       
  6462         var isFn = isCallable(replaceValue);
       
  6463         var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
       
  6464         if (!isFn || !hasCapturingGroups) {
       
  6465             return str_replace.call(this, searchValue, replaceValue);
       
  6466         } else {
       
  6467             var wrappedReplaceValue = function (match) {
       
  6468                 var length = arguments.length;
       
  6469                 var originalLastIndex = searchValue.lastIndex;
       
  6470                 searchValue.lastIndex = 0;
       
  6471                 var args = searchValue.exec(match) || [];
       
  6472                 searchValue.lastIndex = originalLastIndex;
       
  6473                 array_push.call(args, arguments[length - 2], arguments[length - 1]);
       
  6474                 return replaceValue.apply(this, args);
       
  6475             };
       
  6476             return str_replace.call(this, searchValue, wrappedReplaceValue);
       
  6477         }
       
  6478     };
       
  6479 }
       
  6480 
       
  6481 // ECMA-262, 3rd B.2.3
       
  6482 // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
       
  6483 // non-normative section suggesting uniform semantics and it should be
       
  6484 // normalized across all browsers
       
  6485 // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
       
  6486 var string_substr = StringPrototype.substr;
       
  6487 var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
       
  6488 defineProperties(StringPrototype, {
       
  6489     substr: function substr(start, length) {
       
  6490         var normalizedStart = start;
       
  6491         if (start < 0) {
       
  6492             normalizedStart = max(this.length + start, 0);
       
  6493         }
       
  6494         return string_substr.call(this, normalizedStart, length);
       
  6495     }
       
  6496 }, hasNegativeSubstrBug);
       
  6497 
       
  6498 // ES5 15.5.4.20
       
  6499 // whitespace from: http://es5.github.io/#x15.5.4.20
       
  6500 var ws = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' +
       
  6501     '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' +
       
  6502     '\u2029\uFEFF';
       
  6503 var zeroWidth = '\u200b';
       
  6504 var wsRegexChars = '[' + ws + ']';
       
  6505 var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');
       
  6506 var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');
       
  6507 var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());
       
  6508 defineProperties(StringPrototype, {
       
  6509     // http://blog.stevenlevithan.com/archives/faster-trim-javascript
       
  6510     // http://perfectionkills.com/whitespace-deviations/
       
  6511     trim: function trim() {
       
  6512         if (typeof this === 'undefined' || this === null) {
       
  6513             throw new TypeError("can't convert " + this + ' to object');
       
  6514         }
       
  6515         return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
       
  6516     }
       
  6517 }, hasTrimWhitespaceBug);
       
  6518 
       
  6519 // ES-5 15.1.2.2
       
  6520 if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
       
  6521     /* global parseInt: true */
       
  6522     parseInt = (function (origParseInt) {
       
  6523         var hexRegex = /^0[xX]/;
       
  6524         return function parseInt(str, radix) {
       
  6525             var string = $String(str).trim();
       
  6526             var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);
       
  6527             return origParseInt(string, defaultedRadix);
       
  6528         };
       
  6529     }(parseInt));
       
  6530 }
       
  6531 
       
  6532 }));
       
  6533 
       
  6534 },{}],26:[function(_dereq_,module,exports){
       
  6535 var arr = [];
       
  6536 var each = arr.forEach;
       
  6537 var slice = arr.slice;
       
  6538 
       
  6539 
       
  6540 module.exports = function(obj) {
       
  6541     each.call(slice.call(arguments, 1), function(source) {
       
  6542         if (source) {
       
  6543             for (var prop in source) {
       
  6544                 obj[prop] = source[prop];
       
  6545             }
       
  6546         }
       
  6547     });
       
  6548     return obj;
       
  6549 };
       
  6550 
       
  6551 },{}],27:[function(_dereq_,module,exports){
       
  6552 module.exports = isFunction
       
  6553 
       
  6554 var toString = Object.prototype.toString
       
  6555 
       
  6556 function isFunction (fn) {
       
  6557   var string = toString.call(fn)
       
  6558   return string === '[object Function]' ||
       
  6559     (typeof fn === 'function' && string !== '[object RegExp]') ||
       
  6560     (typeof window !== 'undefined' &&
       
  6561      // IE8 and below
       
  6562      (fn === window.setTimeout ||
       
  6563       fn === window.alert ||
       
  6564       fn === window.confirm ||
       
  6565       fn === window.prompt))
       
  6566 };
       
  6567 
       
  6568 },{}],28:[function(_dereq_,module,exports){
       
  6569 "use strict";
       
  6570 
       
  6571 module.exports = function isObject(x) {
       
  6572 	return typeof x === "object" && x !== null;
       
  6573 };
       
  6574 
       
  6575 },{}],29:[function(_dereq_,module,exports){
       
  6576 /*!
       
  6577   * $script.js JS loader & dependency manager
       
  6578   * https://github.com/ded/script.js
       
  6579   * (c) Dustin Diaz 2014 | License MIT
       
  6580   */
       
  6581 
       
  6582 (function (name, definition) {
       
  6583   if (typeof module != 'undefined' && module.exports) module.exports = definition()
       
  6584   else if (typeof define == 'function' && define.amd) define(definition)
       
  6585   else this[name] = definition()
       
  6586 })('$script', function () {
       
  6587   var doc = document
       
  6588     , head = doc.getElementsByTagName('head')[0]
       
  6589     , s = 'string'
       
  6590     , f = false
       
  6591     , push = 'push'
       
  6592     , readyState = 'readyState'
       
  6593     , onreadystatechange = 'onreadystatechange'
       
  6594     , list = {}
       
  6595     , ids = {}
       
  6596     , delay = {}
       
  6597     , scripts = {}
       
  6598     , scriptpath
       
  6599     , urlArgs
       
  6600 
       
  6601   function every(ar, fn) {
       
  6602     for (var i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
       
  6603     return 1
       
  6604   }
       
  6605   function each(ar, fn) {
       
  6606     every(ar, function (el) {
       
  6607       return !fn(el)
       
  6608     })
       
  6609   }
       
  6610 
       
  6611   function $script(paths, idOrDone, optDone) {
       
  6612     paths = paths[push] ? paths : [paths]
       
  6613     var idOrDoneIsDone = idOrDone && idOrDone.call
       
  6614       , done = idOrDoneIsDone ? idOrDone : optDone
       
  6615       , id = idOrDoneIsDone ? paths.join('') : idOrDone
       
  6616       , queue = paths.length
       
  6617     function loopFn(item) {
       
  6618       return item.call ? item() : list[item]
       
  6619     }
       
  6620     function callback() {
       
  6621       if (!--queue) {
       
  6622         list[id] = 1
       
  6623         done && done()
       
  6624         for (var dset in delay) {
       
  6625           every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
       
  6626         }
       
  6627       }
       
  6628     }
       
  6629     setTimeout(function () {
       
  6630       each(paths, function loading(path, force) {
       
  6631         if (path === null) return callback()
       
  6632         path = !force && path.indexOf('.js') === -1 && !/^https?:\/\//.test(path) && scriptpath ? scriptpath + path + '.js' : path
       
  6633         if (scripts[path]) {
       
  6634           if (id) ids[id] = 1
       
  6635           return (scripts[path] == 2) ? callback() : setTimeout(function () { loading(path, true) }, 0)
       
  6636         }
       
  6637 
       
  6638         scripts[path] = 1
       
  6639         if (id) ids[id] = 1
       
  6640         create(path, callback)
       
  6641       })
       
  6642     }, 0)
       
  6643     return $script
       
  6644   }
       
  6645 
       
  6646   function create(path, fn) {
       
  6647     var el = doc.createElement('script'), loaded
       
  6648     el.onload = el.onerror = el[onreadystatechange] = function () {
       
  6649       if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
       
  6650       el.onload = el[onreadystatechange] = null
       
  6651       loaded = 1
       
  6652       scripts[path] = 2
       
  6653       fn()
       
  6654     }
       
  6655     el.async = 1
       
  6656     el.src = urlArgs ? path + (path.indexOf('?') === -1 ? '?' : '&') + urlArgs : path;
       
  6657     head.insertBefore(el, head.lastChild)
       
  6658   }
       
  6659 
       
  6660   $script.get = create
       
  6661 
       
  6662   $script.order = function (scripts, id, done) {
       
  6663     (function callback(s) {
       
  6664       s = scripts.shift()
       
  6665       !scripts.length ? $script(s, id, done) : $script(s, callback)
       
  6666     }())
       
  6667   }
       
  6668 
       
  6669   $script.path = function (p) {
       
  6670     scriptpath = p
       
  6671   }
       
  6672   $script.urlArgs = function (str) {
       
  6673     urlArgs = str;
       
  6674   }
       
  6675   $script.ready = function (deps, ready, req) {
       
  6676     deps = deps[push] ? deps : [deps]
       
  6677     var missing = [];
       
  6678     !each(deps, function (dep) {
       
  6679       list[dep] || missing[push](dep);
       
  6680     }) && every(deps, function (dep) {return list[dep]}) ?
       
  6681       ready() : !function (key) {
       
  6682       delay[key] = delay[key] || []
       
  6683       delay[key][push](ready)
       
  6684       req && req(missing)
       
  6685     }(deps.join('|'))
       
  6686     return $script
       
  6687   }
       
  6688 
       
  6689   $script.done = function (idOrDone) {
       
  6690     $script([null], idOrDone)
       
  6691   }
       
  6692 
       
  6693   return $script
       
  6694 });
       
  6695 
       
  6696 },{}]},{},[19])(19)
       
  6697 });