Skip to content

Instantly share code, notes, and snippets.

@fling
Created June 7, 2011 22:18
Show Gist options
  • Save fling/1013306 to your computer and use it in GitHub Desktop.
Save fling/1013306 to your computer and use it in GitHub Desktop.
Financial Times Web App Javascript
/*!
* jQuery JavaScript Library v1.5
* http://jquery.com/
*
* Copyright 2011, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Mon Jan 31 08:31:29 2011 -0500
*/
(function(a,b){function b$(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function bX(a){if(!bR[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";bR[a]=c}return bR[a]}function bW(a,b){var c={};d.each(bV.concat.apply([],bV.slice(0,b)),function(){c[this]=a});return c}function bJ(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f=a.converters,g,h=e.length,i,j=e[0],k,l,m,n,o;for(g=1;g<h;g++){k=j,j=e[g];if(j==="*")j=k;else if(k!=="*"&&k!==j){l=k+" "+j,m=f[l]||f["* "+j];if(!m){o=b;for(n in f){i=n.split(" ");if(i[0]===k||i[0]==="*"){o=f[i[1]+" "+j];if(o){n=f[n],n===!0?m=o:o===!0&&(m=n);break}}}}!m&&!o&&d.error("No conversion from "+l.replace(" "," to ")),m!==!0&&(c=m?m(c):o(n(c)))}}return c}function bI(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bH(a,b,c,e){d.isArray(b)&&b.length?d.each(b,function(b,f){c||bp.test(a)?e(a,f):bH(a+"["+(typeof f==="object"||d.isArray(f)?b:"")+"]",f,c,e)}):c||b==null||typeof b!=="object"?e(a,b):d.isArray(b)||d.isEmptyObject(b)?e(a,""):d.each(b,function(b,d){bH(a+"["+b+"]",d,c,e)})}function bG(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bD,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l==="string"&&(g[l]?l=b:(c.dataTypes.unshift(l),l=bG(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bG(a,c,d,e,"*",g));return l}function bF(a){return function(b,c){typeof b!=="string"&&(c=b,b="*");if(d.isFunction(c)){var e=b.toLowerCase().split(bz),f=0,g=e.length,h,i,j;for(;f<g;f++)h=e[f],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bn(a,b,c){var e=b==="width"?bh:bi,f=b==="width"?a.offsetWidth:a.offsetHeight;if(c==="border")return f;d.each(e,function(){c||(f-=parseFloat(d.css(a,"padding"+this))||0),c==="margin"?f+=parseFloat(d.css(a,"margin"+this))||0:f-=parseFloat(d.css(a,"border"+this+"Width"))||0});return f}function _(a,b){b.src?d.ajax({url:b.src,async:!1,dataType:"script"}):d.globalEval(b.text||b.textContent||b.innerHTML||""),b.parentNode&&b.parentNode.removeChild(b)}function $(a,b){if(b.nodeType===1){var c=b.nodeName.toLowerCase();b.clearAttributes(),b.mergeAttributes(a);if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(d.expando)}}function Z(a,b){if(b.nodeType===1&&d.hasData(a)){var c=d.expando,e=d.data(a),f=d.data(b,e);if(e=e[c]){var g=e.events;f=f[c]=d.extend({},e);if(g){delete f.handle,f.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)d.event.add(b,h,g[h][i],g[h][i].data)}}}}function Y(a,b){return d.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function O(a,b,c){if(d.isFunction(b))return d.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return d.grep(a,function(a,d){return a===b===c});if(typeof b==="string"){var e=d.grep(a,function(a){return a.nodeType===1});if(J.test(b))return d.filter(b,e,!c);b=d.filter(b,e)}return d.grep(a,function(a,e){return d.inArray(a,b)>=0===c})}function N(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function F(a,b){return(a&&a!=="*"?a+".":"")+b.replace(q,"`").replace(r,"&")}function E(a){var b,c,e,f,g,h,i,j,k,l,m,n,p,q=[],r=[],s=d._data(this,u);typeof s==="function"&&(s=s.events);if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;i<t.length;i++)g=t[i],g.origType.replace(o,"")===a.type?r.push(g.selector):t.splice(i--,1);f=d(a.target).closest(r,a.currentTarget);for(j=0,k=f.length;j<k;j++){m=f[j];for(i=0;i<t.length;i++){g=t[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))){h=m.elem,e=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,e=d(a.relatedTarget).closest(g.selector)[0];(!e||e!==h)&&q.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=q.length;j<k;j++){f=q[j];if(c&&f.level>c)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,p=f.handleObj.origHandler.apply(f.elem,arguments);if(p===!1||a.isPropagationStopped()){c=f.level,p===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function C(a,b,c){c[0].type=a;return d.event.handle.apply(b,c)}function w(){return!0}function v(){return!1}function f(a,c,f){if(f===b&&a.nodeType===1){f=a.getAttribute("data-"+c);if(typeof f==="string"){try{f=f==="true"?!0:f==="false"?!1:f==="null"?null:d.isNaN(f)?e.test(f)?d.parseJSON(f):f:parseFloat(f)}catch(g){}d.data(a,c,f)}else f=b}return f}var c=a.document,d=function(){function I(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(I,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x=!1,y,z="then done fail isResolved isRejected promise".split(" "),A,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,G=Array.prototype.indexOf,H={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5",length:0,size:function(){return this.length},toArray:function(){return E.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?D.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){e=i[c],f=a[c];if(i===f)continue;l&&f&&(d.isPlainObject(f)||(g=d.isArray(f)))?(g?(g=!1,h=e&&d.isArray(e)?e:[]):h=e&&d.isPlainObject(e)?e:{},i[c]=d.extend(l,h,f)):f!==b&&(i[c]=f)}return i},d.extend({noConflict:function(b){a.$=f,b&&(a.jQuery=e);return d},isReady:!1,readyWait:1,ready:function(a){a===!0&&d.readyWait--;if(!d.readyWait||a!==!0&&!d.isReady){if(!c.body)return setTimeout(d.ready,1);d.isReady=!0;if(a!==!0&&--d.readyWait>0)return;y.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=!0;if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",A,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",A),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&I()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):H[B.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");e.type="text/javascript",d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g<h;)if(c.apply(a[g++],e)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(var j=a[0];g<h&&c.call(j,g,j)!==!1;j=a[++g]){}return a},trim:F?function(a){return a==null?"":F.call(a)}:function(a){return a==null?"":(a+"").replace(j,"").replace(k,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var e=d.type(a);a.length==null||e==="string"||e==="function"||e==="regexp"||d.isWindow(a)?D.call(c,a):d.merge(c,a)}return c},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length==="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,b,c){var d=[],e;for(var f=0,g=a.length;f<g;f++)e=b(a[f],f,c),e!=null&&(d[d.length]=e);return d.concat.apply([],d)},guid:1,proxy:function(a,c,e){arguments.length===2&&(typeof c==="string"?(e=a,a=e[c],c=b):c&&!d.isFunction(c)&&(e=c,c=b)),!c&&a&&(c=function(){return a.apply(e||this,arguments)}),a&&(c.guid=a.guid=a.guid||c.guid||d.guid++);return c},access:function(a,c,e,f,g,h){var i=a.length;if(typeof c==="object"){for(var j in c)d.access(a,j,c[j],f,g,e);return a}if(e!==b){f=!h&&f&&d.isFunction(e);for(var k=0;k<i;k++)g(a[k],c,f?e.call(a[k],k,g(a[k],c)):e,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},_Deferred:function(){var a=[],b,c,e,f={done:function(){if(!e){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=d.type(i),j==="array"?f.done.apply(f,i):j==="function"&&a.push(i);k&&f.resolveWith(k[0],k[1])}return this},resolveWith:function(d,f){if(!e&&!b&&!c){c=1;try{while(a[0])a.shift().apply(d,f)}finally{b=[d,f],c=0}}return this},resolve:function(){f.resolveWith(d.isFunction(this.promise)?this.promise():this,arguments);return this},isResolved:function(){return c||b},cancel:function(){e=1,a=[];return this}};return f},Deferred:function(a){var b=d._Deferred(),c=d._Deferred(),e;d.extend(b,{then:function(a,c){b.done(a).fail(c);return this},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,promise:function(a,c){if(a==null){if(e)return e;e=a={}}c=z.length;while(c--)a[z[c]]=b[z[c]];return a}}),b.then(c.cancel,b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){var b=arguments,c=b.length,e=c<=1&&a&&d.isFunction(a.promise)?a:d.Deferred(),f=e.promise(),g;c>1?(g=Array(c),d.each(b,function(a,b){d.when(b).then(function(b){g[a]=arguments.length>1?E.call(arguments,0):b,--c||e.resolveWith(f,g)},e.reject)})):e!==a&&e.resolve(a);return f},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),y=d._Deferred(),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){H["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),G&&(d.inArray=function(a,b){return G.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?A=function(){c.removeEventListener("DOMContentLoaded",A,!1),d.ready()}:c.attachEvent&&(A=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",A),d.ready())});return a.jQuery=a.$=d}();(function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option"));if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:b.getElementsByTagName("input")[0].value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,_scriptEval:null,noCloneEvent:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0},g.disabled=!0,d.support.optDisabled=!h.disabled,d.support.scriptEval=function(){if(d.support._scriptEval===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();e.type="text/javascript";try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(d.support._scriptEval=!0,delete a[f]):d.support._scriptEval=!1,b.removeChild(e),b=e=f=null}return d.support._scriptEval};try{delete b.test}catch(i){d.support.deleteExpando=!1}b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function j(){d.support.noCloneEvent=!1,b.detachEvent("onclick",j)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";var k=c.createDocumentFragment();k.appendChild(b.firstChild),d.support.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",b.removeChild(a).style.display="none",a=e=null}});var l=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function"),b=null;return d};d.support.submitBubbles=l("submit"),d.support.changeBubbles=l("change"),b=e=f=null}})();var e=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!d.isEmptyObject(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={}),typeof c==="object"&&(f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c)),i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,g=b.nodeType,h=g?d.cache:b,i=g?b[d.expando]:d.expando;if(!h[i])return;if(c){var j=e?h[i][f]:h[i];if(j){delete j[c];if(!d.isEmptyObject(j))return}}if(e){delete h[i][f];if(!d.isEmptyObject(h[i]))return}var k=h[i][f];d.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},h[i][f]=k):g&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var g=this[0].attributes,h;for(var i=0,j=g.length;i<j;i++)h=g[i].name,h.indexOf("data-")===0&&(h=h.substr(5),f(this[0],h,e[h]))}}return e}if(typeof a==="object")return this.each(function(){d.data(this,a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(c===b){e=this.triggerHandler("getData"+k[1]+"!",[k[0]]),e===b&&this.length&&(e=d.data(this[0],a),e=f(this[0],a,e));return e===b&&k[1]?this.data(k[0]):e}return this.each(function(){var b=d(this),e=[k[0],c];b.triggerHandler("setData"+k[1]+"!",e),d.data(this,a,c),b.triggerHandler("changeData"+k[1]+"!",e)})},removeData:function(a){return this.each(function(){d.removeData(this,a)})}}),d.extend({queue:function(a,b,c){if(a){b=(b||"fx")+"queue";var e=d._data(a,b);if(!c)return e||[];!e||d.isArray(c)?e=d._data(a,b,d.makeArray(c)):e.push(c);return e}},dequeue:function(a,b){b=b||"fx";var c=d.queue(a,b),e=c.shift();e==="inprogress"&&(e=c.shift()),e&&(b==="fx"&&c.unshift("inprogress"),e.call(a,function(){d.dequeue(a,b)})),c.length||d.removeData(a,b+"queue",!0)}}),d.fn.extend({queue:function(a,c){typeof a!=="string"&&(c=a,a="fx");if(c===b)return d.queue(this[0],a);return this.each(function(b){var e=d.queue(this,a,c);a==="fx"&&e[0]!=="inprogress"&&d.dequeue(this,a)})},dequeue:function(a){return this.each(function(){d.dequeue(this,a)})},delay:function(a,b){a=d.fx?d.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){d.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var g=/[\n\t\r]/g,h=/\s+/,i=/\r/g,j=/^(?:href|src|style)$/,k=/^(?:button|input)$/i,l=/^(?:button|input|object|select|textarea)$/i,m=/^a(?:rea)?$/i,n=/^(?:radio|checkbox)$/i;d.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"},d.fn.extend({attr:function(a,b){return d.access(this,a,b,!0,d.attr)},removeAttr:function(a,b){return this.each(function(){d.attr(this,a,""),this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.addClass(a.call(this,b,c.attr("class")))});if(a&&typeof a==="string"){var b=(a||"").split(h);for(var c=0,e=this.length;c<e;c++){var f=this[c];if(f.nodeType===1)if(f.className){var g=" "+f.className+" ",i=f.className;for(var j=0,k=b.length;j<k;j++)g.indexOf(" "+b[j]+" ")<0&&(i+=" "+b[j]);f.className=d.trim(i)}else f.className=a}}return this},removeClass:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.removeClass(a.call(this,b,c.attr("class")))});if(a&&typeof a==="string"||a===b){var c=(a||"").split(h);for(var e=0,f=this.length;e<f;e++){var i=this[e];if(i.nodeType===1&&i.className)if(a){var j=(" "+i.className+" ").replace(g," ");for(var k=0,l=c.length;k<l;k++)j=j.replace(" "+c[k]+" "," ");i.className=d.trim(j)}else i.className=""}}return this},toggleClass:function(a,b){var c=typeof a,e=typeof b==="boolean";if(d.isFunction(a))return this.each(function(c){var e=d(this);e.toggleClass(a.call(this,c,e.attr("class"),b),b)});return this.each(function(){if(c==="string"){var f,g=0,i=d(this),j=b,k=a.split(h);while(f=k[g++])j=e?j:!i.hasClass(f),i[j?"addClass":"removeClass"](f)}else if(c==="undefined"||c==="boolean")this.className&&d._data(this,"__className__",this.className),this.className=this.className||a===!1?"":d._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(g," ").indexOf(b)>-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,j=c.type==="select-one";if(f<0)return null;for(var k=j?f:0,l=j?f+1:h.length;k<l;k++){var m=h[k];if(m.selected&&(d.support.optDisabled?!m.disabled:m.getAttribute("disabled")===null)&&(!m.parentNode.disabled||!d.nodeName(m.parentNode,"optgroup"))){a=d(m).val();if(j)return a;g.push(a)}}return g}if(n.test(c.type)&&!d.support.checkOn)return c.getAttribute("value")===null?"on":c.value;return(c.value||"").replace(i,"")}return b}var o=d.isFunction(a);return this.each(function(b){var c=d(this),e=a;if(this.nodeType===1){o&&(e=a.call(this,b,c.val())),e==null?e="":typeof e==="number"?e+="":d.isArray(e)&&(e=d.map(e,function(a){return a==null?"":a+""}));if(d.isArray(e)&&n.test(this.type))this.checked=d.inArray(c.val(),e)>=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=j.test(c);if(c==="selected"&&!d.support.optSelected){var n=a.parentNode;n&&(n.selectedIndex,n.parentNode&&n.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&k.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var o=a.getAttributeNode("tabIndex");return o&&o.specified?o.value:l.test(a.nodeName)||m.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var p=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return p===null?b:p}h&&(a[c]=e);return a[c]}});var o=/\.(.*)$/,p=/^(?:textarea|input|select)$/i,q=/\./g,r=/ /g,s=/[^\w\s.|`]/g,t=function(a){return a.replace(s,"\\$&")},u="events";d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a);if(f===!1)f=v;else if(!f)return;var h,i;f.handler&&(h=f,f=h.handler),f.guid||(f.guid=d.guid++);var j=d._data(c);if(!j)return;var k=j[u],l=j.handle;typeof k==="function"?(l=k.handle,k=k.events):k||(c.nodeType||(j[u]=j=function(){}),j.events=k={}),l||(j.handle=l=function(){return typeof d!=="undefined"&&!d.event.triggered?d.event.handle.apply(l.elem,arguments):b}),l.elem=c,e=e.split(" ");var m,n=0,o;while(m=e[n++]){i=h?d.extend({},h):{handler:f,data:g},m.indexOf(".")>-1?(o=m.split("."),m=o.shift(),i.namespace=o.slice(0).sort().join(".")):(o=[],i.namespace=""),i.type=m,i.guid||(i.guid=f.guid);var p=k[m],q=d.event.special[m]||{};if(!p){p=k[m]=[];if(!q.setup||q.setup.call(c,g,o,l)===!1)c.addEventListener?c.addEventListener(m,l,!1):c.attachEvent&&c.attachEvent("on"+m,l)}q.add&&(q.add.call(c,i),i.handler.guid||(i.handler.guid=f.guid)),p.push(i),d.event.global[m]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=v);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),w=s&&s[u];if(!s||!w)return;typeof w==="function"&&(s=w,w=w.events),c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in w)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),t).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=w[h];if(!p)continue;if(!e){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))d.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=d.event.special[h]||{};for(j=f||0;j<p.length;j++){q=p[j];if(e.guid===q.guid){if(l||n.test(q.namespace))f==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(f!=null)break}}if(p.length===0||f!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&d.removeEvent(a,h,s.handle),g=null,delete w[h]}if(d.isEmptyObject(w)){var x=s.handle;x&&(x.elem=null),delete s.events,delete s.handle,typeof s==="function"?d.removeData(a,u,!0):d.isEmptyObject(s)&&d.removeData(a,b,!0)}}},trigger:function(a,c,e){var f=a.type||a,g=arguments[3];if(!g){a=typeof a==="object"?a[d.expando]?a:d.extend(d.Event(f),a):d.Event(f),f.indexOf("!")>=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=e.nodeType?d._data(e,"handle"):(d._data(e,u)||{}).handle;h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(o,""),n=d.nodeName(l,"a")&&m==="click",p=d.event.special[m]||{};if((!p._default||p._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=!0,l[m]())}catch(q){}k&&(l["on"+m]=k),d.event.triggered=!1}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,u),typeof i==="function"&&(i=i.events),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l<m;l++){var n=f[l];if(e||h.test(n.namespace)){c.handler=n.handler,c.data=n.data,c.handleObj=n;var o=n.handler.apply(this,k);o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[d.expando])return a;var e=a;a=d.Event(e);for(var f=this.props.length,g;f;)g=this.props[--f],a[g]=e[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=c.documentElement,i=c.body;a.pageX=a.clientX+(h&&h.scrollLeft||i&&i.scrollLeft||0)-(h&&h.clientLeft||i&&i.clientLeft||0),a.pageY=a.clientY+(h&&h.scrollTop||i&&i.scrollTop||0)-(h&&h.clientTop||i&&i.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:d.proxy,special:{ready:{setup:d.bindReady,teardown:d.noop},live:{add:function(a){d.event.add(this,F(a.origType,a.selector),d.extend({},a,{handler:E,guid:a.handler.guid}))},remove:function(a){d.event.remove(this,F(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){d.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},d.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},d.Event=function(a){if(!this.preventDefault)return new d.Event(a);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?w:v):this.type=a,this.timeStamp=d.now(),this[d.expando]=!0},d.Event.prototype={preventDefault:function(){this.isDefaultPrevented=w;var a=this.originalEvent;a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=w;var a=this.originalEvent;a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=w,this.stopPropagation()},isDefaultPrevented:v,isPropagationStopped:v,isImmediatePropagationStopped:v};var x=function(a){var b=a.relatedTarget;try{while(b&&b!==this)b=b.parentNode;b!==this&&(a.type=a.data,d.event.handle.apply(this,arguments))}catch(c){}},y=function(a){a.type=a.data,d.event.handle.apply(this,arguments)};d.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){d.event.special[a]={setup:function(c){d.event.add(this,b,c&&c.selector?y:x,a)},teardown:function(a){d.event.remove(this,b,a&&a.selector?y:x)}}}),d.support.submitBubbles||(d.event.special.submit={setup:function(a,c){if(this.nodeName&&this.nodeName.toLowerCase()!=="form")d.event.add(this,"click.specialSubmit",function(a){var c=a.target,e=c.type;if((e==="submit"||e==="image")&&d(c).closest("form").length){a.liveFired=b;return C("submit",this,arguments)}}),d.event.add(this,"keypress.specialSubmit",function(a){var c=a.target,e=c.type;if((e==="text"||e==="password")&&d(c).closest("form").length&&a.keyCode===13){a.liveFired=b;return C("submit",this,arguments)}});else return!1},teardown:function(a){d.event.remove(this,".specialSubmit")}});if(!d.support.changeBubbles){var z,A=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},B=function B(a){var c=a.target,e,f;if(p.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=A(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f){a.type="change",a.liveFired=b;return d.event.trigger(a,arguments[1],c)}}};d.event.special.change={filters:{focusout:B,beforedeactivate:B,click:function(a){var b=a.target,c=b.type;if(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")return B.call(this,a)},keydown:function(a){var b=a.target,c=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")return B.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",A(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in z)d.event.add(this,c+".specialChange",z[c]);return p.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return p.test(this.nodeName)}},z=d.event.special.change.filters,z.focus=z.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function c(a){a=d.event.fix(a),a.type=b;return d.event.handle.call(this,a)}d.event.special[b]={setup:function(){this.addEventListener(a,c,!0)},teardown:function(){this.removeEventListener(a,c,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i<j;i++)d.event.add(this[i],a,h,e);return this}}),d.fn.extend({unbind:function(a,b){if(typeof a!=="object"||a.preventDefault)for(var e=0,f=this.length;e<f;e++)d.event.remove(this[e],a,b);else for(var c in a)this.unbind(c,a[c]);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){d.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var c=d.Event(a);c.preventDefault(),c.stopPropagation(),d.event.trigger(c,b,this[0]);return c.result}},toggle:function(a){var b=arguments,c=1;while(c<b.length)d.proxy(a,b[c++]);return this.click(d.proxy(a,function(e){var f=(d._data(this,"lastToggle"+a.guid)||0)%c;d._data(this,"lastToggle"+a.guid,f+1),e.preventDefault();return b[f].apply(this,arguments)||!1}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var D={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};d.each(["live","die"],function(a,c){d.fn[c]=function(a,e,f,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:d(this.context);if(typeof a==="object"&&!a.preventDefault){for(var p in a)n[c](p,e,a[p],m);return this}d.isFunction(e)&&(f=e,e=b),a=(a||"").split(" ");while((h=a[i++])!=null){j=o.exec(h),k="",j&&(k=j[0],h=h.replace(o,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,h==="focus"||h==="blur"?(a.push(D[h]+k),h=h+k):h=(D[h]||h)+k;if(c==="live")for(var q=0,r=n.length;q<r;q++)d.event.add(n[q],"live."+F(h,m),{data:e,selector:m,handler:f,origType:h,origHandler:f,preType:l});else n.unbind("live."+F(h,m),f)}return this}}),d.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){d.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function s(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var j=d[g];if(j){var k=!1;j=j[a];while(j){if(j.sizcache===c){k=d[j.sizset];break}if(j.nodeType===1){f||(j.sizcache=c,j.sizset=g);if(typeof b!=="string"){if(j===b){k=!0;break}}else if(i.filter(b,[j]).length>0){k=j;break}}j=j[a]}d[g]=k}}}function r(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0;[0,0].sort(function(){h=!1;return 0});var i=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var l,m,o,p,q,r,s,u,v=!0,w=i.isXML(d),x=[],y=b;do{a.exec(""),l=a.exec(y);if(l){y=l[3],x.push(l[1]);if(l[2]){p=l[3];break}}}while(l);if(x.length>1&&k.exec(b))if(x.length===2&&j.relative[x[0]])m=t(x[0]+x[1],d);else{m=j.relative[x[0]]?[d]:i(x.shift(),d);while(x.length)b=x.shift(),j.relative[b]&&(b+=x.shift()),m=t(b,m)}else{!g&&x.length>1&&d.nodeType===9&&!w&&j.match.ID.test(x[0])&&!j.match.ID.test(x[x.length-1])&&(q=i.find(x.shift(),d,w),d=q.expr?i.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:n(g)}:i.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),m=q.expr?i.filter(q.expr,q.set):q.set,x.length>0?o=n(m):v=!1;while(x.length)r=x.pop(),s=r,j.relative[r]?s=x.pop():r="",s==null&&(s=d),j.relative[r](o,s,w)}else o=x=[]}o||(o=m),o||i.error(r||b);if(f.call(o)==="[object Array]")if(v)if(d&&d.nodeType===1)for(u=0;o[u]!=null;u++)o[u]&&(o[u]===!0||o[u].nodeType===1&&i.contains(d,o[u]))&&e.push(m[u]);else for(u=0;o[u]!=null;u++)o[u]&&o[u].nodeType===1&&e.push(m[u]);else e.push.apply(e,o);else n(o,e);p&&(i(p,h,e,g),i.uniqueSort(e));return e};i.uniqueSort=function(a){if(p){g=h,a.sort(p);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},i.matches=function(a,b){return i(a,null,null,b)},i.matchesSelector=function(a,b){return i(b,null,null,[a]).length>0},i.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=j.order.length;e<f;e++){var g,h=j.order[e];if(g=j.leftMatch[h].exec(a)){var i=g[1];g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(/\\/g,""),d=j.find[h](g,b,c);if(d!=null){a=a.replace(j.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!=="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},i.filter=function(a,c,d,e){var f,g,h=a,k=[],l=c,m=c&&c[0]&&i.isXML(c[0]);while(a&&c.length){for(var n in j.filter)if((f=j.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=j.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;l===k&&(k=[]);if(j.preFilter[n]){f=j.preFilter[n](f,l,d,k,e,m);if(f){if(f===!0)continue}else g=o=!0}if(f)for(var s=0;(p=l[s])!=null;s++)if(p){o=q(p,f,s,l);var t=e^!!o;d&&o!=null?t?g=!0:l[s]=!1:t&&(k.push(p),g=!0)}if(o!==b){d||(l=k),a=a.replace(j.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)i.error(a);else break;h=a}return l},i.error=function(a){throw"Syntax error, unrecognized expression: "+a};var j=i.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")}},relative:{"+":function(a,b){var c=typeof b==="string",d=c&&!/\W/.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1){}a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&i.filter(b,a,!0)},">":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!/\W/.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&i.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=s;typeof b==="string"&&!/\W/.test(b)&&(b=b.toLowerCase(),d=b,g=r),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=s;typeof b==="string"&&!/\W/.test(b)&&(b=b.toLowerCase(),d=b,g=r),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!=="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!=="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!=="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(/\\/g,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(/\\/g,"")},TAG:function(a,b){return a[1].toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||i.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&i.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(/\\/g,"");!f&&j.attrMap[g]&&(a[1]=j.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(/\\/g,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=i(b[3],null,null,c);else{var g=i.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(j.match.POS.test(b[0])||j.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!i(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){return"text"===a.type},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=j.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||i.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,k=g.length;h<k;h++)if(g[h]===a)return!1;return!0}i.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=j.attrHandle[c]?j.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=j.setFilters[e];if(f)return f(a,c,b,d)}}},k=j.match.POS,l=function(a,b){return"\\"+(b-0+1)};for(var m in j.match)j.match[m]=new RegExp(j.match[m].source+/(?![^\[]*\])(?![^\(]*\))/.source),j.leftMatch[m]=new RegExp(/(^(?:.|\r|\n)*?)/.source+j.match[m].source.replace(/\\(\d+)/g,l));var n=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(o){n=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var p,q;c.documentElement.compareDocumentPosition?p=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(p=function(a,b){var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(a===b){g=!0;return 0}if(h===i)return q(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return q(e[k],f[k]);return k===c?q(a,f[k],-1):q(e[k],b,1)},q=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),i.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=i.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(j.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},j.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(j.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(j.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=i,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){i=function(b,e,f,g){e=e||c;if(!g&&!i.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return n(e.getElementsByTagName(b),f);if(h[2]&&j.find.CLASS&&e.getElementsByClassName)return n(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return n([e.body],f);if(h&&h[3]){var k=e.getElementById(h[3]);if(!k||!k.parentNode)return n([],f);if(k.id===h[3])return n([k],f)}try{return n(e.querySelectorAll(b),f)}catch(l){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e.getAttribute("id"),o=m||d,p=e.parentNode,q=/^\s*[+~]/.test(b);m?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),q&&p&&(e=e.parentNode);try{if(!q||p)return n(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(r){}finally{m||e.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)i[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector,d=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(e){d=!0}b&&(i.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!i.isXML(a))try{if(d||!j.match.PSEUDO.test(c)&&!/!=/.test(c))return b.call(a,c)}catch(e){}return i(c,null,null,[a]).length>0})}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;j.order.splice(1,0,"CLASS"),j.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?i.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?i.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:i.contains=function(){return!1},i.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var t=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=j.match.PSEUDO.exec(a))e+=c[0],a=a.replace(j.match.PSEUDO,"");a=j.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)i(a,f[g],d);return i.filter(e,d)};d.find=i,d.expr=i.selectors,d.expr[":"]=d.expr.filters,d.unique=i.uniqueSort,d.text=i.getText,d.isXMLDoc=i.isXML,d.contains=i.contains}();var G=/Until$/,H=/^(?:parents|prevUntil|prevAll)/,I=/,/,J=/^.[^:#\[\.,]*$/,K=Array.prototype.slice,L=d.expr.match.POS,M={children:!0,contents:!0,next:!0,prev:!0};d.fn.extend({find:function(a){var b=this.pushStack("","find",a),c=0;for(var e=0,f=this.length;e<f;e++){c=b.length,d.find(a,this[e],b);if(e>0)for(var g=c;g<b.length;g++)for(var h=0;h<c;h++)if(b[h]===b[g]){b.splice(g--,1);break}}return b},has:function(a){var b=d(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(d.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(O(this,a,!1),"not",a)},filter:function(a){return this.pushStack(O(this,a,!0),"filter",a)},is:function(a){return!!a&&d.filter(a,this).length>0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e<f;e++)i=a[e],j[i]||(j[i]=d.expr.match.POS.test(i)?d(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=L.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e<f;e++){g=this[e];while(g){if(l?l.index(g)>-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(N(c[0])||N(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=K.call(arguments);G.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!M[a]?d.unique(f):f,(this.length>1||I.test(e))&&H.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var P=/ jQuery\d+="(?:\d+|null)"/g,Q=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,S=/<([\w:]+)/,T=/<tbody/i,U=/<|&#?\w+;/,V=/<(?:script|object|embed|option|style)/i,W=/checked\s*(?:[^=]|=\s*.checked.)/i,X={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};X.optgroup=X.option,X.tbody=X.tfoot=X.colgroup=X.caption=X.thead,X.th=X.td,d.support.htmlSerialize||(X._default=[1,"div<div>","</div>"]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!0:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(P,""):null;if(typeof a!=="string"||V.test(a)||!d.support.leadingWhitespace&&Q.test(a)||X[(S.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(R,"<$1></$2>");try{for(var c=0,e=this.length;c<e;c++)this[c].nodeType===1&&(d.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(f){this.empty().append(a)}}return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(d.isFunction(a))return this.each(function(b){var c=d(this),e=c.html();c.replaceWith(a.call(this,b,e))});typeof a!=="string"&&(a=d(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;d(this).remove(),b?d(b).before(a):d(c).append(a)})}return this.pushStack(d(d.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,e){var f,g,h,i,j=a[0],k=[];if(!d.support.checkClone&&arguments.length===3&&typeof j==="string"&&W.test(j))return this.each(function(){d(this).domManip(a,c,e,!0)});if(d.isFunction(j))return this.each(function(f){var g=d(this);a[0]=j.call(this,f,c?g.html():b),g.domManip(a,c,e)});if(this[0]){i=j&&j.parentNode,d.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?f={fragment:i}:f=d.buildFragment(a,this,k),h=f.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&d.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)e.call(c?Y(this[l],g):this[l],f.cacheable||m>1&&l<n?d.clone(h,!0,!0):h)}k.length&&d.each(k,_)}return this}}),d.buildFragment=function(a,b,e){var f,g,h,i=b&&b[0]?b[0].ownerDocument||b[0]:c;a.length===1&&typeof a[0]==="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!V.test(a[0])&&(d.support.checkClone||!W.test(a[0]))&&(g=!0,h=d.fragments[a[0]],h&&(h!==1&&(f=h))),f||(f=i.createDocumentFragment(),d.clean(a,i,f,e)),g&&(d.fragments[a[0]]=h?f:1);return{fragment:f,cacheable:g}},d.fragments={},d.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){d.fn[a]=function(c){var e=[],f=d(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&f.length===1){f[b](this[0]);return this}for(var h=0,i=f.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if(!d.support.noCloneEvent&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){f=a.getElementsByTagName("*"),g=e.getElementsByTagName("*");for(h=0;f[h];++h)$(f[h],g[h]);$(a,e)}if(b){Z(a,e);if(c&&"getElementsByTagName"in a){f=a.getElementsByTagName("*"),g=e.getElementsByTagName("*");if(f.length)for(h=0;f[h];++h)Z(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||U.test(i)){if(typeof i==="string"){i=i.replace(R,"<$1></$2>");var j=(S.exec(i)||["",""])[1].toLowerCase(),k=X[j]||X._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=T.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]==="<table>"&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var ba=/alpha\([^)]*\)/i,bb=/opacity=([^)]*)/,bc=/-([a-z])/ig,bd=/([A-Z])/g,be=/^-?\d+(?:px)?$/i,bf=/^-?\d/,bg={position:"absolute",visibility:"hidden",display:"block"},bh=["Left","Right"],bi=["Top","Bottom"],bj,bk,bl,bm=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bj(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bj)return bj(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bc,bm)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bn(a,b,e):d.swap(a,bg,function(){f=bn(a,b,e)});if(f<=0){f=bj(a,b,b),f==="0px"&&bl&&(f=bl(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!be.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=ba.test(f)?f.replace(ba,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bk=function(a,c,e){var f,g,h;e=e.replace(bd,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bl=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!be.test(d)&&bf.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bj=bk||bl,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bo=/%20/g,bp=/\[\]$/,bq=/\r?\n/g,br=/#.*$/,bs=/^(.*?):\s*(.*?)\r?$/mg,bt=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bu=/^(?:GET|HEAD)$/,bv=/^\/\//,bw=/\?/,bx=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,by=/^(?:select|textarea)/i,bz=/\s+/,bA=/([?&])_=[^&]*/,bB=/^(\w+:)\/\/([^\/?#:]+)(?::(\d+))?/,bC=d.fn.load,bD={},bE={};d.fn.extend({load:function(a,b,c){if(typeof a!=="string"&&bC)return bC.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}var g="GET";b&&(d.isFunction(b)?(c=b,b=null):typeof b==="object"&&(b=d.param(b,d.ajaxSettings.traditional),g="POST"));var h=this;d.ajax({url:a,type:g,dataType:"html",data:b,complete:function(a,b,e){e=a.responseText,a.isResolved()&&(a.done(function(a){e=a}),h.html(f?d("<div>").append(e.replace(bx,"")).find(f):e)),c&&h.each(c,[e,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||by.test(this.nodeName)||bt.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(bq,"\r\n")}}):{name:b.name,value:c.replace(bq,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,b){d[b]=function(a,c,e,f){d.isFunction(c)&&(f=f||e,e=c,c=null);return d.ajax({type:b,url:a,data:c,success:e,dataType:f})}}),d.extend({getScript:function(a,b){return d.get(a,null,b,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a){d.extend(!0,d.ajaxSettings,a),a.context&&(d.ajaxSettings.context=a.context)},ajaxSettings:{url:location.href,global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bF(bD),ajaxTransport:bF(bE),ajax:function(a,e){function w(a,c,e,l){if(t!==2){t=2,p&&clearTimeout(p),o=b,m=l||"",v.readyState=a?4:0;var n,q,r,s=e?bI(f,v,e):b,u,w;if(a>=200&&a<300||a===304){if(f.ifModified){if(u=v.getResponseHeader("Last-Modified"))d.lastModified[f.url]=u;if(w=v.getResponseHeader("Etag"))d.etag[f.url]=w}if(a===304)c="notmodified",n=!0;else try{q=bJ(f,s),c="success",n=!0}catch(x){c="parsererror",r=x}}else r=c,a&&(c="error",a<0&&(a=0));v.status=a,v.statusText=c,n?i.resolveWith(g,[q,c,v]):i.rejectWith(g,[v,c,r]),v.statusCode(k),k=b,f.global&&h.trigger("ajax"+(n?"Success":"Error"),[v,f,n?q:r]),j.resolveWith(g,[v,c]),f.global&&(h.trigger("ajaxComplete",[v,f]),--d.active||d.event.trigger("ajaxStop"))}}typeof e!=="object"&&(e=a,a=b),e=e||{};var f=d.extend(!0,{},d.ajaxSettings,e),g=(f.context=("context"in e?e:d.ajaxSettings).context)||f,h=g===f?d.event:d(g),i=d.Deferred(),j=d._Deferred(),k=f.statusCode||{},l={},m,n,o,p,q=c.location,r=q.protocol||"http:",s,t=0,u,v={readyState:0,setRequestHeader:function(a,b){t===0&&(l[a.toLowerCase()]=b);return this},getAllResponseHeaders:function(){return t===2?m:null},getResponseHeader:function(a){var b;if(t===2){if(!n){n={};while(b=bs.exec(m))n[b[1].toLowerCase()]=b[2]}b=n[a.toLowerCase()]}return b||null},abort:function(a){a=a||"abort",o&&o.abort(a),w(0,a);return this}};i.promise(v),v.success=v.done,v.error=v.fail,v.complete=j.done,v.statusCode=function(a){if(a){var b;if(t<2)for(b in a)k[b]=[k[b],a[b]];else b=a[v.status],v.then(b,b)}return this},f.url=(""+(a||f.url)).replace(br,"").replace(bv,r+"//"),f.dataTypes=d.trim(f.dataType||"*").toLowerCase().split(bz),f.crossDomain||(s=bB.exec(f.url.toLowerCase()),f.crossDomain=s&&(s[1]!=r||s[2]!=q.hostname||(s[3]||(s[1]==="http:"?80:443))!=(q.port||(r==="http:"?80:443)))),f.data&&f.processData&&typeof f.data!=="string"&&(f.data=d.param(f.data,f.traditional)),bG(bD,f,e,v),f.type=f.type.toUpperCase(),f.hasContent=!bu.test(f.type),f.global&&d.active++===0&&d.event.trigger("ajaxStart");if(!f.hasContent){f.data&&(f.url+=(bw.test(f.url)?"&":"?")+f.data);if(f.cache===!1){var x=d.now(),y=f.url.replace(bA,"$1_="+x);f.url=y+(y===f.url?(bw.test(f.url)?"&":"?")+"_="+x:"")}}if(f.data&&f.hasContent&&f.contentType!==!1||e.contentType)l["content-type"]=f.contentType;f.ifModified&&(d.lastModified[f.url]&&(l["if-modified-since"]=d.lastModified[f.url]),d.etag[f.url]&&(l["if-none-match"]=d.etag[f.url])),l.accept=f.dataTypes[0]&&f.accepts[f.dataTypes[0]]?f.accepts[f.dataTypes[0]]+(f.dataTypes[0]!=="*"?", */*; q=0.01":""):f.accepts["*"];for(u in f.headers)l[u.toLowerCase()]=f.headers[u];if(!f.beforeSend||f.beforeSend.call(g,v,f)!==!1&&t!==2){for(u in {success:1,error:1,complete:1})v[u](f[u]);o=bG(bE,f,e,v);if(o){t=v.readyState=1,f.global&&h.trigger("ajaxSend",[v,f]),f.async&&f.timeout>0&&(p=setTimeout(function(){v.abort("timeout")},f.timeout));try{o.send(l,w)}catch(z){status<2?w(-1,z):d.error(z)}}else w(-1,"No Transport")}else w(0,"abort"),v=!1;return v},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery)d.each(a,function(){f(this.name,this.value)});else for(var g in a)bH(g,a[g],c,f);return e.join("&").replace(bo,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bK=d.now(),bL=/(\=)\?(&|$)|()\?\?()/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bK++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){e=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bL.test(b.url)||e&&bL.test(b.data))){var f,g=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h=a[g],i=b.url,j=b.data,k="$1"+g+"$2";b.jsonp!==!1&&(i=i.replace(bL,k),b.url===i&&(e&&(j=j.replace(bL,k)),b.data===j&&(i+=(/\?/.test(i)?"&":"?")+b.jsonp+"="+g))),b.url=i,b.data=j,a[g]=function(a){f=[a]},b.complete=[function(){a[g]=h;if(h)f&&d.isFunction(h)&&a[g](f[0]);else try{delete a[g]}catch(b){}},b.complete],b.converters["script json"]=function(){f||d.error(g+" was not called");return f[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript"},contents:{script:/javascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bM=d.now(),bN={},bO,bP;d.ajaxSettings.xhr=a.ActiveXObject?function(){if(a.location.protocol!=="file:")try{return new a.XMLHttpRequest}catch(b){}try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(c){}}:function(){return new a.XMLHttpRequest};try{bP=d.ajaxSettings.xhr()}catch(bQ){}d.support.ajax=!!bP,d.support.cors=bP&&"withCredentials"in bP,bP=b,d.support.ajax&&d.ajaxTransport(function(b){if(!b.crossDomain||d.support.cors){var c;return{send:function(e,f){bO||(bO=1,d(a).bind("unload",function(){d.each(bN,function(a,b){b.onreadystatechange&&b.onreadystatechange(1)})}));var g=b.xhr(),h;b.username?g.open(b.type,b.url,b.async,b.username,b.password):g.open(b.type,b.url,b.async),(!b.crossDomain||b.hasContent)&&!e["x-requested-with"]&&(e["x-requested-with"]="XMLHttpRequest");try{d.each(e,function(a,b){g.setRequestHeader(a,b)})}catch(i){}g.send(b.hasContent&&b.data||null),c=function(a,e){if(c&&(e||g.readyState===4)){c=0,h&&(g.onreadystatechange=d.noop,delete bN[h]);if(e)g.readyState!==4&&g.abort();else{var i=g.status,j,k=g.getAllResponseHeaders(),l={},m=g.responseXML;m&&m.documentElement&&(l.xml=m),l.text=g.responseText;try{j=g.statusText}catch(n){j=""}i=i===0?!b.crossDomain||j?k?304:0:302:i==1223?204:i,f(i,j,l,k)}}},b.async&&g.readyState!==4?(h=bM++,bN[h]=g,g.onreadystatechange=c):c()},abort:function(){c&&c(0,1)}}}});var bR={},bS=/^(?:toggle|show|hide)$/,bT=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,bU,bV=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(bW("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)e=this[g],f=e.style.display,!d._data(e,"olddisplay")&&f==="none"&&(f=e.style.display=""),f===""&&d.css(e,"display")==="none"&&d._data(e,"olddisplay",bX(e.nodeName));for(g=0;g<h;g++){e=this[g],f=e.style.display;if(f===""||f==="none")e.style.display=d._data(e,"olddisplay")||""}return this},hide:function(a,b,c){if(a||a===0)return this.animate(bW("hide",3),a,b,c);for(var e=0,f=this.length;e<f;e++){var g=d.css(this[e],"display");g!=="none"&&!d._data(this[e],"olddisplay")&&d._data(this[e],"olddisplay",g)}for(e=0;e<f;e++)this[e].style.display="none";return this},_toggle:d.fn.toggle,toggle:function(a,b,c){var e=typeof a==="boolean";d.isFunction(a)&&d.isFunction(b)?this._toggle.apply(this,arguments):a==null||e?this.each(function(){var b=e?a:d(this).is(":hidden");d(this)[b?"show":"hide"]()}):this.animate(bW("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,e){var f=d.speed(b,c,e);if(d.isEmptyObject(a))return this.each(f.complete);return this[f.queue===!1?"each":"queue"](function(){var b=d.extend({},f),c,e=this.nodeType===1,g=e&&d(this).is(":hidden"),h=this;for(c in a){var i=d.camelCase(c);c!==i&&(a[i]=a[c],delete a[c],c=i);if(a[c]==="hide"&&g||a[c]==="show"&&!g)return b.complete.call(this);if(e&&(c==="height"||c==="width")){b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(d.css(this,"display")==="inline"&&d.css(this,"float")==="none")if(d.support.inlineBlockNeedsLayout){var j=bX(this.nodeName);j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)}else this.style.display="inline-block"}d.isArray(a[c])&&((b.specialEasing=b.specialEasing||{})[c]=a[c][1],a[c]=a[c][0])}b.overflow!=null&&(this.style.overflow="hidden"),b.curAnim=d.extend({},a),d.each(a,function(c,e){var f=new d.fx(h,b,c);if(bS.test(e))f[e==="toggle"?g?"show":"hide":e](a);else{var i=bT.exec(e),j=f.cur()||0;if(i){var k=parseFloat(i[2]),l=i[3]||"px";l!=="px"&&(d.style(h,c,(k||1)+l),j=(k||1)/f.cur()*j,d.style(h,c,j+l)),i[1]&&(k=(i[1]==="-="?-1:1)*k+j),f.custom(j,k,l)}else f.custom(j,e,"")}});return!0})},stop:function(a,b){var c=d.timers;a&&this.queue([]),this.each(function(){for(var a=c.length-1;a>=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:bW("show",1),slideUp:bW("hide",1),slideToggle:bW("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(d.css(this.elem,this.prop));return a||0},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||"px",this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!bU&&(bU=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||d.fx.stop()},interval:13,stop:function(){clearInterval(bU),bU=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){d.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),d.expr&&d.expr.filters&&(d.expr.filters.animated=function(a){return d.grep(d.timers,function(b){return a===b.elem}).length});var bY=/^t(?:able|d|h)$/i,bZ=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?d.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,g=f.documentElement;if(!c||!d.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=f.body,i=b$(f),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||d.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||d.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:d.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);d.offset.initialize();var c,e=b.offsetParent,f=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(d.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===e&&(l+=b.offsetTop,m+=b.offsetLeft,d.offset.doesNotAddBorder&&(!d.offset.doesAddBorderForTableAndCells||!bY.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),f=e,e=b.offsetParent),d.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;d.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},d.offset={initialize:function(){var a=c.body,b=c.createElement("div"),e,f,g,h,i=parseFloat(d.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),a=b=e=f=g=h=null,d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=e==="absolute"&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=bZ.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!bZ.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=b$(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=b$(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}})})(window);
if(!this.JSON){this.JSON={};}
(function(){function f(n){return n<10?'0'+n:n;}
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
v=partial.length===0?'[]':gap?'[\n'+gap+
partial.join(',\n'+gap)+'\n'+
mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
return reviver.call(holder,key,value);}
text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
throw new SyntaxError('JSON.parse');};}}());
/**
* @license
*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
* Copyright (C) 2010 David Aurelio. All Rights Reserved.
* Copyright (C) 2010 uxebu Consulting Ltd. & Co. KG. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC., DAVID AURELIO, AND UXEBU
* CONSULTING LTD. & CO. KG ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL APPLE INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Represents a two-dimensional cubic bezier curve with the starting
* point (0, 0) and the end point (1, 1). The two control points p1 and p2
* have x and y coordinates between 0 and 1.
*
* This type of bezier curves can be used as CSS transform timing functions.
*/
function CubicBezier(p1x, p1y, p2x, p2y){
if (!(p1x >= 0 && p1x <= 1)) {
throw new RangeError("'p1x' must be a number between 0 and 1. "
+ "Got " + p1x + "instead.");
}
if (!(p1y >= 0 && p1y <= 1)) {
throw new RangeError("'p1y' must be a number between 0 and 1. "
+ "Got " + p1y + "instead.");
}
if (!(p2x >= 0 && p2x <= 1)) {
throw new RangeError("'p2x' must be a number between 0 and 1. "
+ "Got " + p2x + "instead.");
}
if (!(p2y >= 0 && p2y <= 1)) {
throw new RangeError("'p2y' must be a number between 0 and 1. "
+ "Got " + p2y + "instead.");
}
// Control points
this._p1 = { x: p1x, y: p1y };
this._p2 = { x: p2x, y: p2y };
}
CubicBezier.prototype._getCoordinateForT = function(t, p1, p2){
var c = 3 * p1,
b = 3 * (p2 - p1) - c,
a = 1 - c - b;
return ((a * t + b) * t + c) * t;
};
CubicBezier.prototype._getCoordinateDerivateForT = function(t, p1, p2){
var c = 3 * p1,
b = 3 * (p2 - p1) - c,
a = 1 - c - b;
return (3 * a * t + 2 * b) * t + c;
};
CubicBezier.prototype._getTForCoordinate = function(c, p1, p2, epsilon){
if (!isFinite(epsilon) || epsilon <= 0) {
throw new RangeError("'epsilon' must be a number greater than 0.");
}
// First try a few iterations of Newton's method -- normally very fast.
for (var t2 = c, i = 0, c2, d2; i < 8; i++) {
c2 = this._getCoordinateForT(t2, p1, p2) - c;
if (Math.abs(c2) < epsilon){
return t2;
}
d2 = this._getCoordinateDerivateForT(t2, p1, p2);
if (Math.abs(d2) < 1e-6){
break;
}
t2 = t2 - c2 / d2;
}
// Fall back to the bisection method for reliability.
t2 = c;
var t0 = 0,
t1 = 1,
c2;
if (t2 < t0){
return t0;
}
if (t2 > t1){
return t1;
}
while (t0 < t1) {
c2 = this._getCoordinateForT(t2, p1, p2);
if (Math.abs(c2 - c) < epsilon){
return t2;
}
if (c > c2){
t0 = t2;
}
else{
t1 = t2;
}
t2 = (t1 - t0) * .5 + t0;
}
// Failure.
return t2;
};
/**
* Computes the point for a given t value.
*
* @param {number} t
* @returns {Object} Returns an object with x and y properties
*/
CubicBezier.prototype.getPointForT = function(t) {
// Special cases: starting and ending points
if (t == 0 || t == 1) {
return { x: t, y: t };
}
// check for correct t value (must be between 0 and 1)
else if (!(t > 0) || !(t < 1)) {
throw new RangeError("'t' must be a number between 0 and 1"
+ "Got " + t + " instead.");
}
return {
x: this._getCoordinateForT(t, this._p1.x, this._p2.x),
y: this._getCoordinateForT(t, this._p1.y, this._p2.y)
}
};
CubicBezier.prototype.getTforX = function(x, epsilon){
return this._getTForCoordinate(x, this._p1.x, this._p2.x, epsilon);
};
CubicBezier.prototype.getTforY = function(y, epsilon){
return this._getTForCoordinate(y, this._p1.y, this._p2.y, epsilon);
};
/**
* Computes auxiliary points using De Casteljau's algorithm.
*
* @param {number} t must be greater than 0 and lower than 1.
* @returns {Object} with members i0, i1, i2 (first iteration),
* j1, j2 (second iteration) and k (the exact point for t)
*/
CubicBezier.prototype._getAuxPoints = function(t){
if (!(t > 0) || !(t < 1)) {
throw new RangeError("'t' must be greater than 0 and lower than 1");
}
// First series of auxiliary points
var i0 = { // first control point of the left curve
x: t * this._p1.x,
y: t * this._p1.y
},
i1 = {
x: this._p1.x + t*(this._p2.x - this._p1.x),
y: this._p1.y + t*(this._p2.y - this._p1.y)
},
i2 = { // second control point of the right curve
x: this._p2.x + t*(1 - this._p2.x),
y: this._p2.y + t*(1 - this._p2.y)
};
// Second series of auxiliary points
var j0 = { // second control point of the left curve
x: i0.x + t*(i1.x - i0.x),
y: i0.y + t*(i1.y - i0.y)
},
j1 = { // first control point of the right curve
x: i1.x + t*(i2.x - i1.x),
y: i1.y + t*(i2.y - i1.y)
};
// The division point (ending point of left curve, starting point of right curve)
var k = {
x: j0.x + t*(j1.x - j0.x),
y: j0.y + t*(j1.y - j0.y)
};
return {
i0: i0,
i1: i1,
i2: i2,
j0: j0,
j1: j1,
k: k
}
};
/**
* Divides the bezier curve into two bezier functions.
*
* De Casteljau's algorithm is used to compute the new starting, ending, and
* control points.
*
* @param {number} t must be greater than 0 and lower than 1.
* t == 1 or t == 0 are the starting/ending points of the curve, so no
* division is needed.
*
* @returns {CubicBezier[]} Returns an array containing two bezier curves
* to the left and the right of t.
*/
CubicBezier.prototype.divideAtT = function(t){
if (t < 0 || t > 1) {
throw new RangeError("'t' must be a number between 0 and 1. "
+ "Got " + t + " instead.");
}
// Special cases t = 0, t = 1: Curve can be cloned for one side, the other
// side is a linear curve (with duration 0)
if (t === 0 || t === 1){
var curves = [];
curves[t] = CubicBezier.linear();
curves[1-t] = this.clone();
return curves;
}
var left = {},
right = {},
points = this._getAuxPoints(t);
var i0 = points.i0,
i1 = points.i1,
i2 = points.i2,
j0 = points.j0,
j1 = points.j1,
k = points.k;
// Normalize derived points, so that the new curves starting/ending point
// coordinates are (0, 0) respectively (1, 1)
var factorX = k.x,
factorY = k.y;
left.p1 = {
x: i0.x / factorX,
y: i0.y / factorY
};
left.p2 = {
x: j0.x / factorX,
y: j0.y / factorY
};
right.p1 = {
x: (j1.x - factorX) / (1 - factorX),
y: (j1.y - factorY) / (1 - factorY)
};
right.p2 = {
x: (i2.x - factorX) / (1 - factorX),
y: (i2.y - factorY) / (1 - factorY)
};
return [
new CubicBezier(left.p1.x, left.p1.y, left.p2.x, left.p2.y),
new CubicBezier(right.p1.x, right.p1.y, right.p2.x, right.p2.y)
];
};
CubicBezier.prototype.divideAtX = function(x, epsilon) {
if (x < 0 || x > 1) {
throw new RangeError("'x' must be a number between 0 and 1. "
+ "Got " + x + " instead.");
}
var t = this.getTforX(x, epsilon);
return this.divideAtT(t);
};
CubicBezier.prototype.divideAtY = function(y, epsilon) {
if (y < 0 || y > 1) {
throw new RangeError("'y' must be a number between 0 and 1. "
+ "Got " + y + " instead.");
}
var t = this.getTforY(y, epsilon);
return this.divideAtT(t);
};
CubicBezier.prototype.clone = function() {
return new CubicBezier(this._p1.x, this._p1.y, this._p2.x, this._p2.y);
};
CubicBezier.prototype.toString = function(){
return "cubic-bezier(" + [
this._p1.x,
this._p1.y,
this._p2.x,
this._p2.y
].join(", ") + ")";
};
CubicBezier.linear = function(){
return new CubicBezier
};
CubicBezier.ease = function(){
return new CubicBezier(0.25, 0.1, 0.25, 1.0);
};
CubicBezier.linear = function(){
return new CubicBezier(0.0, 0.0, 1.0, 1.0);
};
CubicBezier.easeIn = function(){
return new CubicBezier(0.42, 0, 1.0, 1.0);
};
CubicBezier.easeOut = function(){
return new CubicBezier(0, 0, 0.58, 1.0);
};
CubicBezier.easeInOut = function(){
return new CubicBezier(0.42, 0, 0.58, 1.0);
};
/*
Copyright (c) 2010 uxebu Consulting Ltd. & Co. KG
Copyright (c) 2010 David Aurelio
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @static
* @type {Object} Global configuration options for TouchScroll.
*/
TouchScroll.config = {
/** @type {Number} The minimum move distance to trigger scrolling (in pixels). */
threshold: 5,
/** @type {Number} The minimum scroll handle size. */
scrollHandleMinSize: 25,
/** @type {Object} Flicking detection and configuration. */
flicking: {
/**
* Maximum duration between last touchmove and the touchend event
* to trigger flicking.
*
* @type {Number}
*/
triggerThreshold: 250,
/**
* Friction factor (per milisecond). This factor is used to
* precalculate the flick length. Lower numbers make flicks
* decelerate earlier.
*
* @type {Number}
*/
friction: 0.998,
/**
* Minimum speed needed before the animation stop (px/ms) This value is
* used to precalculate the flick length. Larger numbers lead to
* shorter flicking lengths and durations.
*
* @type {Number}
*/
minSpeed: 0.15,
/**
* The timing function for flicking animinations (control points
* for a cubic bezier curve).
*
* @type {Number[]}
*/
timingFunc: [0, 0.3, 0.6, 1]
},
/** @type {Object} Bouncing configuration */
elasticity: {
/** @type {Number} Factor for the bounce length while dragging. */
factorDrag: 0.5,
/** @type {Number} Factor for the bounce length while flicking. */
factorFlick: 0.2,
/** @type {Number} Maximum bounce (in px) when flicking. */
max: 100
},
/** @type {Object} Snap back configuration. */
snapBack: {
/**
* The timing function for snap back animations (control points for
* a cubic bezier curve) when bouncing out before, the first
* control point is overwritten to achieve a smooth transition
* between bounce and snapback.
*
* @type {Number[]}
*/
timingFunc: [0, 0.25, 0, 1],
/** @type {Number} Default snap back time. */
defaultTime: 750,
/**
* Whether the snap back effect always uses the default time or
* uses the bounce out time.
*
* @type {Boolean}
*/
alwaysDefaultTime: true
}
};
//
// FEATURE DETECTION
//
/**
* @type {Boolean} Whether touch events are supported by the user agent.
* @private
*/
TouchScroll._hasTouchSupport = (function() {
if ("createTouch" in document) { // True on the iPhone
return true;
}
try {
var event = document.createEvent("TouchEvent"); // Should throw an error if not supported
return !!event.initTouchEvent; // Check for existance of initialization method
} catch(error) {
return false;
}
}());
/**
* Whether WebKitCSSMatrix is supported properly by the user agent.
*
* In some older versions of Android, WebKitCSSMatrix is broken and does
* not parse a "matrix" directive properly.
*
* @type {Boolean}
* @private
*/
TouchScroll._parsesMatrixCorrectly = (function() {
// Assanka change: avoid a runtime error on older/non-WebKit UAs
if (typeof WebKitCSSMatrix === 'undefined') {
return false;
}
var m = new WebKitCSSMatrix("matrix(1, 0, 0, 1, -20, -30)");
return m.e === -20 && m.f === -30;
}());
/**
* Whether we are on Android.
*
* @type {Number} Android version number or `null`.
* @private
*/
TouchScroll._android = (function() {
var match = navigator.userAgent.match(/Android\s+(\d+(?:\.\d+)?)/);
return match && parseFloat(match[1]);
}());
/**
* Contains the name of the events to listen for.
*
* Depends on touch support.
*
* @type {Object}
* @private
*/
TouchScroll._eventNames = {
/** @type {String} The name of the start event. */
start: "touchstart",
/** @type {String} The name of the move event. */
move: "touchmove",
/** @type {String} The name of the end event. */
end: "touchend",
/** @type {String} The name of the cancel event. */
cancel: "touchcancel"
};
if (!TouchScroll._hasTouchSupport) { // overwrite event names
TouchScroll._eventNames = {
start: "mousedown",
move: "mousemove",
end: "mouseup",
cancel: "touchcancel" // unnecessary here
};
}
/**
* @private
* @static
* @type {CSSStyleSheet}
*/
TouchScroll._styleSheet = (function() {
var doc = document;
var parent = doc.querySelector("head") || doc.documentElement;
var styleNode = document.createElement("style");
parent.insertBefore(styleNode, parent.firstChild);
for (var i = 0, sheet; (sheet = doc.styleSheets[i]); i++) {
if (styleNode === sheet.ownerNode) {
return sheet; // return the newly created stylesheet
}
}
return doc.styleSheets[0]; // return a random stylesheet
}());
[
".TouchScroll{" +
"position:relative;" +
"display:-webkit-box;" +
"}",
".-ts-layer{" +
"-webkit-transition-property:-webkit-transform;" +
"-webkit-transform:translate3d(0,0,0);" +
//"-webkit-transform-style:-3d;" +
"position:absolute;" +
"height:100%;" +
"top:0;" +
"right:0;" +
"left:0;" +
"}",
".-ts-outer{" +
"-webkit-box-flex:1;" +
"position:relative;" +
"height:auto;" +
"}",
".-ts-inner {" +
"position:relative;" +
"-webkit-transform-style:flat;" +
"}",
".-ts-inner.scrolling{" +
"-webkit-user-select:none;" +
"pointer-events:none;" +
"}",
".-ts-bars{" +
"bottom:0;" +
"left:0;" +
"overflow:hidden;" +
"pointer-events:none;" +
"position:absolute;" +
"opacity:0;" +
"right:0;" +
"top:0;" +
"z-index:2147483647;" +
"-webkit-transition:opacity 250ms;" +
"}",
".-ts-bars-active{" +
"opacity:1;" +
"-webkit-transition:none;" +
"}",
".-ts-bar{" +
"display:none;" +
"position:absolute;" +
"right:3px;" +
"bottom:3px;" +
//"-webkit-transform-style:preserve-3d;" +
"}",
".-ts-bar.active{" +
"display:block;" +
"}",
".-ts-bar-e{" +
"height:7px;" +
"left:3px;" +
"-webkit-transform:rotate(-90deg) translateX(-7px);" +
"-webkit-transform-origin:0 0;" +
"}",
".-ts-bar-f{" +
"width:7px;" +
"top:3px;" +
"}",
".-ts-bars-both .-ts-bar-e{" +
"right:9px;" +
"}",
".-ts-bars-both .-ts-bar-f{" +
"bottom:9px;" +
"}",
".-ts-indicator-e,.-ts-indicator-f,.-ts-bar-part{" +
"position:absolute;" +
"}",
".-ts-bar-part{" +
"width: 7px;" +
"-webkit-border-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOBAMAAADtZjDiAAAALVBMVEUAAAD///8AAAD///+kpKT///////////////////8nJycBAQEJCQn///9YWFgbIh+zAAAAD3RSTlOATQASUTVFQwMkaIB3TFtjuC6yAAAATElEQVQI12NQ0piaFtmkxKBkLigoWKzEoHzR68wSWSOGdrkNDNwPKxgmejMwMGyRZAhcAKS5RBkSDwBpHjE4DROHqYPpg5kDMxdqDwDB4xorHHHNdAAAAABJRU5ErkJggg==) 6 stretch;" +
"-webkit-box-sizing:border-box;"+
"-webkit-transform-origin:0 0;" +
//"-webkit-transform-style:preserve-3d;" +
"}",
".-ts-bar-1,.-ts-bar-3{" +
"border-width:3px 3px 0;" +
"height:0;" +
"}",
".-ts-bar-3{" +
"border-width:0 3px 3px;" +
"}",
".-ts-bar-2{" +
"height:1px;" +
"border-width:0 3px;" +
"}",
".-ts-bar-2{" +
"height:1px;" +
"}"
].forEach(function(rule, i) { this.insertRule(rule, i); }, TouchScroll._styleSheet);
/**
* @class
* @param {HTMLElement} scrollElement The HTML element to make scrollable.
* @param {Objects} [options] An expando for options. Supported options are:#
* - elastic {Boolean}, defaults to `false`
* - scrollbars {Boolean}, defaults to `true`
* - scrollevents {Boolean}, defaults to `false`
*/
function TouchScroll(scrollElement, options) {
options = options || {};
/** @type {Boolean} Whether the scroller bounces across its bounds. */
this.elastic = !!options.elastic;
/** @type {Boolean} Whether to fire DOM scroll events */
this.scrollevents = !!options.scrollevents;
var snapToGrid =
/** @type {Boolean} Whether to snap to a 100%x100%-grid -- "paging mode". */
this.snapToGrid = !!options.snapToGrid;
/** @type {Object} Contains the number of segments for each axis (for paging mode). */
this.maxSegments = {e: 1, f: 1};
/** @type {Object} Contains the current of segments for each axis (for paging mode). */
this.currentSegment = {e: 0, f: 0};
/** @type {Boolean} Whether to build and use scrollbars. */
var useScrollbars = !snapToGrid;
if (useScrollbars && "scrollbars" in options) {
useScrollbars = !!options.scrollbars;
}
/**
* An array of timeout handles for queued animations and actions that have
* to be cancelled on animation stop.
*
* @type {Number[]}
*/
this._scrollTimeouts = [];
/** @type {Object} Holds scrollbar related metrics. */
this._barMetrics = {
/** @type {Object} Stores the offset height of the scrollbar "tracks". */
availLength: {e: 0, f: 0}, //TODO: Check if necessary!
/** @type {Number} Stores the size of the bar ends in pixels (assuming all have the same size). */
tipSize: 0,
/** @type {Object} Stores the maximum offset for each scroll indicator. */
maxOffset: {e: 0, f: 0}, //TODO: Check if necessary!
/** @type {Object} Stores the ratio of scroll layer and scroll indicator offsets. */
offsetRatios: {e: 0, f:0},
/** @type {Object} Stores the calculated sizes of the scroll indicators. */
sizes: {e: 0, f: 0}
};
/** @type {Object} Holds references to the DOM nodes used by the scroller. */
this._dom = {
/** @type {HTMLElement} A reference to the outer/main DOM node. */
outer: scrollElement
};
/** @type {Object} Stores whether each axis is scrolling. */
this._isScrolling = {e: false, f: false, general: false};
/** @type {String[]} Stores the the ids of all scrolling axes */
this._activeAxes = [];
/** @type {Boolean} Whether the scroller is currently tracking touches (other than start). */
this._isTracking = false;
/** @type {Event[]} The last two tracked events .*/
this._lastEvents = [];
/** @type {Object} Stores the maximum scroll offset for each axis. */
this._maxOffset = {e: 0, f: 0};
/** @type {Object} Stores the relevant metrics of the last call to {@link setupScroller}. */
this._metrics = {
offsetWidth: -1,
offsetHeight: -1,
scrollWidth: -1,
scrollHeight: -1
};
/** @type {Object} Stores the relevant metrics of the innermost scrolling layer. */
this._innerSize = null;
/** @type {Boolean} Whether the scroll threshold has been exceeded. */
this._scrollBegan = false;
/** @type {Boolean} Assanka change: whether a scroll animation is currently in progress. */
this._isCompletingScroll = true;
/** @type {Boolean} Assanka change: whether a scroll has been triggered programatically. */
this._actioningScroll = true;
/** @type {CSSMatrix} The current scroll offset. Not valid while flicking. */
this._scrollOffset = new this._Matrix();
this._initDom(useScrollbars);
}
TouchScroll.prototype = {
config: TouchScroll.config,
/**
* All axes -- "e" is the x-axis, "f" is the y-axis.
*
* This property exists to avoid dynamic object creation during runtime.
*
* @private
* @static
* @type {String[]}
*/
_axes: ["e", "f"],
_eventNames: TouchScroll._eventNames,
/**
* @private
* @static
* @type {Object} Mapping from event types to handler names.
*/
_handlerNames: {
touchstart: "onTouchStart",
mousedown: "onTouchStart",
touchmove: "onTouchMove",
mousemove: "onTouchMove",
touchend: "onTouchEnd",
mouseup: "onTouchEnd",
touchcancel: "onTouchEnd",
DOMSubtreeModified: "onDOMChange",
focus: "onChildFocused"
},
/**
* @private
* @type Boolean
* @static
*
* Whether the rendering engine has 3D-transform support. Can be sued to
* enforce hardware-acceleration.
*/
// Assanka change: hardcoded to false, as we use preserve-3d and .uses3d to allow toggling on Android
_has3d: false,//"m11" in new WebKitCSSMatrix(),
/**
* The CSSMatrix constructor to use. Defaults to WebKitCSSMatrix.
*
* @static
* @private
* @type {Function}
*/
// Assanka change: avoid a runtime error on UAs with no support for WebKitCSSMatrix
_Matrix: (function() {
if (typeof WebKitCSSMatrix !== 'undefined') {
return WebKitCSSMatrix;
}
})(),
/**
* @private
* @static
* @type {String} HTML for TouchScroll instances.
*/
_scrollerTemplate: [
// Assanka change: add 'uses3d' to three major elements for Android fixes
'<div class="-ts-layer -ts-outer uses3d">', // scrolling layer y-axis
'<div class="-ts-layer uses3d">', // scrolling layer x-axis
'<div class="-ts-layer -ts-inner uses3d"></div>', // wrapper
'</div>',
'</div>',
'<div class="-ts-bars"></div>'
].join(""),
/**
* @private
* @static
* @type {String} HTML for scrollbars. Used on instances with scrollbars.
*/
_scrollbarTemplate : [
'<div class="-ts-bar -ts-bar-e">',
'<div class="-ts-indicator-e">',
'<div class="-ts-bar-part -ts-bar-1"></div>',
'<div class="-ts-bar-part -ts-bar-2"></div>',
'<div class="-ts-bar-part -ts-bar-3"></div>',
'</div>',
'</div>',
'<div class="-ts-bar -ts-bar-f -ts-indicator-f">',
'<div class="-ts-bar-part -ts-bar-1"></div>',
'<div class="-ts-bar-part -ts-bar-2"></div>',
'<div class="-ts-bar-part -ts-bar-3"></div>',
'</div>'
].join(""),
_styleSheet: TouchScroll._styleSheet,
/**
* Centers the scroller at given coordinates.
*
* @param {Number} left The horizontal offset.
* @param {Number} top The vertical offset.
* @param {Number} [duration] Duration in milliseconds for the transition.
*/
centerAt: function centerAt(left, top, duration) {
var m = this._metrics;
left += Math.ceil(m.offsetWidth / 2);
top += Math.ceil(m.offsetHeight / 2);
this.scrollTo(left, top, duration);
},
/**
* DOM Level 2 event handler method.
*
* @private
* @param {Event} event.
*/
handleEvent: function handleEvent(event) {
var handlerName = this._handlerNames[event.type];
if (handlerName) {
this[handlerName](event);
}
},
hideScrollbars: function hideScrollbars() {
var bars = this._dom.bars;
if (bars) {
bars.outer.className = "-ts-bars";
}
},
onChildFocused: function onChildFocused(event) {
var innerScroller = this._dom.scrollers.inner;
var node = event.target;
if (node === innerScroller) {
return;
}
var offsetLeft = 0, offsetTop = 0;
do {
offsetLeft += node.offsetLeft;
offsetTop += node.offsetTop;
node = node.offsetParent;
} while (node !== innerScroller);
var offset = this._scrollOffset.inverse();
var m = this._metrics;
// if element not visible scroll there
var doScroll = false, scrollE = offset.e, scrollF = offset.f;
var visibleHorizontal = offsetLeft > scrollE && offsetLeft < scrollE + m.offsetWidth;
var visibleVertical = offsetTop > scrollF && offsetTop < scrollF + m.offsetHeight;
if (!visibleHorizontal) { scrollE = offsetLeft; doScroll = true; }
if (!visibleVertical) { scrollF = offsetTop; doScroll = true; }
if (doScroll) {
this.scrollTo(offsetLeft, offsetTop, 100);
}
},
onDOMChange: function onDOMChange(){
this.setupScroller();
},
onTouchStart: function onTouchStart(event) {
if (!this._isScrolling.general) {
return;
}
this._stopAnimations();
this.setupScroller();
this._isTracking = true;
this._scrollBegan = false;
// Assanka change: track manual scrolls
this._actioningScroll = false;
event = event.touches && event.touches.length ? event.touches[0] : event;
this._lastEvents[1] = {
pageX: event.pageX,
pageY: event.pageY,
timeStamp: event.timeStamp
};
},
onTouchMove: function onTouchMove(event) {
if (!this._isTracking) {
return;
}
event.preventDefault();
// Assanka change: stop propagation
event.stopPropagation();
var lastEvents = this._lastEvents;
var lastEvent = lastEvents[1];
var touch = event.touches && event.touches.length ? event.touches[0] : event;
var pageX = touch.pageX;
var pageY = touch.pageY;
var scrollOffset = new this._Matrix();
scrollOffset.e = pageX - lastEvent.pageX;
scrollOffset.f = pageY - lastEvent.pageY;
var scrollBegan = this._scrollBegan;
if (!scrollBegan) {
var threshold = this.config.threshold;
this._scrollBegan = scrollBegan =
threshold <= scrollOffset.e ||
threshold <= -scrollOffset.e ||
threshold <= scrollOffset.f ||
threshold <= -scrollOffset.f;
if (scrollBegan) {
this.showScrollbars();
// catch pointer events with the scrollbar layer
// Assanka change: keep the uses3d class in use here
this._dom.scrollers.inner.className = "-ts-layer -ts-inner uses3d scrolling";
}
}
if (scrollBegan) {
this._scrollBy(scrollOffset);
lastEvents[0] = lastEvent;
lastEvents[1] = {
pageX: pageX,
pageY: pageY,
timeStamp: event.timeStamp
};
}
},
onTouchEnd: function onTouchEnd(event) {
if (!this._isTracking || !this._scrollBegan) {
this.hideScrollbars();
// Assanka change: if a scroll was still in progress before interruption, ensure it's completed
if (this._isTracking && !this._actioningScroll && this._isCompletingScroll) this.snapBack();
return;
}
event.preventDefault();
event.stopPropagation();
this._isTracking = this._scrollBegan = false;
// calculate flick
var isScrolling = this._isScrolling;
var configFlicking = this.config.flicking;
var lastEvents = this._lastEvents;
var event0 = lastEvents[0];
var event1 = lastEvents[1];
var lag = event.timeStamp - event1.timeStamp;
var moveX = isScrolling.e ? event1.pageX - event0.pageX : 0;
var moveY = isScrolling.f ? event1.pageY - event0.pageY : 0;
var moveDistance = Math.sqrt(moveX * moveX + moveY * moveY);
var moveDuration = event1.timeStamp - event0.timeStamp;
var moveSpeed = moveDistance / moveDuration;
var flickAllowed = lag <= configFlicking.triggerThreshold &&
moveSpeed >= configFlicking.minSpeed;
var flick, flickDistance, flickDuration;
if (flickAllowed) {
flick = this._computeFlick(moveSpeed);
flickDuration = flick[0];
flickDistance = flick[1];
}
if (flickAllowed && flickDuration && flickDistance) {
var flickVector = new this._Matrix();
flickVector.e = moveX / moveDistance * flickDistance;
flickVector.f = moveY / moveDistance * flickDistance;
this._flick(flickDuration, flickVector);
}
else {
// snap back to bounds
this.snapBack();
}
this._lastEvents[0] = this._lastEvents[1] = null;
},
/**
* Scroll the scroller by the given amount of pixels.
*
* @param {Number} e The horizontal amount of pixels to scroll.
* @param {Number} f The vertical amount of pixels to scroll.
* @param {Number} [duration] Duration in milliseconds for the transition.
*/
scrollBy: function scrollBy(e, f, duration) {
// Assanka change: track programmatic scorlling
if ((e || f) && duration) this._actioningScroll = true;
var scrollMatrix = this._determineOffset(true).inverse().translate(e, f, 0);
return this.scrollTo(scrollMatrix.e, scrollMatrix.f, duration);
},
/**
* Scroll the scroller to the given coordinates.
*
* @param {Number} e The horizontal offset.
* @param {Number} f The vertical offset.
* @param {Number} [duration] Duration in milliseconds for the transition.
*/
scrollTo: function scrollTo(e, f, duration) {
// Assanka change: track programmatic scorlling
if ((e || f) && duration) this._actioningScroll = true;
if (duration <= 0) {
// limit to bounds if not flicking
var maxOffset = this._maxOffset;
e = Math.max(Math.min(e, maxOffset.e), 0);
f = Math.max(Math.min(f, maxOffset.f), 0);
}
var scrollMatrix = this._scrollOffset.translate(e, f, 0).inverse();
if (duration > 0) {
this._flick(duration, scrollMatrix);
}
else {
this._scrollBy(scrollMatrix);
}
},
/**
* Sets up the scroller according to its metrics.
*
* This method does nothing if offsetWidth/Height and scrollWidth/Height
* are unchanged.
*
* @param {Boolean} force Whether to force the setup.
* @returns {Boolean} Whether setup has run. False, if skipped due to
* unchanged metrics.
*/
setupScroller: function setupScroller(force) {
var dom = this._dom;
var scrollerElement = dom.outer;
var offsetWidth = scrollerElement.offsetWidth;
var offsetHeight = scrollerElement.offsetHeight;
var scrollWidth = scrollerElement.scrollWidth;
var scrollHeight = scrollerElement.scrollHeight;
var m = this._metrics;
// Check whether we really need to refresh ... if not, leave here.
if (!force &&
offsetWidth === m.offsetWidth && offsetHeight === m.offsetHeight &&
scrollWidth === m.scrollWidth && scrollHeight === m.scrollHeight
) {
return false;
}
m.offsetWidth = offsetWidth;
m.offsetHeight = offsetHeight;
m.scrollWidth = scrollWidth;
m.scrollHeight = scrollHeight;
// instance properties
var maxOffset = this._maxOffset = {
e: Math.max(scrollWidth - offsetWidth, 0),
f: Math.max(scrollHeight - offsetHeight, 0)
};
var isScrolling = this._isScrolling = {
e: maxOffset.e > 0,
f: maxOffset.f > 0
};
isScrolling.general = isScrolling.e || isScrolling.f;
var activeAxes = this._activeAxes = this._axes.filter(function(axis) {
return isScrolling[axis];
});
var scrollers = dom.scrollers
var innerNode = scrollers.inner;
var innerOffsetWidth = innerNode.offsetWidth;
var innerOffsetHeight = innerNode.offsetHeight;
var innerScrollWidth = innerNode.scrollWidth;
var innerScrollHeight = innerNode.scrollHeight;
var innerSize = this._innerSize = {e: innerOffsetWidth, f: innerOffsetHeight};
this.maxSegments = {
e: Math.ceil(innerScrollWidth / innerOffsetWidth),
f: Math.ceil(innerScrollHeight / innerOffsetHeight)
};
// force scrollers into bounds
var offsetSpecs = [];
var scrollOffset = this._scrollOffset;
var zeroMatrix = new this._Matrix(), matrix;
var i = 0, axes = this._axes, axis;
while ((axis = axes[i++])) {
var axisOffset = scrollOffset[axis];
var axisMinOffset = -maxOffset[axis];
if (axisOffset > 0 || axisOffset < axisMinOffset) {
scrollOffset[axis] = axisOffset = axisOffset > 0 ? 0 : axisMinOffset;
matrix = zeroMatrix.translate(0, 0, 0);
matrix[axis] = axisOffset;
offsetSpecs[offsetSpecs.length] = {
style: scrollers[axis].style,
matrix: matrix
};
}
}
// hide/show scrollbars
var bars = dom.bars;
if (bars) {
var bothScrolling = true, bar;
i = 0;
while ((axis = axes[i++])) {
bar = bars[axis];
bar.className = bar.className.replace(" active", "");
if (isScrolling[axis]) {
bar.className += " active";
}
else {
bothScrolling = false;
}
}
bars.outer.className = bars.outer.className.replace(" -ts-bars-both", "");
if (bothScrolling) {
bars.outer.className += " -ts-bars-both";
}
// calculate and apply scroll indicator sizes
var scrollHandleMinSize = this.config.scrollHandleMinSize;
var barMetrics = this._barMetrics;
var availLength = barMetrics.availLength;
availLength.e = bars.e.offsetWidth;
availLength.f = bars.f.offsetHeight;
var barSizes = barMetrics.sizes;
barSizes.e = Math.round(Math.max(
availLength.e * offsetWidth / scrollWidth
), scrollHandleMinSize);
barSizes.f = Math.round(Math.max(
availLength.f * offsetHeight / scrollHeight
), scrollHandleMinSize);
var tipSize = barMetrics.tipSize;
var barMaxOffset = barMetrics.maxOffset;
barMaxOffset.e = availLength.e;
barMaxOffset.f = availLength.f;
var offsetRatios = barMetrics.offsetRatios;
offsetRatios.e = barMaxOffset.e / -scrollWidth;
offsetRatios.f = barMaxOffset.f / -scrollHeight;
var parts, size, scale, offset;
i = 0;
axes = activeAxes;
while ((axis = axes[i++])) {
parts = bars.parts[axis];
tipSize = tipSize || parts[0].offsetHeight;
size = barSizes[axis];
scale = size - tipSize * 2;
barMetrics.maxOffset[axis] = availLength[axis] - size;
offset = offsetRatios[axis] * scrollOffset[axis];
parts[1].style.height = scale + "px";
offsetSpecs.push(
{
style: parts[3].style,
matrix: {e: 0, f: offset}
},
{
style: parts[1].style,
matrix: {e: 0, f: tipSize}
},
{
style: parts[2].style,
matrix: {e: 0, f: tipSize + scale}
}
);
}
barMetrics.tipSize = tipSize;
}
this._setStyleOffset(offsetSpecs);
return true;
},
showScrollbars: function showScrollbars() {
var bars = this._dom.bars;
if (bars) {
bars.outer.className += " -ts-bars-active";
}
},
/**
* Scrolls back to the bounds of the scroller if the scroll position
* exceeds these.
*
* @param {String|null} [snapAxis] Which axis to snap back. `null` snaps
* back both axes.
* @returns {Boolean} Whether the scroller was beyond regular bounds.
*/
snapBack: function snapBack(snapAxis, duration, timeout) {
if (timeout > 0) {
var timeouts = this._scrollTimeouts;
var that = this;
timeouts[timeouts.length] = setTimeout(function() {
that.snapBack();
}, timeout);
return null;
}
var axes = snapAxis ? [snapAxis] : this._activeAxes;
var snapBackConfig = this.config.snapBack;
if (typeof duration === "undefined") { duration = snapBackConfig.defaultTime; }
var timingFunc = snapBackConfig.timingFunc;
var dom = this._dom;
var scrollers = dom.scrollers;
var bars = dom.bars;
var hasBars = !!bars;
var snapToGrid = this.snapToGrid;
var innerSize, maxSegments, currentSegments;
if (snapToGrid) {
innerSize = this._innerSize;
maxSegments = this.maxSegments;
currentSegments = this.currentSegment;
}
var barMetrics, barSizes, tipSize, barMaxOffset, barParts;
if (hasBars) {
barMetrics = this._barMetrics;
barSizes = barMetrics.sizes;
tipSize = barMetrics.tipSize;
barMaxOffset = barMetrics.maxOffset;
barParts = bars.parts;
}
var scrollOffset = this._determineOffset(true);
var maxOffsets = this._maxOffset;
var i = 0, axis;
var zeroMatrix = new this._Matrix(), matrix;
var snapsBack = false;
var offsetSpecs = [], numOffsetSpecs = 0;
while ((axis = axes[i++])) {
var offset = scrollOffset[axis];
var maxOffset = 0;
var minOffset = -maxOffsets[axis];
if (snapToGrid) {
var axisInnerSize = innerSize[axis];
var currentSegment = -Math.floor((offset + 0.5*axisInnerSize) / axisInnerSize);
var axisMaxSegments = maxSegments[axis];
if (currentSegment < 0) {
currentSegment = 0;
}
else if (currentSegment >= axisMaxSegments) {
currentSegment = axisMaxSegments - 1;
}
minOffset = maxOffset = -currentSegment * axisInnerSize;
if (currentSegment !== currentSegments[axis]) {
currentSegments[axis] = currentSegment;
this._fireEvent("segmentchange", {
axis: axis,
segment: currentSegment,
numSegments: axisMaxSegments
});
}
}
if (offset >= minOffset && offset <= maxOffset) {
continue;
}
snapsBack = true;
// snap back bouncer layer
matrix = zeroMatrix.translate(0, 0, 0);
matrix[axis] = offset > maxOffset ? maxOffset : minOffset;
offsetSpecs[numOffsetSpecs++] = {
style: scrollers[axis].style,
matrix: matrix,
duration: duration,
timingFunc: timingFunc
};
var bounceAtEnd = offset < minOffset;
var snapBackLength = bounceAtEnd ? minOffset - offset : offset - maxOffset;
// snap back bars
if (hasBars) {
var size = barSizes[axis];
var scale = size - 2 * tipSize;
var barDuration = duration;
var barTimingFunc = timingFunc;
if (snapBackLength > scale && duration > 0) { // bars start growing during snap back
var bezier = bezier || new CubicBezier(timingFunc[0], timingFunc[1], timingFunc[2], timingFunc[3]);
var t = bezier.getTforY(1 - scale/snapBackLength, 1 / duration);
var timeFraction = bezier.getPointForT(t).x;
barDuration *= 1 - timeFraction;
barTimingFunc = bezier.divideAtT(t)[1];
}
var parts = barParts[axis];
var barDelay = duration - barDuration;
offsetSpecs[numOffsetSpecs++] = {
style: parts[0].style,
matrix: {e: 0, f: 0},
delay: barDelay,
duration: barDuration,
timingFunc: barTimingFunc
};
offsetSpecs[numOffsetSpecs++] = {
style: parts[1].style,
matrix: {e: 0, f: tipSize},
delay: barDelay,
duration: barDuration,
timingFunc: barTimingFunc
};
offsetSpecs[numOffsetSpecs++] = {
style: parts[2].style,
matrix: {e: 0, f: tipSize + scale},
delay: barDelay,
duration: barDuration,
timingFunc: barTimingFunc
};
}
}
this._setStyleOffset(offsetSpecs);
if (snapsBack) {
this.showScrollbars();
// Assanka change: mark that a scroll is being completed
this._isCompletingScroll = true;
// Assanka change: end the scroll after finishing the snapback.
var that = this;
var timeouts = this._scrollTimeouts;
timeouts[timeouts.length] = setTimeout(function() {
that._endScroll();
}, duration);
}
else if (!snapAxis) {
this._endScroll();
}
return snapsBack;
},
/**
* Computes the duration and the distance of a flick from a given initial
* speed.
*
* @param {Number} initialSpeed The initial speed of the flick in
* pixels per millisecond.
* @returns {Number[]} An array containing flick duration (in milliseconds)
* and flick distance (in pixels).
*/
_computeFlick: function _computeFlick(initialSpeed) {
/*
The duration is computed as follows:
variables:
m = minimum speed before stopping = config.flicking.minSpeed
d = duration
s = speed = initialSpeed
f = friction per milisecond = config.flicking.friction
The minimum speed is computed as follows:
m = s * f ^ d
// as the minimum speed is given and we need the duration we
// can solve the equation for d:
<=> d = log(m/s) / log(f)
*/
var configFlicking = this.config.flicking;
var friction = configFlicking.friction;
var duration = Math.log(configFlicking.minSpeed / initialSpeed) /
Math.log(friction);
duration = duration > 0 ? Math.round(duration) : 0;
/*
The amount of pixels to flick is the sum of the distance covered
every milisecond of the flicking duration.
Because the distance is decelerated by the friction factor, the
speed at a given time t is:
pixelsPerMilisecond * friction^t
and the distance covered is:
d = distance
s = initial speed = pixelsPerMilisecond
t = time = duration
f = friction per milisecond = config.flicking.friction
d = sum of s * f^n for n between 0 and t
<=> d = s * (sum of f^n for n between 0 and t)
which is a geometric series and thus can be simplified to:
d = s * (1 - f^(d+1)) / (1 - f)
*/
var factor = (1 - Math.pow(friction, duration + 1)) / (1 - friction);
var distance = initialSpeed * factor;
return [duration, distance];
},
/**
* Gets the current offset from the scrolling layers.
*
* @param {Boolean} round Whether to round the offfset to whole pixels.
* @returns {CSSMatrix} This is a reference to {@link _scrollOffset}
*/
_determineOffset: function _determineOffset(round) {
var scrollers = this._dom.scrollers;
var offset = this._scrollOffset;
var i = 0, axes = this._activeAxes, axis;
while ((axis = axes[i++])) {
var axisOffset = this._getNodeOffset(scrollers[axis])[axis];
if (round) {
// This is a high performance rounding method:
// Add 0.5 and then do a double binary inversion
axisOffset = ~~(axisOffset + 0.5);
}
offset[axis] = axisOffset;
}
return offset;
},
/**
* Does cleanup work after ending a scroll.
*/
_endScroll: function _endScroll() {
// Assanka change: mark that animation is complete.
this._isCompletingScroll = false;
// Assanka change: keep the uses3d class here
this._dom.scrollers.inner.className = "-ts-layer -ts-inner uses3d";
this.hideScrollbars();
// Assanka change: fire an event
this._fireEvent('scrollend');
},
/**
* Plays a flicking animation.
*
* @param {Number} duration The animation duration in milliseconds
* @param {CSSMatrix} vector The scroller offsets.
*/
_flick: function _flick(duration, vector) {
// local variables for everything to minimize lookups
var config = this.config;
var scrollOffset = this._scrollOffset;
var maxOffset = this._maxOffset;
var dom = this._dom;
var scrollers = dom.scrollers;
var bars = dom.bars;
var hasBars = !!bars;
var maxSegments, currentSegments, innerSizes;
var snapToGrid = this.snapToGrid;
if(snapToGrid){
maxSegments = this.maxSegments;
currentSegments = this.currentSegment;
innerSizes = this._innerSize;
}
var barMetrics, barOffsetRatios, barTipSize, barSizes, barParts;
if (hasBars) {
barMetrics = this._barMetrics;
barOffsetRatios = barMetrics.offsetRatios;
barTipSize = barMetrics.tipSize;
barSizes = barMetrics.sizes;
barParts = bars.parts;
}
var tf = config.flicking.timingFunc;
var timingFunc = new CubicBezier(tf[0], tf[1], tf[2], tf[3]);
var epsilon = 1 / duration; // precision for bezier computations
var isElastic = this.elastic;
var configElasticity = config.elasticity;
var configBounceFactor = configElasticity.factorFlick;
var maxBounceLength = configElasticity.max;
var configSnapBack = config.snapBack;
var configSnapBackAlwaysDefaultTime = configSnapBack.alwaysDefaultTime;
var configSnapBackDefaultTime = configSnapBack.defaultTime;
var flickTarget = scrollOffset.multiply(vector);
var zeroMatrix = new this._Matrix();
var offsetSpecs = [], numOffsetSpecs = 0;
var bounceSpecs, numBounceSpecs; // set individually for each axis
var maxDuration = 0;
var animDuration;
// flick for every axis
var i = 0, axes = this._activeAxes, axis;
while ((axis = axes[i++])) {
var distance = vector[axis];
if (!distance) {
this.snapBack(axis);
continue;
}
var targetFlick = flickTarget[axis];
var axisMin = -maxOffset[axis];
var axisMax = 0;
var scrollFrom = scrollOffset[axis];
if(snapToGrid){
var innerSize = innerSizes[axis];
var segmentIncrement = distance > 0 ? -1 : 1;
var maxSegment = maxSegments[axis];
var currentSegment = currentSegments[axis];
var flickToSegment = currentSegment + segmentIncrement;
if (flickToSegment < 0) {
flickToSegment = 0;
}
else if (maxSegment <= flickToSegment) {
flickToSegment = maxSegment - 1;
}
currentSegments[axis] = flickToSegment;
if(flickToSegment === currentSegment){
this.snapBack(axis);
continue;
}
else {
this._fireEvent("segmentchange", {
axis: axis,
segment: flickToSegment,
numSegments: maxSegment
});
}
axisMin = axisMax = -flickToSegment * innerSize;
}
var distanceFlick = distance;
// compute distance fraction where flicking crosses the bounds of the scroller.
if (targetFlick < axisMin) {
distanceFlick = axisMin - scrollFrom;
targetFlick = axisMin;
}
else if (targetFlick > axisMax) {
distanceFlick = axisMax - scrollFrom;
targetFlick = axisMax;
}
var distanceBounce = snapToGrid ? 0 : distance - distanceFlick;
// calculate timing functions
var t = timingFunc.getTforY(distanceFlick / distance, epsilon);
if (t < 0 || t > 1) { // already beyond scroller bounds
t = 0;
distanceFlick = 0;
distanceBounce = distance;
}
var bezierCurves = timingFunc.divideAtT(t);
var timingFuncFlick = bezierCurves[0];
var timingFuncBounce = timingFuncFlick;
var durationFlick = duration * timingFunc.getPointForT(t).x;
var durationBounce = duration - durationFlick;
animDuration = durationFlick;
var bounceSign, distanceBounceAbs;
if (isElastic && distanceBounce) {
durationBounce *= configBounceFactor;
distanceBounce *= configBounceFactor;
bounceSign = distanceBounce < 0 ? -1 : 1;
distanceBounceAbs = distanceBounce * bounceSign;
// limit the bounce to the configured maximum
if (distanceBounceAbs > maxBounceLength) {
durationBounce *= maxBounceLength / distanceBounceAbs;
distanceBounce = maxBounceLength * bounceSign;
distanceBounceAbs = maxBounceLength;
}
}
/*
Assemble animation
*/
// create matrixes for flick and bounce
var flickMatrix = zeroMatrix.translate(0, 0, 0);
flickMatrix[axis] = ~~(targetFlick + 0.5); // fast round
var bounceMatrix = flickMatrix.translate(0, 0, 0);
bounceMatrix[axis] += distanceBounce;
// queue each transition
// flick
var scrollerStyle = scrollers[axis].style;
if (distanceFlick) {
offsetSpecs[numOffsetSpecs++] = {
style: scrollerStyle,
matrix: flickMatrix,
timingFunc: timingFuncFlick,
duration: durationFlick
};
}
var parts = barParts && barParts[axis];
if (hasBars) {
offsetSpecs[numOffsetSpecs++] = {
style: parts[3].style,
matrix: {e: 0, f: ~~(flickMatrix[axis] * barOffsetRatios[axis])},
timingFunc: timingFuncFlick,
duration: durationFlick
};
}
if (isElastic && distanceBounce) {
animDuration += durationBounce;
bounceSpecs = [];
numBounceSpecs = 0;
if (hasBars) {
var barSize = barSizes[axis] - 2 * barTipSize;
if (distanceFlick) {
// reset potential bar scaling. Will be applied with the flick
offsetSpecs[numOffsetSpecs++] = {
style: parts[0].style,
matrix: {e: 0, f: 0}
};
offsetSpecs[numOffsetSpecs++] = {
style: parts[1].style,
matrix: {e: 0, barTargetSize: 0}
};
offsetSpecs[numOffsetSpecs++] = {
style: parts[2].style,
matrix: {e: 0, f: barSize + barTipSize}
};
}
// bounce scrollbar
var durationBounceBar = durationBounce;
var timingFuncBounceBar = timingFuncBounce;
var barTargetSize = ~~(barSize - distanceBounceAbs + 0.5); // round
if (barTargetSize < 1) { barTargetSize = 1; }
if (distanceBounceAbs > barSize) {
t = timingFuncBounceBar.getTforY(barSize/ distanceBounceAbs, epsilon);
var timeFraction = timingFuncBounce.getPointForT(t).x;
durationBounceBar *= timeFraction;
timingFuncBounceBar = timingFuncBounceBar.divideAtT(t)[0];
}
var barOffset = distanceBounce < 0 ? barSize - barTargetSize : 0;
bounceSpecs[numBounceSpecs++] = {
style: parts[0].style,
matrix: {e: 0, f: barOffset},
duration: durationBounceBar
};
var barMatrix = zeroMatrix.translate(0, barOffset + barTipSize, 0);
barMatrix.d = barTargetSize/barSize;
bounceSpecs[numBounceSpecs++] = {
style: parts[1].style,
matrix: barMatrix,
duration: durationBounceBar
};
bounceSpecs[numBounceSpecs++] = {
style: parts[2].style,
matrix: {e: 0, f: barOffset + barTipSize + barTargetSize},
duration: durationBounceBar
};
}
// bounce layer
bounceSpecs[numBounceSpecs++] = {
style: scrollerStyle,
matrix: bounceMatrix,
timingFunc: timingFuncBounce,
duration: durationBounce
};
this._setStyleOffset(bounceSpecs, durationFlick);
animDuration += durationBounce;
var durationSnapBack = configSnapBackAlwaysDefaultTime ? configSnapBackDefaultTime : durationBounce;
this.snapBack(axis, durationSnapBack, animDuration);
animDuration += durationSnapBack;
}
if (animDuration > maxDuration) {
maxDuration = animDuration;
}
}
this._setStyleOffset(offsetSpecs, 0);
// Assanka change: track that an animation is in progress
this._isCompletingScroll = true;
var that = this;
var timeouts = this._scrollTimeouts;
timeouts[timeouts.length] = setTimeout(function() {
that._endScroll();
}, maxDuration);
if (this.scrollevents && maxDuration) {
var iterations = 0;
var interval = setInterval(function() {
if (++iterations * 100 < maxDuration) {
that._fireEvent("scroll");
}
else {
clearInterval(interval);
}
}, 100);
}
},
/**
* Fires a custom event on the scroller element (default is "scroll").
*
* @param {String} [type] The type of event to fire. Defaults to "scroll".
* @param {Object} [properties] All properties of this object will be mixed
* into the event.
*/
_fireEvent: function _fireEvent(type, properties) {
var event = document.createEvent("Event");
event.touchscroll = this;
if (properties) {
for (var prop in properties) {
event[prop] = properties[prop];
}
}
event.initEvent(type || "scroll", true, false);
this._dom.outer.dispatchEvent(event);
},
/**
* @private
* @param {HTMLElement} node
* @returns {CSSMatrix} A matrix representing the current css transform of a node.
*/
_getNodeOffset: (function() {
if (TouchScroll._parsesMatrixCorrectly) {
return function _getNodeOffset(node) {
var computedStyle = window.getComputedStyle(node);
return new this._Matrix(computedStyle.webkitTransform);
};
}
var reMatrix = /matrix\(\s*-?\d+(?:\.\d+)?\s*,\s*-?\d+(?:\.\d+)?\s*,\s*-?\d+(?:\.\d+)?\s*,\s*-?\d+(?:\.\d+)?\s*\,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)/;
return function _getNodeOffset(node) {
var computedStyle = window.getComputedStyle(node);
var match = reMatrix.exec(computedStyle.webkitTransform);
var matrix = new this._Matrix();
if (match) {
matrix.e = match[0];
matrix.f = match[1];
}
return matrix;
};
}()),
/**
* Initializes the DOM of the scroller.
*/
_initDom: function _initDom(scrollbars) {
var dom = this._dom;
var scrollElement = dom.outer;
scrollElement.className += " TouchScroll";
// remove scroller contents
var firstChild, children = document.createDocumentFragment();
while ((firstChild = scrollElement.firstChild)) {
children.appendChild(firstChild);
}
this._insertNodes(scrollbars);
// put original contents back into DOM
var innerScroller = dom.scrollers.inner;
innerScroller.appendChild(children);
// register event listeners
var eventNames = this._eventNames;
[
eventNames.start,
eventNames.move,
eventNames.end
].forEach(function(type) { scrollElement.addEventListener(type, this, false); }, this);
innerScroller.addEventListener("DOMSubtreeModified", this, false);
innerScroller.addEventListener("focus", this, true);
this.setupScroller();
},
/**
* Inserts additional elements for scrolling layers and
* scrollbars/indicators. Also sets up references.
*
* @private
* @param {Boolean} scrollbars Whether to build scrollbars.
*/
_insertNodes: function _insertNodes(scrollbars) {
var dom = this._dom;
var scrollElement = dom.outer;
// set innerHTML from template
scrollElement.innerHTML = this._scrollerTemplate;
// setup references to scroller HTML nodes
var scrollers = dom.scrollers = {
inner: scrollElement.querySelector(".-ts-inner"),
e: null, f: null
};
// find layers
var layers = scrollElement.querySelectorAll(".-ts-layer");
scrollers.f = layers[0];
scrollers.e = layers[1];
// build scrollbars
if (scrollbars) {
var bars = dom.bars = {
outer: scrollElement.querySelector(".-ts-bars")
};
bars.outer.innerHTML = this._scrollbarTemplate;
var parts = bars.parts = {};
var i = 0, axes = this._axes, axis;
while ((axis = axes[i++])) {
var bar = bars[axis] = scrollElement.querySelector(".-ts-bar-"+axis);
parts[axis] = [
bar.querySelector(".-ts-bar-1"),
bar.querySelector(".-ts-bar-2"),
bar.querySelector(".-ts-bar-3"),
bars.outer.querySelector(".-ts-indicator-" + axis)
];
}
}
},
/**
* Scrolls by applying a transform matrix to the scroll layers.
*
* As this method is called for every touchmove event, the code is rolled
* out for both axes (leading to redundancies) to get maximum performance.
*
* @param {CSSMatrix} matrix Holds the offsets to apply.
*/
_scrollBy: function _scrollBy(matrix) {
var isScrolling = this._isScrolling;
if (!isScrolling.e) {
matrix.e = 0;
}
if (!isScrolling.f) {
matrix.f = 0;
}
var maxOffset = this._maxOffset, axisMaxOffset;
var scrollOffset = this._scrollOffset, axisScrollOffset;
var newOffset = scrollOffset.multiply(matrix), axisNewOffset;
var axisBounce;
var isElastic = this.elastic;
var zeroMatrix = new this._Matrix();
var dom = this._dom;
var scrollers = dom.scrollers;
var bars = dom.bars;
var hasBars = !!bars;
var barMetrics, barParts, sizes, tipSize, offsetRatios, barMaxOffsets;
var parts, defaultSize, size, indicatorOffset, barMaxOffset, barMatrix, barSizeSubstract;
if (hasBars) {
barMetrics = this._barMetrics;
barParts = bars.parts;
sizes = barMetrics.sizes;
tipSize = barMetrics.tipSize;
offsetRatios = barMetrics.offsetRatios;
barMaxOffsets = barMetrics.maxOffset;
}
var offsetSpecs = [], numOffsetSpecs = 0;
var isOutOfBounds, wasOutOfBounds;
var bounceOffset;
var factor = this.config.elasticity.factorDrag;
var i = 0, axes = this._activeAxes, axis;
while ((axis = axes[i++])) {
axisMaxOffset = -maxOffset[axis];
axisScrollOffset = scrollOffset[axis];
axisNewOffset = newOffset[axis];
bounceOffset = 0;
if (isElastic) {
axisScrollOffset = scrollOffset[axis];
// whether the scroller was already beyond scroll bounds
wasOutOfBounds = axisScrollOffset < axisMaxOffset || axisScrollOffset > 0;
if (wasOutOfBounds) {
axisNewOffset -= matrix[axis] * (1 - factor);
}
isOutOfBounds = axisNewOffset < axisMaxOffset || axisNewOffset > 0;
// whether the drag/scroll action went across scroller bounds
var crossingBounds = (wasOutOfBounds && !isOutOfBounds) ||
(isOutOfBounds && !wasOutOfBounds);
if (crossingBounds) {
/*
If the drag went across scroll bounds, we need to apply a
"mixed strategy": The part of the drag outside the bounds
is mutliplicated by the elasticity factor.
*/
if (axisScrollOffset > 0) {
axisNewOffset /= factor;
}
else if (axisNewOffset > 0) {
axisNewOffset *= factor;
}
else if (axisScrollOffset < axisMaxOffset) {
axisNewOffset += (axisMaxOffset - axisScrollOffset) / factor;
}
else if (axisNewOffset < axisMaxOffset) {
axisNewOffset -= (axisMaxOffset - axisNewOffset) * factor;
}
}
if (isOutOfBounds) {
bounceOffset = axisNewOffset > 0 ? axisNewOffset : axisNewOffset - axisMaxOffset;
}
}
// Constrain scrolling to scroller bounds
var unlimitedNewOffset = axisNewOffset;
if (axisNewOffset < axisMaxOffset) { axisNewOffset = axisMaxOffset; }
else if (axisNewOffset > 0) { axisNewOffset = 0; }
var scrollMatrix = zeroMatrix.translate(0, 0, 0);
scrollMatrix[axis] = axisNewOffset + bounceOffset;
offsetSpecs[numOffsetSpecs++] = {
style: scrollers[axis].style,
matrix: scrollMatrix
};
newOffset[axis] = isElastic ? unlimitedNewOffset : axisNewOffset;
if (hasBars) {
parts = barParts[axis];
// adjust offset
indicatorOffset = ~~(axisNewOffset * offsetRatios[axis] + 0.5); // round
barMaxOffset = barMaxOffsets[axis];
if (indicatorOffset < 0) { indicatorOffset = 0; }
else if (indicatorOffset > barMaxOffset) { indicatorOffset = barMaxOffset + defaultSize - size - 2 * tipSize; }
offsetSpecs[numOffsetSpecs++] = {
style: parts[3].style,
matrix: {e: 0, f: indicatorOffset}
};
// scale
defaultSize = size = sizes[axis] - 2*tipSize;
var partsOffset = 0;
if (isOutOfBounds) {
barSizeSubstract = bounceOffset < 0 ? -bounceOffset : bounceOffset;
size -= ~~(barSizeSubstract + 0.5);
if (size < 1) { size = 1; }
if (bounceOffset < 0) {
partsOffset = defaultSize - size;
}
}
if (isOutOfBounds || wasOutOfBounds) {
// upper indicator tip
offsetSpecs[numOffsetSpecs++] = {
style: parts[0].style,
matrix: {e: 0, f: partsOffset}
};
}
// middle indicator part
barMatrix = zeroMatrix.translate(0, partsOffset + tipSize, 0);
barMatrix.d = size/defaultSize;
offsetSpecs[numOffsetSpecs++] = {
style: parts[1].style,
matrix: barMatrix
};
// indicator end
offsetSpecs[numOffsetSpecs++] = {
style: parts[2].style,
matrix: {e: 0, f: partsOffset + size + tipSize}
};
}
}
this._setStyleOffset(offsetSpecs);
this._scrollOffset = newOffset;
if (this.scrollevents && offsetSpecs.length) {
this._fireEvent("scroll");
}
},
/**
* Sets transform offsets onto style elements.
*
* This function can apply individual transforms to multiple style
* properties to ensure they are all applied within the same function call
* and don't trigger repaints in between.
*
* @private
* @param specs {Object[]} An array of transform "specs". Every spec
* contains the following properties:
* {CSSStyleDeclaration} style A style property of an HTMLElement.
* {WebKitCSSMatrix|Object} matrix An object that has `e` and `f`
* properties for x and y offsets.
* {Array|Object|String} [timingFunc] Control points for a "cubic-bezier"
* declaration, or a string containing a valid easing functions.
* Non-arrays will be converted to strings.
* {Number} [duration] Miliseconds
* {Number} [delay] The `transition-delay` to apply in miliseconds.
*/
_setStyleOffset: function _setStyleOffset(specs, timeout) {
if (timeout) {
var t = this._scrollTimeouts;
t[t.length] = setTimeout(function() {_setStyleOffset(specs);}, timeout);
}
else {
var beginTransform, endTransform;
if (this._has3d) {
beginTransform = "translate3d(";
endTransform = ", 0)";
}
else {
beginTransform = "translate(";
endTransform = ")";
}
var style, matrix, timingFunc, duration;
var spec, i = 0;
while ((spec = specs[i++])) {
style = spec.style;
matrix = spec.matrix;
duration = spec.duration;
timingFunc = spec.timingFunc;
if (timingFunc) {
timingFunc = timingFunc && timingFunc.join ?
"cubic-bezier(" + timingFunc.join(",") + ")" :
timingFunc;
}
else {
timingFunc = "";
}
//style.webkitTransitionDuration = (spec.duration || 0) + "ms";
//style.webkitTransitionTimingFunction = timingFunc;
//style.webkitTransitionDelay = (spec.delay || 0) + "ms";
style.webkitTransition = duration ?
"-webkit-transform " + timingFunc + " " + spec.duration + "ms " + (spec.delay || 0) + "ms" :
"";
var scaleY = matrix.d;
style.webkitTransform = scaleY && scaleY !== 1 ?
matrix :
beginTransform + matrix.e + "px, " + matrix.f + "px" + endTransform;
}
}
},
/**
* Stops all running animations.
*/
_stopAnimations: function _stopAnimations() {
var timeouts = this._scrollTimeouts;
for (var i = 0, len = timeouts.length; i < len; i++) {
clearTimeout(timeouts[i]);
}
timeouts.length = 0;
var dom = this._dom;
var scrollers = this._dom.scrollers;
var bars = dom.bars;
var barParts = bars && bars.parts;
var offset = this._determineOffset();
var maxOffset = this._maxOffset;
var barMetrics = this._barMetrics;
var barOffsetRatios = barMetrics.offsetRatios;
var barTipSize = barMetrics.tipSize;
var barSizes = barMetrics.sizes;
var zeroMatrix = new this._Matrix();
var axes = this._axes, axis, axisOffset, axisMaxOffset;
var matrix, parts, part, barSize, barOffset;
var offsetSpecs = [], j = 0;
i = 0;
while ((axis = axes[i++])) {
axisOffset = offset[axis];
axisMaxOffset = -maxOffset[axis];
if (axisOffset > 0) {
offset[axis] = axisOffset = 0;
}
else if (axisOffset < axisMaxOffset) {
offset[axis] = axisOffset = axisMaxOffset;
}
matrix = {e: 0, f: 0};
matrix[axis] = axisOffset;
offsetSpecs[j++] = {
style: scrollers[axis].style,
matrix: matrix
};
if (barParts) {
parts = barParts[axis];
barSize = barSizes[axis] - 2 * barTipSize;
offsetSpecs[j++] = {
style: parts[3].style,
matrix: {e: 0, f: ~~(axisOffset * barOffsetRatios[axis])}
};
offsetSpecs[j++] = {
style: parts[0].style,
matrix: {e: 0, f: 0}
};
offsetSpecs[j++] = {
style: parts[1].style,
matrix: {e: 0, f: barTipSize}
};
offsetSpecs[j++] = {
style: parts[2].style,
matrix: {e: 0, f: barTipSize + barSize}
};
}
}
this._setStyleOffset(offsetSpecs);
}
};
// Add getter + setter functions for scroll positions
[
[
"scrollTop",
function() {
var offset = this._scrollTimeouts.length ? this._determineOffset() : this._scrollOffset;
return -offset.f;
},
function (val) {
this.scrollTo(0, val);
}
],
[
"scrollLeft",
function() {
var offset = this._scrollTimeouts.length ? this._determineOffset() : this._scrollOffset;
return -offset.e;
},
function (val) {
this.scrollTo(val, 0);
}
]
].forEach(function(p) {
TouchScroll.prototype.__defineGetter__(p[0], p[1]);
TouchScroll.prototype.__defineSetter__(p[0], p[2]);
});
// Add getter/setter functions for DOM facade
[
"childNodes",
"children",
"firstChild",
"firstElementChild",
"innerHTML",
"innerText",
"lastChild",
"lastElementChild"
].forEach(function(prop) {
TouchScroll.prototype.__defineGetter__(prop, function() {
return this._dom.scrollers.inner[prop];
});
TouchScroll.prototype.__defineSetter__(prop, function(val) {
this._dom.scrollers.inner[prop] = val;
});
});
// Add DOM methods facade
[
"insertAdjacentElement",
"insertAdjacentHTML",
"insertAdjacentText",
"querySelector",
"querySelectorAll",
"addEventListener",
"appendChild",
"insertBefore",
"replaceChild"
].forEach(function(method) {
TouchScroll.prototype[method] = function() {
var inner = this._dom.scrollers.inner;
return inner[method].apply(inner, arguments);
};
});
function LocalDatabase(openFullDatabase){
try{if(openFullDatabase){
this.db=window.openDatabase("fthtml5app","","FT HTML5 App Content",40*1024*1024)}
else this.db=window.openDatabase("fthtml5preview","","FT HTML5 App Preview",5*1024*1024)}catch(error){this.db=false};
if(!this.db)return false;
this.fulldatabase=openFullDatabase;
this.db.compatibleReadTransaction=(typeof this.db.readTransaction=='function')?this.db.readTransaction:this.db.transaction;
var ftstory=this;
this.checkVersion=function(aVersion,doneCallback){
var oldversion=localStorage.getItem('databaseversion');
if(oldversion==aVersion)return doneCallback();
this.dropAllTables(function(){
localStorage.setItem('databaseversion',aVersion);
doneCallback()},function(error){
alert(error)})};
this.init=function(successCallback){
var querycount=this.fulldatabase?3:2,successhandler=function(){
querycount--;
if(!querycount)successCallback()};
try{ftstory.db.transaction(function(tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS Articles(id INTEGER PRIMARY KEY, name TEXT, byline TEXT, content TEXT, details TEXT)',[],null,function(error){
ftstory.errorHandler("Create table broke (A; "+error.code+")")});
tx.executeSql('CREATE TABLE IF NOT EXISTS Analytics(dateinserted JULIAN, type TEXT, detail TEXT)',[],null,function(error){
ftstory.errorHandler("Create table broke (V; "+error.code+")")});
if(ftstory.fulldatabase)tx.executeSql('CREATE TABLE IF NOT EXISTS ArticleImages(id TEXT PRIMARY KEY, data BLOB)',[],null,function(error){
ftstory.errorHandler("Create table broke (I; "+error.code+")")})},function(err){
console.log('The application will not function correctly as one or more images could not be created. TE: '+error.code)},successCallback)}catch(e){console.log('Erroring on table creation: '+e)}}};
LocalDatabase.prototype.loadedSuccessfully=function(){
return !!this.db};
LocalDatabase.prototype.errorHandler=function(e){
console.log('Error: '+e);
return true};
LocalDatabase.prototype.nullDataHandler=function(){
console.log('null data transaction succeeded');
return true};
LocalDatabase.prototype.dbEmptyCheck=function(successCallback,table){
var ftstory=this;
ftstory.db.compatibleReadTransaction(function(tx){
tx.executeSql('SELECT id FROM '+table+' LIMIT 1',[],successCallback,function(){
ftstory.errorHandler("table empty check broke")})})};
LocalDatabase.prototype.trackAnalytics=function(type,detail,ftuser){
if(typeof (TrackParams)!="undefined"&&(typeof (_disableAnalytics)=="undefined"||!_disableAnalytics)){
var AssetType='',articleId='undefined';
if(type=='content'){
var pageUrl=detail.guid;
pageUrl=pageUrl.replace('www.ft.com','html5.m.ft.com');
pageUrl=pageUrl.replace('ftalphaville.ft.com','html5.m.ft.com');
pageUrl=pageUrl.replace('blogs.ft.com','html5.m.ft.com');
AssetType='story';
var cmsidre=new RegExp('([0-9a-f\-]{32,})'),m=cmsidre.exec(detail.guid);
if(m!==null)articleId=m[1]}
else if(type=='section'){
var pageUrl='http://html5.m.ft.com/'+type+'/'+detail.id+'/'+detail.name}
else var pageUrl='http://html5.m.ft.com/'+type+'/'+((typeof detail=="string")?detail:JSON.stringify(detail));
var handlingCode='1';
if(detail.protectionlevel=='free')handlingCode='0';
if(detail.protectionlevel=='premium')handlingCode='2';
var pid='',subtype='1';
if(ftuser){
pid=ftuser.passportid;
subtype=3;
if(ftuser.level=='registered')subtype=2};
var channel='HTML5',matches=/ FTAndroid(-(\d+))?$/gim.exec(window.navigator.userAgent);
if(matches!=null)channel+=' Android';
if(matches&&matches.length>1)channel+=' '+matches[2];
if(!!window.navigator.standalone)channel+=' iOS-standalone-app';
channel+=' r'+resourcesVersion;
if(type=='psp'){
HurdleType='h8'}
else if(type!='content')HurdleType='undefined';
var ipCountry='',sPageName='',sPageNumber='',FTSection='',FTPage='',FTBarrier='',ed='',metroArea="undefined",regArea="undefined",siParams=new TrackParams();
siParams.add("AssetType",typeof AssetType!="undefined"?AssetType:null);
siParams.add("sub",handlingCode?handlingCode:"undefined");
siParams.add("WT.ipCountry_s",ipCountry?ipCountry:"undefined");
siParams.add("WT.pid_s",pid);
siParams.add("WT.si_n",typeof sPageName!="undefined"?sPageName:null);
siParams.add("WT.si_x",typeof sPageNumber!="undefined"?sPageNumber:null);
siParams.add("WT.ti",typeof detail.title!="undefined"?detail.title:null);
siParams.add("WT.uuid",articleId?articleId:"undefined");
siParams.add("FTSection",typeof FTSection!="undefined"?FTSection:"undefined");
siParams.add("FTPage",typeof FTPage!="undefined"?FTPage:"undefined");
if(typeof _campaignreference!="undefined")siParams.add("segid",_campaignreference);
siParams.add("FTBarrier",typeof FTBarrier!="undefined"?FTBarrier:null);
siParams.add("subType",subtype);
siParams.add("WT.metroArea_s",metroArea?metroArea:"undefined");
siParams.add("WT.regArea_s",regArea?regArea:"undefined");
siParams.add("HurdleType",(typeof HurdleType!="undefined"&&HurdleType!='undefined')?HurdleType:null);
siParams.add("sm",typeof siteMapTerm!="undefined"?siteMapTerm:null);
siParams.add("ed",typeof navEdition!="undefined"?navEdition:null);
siParams.add("channel",channel);
var qs=siParams.buildQueryString(),campparam=/(ftcamp=(\w*\/){4}\w*)/.exec(window.location.href);
if(campparam!=null){
campparam=campparam[1]+"&"}
else campparam="";
SiNewPageContext();
SiTrackPage(pageUrl+"?"+campparam+qs)};
if(typeof (window.appBridge)!="undefined"){
if(type=='content')detail=detail.guid;
var a={};
a.tp=type;
a.dt=detail;
a.ts=Math.round(new Date().getTime()/1000);
if(typeof (window.appBridge.setMessagesToSend)!="undefined")window.appBridge.setMessagesToSend(JSON.stringify(a));
if(typeof (window.appBridge.setMesagesToSend)!="undefined")window.appBridge.setMesagesToSend(JSON.stringify(a))}
else{
if(typeof (detail)=='object')detail=JSON.stringify(detail);
var ftstory=this;
ftstory.db.transaction(function(tx){
tx.executeSql('INSERT INTO Analytics (dateinserted, type, detail) VALUES (julianday("now"), ?, ?)',[type,detail],function(){
return true},function(){
console.log("Track analytics failed")})})}};
LocalDatabase.prototype.trackAdImpression=function(guid){
};
LocalDatabase.prototype.removeStoriesExcept=function(data,callback){
var ftstory=this;
ftstory.db.transaction(function(tx){
tx.executeSql('DELETE FROM Articles WHERE id NOT IN ('+data.join(',')+')',[],function(){
if(callback)callback()},function(){
ftstory.errorHandler("remove stories from table broke");
if(callback)callback()})},function(error){
console.log('Error: '+error.code+': '+error.message)})};
LocalDatabase.prototype.insertArticle=function(postdata,successhandler){
this.insertArticles([postdata],successhandler)};
LocalDatabase.prototype.insertArticles=function(articles,successhandler,errorhandler){
if(!errorhandler)errorhandler=function(){
};
var ftstory=this;
try{ftstory.db.transaction(function(tx){
for(var articlekey in articles){
var postdata=articles[articlekey];
postdata.details=JSON.stringify(postdata.details);
if(!postdata.byline)postdata.byline='';
tx.executeSql('INSERT OR REPLACE INTO Articles (id, name, byline, content, details) VALUES (?,?,?,?,?)',[postdata.id,postdata.name,postdata.byline,postdata.content,postdata.details],null,function(err){
console.log("Unable to store article in database: "+err);
return false})}},function(err){
console.log('Unable to store articles in database: ',err);
if(err.code==4)ftstory.db.transaction(function(tx){
tx.executeSql('DELETE FROM Analytics',[],function(){
console.log("Successfully emptied analytics");
errorhandler},function(){
console.log("Emptying analytics failed");
errorhandler})})},successhandler)}catch(e){console.log("Exception whilst storing articles in database: "+e);
errorhandler}};
LocalDatabase.prototype.getArticleList=function(callback){
var ftstory=this;
ftstory.db.compatibleReadTransaction(function(tx){
tx.executeSql('SELECT id FROM Articles',[],callback,function(tx,err){
ftstory.errorHandler(console.log(err))})})};
LocalDatabase.prototype.insertImages=function(images,successhandler,errorhandler){
if(!errorhandler)errorhandler=function(){
};
if(!successhandler)successhandler=function(){
};
var ftstory=this;
try{ftstory.db.transaction(function(tx){
for(var imageid in images)tx.executeSql('INSERT OR REPLACE INTO ArticleImages (id, data) VALUES (?,?)',[imageid,images[imageid]],null,function(err){
console.log("Unable to store article image in database: "+err);
return false})},function(err){
console.log('Unable to store article image in database: ',err)},successhandler)}catch(e){console.log("Exception whilst storing article images in database: "+e);
errorhandler}};
LocalDatabase.prototype.getImages=function(idlist,successhandler){
var ftstory=this;
ftstory.db.compatibleReadTransaction(function(tx){
tx.executeSql('SELECT id, data FROM ArticleImages WHERE id IN ("'+idlist.join('","')+'")',[],function _anon_getImageListSuccessCallback(tx,rs){
var returnedImages={};
for(var i=rs.rows.length-1;i>=0;i--){
var theRow=rs.rows.item(i);
returnedImages[theRow.id]=theRow.data};
successhandler(returnedImages)},function _anon_getImageListErrorCallback(tx,err){
ftstory.errorHandler(console.log(err))})})};
LocalDatabase.prototype.removeImages=function(idlist,callback){
var ftstory=this;
ftstory.db.transaction(function(tx){
tx.executeSql('DELETE FROM ArticleImages WHERE id IN ("'+idlist.join('","')+'")',[],function(){
if(callback)callback()},function(){
ftstory.errorHandler("Article image clean failed");
if(callback)callback()})},function(error){
console.log('Error: '+error.code+': '+error.message)})};
LocalDatabase.prototype.getImageList=function(callback){
var ftstory=this;
ftstory.db.compatibleReadTransaction(function(tx){
tx.executeSql('SELECT id FROM ArticleImages',[],callback,function(tx,err){
ftstory.errorHandler(console.log(err))})})};
LocalDatabase.prototype.fetchArticle=function(id,successhandler){
var ftstory=this;
id=parseInt(id);
ftstory.db.compatibleReadTransaction(function(tx){
tx.executeSql('SELECT name, byline, content, details FROM Articles WHERE id='+id,[],successhandler,function(tx,err){
console.log(err)})})};
LocalDatabase.prototype.dropAllTables=function(callback,errorcallback){
var tablesToDrop=['Articles','Analytics'],ftstory=this,dropFunction=function(tableName){
ftstory.db.transaction(function(tx){
tx.executeSql('DROP TABLE IF EXISTS '+tableName,[],function(){
if(nextTable=tablesToDrop.shift()){
dropFunction(nextTable)}
else callback()},function(error){
errorcallback('Version upgrade failed; D+'+tableName.substring(0,3)+': '+error.code)})})};
dropFunction(tablesToDrop.shift())}
if(!document.cookie.match(/FTUserTrack=((\d{1,3}\.){3}\d{1,3})/))
{var call='<scr'+'ipt type="text/javascript" src="';call+=isSecure(document)?'https:':'http:';call+='//track.ft.com/track/';call+=isSecure(document)?'strack.js':'track.js';call+='"></sc'+'ript>';/* document.write(call); */}
siAutoTracer=false;if(typeof FT==="undefined")
{FT={};}
FT.getExcludedQueryParamsList=function()
{return['sticky','pspUrl','location','referer','_i_location','_i_referer'];};FT.excludeParams=function(queryString)
{if(typeof queryString==="undefined"){return queryString;}
if(!FT.getExcludedQueryParamsList){return queryString;}
var excludedParams=FT.getExcludedQueryParamsList();for(var currentExcludedParamKey in excludedParams)
{if(excludedParams.hasOwnProperty(currentExcludedParamKey))
{var currentExcludedParam=excludedParams[currentExcludedParamKey];var RE=new RegExp("([&?])"+currentExcludedParam+"=[^&]*");queryString=queryString.replace(RE,"");}}
if(queryString.indexOf('?')==-1&&queryString.indexOf('&')!=-1)
{queryString=queryString.replace('&','?');}
return queryString;};FT.excludeQueryParams=function(url)
{if(typeof url==="undefined"){return url;}
var qIndex=url.indexOf('?');var qs=url.substring(qIndex);var path=url.substring(0,qIndex);url=path+FT.excludeParams(qs);return url;};eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('7 1T;m(C["1D"]==1T){C.1D=I}7 1a="/1U";7 14="3m.3n.2q";7 15="3o";7 1p="3p";7 1q="1U:2r";7 1f="3q";7 1E="/";7 1V=3r;7 1F=2s;7 1W=M 2t(".2u.3s",".2q");7 1X=O;7 1Y="2v";7 1Z="3t";7 20="";7 21=1a+"/3u.3v";7 3w="5.1.13";7 22="N";7 1G=A;7 1H="t"+(M 1g()).1r()+"h"+C.23.B;7 L="";7 1s="";7 E="";7 P="";7 17="";7 1h=0;7 1b=M 2t(1);7 1t=v.2w;7 1i=v.1u;7 24="1U:3x";7 J="";7 2x=3y;7 3z=O;7 26=0;7 V=A;o 27(a){7 b=A;7 c=a.1c;7 d=a.1j("3A");m(d&&d!="3B"){m(d=="3C"){b="2y"}F{m(d=="3D"){b="3E"}F{m(d=="3F"){z o(){C.2z(c)}}F{b=2y.3G[d];m(!b){z o(){C.2z(c,d)}}}}}}m(b==A){z o(){D.1c=c}}F{z o(){b.D.1c=c}}};o 2A(a){m(!a){z""}7 b="3H+/";7 c="";W(7 i=0;i<a.B;i+=3){7 d=a.B-i;7 e=0;e=(a.28(i)<<16)&3I;e|=(d>1)?(a.28(i+1)<<8)&3J:0;e|=(d>2)?a.28(i+2)&3K:0;c+=b.1v((e&3L)>>18);c+=b.1v((e&3M)>>12);c+=(d>1)?b.1v((e&3N)>>6):"2B";c+=(d>2)?b.1v((e&3O)):"2B"}z c};o 1I(a){7 b="";W(7 i=0;i<a.B;i++){7 c;3P(a.1v(i)){Q"r":1t=2C.2D(1t);c=1t;R;Q"p":1i=2C.2D(1i);c=1i;R;Q"d":c=1k.3Q+"x"+1k.3R+"x"+1k.2E+"."+1J.2F();m(1J.2G){c+="."+1J.2G.B}R;Q"c":c=1G;R;Q"u":c=C.23.B+"."+(3S.3T()*2s)+"."+(M 1g()).1r();R;Q"t":c=1H;R;Q"f":c=E;R;Q"q":c=P;R;Q"g":c=2H();R;Q"w":c=22;R;Q"y":c=J;R}b+=2A(c)+"*"}z b};o 2H(){7 a="";a+="2u="+C.1k.2E;a+="&3U="+C.1k.3V+"x"+C.1k.3W;29=M 1g();m(A!=29){a+="&3X="+2I(29)}m(1J.2F()){a+="&2J=1"}F{a+="&2J=0"}a+=2K();m(v.2a){7 b=v.2a.1j(24);m(b){a+="&2v="+b}}m(L&&L.B>0){a+="&3Y="+L}m(1s.B>0){a+="&3Z="+1s}z a};o 2K(){7 a="";m(C.2L){a+="&1d:40"}m(C.2M){a+="&1d:41"}m(C.2N){a+="&1d:x-42"}m(C.2O){a+="&1d:43"}m(C.2P){a+="&1d:44"}z a};o 45(){C.2M=I};o 46(){C.2L=I};o 47(){C.2N=I};o 48(){C.2O=I};o 49(){C.2P=I};o 4a(a){v.2a.1K(24,a)};o 2I(a){7 b="";b+=a.4b()+"";b+="-";b+=1l(a.4c()+1);b+="-";b+=1l(a.4d());b+="T";b+=1l(a.4e());b+=":";b+=1l(a.4f());b+=":";b+=1l(a.4g());z b};o 1l(n){m(n<1){z"4h"}z(n>9?"":"0")+n};o 2b(){7 a=A;7 b;7 c;7 d;7 e=v.D.X;m(e!=A){7 f;W(f=0;(f<1W.B)&&(a==A);f++){7 g=e.2c(1W[f]);m(g>0){7 h=e.2c(".",g-1);m(h>=0){a=e.10(h)}F{a="."+e}}}}z a};o 4i(a){G{J="1w";m(/2d/.2e(2f(a))){L=a}F{L=a.1j(1q)}2Q();z I}H(e){z K(e)}};o 2Q(){1m(2g)};o 2R(){1m(1x)};o 2S(){1m(1n)};o 4j(){1m(4k)};o 2T(a,b){m(!b){b=27(a)}1m(1x,b,1F)};o 1m(a,b,c){1s=1H;E="1o://"+v.D.X+1a+"/2r";P="";m(b){m(c){a("1L","1M",b,c)}F{a("1L","1M",b)}}F{a("1L","1M")}L="";1s="";E=""};o 4l(a){G{J="1w";m(/2d/.2e(2f(a))){L=a}F{L=a.1j(1q)}2S()}H(e){K(e)}};o 4m(a,b){G{J="1w";m(/2d/.2e(2f(a))){L=a}F{L=a.1j(1q)}2T(a,b);z O}H(e){z K(e)}};o 4n(a){G{L=a.1j(1q);J="1w";2R();J="1d";E=a.1c;m(E.19("://")==-1){m(E.10(0,1)!="/"){7 b=v.D.2U.2c("/");7 c=v.D.2U.10(0,b+1);E=c+E}m(E.10(0,2)!="//"){E="//"+v.D.X+E}E=v.D.1y+E}7 d=27(a);1x("1L","1M",d,1F);z O}H(e){z K(e)}};o 2V(a){E="1o://"+v.D.X+1a+"/4o";P=a;J="1N";1n("1z","1A")};o 4p(a,b){G{m(17!=""){17+="&"}17+=1e(a)+"="+1e(b);m(17.B>=4q){2W()}}H(e){K(e)}};o 2W(){m(17!=""){2V(17);17=""}};o 1O(a,b,c){7 d=M 1g;d.2X(d.1r()+c);7 e=2b();7 f=a+"="+b+((1E)?"; 2Y="+1E:"")+((e)?"; 2Z="+e:"");v.1P=f+"; 30="+d.31();m(Z(a)!=b){v.1P=f}};o Z(a){z 1B(a,v.1P,";")};o 1B(a,b,c){7 d=a+"=";7 e=A;7 f=b.19(d);m((f!=-1)&&(a.B>0)){7 g=b.19(c,f);m(g==-1){g=b.B}e=b.10(f+d.B,g)}z e};o 32(a,b,c){7 d=M 1g();d.2X(d.1r()-1);m(!b){b=1E}m(!c){c=2b()}7 e=a+"=A"+((b)?"; 2Y="+b:"")+((c)?"; 2Z="+c:"");v.1P=e+"; 30="+d.31()};o 33(){7 a=1B(1f,v.1u,"&");m(a!=A){1O(15,a,1V);m(1X){7 b=1B(1Z,v.1u,"&");m(b!=A){1t=34(b)}b=1B(1Y,v.1u,"&");m(b!=A){1i=34(b)}}}F{a=Z(15);m(a==A){a=1I("u");22="Y";1O(15,a,1V);m(1X){a=Z(15);m(a!=A){7 c=20;m(20.19("?")==-1){c+="?"}F{c+="&"}c+=1Y+"="+1e(v.1u)+"&"+1Z+"="+1e(v.2w);1D=O;v.D=c}}}}a=Z(15);z a};o 4r(a){7 b=Z(15);m(b!=A){a.1c=a.1c+((a.1c.19("?")>0)?"&":"?")+1f+"="+b}z I};o 4s(a){7 b=Z(15);m(b!=A){m(a.4t.4u()=="4v"){G{G{7 c=v.35("<36 S=\\""+1f+"\\" 11=\\"37\\" 1Q=\\""+b+"\\" />")}H(e){7 c=v.35("36");c.1K("S",1f);c.1K("11","37");c.1K("1Q",b)}a.4w(c)}H(4x){}}F{a.2h=a.2h+((a.2h.19("?")>0)?"&":"?")+1f+"="+b}}z I};o 1R(a,b,c){7 d;m(1G==A){d=14+21+"?f="+b+"&d="+1I(b)}F{d=14+21+"?f="+a+"&d="+1I(a)}J="";c(d)};o 1n(c,d){7 e=o(a){7 b=M 2i();b.2j=a;1b[1b.B]=b};1R(c,d,e)};o 1x(h,i,j,k){7 l=o(b){7 c=M 2i();m(j){V=j;m(k){7 d=o(){m(V){7 a=V;V=A;a()}};d.4y=o(){z"7 38 = V; V = A; 38();"};7 f=C.4z(d,k)}}7 g=o(){m(c.4A&&--26==0&&V){m(f){C.4B(f)}7 a=V;V=A;a()}};G{c.39?c.39("4C",g,O):c.4D("4E",g)}H(e){}++26;c.2j=b;1b[1b.B]=c};1R(h,i,l)};o 2g(c,d){m(1h<25){7 e=o(a){m(1h>0){m(Z(1p+(1h-1))==A){1h=0}}7 b=1p+1h++;1O(b,a,4F)};1R(c,d,e)}};o 4G(a,b){z 3a(A,a,b)};o 4H(a,b,c){G{E="1o://"+v.D.X+1a+"/1S";J="1N";m(!c){c=o(){a.2k()}}7 s=o(){1x("1z","1A",c,1F)};2l(a,s,b);z O}H(e){z K(e)}};o 3a(a,b,c){G{E="1o://"+v.D.X+(a==A?1a+"/1S":a);J="1N";2l(b,o(){2g("1z","1A")},c);z I}H(e){z K(e)}};o 4I(a,b){G{m(a.U&&(a.U.B>0)){a.3b=[];W(7 i=0;i<a.U.B;i++){7 c=a.U[i];m(c.S){7 d=(b==A);m(b!=A){W(7 j=0;!d&&(j<b.B);j++){m(c.S==b[j]){d=I}}}m(d){7 f=c.3c;c.3c=o(){m(f){f()}3d(a,1C)}}}}}}H(e){K(e)}};o 3d(a,b){m(b.S&&((b.11=="3e"||b.11=="3f")?(b.2m!=b.4J):(b.1Q!=b.4K))){7 c=a.3b;W(7 i=0;i<c.B;i++){m(b.S==c[i]){z}}7 d="4L:"+b.S;7 e=1e(d)+"=Y";E="1o://"+v.D.X+1a+"/4M";P=e;J="1N";1n("1z","1A");c[c.B]=b.S}};o 2l(a,b,c){P="";m(a.U&&(a.U.B>0)){7 d=O;W(7 i=0;i<a.U.B;i++){7 e=a.U[i];m(e.S){7 f=(c==A);m(c!=A){W(7 j=0;!f&&(j<c.B);j++){m(e.S==c[j]){f=I}}}m(f&&(e.11=="3e")){f=e.2m}m(e.11=="4N"){f=O}m(e.11=="2k"){f=(e==a.2n)}m(f){7 g=1e(e.S)+"="+((e.11=="3f")?((e.2m)?"I":"O"):1e(e.1Q));m(P.B+g.B>2x){b();P="";d=O}m(d){P+="&"}P+=g;d=I}}}b()}};o 4O(a,b){G{2o(a,b,A)}H(e){K(e)}};o 4P(a,b){G{2o(a,b,"1w")}H(e){K(e)}};o 2o(a,b,c){m(a.10(0,1)=="/"){a=v.D.1y+"//"+v.D.X+a}E=a;P=b;J=c;1n("1z","1A")};o 3g(a){G{m(a!=1T){m(a.19("://")==-1){m(a.10(0,1)!="/"){a="/"+a}a=v.D.1y+"//"+v.D.X+a}1i=a.19("?")==-1?a+C.D.3h:a+"&"+C.D.3h.10(1)}J="1d";1n("4Q","4R")}H(e){K(e)}};o 4S(){G{7 b=o(){1C.1S.2n=1C};W(7 i=0;i<v.3i.B;i++){7 c=v.3i[i];W(7 j=0;j<c.U.B;j++){m(c.U[j].11=="2k"){7 d=c.U[j];7 f=d.2p;m(f){(o(){7 a=f;d.2p=o(){1C.1S.2n=1C;a()}})()}F{d.2p=b}}}}}H(e){K(e)}};o 3j(){G{m(14==A){14=v.D.1y+"//"+v.D.X+":"+v.D.3k}F{m(14.10(0,4)!="1o"){14=v.D.1y+"//"+14+":"+v.D.3k}}1G=33();3l()}H(e){K(e)}};o 3l(){7 i=0;7 a=1p+i++;7 b=Z(a);4T(b){7 c=M 2i();c.2j=b;1b[1b.B]=c;32(a);a=1p+i++;b=Z(a)}};o 4U(){1H="t"+(M 1g()).1r()+"h"+C.23.B};o K(e){z I};3j();m(C.1D){3g()}',62,305,'|||||||var|||||||||||||||if||function|||||||document||||return|null|length|window|location|siTracerPath|else|try|catch|true|siTagType|SiInternalError|siClickedLinkID|new||false|siTracerQuery|case|break|name||elements|siSyncFinishedAction|for|hostname||SiGetCookie|substring|type|||siTaggingServer|siCookieName||siSendParams||indexOf|siBaseDirectory|siImageSet|href|page|escape|siCookieQPName|Date|siTracerCookieIdx|siRequest|getAttribute|screen|leadingZero|SiInternalDoLinkTrack|SiSendTracer|http|siTracerCookieName|siLinkAttribute|getTime|siRefClickID|siReferrer|URL|charAt|trace|SiSyncTracer|protocol|fqcty|fqdty|SiExtractPart|this|siAutoTracer|siCookiePath|siTracerTimeout|siCookieValue|siExtClickID|SiEncodeDetails|navigator|setAttribute|fctgy|fdtgy|extra|SiSetCookie|cookie|value|SiProcessTracer|form|undefined|si|siCookieTimeout|siDomainList|siCentralCookie|siCentralReqName|siCentralRefName|siCentralURL|siTrackerUrl|siIsCookieNew|history|siPageIDAttrName||siSyncTracersOutstanding|SiInternalGetLinkClickingClosure|charCodeAt|today|body|SiGetDomain|lastIndexOf|string|test|typeof|SiDeferTracer|action|Image|src|submit|SiInternalBuildAndSendFormTracerQuery|checked|siActivatedSubmit|SiInternalTrackTracer|onclick|com|link|1000|Array|co|req|referrer|siFormQueryLimit|top|open|SiEncodeString|_|FT|excludeQueryParams|colorDepth|javaEnabled|plugins|SiCollateTagData|SiFormatDate|jv|SiCollatePageRules|siIsFrameset|siIsMenu|siIsExtraFrame|siIsRedirection|siIsPopup|SiInternalTrackLink|SiInternalTrackLinkImmediate|SiInternalTrackLinkPassiveSend|SiInternalTrackLinkViaSynchronousSend|pathname|SiTrackData|SiSendTrackParams|setTime|path|domain|expires|toGMTString|SiDeleteCookie|SiBuildCookie|unescape|createElement|input|hidden|exec|addEventListener|SiTrackForm|siFilledFields|onblur|SiInternalActiveTrackElement|radio|checkbox|SiTrackPage|search|forms|SiInitPage|port|SiSendDeferredTracers|stats|ft|FTUserTrack|SITRACER|simigvis|315360000000|uk|refer|track|gif|siTrackerVersion|pageID|1200|siSentPageTag|target|_self|_top|_parent|parent|_new|frames|ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789|16711680|65280|255|16515072|258048|4032|63|switch|availWidth|availHeight|Math|random|sr|width|height|lt|rl|rcid|fset|menu|frame|redir|popup|SiIsMenu|SiIsFrameset|SiIsExtraFrame|SiIsRedirection|SiIsPopup|SiSetPageID|getFullYear|getMonth|getDate|getHours|getMinutes|getSeconds|00|SiTrackLink|SiInternalTrackLinkWait|SiSendTracerWithWait|SiTrackEvent|SiTrackExternalLink|SiTrackLinkToUntagged|data|SiAddTrackParam|512|SiMigrateCookie|SiMigrateCookieForm|method|toUpperCase|GET|appendChild|andIgnore|toString|setTimeout|complete|clearTimeout|load|attachEvent|onreadystatechange|1800000|SiTrackFormData|SiTrackExternalFormData|SiActiveTrackForm|defaultChecked|defaultValue|siform|formfield|file|SiTrackTracer|SiSendAdditionalTracer|pcrtgy|pdrtgy|SiRegisterForms|while|SiNewPageContext'.split('|'),0,{}))
function TrackParams(){var hashTable=[];this.add=function(key,val){if(key&&val){hashTable[key]=val;}};this.buildQueryString=function(){var qs="";var key="";for(key in hashTable){if(typeof hashTable[key]!="function"){qs+=escape(key)+"="+escape(hashTable[key])+"&";}}
return qs.substring(0,qs.length-1);};}
function isSecure(doc){return(doc.location.protocol=='https:');}
function findSubType(prods){var ANONYMOUS=1;var REGISTERED=2;var SUBSCRIBER=3;var REGISTERED_NA=4;var SUBSCRIBER_NA=5;var PAYG=6;if(prods.length==0){return REGISTERED_NA;}
if(prods&&prods.length>1){var result=prods.split("|");var hasNewspaper=false;var hasP0=false;var hasP1=false;var hasP2=false;var hasP1NA=false;var hasP2NA=false;var hasP3NA=false;var hasPAYG=false;for(var idx=0;idx<result.length;idx++){switch(result[idx].toString()){case"72":hasP0=true;break;case"73":hasP1=true;break;case"75":hasP1NA=true;break;case"74":hasP2=true;break;case"76":hasP2NA=true;break;case"77":hasP3NA=true;break;case"35786":hasPAYG=true;break;default:}}
if(hasPAYG){return PAYG;}else if(hasP1||hasP2){return SUBSCRIBER;}else if(hasP0){return REGISTERED;}else if(hasP1NA||hasP2NA||hasP3NA){return SUBSCRIBER_NA;}else{return ANONYMOUS;}}else{return ANONYMOUS;}}
var tp=new TrackParams();var tpRef=new TrackParams();var tpTrans=new TrackParams();var tpTitle=new TrackParams();var siParams=new TrackParams();function doTrack2(){var subtype=1;var ftReferrer=document.referrer;if(ftReferrer){ftReferrer=ftReferrer.replace(/\/cms\/s\/[0-2]\//,"/cms/s/");}
var thisAYSC=document.cookie.match(/AYSC=([^;]*)/)?RegExp.$1:"";var ipCountry=thisAYSC.match(/_14([^_]*)/)?RegExp.$1:null;var regArea=thisAYSC.match(/_17([^_]*)/)?RegExp.$1:null;var metroArea=thisAYSC.match(/_18([^_]*)/)?RegExp.$1:null;var thisFTP=document.cookie.match(/FT_P=([^;]*)/)?RegExp.$1:"";if(thisFTP){var prods=thisFTP.match(/prod=([^_]*)/)?RegExp.$1:null;subtype=findSubType(prods);}
var thisFTMD=document.cookie.match(/FTMD=([^;]*)/)?RegExp.$1:"";var ftmdParams=thisFTMD.match(/([^;]*)/)?RegExp.$1:null;var ipPC=document.cookie.match(/FTUserTrack=((\d{1,3}\.){3}\d{1,3})/)?RegExp.$1:"undefined";var pid=document.cookie.match(/USERID=([^:]*)/)?RegExp.$1:"undefined";var logged_in=(pid==="undefined")?"0":"1";var use=document.URL;var lastSlash=use.lastIndexOf("/");if(use.charAt(lastSlash+1)==='')
{use=use.substring(0,use.length-1);}
if(typeof AssetType!="undefined"&&AssetType=="story"){var hasS=use.match(/\/cms\/s/)?RegExp.$1:null;if(!hasS)
{use=use.replace(/\/cms\//,"/cms/s/");}}
var articleId=use.match(/[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}/);if(articleId)
{articleId=articleId.toString();}
if(articleId)
{var remainder=use.substring(use.search(articleId)+articleId.length,use.length);use=use.replace(remainder,'')+'.html?'+(remainder.substring(1,remainder.length)).replace(',','&');use=use.substring(0,use.length-5);}
var dc=document.cookie;var re=new RegExp("TRK_REF="+window.location.href);var call='<scr'+'ipt type="text/javascript" src="';call+=isSecure(document)?'https:':'http:';call+='//track.ft.com/track/';call+=isSecure(document)?'strack.js':'track.js';call+='"></sc'+'ript>';if(thisFTMD===""||ftmdParams!='qv'){/* document.write(call); */}
var pageUrl=window.location.pathname;if(pageUrl.match(/\/cms\/s\/([0-2])\//)){var handlingCode=RegExp.$1;}
siParams.add("AssetType",typeof AssetType!="undefined"?AssetType:null);siParams.add("sub",handlingCode?handlingCode:"undefined");siParams.add("WT.ipCountry_s",ipCountry?ipCountry:"undefined");siParams.add("WT.pid_s",pid);siParams.add("WT.si_n",typeof sPageName!="undefined"?sPageName:null);siParams.add("WT.si_x",typeof sPageNumber!="undefined"?sPageNumber:null);siParams.add("WT.ti",typeof FTDocumentTitle!="undefined"?FTDocumentTitle:document.title);siParams.add("WT.uuid",articleId?articleId:"undefined");siParams.add("FTSection",typeof FTSection!="undefined"?FTSection:"undefined");siParams.add("FTPage",typeof FTPage!="undefined"?FTPage:"undefined");siParams.add("segid",location.search.match(/segid=([^&]*)/)?RegExp.$1:null);siParams.add("FTBarrier",typeof FTBarrier!="undefined"?FTBarrier:null);siParams.add("subType",subtype);if(re.test(dc)){siParams.add("ad_refresh","yes");FT.bIsAdRefresh=true;}
siParams.add("WT.metroArea_s",metroArea?metroArea:"undefined");siParams.add("WT.regArea_s",regArea?regArea:"undefined");siParams.add("HurdleType",typeof HurdleType!="undefined"?HurdleType:null);siParams.add("video",typeof video!="undefined"?video:null);var qs="?"+siParams.buildQueryString();var siCall='<scr'+'ipt type="text/javascript">SiTrackPage("'+pageUrl+qs+'");<\/sc'+'ript>';document.write(siCall);document.cookie="TRK_REF=null";}
/*doTrack2();*/function doTrackRefresh(){document.cookie="TRK_REF="+window.location.href;setTimeout("window.location.reload(false)",2000);}
var subsLevelReplaceLookup={'edt':/^edit$/,'int':/^Ftemp$/,'cor':/^[PL]0[PL][12][A-Za-z][A-Za-z]/,'lv1':/^[PL]1[A-Za-z][A-Za-z]/,'lv2':/^[PL]2[A-Za-z][A-Za-z]/,'reg':/^[PL]0[A-Za-z][A-Za-z]/};var getdecodedSubsLevel=function(keyValue){if(keyValue!=null){for(subLevel in subsLevelReplaceLookup){var pattern=subsLevelReplaceLookup[subLevel]
if(keyValue.match(pattern)){return subLevel;}}}
return"anon";}
if(typeof DM_addEncToLoc!="undefined")
{var rsiAYSC=document.cookie.match(/AYSC=([^;]*)/)?RegExp.$1:"";var rsiPos=rsiAYSC.match(/_07([^_]*)/)?RegExp.$1:null;var rsiResp=rsiAYSC.match(/_06([^_]*)/)?RegExp.$1:null;var rsiInd=rsiAYSC.match(/_05([^_]*)/)?RegExp.$1:null;var rsiCoun=rsiAYSC.match(/_14([^_]*)/)?RegExp.$1:null;var rsiCompSize=rsiAYSC.match(/_19([^_]*)/)?RegExp.$1:null;var rsiSubscriptionLevel=rsiAYSC.match(/_22([^_]*)/)?RegExp.$1:null;var temppos=typeof rsiPos!="undefined"?rsiPos:"undefined";var tempresp=typeof rsiResp!="undefined"?rsiResp:"undefined";var tempind=typeof rsiInd!="undefined"?rsiInd:"undefined";var tempcountry=typeof rsiCoun!="undefined"?rsiCoun:"undefined";var tempcompsize=typeof rsiCompSize!="undefined"?rsiCompSize:"undefined";var tempsubscriptionLevel=typeof rsiSubscriptionLevel!="undefined"?getdecodedSubsLevel(rsiSubscriptionLevel):"anon";var rsi_call="<scr"+"ipt type=\"text\/javascript\">";var tempsec=typeof FTSection!="undefined"?FTSection:"undefined";var temppage=typeof FTPage!="undefined"?FTPage:"undefined";rsi_call+=" DM_addEncToLoc(\"FTSectionCode\", \""+tempsec+"\"); DM_addEncToLoc(\"FTPageCode\", \""+temppage+"\"); ";rsi_call+=" DM_addEncToLoc(\"FTP\", \""+temppos+"\"); DM_addEncToLoc(\"FTR\", \""+tempresp+"\"); ";rsi_call+=" DM_addEncToLoc(\"FTI\", \""+tempind+"\"); DM_addEncToLoc(\"FTC\", \""+tempcountry+"\"); ";rsi_call+=" DM_addEncToLoc(\"FTCS\", \""+tempcompsize+"\"); ";rsi_call+=" DM_addEncToLoc(\"SubsLevel\", \""+tempsubscriptionLevel+"\"); ";if(FT&&FT.env&&FT.env.dfp_site&&FT.env.dfp_zone)
{rsi_call+=" DM_addEncToLoc('dfp_site', FT.env.dfp_site); ";rsi_call+=" DM_addEncToLoc('dfp_zone', FT.env.dfp_zone); ";}
rsi_call+="DM_tag();";rsi_call+="</scr"+"ipt>";document.write(rsi_call);}
if(typeof FT==="undefined")
{FT={};}
FT.Conker=function(jQuery,urlConker,urlPopup)
{urlConker=urlConker||'http://conker.ft.com/conker/service/pageView?callback=?';urlPopup=urlPopup||'/FTCOM/HTML/conker-popup.html';this.urlConker=urlConker;this.urlPopup=urlPopup;this.jQuery=jQuery;this.bDebug=false;this.bShowDebug=false;this.bForcePopup=false;this.bUseTimer=true;this.resetFlags=FT.Conker.resetFlags;this.checkConcurrency=FT.Conker.checkConcurrency;this.getCookies=FT.Conker.getCookies;this.deleteCookies=FT.Conker.deleteCookies;this.isEmpty=FT.Conker.isEmpty;this.getViewportSize=FT.Conker.getViewportSize;this.injectMessage=FT.Conker.injectMessage;this.createConkerDiv=FT.Conker.createConkerDiv;this.positionPopup=FT.Conker.positionPopup;this.positionOverlay=FT.Conker.positionOverlay;this.monitorResize=FT.Conker.monitorResize;this.getPopupPosition=FT.Conker.getPopupPosition;this.addStyledHTML=FT.Conker.addStyledHTML;this.addStyle=FT.Conker.addStyle;this.debug=FT.Conker.debug;this.resetFlags();FT.Conker.instance=this;return this;};FT.Conker.resetFlags=function()
{this.eRightsId=undefined;this.trackId=undefined;this.eSessionId=undefined;this.isRegistered=undefined;this.isHelpDesk=undefined;};FT.Conker.isEmpty=function(value)
{return(typeof value==='undefined'||value===null);};FT.Conker.checkConcurrency=function(eRightsId,eSessionId,trackId,rcCallBack)
{var self=this;var AjaxParams={'eUserId':eRightsId,'trackId':trackId};if(!this.isEmpty(eSessionId))
{AjaxParams.eSessionId=eSessionId;}
else
{AjaxParams.eSessionId='';}
this.debug('checkConcurrency('+this.urlConker+', '+_dumpThis(AjaxParams,'AjaxParams')+')');this.jQuery.getJSON(this.urlConker,AjaxParams,function(data){rcCallBack(data,self);});};FT.Conker.getCookies=function()
{var bSuccess=true;this.debug('getCookies()');this.resetFlags();this.trackId=this.jQuery.cookie('FTUserTrack');if(this.isEmpty(this.trackId))
{bSuccess=false;}
else
{var cookieFTU=this.jQuery.cookie('FT_U');if(!this.isEmpty(cookieFTU))
{cookieFTU.match(/_EID=([^_]*)_/);this.eRightsId=RegExp.$1;cookieFTU.match(/_RI=([^_]*)_/);this.isRegistered=RegExp.$1==='1'?true:false;this.eSessionId=this.jQuery.cookie('FTSession');if(this.isEmpty(this.eSessionId))
{bSuccess=false;}}
else
{var cookieRemember=this.jQuery.cookie('FT_Remember');if(!this.isEmpty(cookieRemember))
{cookieRemember.match(/^(\d+):/);this.eRightsId=RegExp.$1;this.isRegistered=false;}
else
{bSuccess=false;}}}
var cookieHelpDesk=this.jQuery.cookie('FT_HelpDesk');this.isHelpDesk=!this.isEmpty(cookieHelpDesk);this.debug('getCookies() return '+bSuccess);return bSuccess;};FT.Conker.deleteCookies=function()
{var options={path:'/',domain:'.ft.com'};this.jQuery.cookie('FT_U',null,options);this.jQuery.cookie('FT_User',null,options);this.jQuery.cookie('FTSession',null,options);this.jQuery.cookie('FT_Remember',null,options);this.resetFlags();};FT.Conker.addStyle=function(rDocument,stylesheet)
{stylesheet=stylesheet.replace(/<\/?style[^>]*?>/gi,' ');var rStyle=rDocument.createElement('style');rStyle.setAttribute("type","text/css");if(rStyle.styleSheet)
{rStyle.styleSheet.cssText=stylesheet;}
else
{var rText=rDocument.createTextNode(stylesheet);rStyle.appendChild(rText);}
var rHead=rDocument.getElementsByTagName('head')[0];rHead.appendChild(rStyle);return rStyle;};FT.Conker.addStyledHTML=function(rDocument,rElement,styledHTML)
{styledHTML=styledHTML.replace(/[\r\n]+/g,' ');var Styles=styledHTML.match(/<style[^>]*?>(.*?)<\/style[^>]*?>/gi);var html=styledHTML.replace(/<style[^>]*?>.*?<\/style[^>]*?>/gi,' ');html=html.replace(/^.*<body[^>]*>/,'');html=html.replace(/<\/body>.*$/,'');if(Styles)
{for(var idx=0;idx<Styles.length;++idx)
{FT.Conker.addStyle(rDocument,Styles[idx]);}}
rElement.innerHTML=html;return rElement;};FT.Conker.getPopupPosition=function(rDocument,width,why)
{var bFound=false;var rPos={'top':'110px','left':'650px'};var DivIds=['#ftapage','#ft_header','#page-header','#header'];var rDiv;var idx;var targetName='none';for(idx=0;!bFound&&idx<DivIds.length;++idx)
{rDiv=this.jQuery(DivIds[idx]);if(rDiv.length)
{targetName=DivIds[idx];bFound=true;}}
if(bFound)
{var leftOffset=0;var rOffsetDiv=this.jQuery('#header-wrapper');if(rOffsetDiv.length)
{leftOffset=rOffsetDiv[0].offsetLeft;}
this.debug("("+why+") Left Offset: "+leftOffset);rPos.top=rDiv.position().top+'px';rPos.left=(leftOffset+rDiv.position().left+rDiv.outerWidth()-width)+'px';this.debug("("+why+") Div Pos: "+targetName+" ("+rDiv.position().left+", "+rDiv.position().top+") r: "+rDiv.position().right+" w: "+rDiv.outerWidth()+" pw: "+width);}
this.debug("("+why+") Target Name: "+targetName+" ("+rPos.left+", "+rPos.top+")");return rPos;};FT.Conker.injectMessage=function(rDocument,idDiv)
{var self=this;this.debug('injectMessage('+this.urlPopup+')');this.jQuery.get(this.urlPopup,function(data){var rDiv=self.createConkerDiv(rDocument,idDiv);var rInjectDiv=rDocument.getElementById('#header-wrapper');if(!rInjectDiv)
{rInjectDiv=rDiv;}
self.addStyledHTML(rDocument,rInjectDiv,data);self.monitorResize(rDocument);FT.Conker.resizeOverlay(self,rDocument,'#popconker','#popconker-overlay','inject');});};FT.Conker.createConkerDiv=function(rDocument,idDiv)
{var rDiv=rDocument.getElementById(idDiv);if(!rDiv)
{rDiv=rDocument.createElement('div');rDiv.id=idDiv;rDocument.body.appendChild(rDiv);}
return rDiv;};FT.Conker.positionOverlay=function(rDocument,idOverlay,why)
{var docWidth=this.jQuery(rDocument).width();var docHeight=this.jQuery(rDocument).height();this.debug("("+why+") Overlay Div Pos: ["+idOverlay+"] ("+docWidth+", "+docHeight+")");var rOverlay=this.jQuery(idOverlay);if(rOverlay.length)
{rOverlay.css('width',docWidth+'px');rOverlay.css('height',docHeight+'px');}};FT.Conker.positionPopup=function(rDocument,idPopup,why)
{var rPopup=this.jQuery(idPopup);if(rPopup.length)
{var popupWidth=rPopup.outerWidth();var rPosition=this.getPopupPosition(rDocument,popupWidth,why);rPopup.css('top',rPosition.top);rPopup.css('left',rPosition.left);}};FT.Conker.getViewportSize=function(rWindow,rDocument)
{rWindow=rWindow||window;rDocument=rDocument||document;var size=[0,0];if(typeof rWindow.innerWidth!=='undefined')
{size=[rWindow.innerWidth,rWindow.innerHeight];}
else if(typeof rDocument.documentElement!=='undefined'&&typeof rDocument.documentElement.clientWidth!=='undefined'&&rDocument.documentElement.clientWidth!==0)
{size=[rDocument.documentElement.clientWidth,rDocument.documentElement.clientHeight];}
else
{var rBody=rDocument.body||rDocument.getElementsByTagName('body')[0];size=[rBody.clientWidth,rBody.clientHeight];}
return size;};FT.Conker.windowResize=function(rConker,rDocument,idPopup,idOverlay)
{var currentSize=rConker.getViewportSize(window,rDocument);if(!rConker.bDebug||(currentSize[0]!==rConker.viewportSize[0]||currentSize[1]!==rConker.viewportSize[1]))
{rConker.viewportSize=currentSize;FT.Conker.resizeOverlay(rConker,rDocument,idPopup,idOverlay,'window');}};FT.Conker.resizeOverlay=function(rConker,rDocument,idPopup,idOverlay,label)
{rConker.positionOverlay(rDocument,idOverlay,label);rConker.positionPopup(rDocument,idPopup,label);};FT.Conker.monitorResize=function(rDocument,rWindow)
{var self=this;rWindow=rWindow||window;var idPopup='#popconker';var idOverlay="#popconker-overlay";var WatchDivs=['#page-header-ad','#top-ad','#ad-placeholder-banlb','#leaderboard','#ad-placeholder-nessubs'];var label='window';self.debug('Add resize handler to: '+label);self.viewportSize=self.getViewportSize(rWindow,rDocument);this.jQuery(rWindow).resize(function()
{FT.Conker.windowResize(self,rDocument,idPopup,idOverlay);});for(var idx=0;idx<WatchDivs.length;++idx)
{(function()
{var div_id=WatchDivs[idx];var rDiv=self.jQuery(div_id);if(rDiv.length)
{var label=div_id;self.debug('Add resize handler to: '+label);rDiv.resize(function()
{FT.Conker.resizeOverlay(self,rDocument,idPopup,idOverlay,label);});}})();}
if(this.bUseTimer)
{label='timer';this.debug('Add interval event to reposition popup');this.timerId=setInterval(function()
{FT.Conker.resizeOverlay(self,rDocument,idPopup,idOverlay,label);},5000);this.debug('Add interval event to reposition popup: '+this.timerId);}};FT.Conker.debug=function(message)
{if(this.bDebug)
{var rOutputNode=document.getElementById('conker_debug_log');if(!rOutputNode)
{rOutputNode=document.createElement('div');rOutputNode.id='conker_debug_log';if(!this.bShowDebug)
{rOutputNode.style.visibility='hidden';}
document.body.appendChild(rOutputNode);}
var rNewNode=document.createElement('p');rNewNode.innerHTML=message;rOutputNode.appendChild(rNewNode);}};FT.Conker.applyConcurrencyLogic=function(jQuery,rcCallback,urlConker,urlPopup,bForcePopup,bUseTimer,bDebug,bShowDebug)
{var rConker=new FT.Conker(jQuery,urlConker,urlPopup);rConker.bForcePopup=false;rConker.bUseTimer=bUseTimer?true:false;rConker.bDebug=bDebug?true:false;rConker.bShowDebug=bShowDebug?true:false;if(bForcePopup)
{rConker.debug('Forcing popup to show');rConker.bForcePopup=true;rConker.getCookies();if(rConker.isEmpty(rConker.eRightsId))
{rConker.eRightsId='1';}
if(rConker.isEmpty(rConker.eSessionId))
{rConker.eSessionId='1';}
if(rConker.isEmpty(rConker.trackId))
{rConker.trackId='127.0.0.1.123456789012345678';}
rConker.debug('rConker: '+_dumpThis(rConker,'rConker'));}
else if(rConker.getCookies())
{if(!rConker.isRegistered&&!rConker.isHelpDesk)
{bForcePopup=true;}}
if(bForcePopup)
{rConker.checkConcurrency(rConker.eRightsId,rConker.eSessionId,rConker.trackId,rcCallback);}};FT.Conker.hidePopup=function(rDocument,id)
{var bForcePopup=false;if(typeof FT.Conker.instance!=='undefined')
{FT.Conker.instance.debug('Clearing timer interval: '+FT.Conker.instance.timerId);if(FT.Conker.instance.timerId)
{clearInterval(FT.Conker.instance.timerId);}
bForcePopup=FT.Conker.instance.bForcePopup;}
if(bForcePopup)
{rDocument.getElementById(id).style.visibility='hidden';}};FT.Conker.receiveConkerResponse=function(data,rConker)
{rConker.debug('receiveConkerResponse()');if(data.deny)
{rConker.debug('receiveConkerResponse() denied');if(!this.bForcePopup)
{rConker.deleteCookies();}
rConker.injectMessage(document,'conker-div');}};if(typeof _dumpThis==='undefined')
{_dumpThis=function(thing)
{return thing;};}
if(typeof jQuery!=='undefined'&&typeof jQuery.cookie!=='undefined')
{jQuery.noConflict();jQuery(document).ready(function()
{var bConkerKillSwitch=false;if(!bConkerKillSwitch&&typeof FT!=='undefined'&&typeof FT.Conker!=='undefined'&&typeof FT.Conker.applyConcurrencyLogic!=='undefined'){if(!FT.bIsAdRefresh){FT.Conker.applyConcurrencyLogic(jQuery,FT.Conker.receiveConkerResponse,undefined,undefined,false,false,false,false);}}});}
FT.Tynt={initTynt:function(){var Tynt=Tynt||[];Tynt.push('cqolxGrS4r34rIadbiUt4I');Tynt.i={"cc":"0","b":true,"ap":"Please respect FT.com's <a href='http://www.ft.com/servicestools/help/terms'>ts&amp;cs</a> and <a href='http://www.ft.com/servicestools/help/copyright'>copyright policy</a> which allow you to: share links; copy content for personal use; &amp; redistribute limited extracts. Email ftsales.support@ft.com to buy additional rights or use this link to reference the article -","t":true};return Tynt;},doTynt:function(){if(typeof Tynt!="undefined"&&document.location.protocol=='http:'){var s=document.createElement('script');s.async="async";s.type="text/javascript";s.src='http://tcr.tynt.com/ti.js';var h=document.getElementsByTagName('script')[0];h.parentNode.insertBefore(s,h);}}};
var FT = window.FT || {};
FT.env = {
// THIRD PARTY CUSTOMISATION HERE
'dfp_site': 'mob.5887.html5-app',
'dfp_zone': 'unclassified',
'targeting': '', //';key=value',
'formats': {
'small': {
'banlb': '300x50',
'banlb2': '300x50',
'-ds': 's'
},
'medium': {
'banlb': '600x100',
'banlb2': '600x100',
'-ds': 'm'
},
'large': {
'banlb': '728x90',
'mpu': '300x250',
'hlfmpu': '300x600',
'-ds': 'l'
},
'largewide': {
'banlb': '728x90',
'mpu': '300x250',
'hlfmpu': '300x600',
'-ds': 'lw'
},
'-': '-'
},
'audSciLimit': 0,
'pageCountWrap': 6,
'maxHistory': 25,
// END THIRD PARTY CUSTOMISATION
'isTest': false,
'screenMode': undefined,
'offline': false,
'debug': false,
'server': '',
'method': '/adj/',
'ord': Math.floor(Math.random() * 1E16),
'tile': 0,
'device_size': 's',
'pageCount': {},
'Requests': {},
'History': [],
'getAudSci': function (cookie) {
var ft = this;
var idx;
ft.cookie = cookie === undefined ? document.cookie : cookie;
ft.audSci = '';
if (ft.audSciLimit) {
var rsiSegs = ft.cookie.replace(/^.*\brsi_segs=([^;]*).*$/, '$1');
if (rsiSegs !== ft.cookie) {
var Segments = rsiSegs.split(/\|/);
var Found = [];
for (idx = 0; Found.length < ft.audSciLimit && idx < Segments.length; ++idx) {
var segment = Segments[idx];
if (segment.match(/^J07717_/)) {
segment = segment.replace(/^J07717_/, '');
segment = ';a=z' + (parseInt(segment, 10) - 10000);
Found.push(segment);
}
}
ft.audSci = Found.join('');
}
}
return ft.audSci;
},
'getURL': function (pos) {
var ft = this;
ft.url = undefined;
ft.URLParts = undefined;
ft.pos = pos;
if (!ft.offline) {
ft.sz = ft.formats[ft.screenMode][ft.pos];
ft.ac = ft.pageCount.article;
if (ft.audSci === undefined) {
ft.audSci = ft.getAudSci(ft.cookie);
}
ft.ac = ft.ac ? ";ac=" + ft.ac % ft.pageCountWrap : "";
if (ft.sz) {
ft.URLParts = ['http://ad.', ft.server, 'doubleclick.net', ft.method, ft.dfp_site, '/', ft.dfp_zone, ';ds=', ft.device_size, ';sz=', ft.sz, ';pos=', ft.pos, ft.targeting, ft.audSci, ft.ac, ';tile=', ++ft.tile, ';ord=', ft.ord, '?'];
ft.url = ft.URLParts.join('');
}
}
ft.Requests[ft.pos] = ft.url;
ft.logHistory("getURL: " + ft.pos + ": " + ft.url);
return ft.url;
},
'getTag': function (pos) {
var ft = this;
ft.tag = undefined;
ft.Parts = undefined;
var url = ft.getURL(pos);
if (url) {
ft.Parts = ['<', 'script type="text/javascript" src="', url, '"><', '/script>'];
ft.tag = ft.Parts.join('');
}
return ft.tag;
},
'adCall': function (pos) {
var tag = this.getTag(pos);
if (tag) {
document.write(tag);
}
},
'getCookieSettings': function ()
{
var ft = this;
// Parse the cookie
// FTQA=debug%2Cenv%3Dtest; expires=Wed, 01 Jun 2011 09:25:21 GMT; path=/; domain=.ft.com
var Match = document.cookie.match(/(?:^|;|\s)FTQA=(?:[^;]+)(?:;|$)/g);
var FTQA = "FTQA=";
if (Match)
{
// Could be the same cookie setting multiple times so we use the last one found.
FTQA = Match[Match.length - 1].replace(/%3D/g, "=");
FTQA = FTQA.replace(/%2C/g, ",");
if (FTQA.match(/debug/))
{
ft.debug = true;
}
if (FTQA.match(/env=test/))
{
ft.isTest = true;
}
}
ft.logHistory("Cookie " + FTQA);
},
'setup': function (size, offline) {
// size = small, medium, large, largewide
var ft = this;
ft.getCookieSettings();
ft.logHistory("setup: size=" + size + " offline=" + offline);
ft.screenMode = size;
ft.offline = offline;
if (ft.formats[size]) {
ft.device_size = ft.formats[size]['-ds'];
if (ft.isTest) {
ft.dfp_site = ft.dfp_site.replace(/^[^\.]+\./, "test.");
}
} else {
// If it's a size we don't know then go to offline mode.
ft.offline = true;
}
ft.logHistory("setup is: site=" + ft.dfp_site + " device_size=" + ft.device_size + " offline=" + ft.offline + " isTest=" + ft.isTest);
},
'startPage': function (zone, pageType) {
var ft = this;
ft.logHistory("===== startPage: zone=" + zone + " pageType=" + pageType);
ft.dfp_zone = zone;
if (!ft.pageCount[pageType]) {
ft.pageCount[pageType] = 0;
}
ft.pageCount[pageType]++;
ft.tile = 0;
ft.ord = Math.floor(Math.random() * 1E16);
ft.Requests = {};
if (ft.History.length >= ft.maxHistory) {
ft.History = [];
}
},
'logHistory': function (message) {
var ft = this;
ft.History.push(message);
if (ft.debug) {
console.log(message);
}
},
'showHistory': function () {
var ft = this;
alert("FT.env.History:\n\n" + ft.History.join("\n"));
},
'_': '_'
};
var Assanka = Assanka || {}; Assanka.$ = jQuery;
var mFT = (function() {
mFT = {}
// Is the webview running on a Samsung Galaxy Tab?
var _userAgentString = window.navigator.userAgent.toLowerCase();
var _tabUserAgents = ['gt-p1000', 'gt-p1010', 'sgh-i987', 'sph-p100', 'sgh-t849', 'sch-i800'];
var _onSamsungTab = false;
Array.prototype.forEach.call(_tabUserAgents, function(userAgentKey) {
if (_userAgentString.indexOf(userAgentKey) != -1) _onSamsungTab = true;
});
var _samsungTabInnerHeight = 0;
var _isAndroid = (_userAgentString.search('android') > -1);
var _isiOS = (_userAgentString.search('iphone') > -1 || _userAgentString.search('ipad') > -1 || _userAgentString.search('ipod') > -1 || _userAgentString.search('playbook') > -1);
var _isiOS3 = _isiOS && !('EventSource' in window);
// Basic functionality checks before execution
if (typeof WebKitCSSMatrix == 'undefined' || typeof localStorage == 'undefined' || !window.openDatabase || !_isiOS) {
var threshold = 640 * 480;
if (window.screen && screen.height && screen.width && (screen.height * screen.width) > threshold) {
// Incapable 'big' screen devices (with a product of sreen height and width greater than the threshold)
location.replace('http://www.ft.com/ftwebapp');
} else {
// Incapable 'small' screen devices
location.replace('http://app.ft.com/slowdevice');
}
return;
}
// Redirect HTTPS to HTTP
if (location.protocol && location.protocol == 'https:') {
location.protocol = 'http:';
}
/**
* SETUP AND CONFIG
*/
var _initialPageTitle = '';
var _screensizemode = 'large';
var _articlecolumnsmode = false;
var _3daccelerated = true;
var _dateConstants = { 'days':['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 'months':['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] };
var _shortDateCutoffDate = new Date();
_shortDateCutoffDate.setDate(_shortDateCutoffDate.getDate() - 5);
var _fontSizeNames = ['Extra-Small', 'Small', 'Medium', 'Large', 'Extra-Large' ];
var _fontSizeClasses = [ 'extra-small-text', 'small-text', 'standard-text', 'large-text', 'extra-large-text' ];
var _currentFontSize = 0;
var _screenColumns = {
left : { id:'col1', pageType:false, pageIdentifier:false, requiresUpdate:false, genBaseTime:0 },
center : { id:'col2', pageType:false, pageIdentifier:false, requiresUpdate:false, genBaseTime:0 },
right : { id:'col3', pageType:false, pageIdentifier:false, requiresUpdate:false, genBaseTime:0 }
};
var _columnsAnimating = false;
var _screenTransitionEndFunction = false;
var _screenIsPanning = false;
var _screenPanActionRequired = false;
var _screenPanVerticalOffset = 0;
var _screenPanTargetVerticalOffset = 0;
var _swipingReady = false;
var _lastorientation = _getWindowOrientation();
var _campaignreference = localStorage.campaignreference;
var _currentPageAnchor = false;
var _currentPageGUID = '/';
var _sectionSelectorScroller = null;
var _sectionSelectorOpen = false;
var _sectionSelectorClosing = false;
var _loadingContent = {};
var _isLoadingArticle = false;
var _advertsShowing = false;
var _floatingAdvertTimer = false;
var _resizeActionTimer = false;
var _popoverShowing = false;
var _popoverReferenceElement = false;
var _popoverScroller = false;
var _ftuser = false;
var _updateftuseronnextload = false;
// Set up initial Mockingbird limits - note that these are subsequently overridden from local storage to
// previously stored values, and are updated from the structure when it's retrieved.
var _mbird = { limits:{ loggedout:3, loggedin:-1}, tracking:{} };
var _readcontent = {};
var _mbirdoverride = false;
var _regionlist = { uk:'United Kingdom', us:'United States', europe:'Europe', asia:'Asia Pacific', middleeast:'Middle East', india:'India' };
var _currentregion = localStorage.region || false;
var _resourcesupdating = false;
var _resourcesupdated = false;
var _resourcesprogress = 0;
var _structure = {};
var _laststructureupdate = 0;
var _currentstructuretype = 'latest';
var _initialstructuretimer = false;
var _initialstructurecancancel = false;
var _initialstructurestarttime = 0;
var _marketdata = {};
var _lastmarketdataupdate = 0;
var _barrierdisplaying = true;
var _structureupdating = false;
var _preloadcontentmode = false;
var _waitgetstructactive = false;
var _waitgetstructtimer = false;
var _marketsdataupdating = false;
var _downloadprocesscancelled = false;
var _articlesupdating = false;
var _articlestofetch = 0;
var _articlesfetched = 0;
var _imagesupdating = false;
var _imagestofetch = 0;
var _imagesfetched = 0;
var _pageinited = false;
var _structureinited = false;
var _sortedprimarynav = [];
var _primarynavlookup = {};
var _sortedprimarynavofflinestate = false;
var _currentcategory = 2;
var _podcasts = [];
var _Scroller = false;
var _accountPageHistoryStart = false;
var _historyGoingBack = false;
var _historyLastEntry = false;
var _sectionScrollPositions = [];
// Does the webview exist within a supporting native wrapper?
var _inWrapper = (typeof(window.appBridge) != "undefined");
var _wrapperUsesGallery = (_inWrapper && 'loadHome' in window.appBridge);
var _wrapperProvidesNavigation = (_inWrapper && 'getHandlesNavigation' in window.appBridge && window.appBridge.getHandlesNavigation());
var _wrapperInBackground = false;
var _wrapperSplashClosed = false;
var _disable3dForInteraction = _isAndroid && (!window.appBridge || !'getAndroidSDKVersion' in window.appBridge || window.appBridge.getAndroidSDKVersion() < 11);
// Should the search popover be showing?
var _showSearch = false;
var _lastSearch = "";
var _enableNavigationHack = _wrapperProvidesNavigation && (!'getAndroidSDKVersion' in window.appBridge || window.appBridge.getAndroidSDKVersion() <= 11);
// Adjust site to perform better on slower devices:
var cpuperformance = localStorage.cpuspeedtest;
if (!cpuperformance) {
var init = new Date(),
iterations = 25000;
while (iterations--) Math.sqrt(iterations*Math.random());
cpuperformance = new Date - init;
localStorage.setItem('cpuspeedtest', cpuperformance);
}
// With 25000 iterations: iPad = 19,19,19 iPad2 = 9,9,9, iPhone 3GS = 26,25,25, iPhone4 = 58,24,25,47 iPhone 3G = 90,98,97,66
var _isSlowDevice = (cpuperformance > 63);
if (_isSlowDevice & _userAgentString.search('ipad') == -1) {
localStorage.removeItem('cpuspeedtest');
window.location.pathname = '/slowdevice';
}
// Control behaviour based on device and firmware capabilities:
var _disableAdverts = _isiOS3 || _isSlowDevice;
var _disableAnalytics = _isiOS3 || _isSlowDevice;
var _disableImages = _isiOS3 || _isSlowDevice;
var _disableLiveStocksInArticles = _isiOS3 || _isSlowDevice;
// Does the webview support position fixed?
var _positionFixedSupport = (_isAndroid && ('onhashchange' in window));
// Should the webview load only very basic information, skipping most init, as it's being used for a
// specific task?
var _inFragment = false;
if (window.location.hash && window.location.hash.indexOf('#fragment') == 0) _inFragment = true;
// localdb is a wrapper for the sqlite database
var _localdb = false;
var _bigdatabasemode = localStorage.useBigDatabaseMode && (_inWrapper || navigator.standalone);
// Global variables for analytics:
siteMapTerm = 'Home';
HurdleType = 'undefined';
if(localStorage.getItem('debugintofooter')&&localStorage.getItem('debugintofooter')=='true')console.log=function log(s){
try{var n=document.createElement('div'),now=new Date(),hour=now.getHours(),minute=now.getMinutes(),second=now.getSeconds(),footers=document.querySelectorAll('#footertemplate');
for(var footidx in footers)footers[footidx].innerHTML+='<div>'+hour+":"+minute+":"+second+": "+s.toString()+'</div>'}catch(e){}};
if(_onSamsungTab&&_inWrapper&&!('screenSizeChange' in window.appBridge))var _tabLoadingInterval=window.setInterval(function _anon_heightChecksWhileLoading(){
if(!window.innerHeight)return;
_samsungTabInnerHeight=window.innerHeight;
updateContentHeight();
window.clearInterval(_tabLoadingInterval)},250);
if('applicationCache' in window&&document.querySelector('html').getAttribute('manifest')){
var appcache=window.applicationCache;
appcache.addEventListener('error',function(e){
if('onLine' in navigator&&!navigator.onLine)return;
_resourcesupdating=false;
_updateLastUpdatedHTML();
console.log('A problem occurred when saving resources for offline use - the app may not be available offline. Please try clearing your cache and restarting this '+(window.navigator.standalone?'app':'browser')+', then try again.\n\nIf you continue to have problems, please email dotcomsupport@ft.com\n\n(onError)');
var date=new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
document.cookie="manifestdebug=onerror; expires="+date.toGMTString()+"; path=/"},false);
appcache.addEventListener('downloading',function(){
_resourcesupdating=true;
_updateLastUpdatedHTML()},false);
appcache.addEventListener('noupdate',function(){
_resourcesupdating=false;
_updateLastUpdatedHTML()},false);
appcache.addEventListener('progress',function(e){
if(e.lengthComputable){
_resourcesprogress=e.loaded/e.total}
else _resourcesprogress+=1/33;
_updateLastUpdatedHTML()},false);
appcache.addEventListener('cached',function(){
_resourcesupdating=false;
_resourcesupdated=true;
_updateLastUpdatedHTML()},false);
appcache.addEventListener('updateready',function _anon_manifestUpdateReady(){
_resourcesupdating=false;
_resourcesupdated=true;
_updateLastUpdatedHTML();
try{appcache.swapCache()}catch(error){console.log('A problem occurred when saving resources for offline use - the app may not be available offline. Please try clearing your cache and restarting this '+(window.navigator.standalone?'app':'browser')+', then try again.\n\nIf you continue to have problems, please email dotcomsupport@ft.com\n\n(onupdateready, '+error+')')}},false);
if(appcache.status==appcache.DOWNLOADING){
_resourcesupdating=true}
else if(appcache.status==appcache.UPDATEREADY){
_resourcesupdated=true;
try{appcache.swapCache()}catch(error){console.log('A problem occurred when saving resources for offline use - the app may not be available offline. Please try clearing your cache and restarting this '+(window.navigator.standalone?'app':'browser')+', then try again.\n\nIf you continue to have problems, please email dotcomsupport@ft.com\n\n(startup, '+error+')')}}};
var _startupActionCount=_inFragment?2:4
function _startupActionCompleteCallback(){
_startupActionCount--;
if(_startupActionCount<=0)window.setTimeout(function _anon_delayedInitComplete(){
_completeInit()},10)};
window.onload=function _anon_windowOnLoad(){
_pageinited=true;
_startupActionCompleteCallback();
if(_inWrapper&&!_wrapperSplashClosed)window.setTimeout(function _anon_delayedSplashScreenClose(){
if(!_wrapperSplashClosed){
_wrapperSplashClosed=true;
if(!_inFragment)window.appBridge.closeSplash();
updateContentHeight()}},(('screenSizeChange' in window.appBridge)?5000:4000))};
if(!_inFragment){
_localdb=new LocalDatabase(_bigdatabasemode);
if(_bigdatabasemode&&!_localdb.loadedSuccessfully()){
localStorage.useBigDatabaseMode=false;
_bigdatabasemode=false;
_localdb=new LocalDatabase(false)};
_localdb.checkVersion(dbVersion,function _anon_dbVersionCheckCallback(){
_localdb.init(function _anon_dbInitCallback(){
_startupActionCompleteCallback()})});
var storedStructureUpdate=localStorage.getItem('structureupdated');
if(storedStructureUpdate)_laststructureupdate=parseInt(storedStructureUpdate);
window.setTimeout(function _anon_setupStructure(){
var editionToLoad=localStorage.getItem('activeedition')||'latest';
if(window.navigator.standalone&&localStorage.lastaccesstime&&(new Date().getTime()-localStorage.lastaccesstime)>(30*60*1000))editionToLoad='latest';
if('structure' in localStorage&&(editionToLoad=='latest'||!('previousstructure' in localStorage))){
_currentstructuretype='latest';
_constructStructureFromString(localStorage.structure,'latest',false,_startupActionCompleteCallback)}
else if('previousstructure' in localStorage){
_currentstructuretype='previous';
_constructStructureFromString(localStorage.previousstructure,'previous',false,_startupActionCompleteCallback)}
else{
if(_barrierdisplaying){
var splashLoadTextEle=_eleWithId('splashloadtext');
if(splashLoadTextEle)splashLoadTextEle.innerHTML='Updating latest news'};
if(_inWrapper){
if(!_waitgetstructactive)_waitGetStruct(_startupActionCompleteCallback,false)}
else{
_barrierdisplaying=true;
if(_eleWithId('splashloadtext')){
document.body.className+=" structureloading";
_eleWithId('splashloadtext').innerHTML='Updating content...'};
_updateStructureFromServer(false,_startupActionCompleteCallback)}}},10)};
if(_inWrapper&&('screenSizeChange' in window.appBridge)){
window.onresize=function _anon_onResize(){
if(!document.body)return;
var theClientHeight=document.body.clientHeight,theClientWidth=document.body.clientWidth,theScale=parseFloat(window.appBridge.getScale());
_samsungTabInnerHeight=theClientHeight;
if(theClientHeight&&theScale==1.0&&!_wrapperSplashClosed){
_wrapperSplashClosed=true;
window.setTimeout(function _anon_onResizeSplashClose(){
if(!_inFragment)window.appBridge.closeSplash();
updateContentHeight()},1500)};
if(_enableNavigationHack){
var targetWidth=window.appBridge.getWidth()+'px';
switch(_screenColumns.center.pageType){case'home':document.querySelector('#col2 .headertitle').style.width=targetWidth;
document.querySelector('#col2 .skyline').style.width=targetWidth;case'section':case'content':case'marketsdata':case'portfolio':document.querySelector('#col2 .headerbar').style.width=targetWidth;
break}};
window.appBridge.screenSizeChange(theClientHeight,theClientWidth);
_performWindowResizeTasks()};
window.onresize()}
else if(/iPad|iPhone|iPod/.exec(navigator.userAgent)){
window.addEventListener('orientationchange',_performWindowResizeTasks,false)}
else window.onresize=_performWindowResizeTasks;
Assanka.$(function _anon_documentReady(){
_startSetupInit(_startupActionCompleteCallback)})
function _startSetupInit(completionCallbackFunction){
_setupFastTouchClick();
window.addEventListener('message',_receiveWindowMessage,false);
var storedUserDetails=localStorage.getItem('user');
if(storedUserDetails){
storedUserDetails=JSON.parse(storedUserDetails);
if(storedUserDetails)_ftuser=storedUserDetails};
var storedMbirdDetails=localStorage.getItem('mockingbird');
if(storedMbirdDetails){
storedMbirdDetails=JSON.parse(storedMbirdDetails);
if(storedMbirdDetails)_mbird=storedMbirdDetails;
var boundaryTime=(new Date().getTime())-2592000000;
for(var mbirdKey in _mbird.tracking)if(boundaryTime>_mbird.tracking[mbirdKey].anniversary)delete _mbird.tracking[mbirdKey]};
var storedReadContent=localStorage.getItem('readcontent');
if(storedReadContent){
storedReadContent=JSON.parse(storedReadContent);
if(storedReadContent)_readcontent=storedReadContent};
var bodyClasses=[];
bodyClasses.push(_classNameForScreenSize(_updateScreenSize()));
if(_wrapperUsesGallery)bodyClasses.push('ingallery');
if(_wrapperProvidesNavigation)bodyClasses.push('nonavigation');
var ss=_updateScreenSize();
if(/iPad/.test(navigator.userAgent))ss='large';
FT.env.setup(ss,false);
var storedFontSize=localStorage.getItem('fontsize');
if(storedFontSize!==null&&_fontSizeClasses[storedFontSize])_currentFontSize=storedFontSize;
bodyClasses.push(_fontSizeClasses[_currentFontSize]);
if(!_positionFixedSupport)bodyClasses.push('nopositionfixed');
if(_wrapperUsesGallery)bodyClasses.push('ingallery');
if(_wrapperProvidesNavigation)bodyClasses.push('nonavigation');
if(_structure&&_structure.weekend)bodyClasses.push('weekend');
if(!_bigdatabasemode)bodyClasses.push('smalldbmode');
if(!_inFragment&&!_ftuser&&document.getElementById('mockingbirdannouncement')){
var lastmockingbirdannouncement=parseInt(localStorage.getItem('lastmockingbirdannouncement'));
if(!lastmockingbirdannouncement||lastmockingbirdannouncement+(24*60*60*1000)<new Date().getTime()){
bodyClasses.push('mockingbirdannouncement');
localStorage.setItem('lastmockingbirdannouncement',new Date().getTime())}};
if(_structureupdating){
bodyClasses.push('structureupdating');
_eleWithId('splashloadtext').innerHTML='Updating content...'};
if(bodyClasses.length)document.body.className+=' '+bodyClasses.join(' ');
var sectionScrollerElement=document.getElementById('sectionscroller');
_sectionSelectorScroller=new TouchScroll(sectionScrollerElement,{elastic:true,scrollbars:false});
sectionScrollerElement.addEventListener('scrollend',_updateSectionSelectorArrowsWithScroll,false);
completionCallbackFunction()}
function _completeInit(){
_structureinited=true;
_checkResourcesVersion();
if('marketsdata' in localStorage){
_constructMarketsDataFromString(localStorage.marketsdata,false,false)}
else _updateMarketsDataFromServer();
var href=window.location.href,hash=window.location.hash;
_campaignreference=/segid=([0-9]*)/.exec(href);
if(hash)_currentPageAnchor=hash.substring(1);
var lastUsedTime=localStorage.getItem('lastaccesstime'),lastUsedLocation=localStorage.getItem('lastaccesslocation');
if(window.navigator.standalone||!_currentPageAnchor||_currentPageAnchor=='home'){
if(lastUsedLocation)_currentPageAnchor=lastUsedLocation;
if(window.navigator.standalone&&lastUsedTime&&(new Date().getTime()-lastUsedTime)>(30*60*1000))_currentPageAnchor=''};
if(!_inWrapper||!_wrapperUsesGallery)mFT.addSwipeListenerToPagesContainer(document.getElementById('columnscontainer'));
if(window.history.pushState)window.history.replaceState({slug:_currentPageAnchor?_currentPageAnchor:'home'},_initialPageTitle,_currentPageAnchor?'#'+_currentPageAnchor:'#home');
_setupHistoryHandler();
var anchorparts=[''];
if(_currentPageAnchor)anchorparts=_currentPageAnchor.split('/');
_trackView(anchorparts[0],(anchorparts.length>1)?anchorparts[1]:'');
setDataToSend();
_barrierdisplaying=false;
_checkStructureUpdateOnStartup();
if(!_barrierdisplaying){
loadPage(_currentPageAnchor);
_showDiscountPopoverIfNecessary();
hideBarrier(false)};
Assanka.$(document.body).removeClass("loading");
updateContentHeight();
setTimeout(preloadAdjacentContent,50);
if(window.navigator.standalone){
localStorage.homescreenAccessDate=new Date().getTime();
if(uaIsOffline())return;
if(!localStorage.hasShownWelcome){
var welcomeImg=new Image();
welcomeImg.src='/lib/img/ios-welcome.png';
setTimeout(welcomePopover,500)}
else if(!_bigdatabasemode)showSystemMessage('small-database-message')}
else if(device=/iPad|iPhone/.exec(navigator.userAgent)){
device=device[0];
if(!localStorage.homescreenTipDate){
floatTip(device);
localStorage.homescreenTipDate=new Date().getTime()}
else if((new Date().getTime()-parseInt(localStorage.homescreenAccessDate))/1000/60/60/24<3){
showSystemMessage('added-to-homescreen-but-since-forgotten-message')}
else showSystemMessage('never-added-to-homescreen-message')}}
function hideBarrier(hideAction){
if(typeof hideAction=='undefined')hideAction=false;
if(hideAction&&typeof hideAction=='number'&&hideAction>=1){
_eleWithId('structurehidebutton').style.display='inline-block';
if(hideAction<10)_eleWithId('hidebarrierbuttoncount').innerHTML='('+hideAction+')';
window.setTimeout(function _anon_hideBarrier(){
hideBarrier(--hideAction)},900);
return};
_eleWithId('hidebarrierbuttontext').innerHTML='';
_eleWithId('hidebarrierbuttoncount').innerHTML='';
if(!_screenColumns.center.pageType){
loadPage(_currentPageAnchor);
_showDiscountPopoverIfNecessary()};
Assanka.$(document.body).removeClass("structureloading");
_barrierdisplaying=false};
mFT.hideBarrier=hideBarrier
function loadBlankPage(){
var targetNode=_eleWithId(_screenColumns.center.id);
targetNode.innerHTML='';
_screenColumns.center.pageType='blank'};
mFT.loadBlankPage=loadBlankPage
function _constructStructureFromString(structureString,structureEdition,removeOldItemsAndRecreateLimits,structureReadyCallback){
if(typeof (structureReadyCallback)=='undefined')structureReadyCallback=false;
try{var newstructure=JSON.parse(structureString)}catch(e){return false};
var oldstructureexisted=_structure?true:false;
if(structureEdition=='latest'){
var prechecktime=new Date().getTime();
for(var colKey in _screenColumns){
var colToCheck=_screenColumns[colKey];
if(colToCheck.genBaseTime>=_laststructureupdate){
colToCheck.requiresUpdate=false;
continue};
switch(_screenColumns[colKey].pageType){case'home':colToCheck.requiresUpdate=_hasHomePageChanged(_structure,newstructure);
break;case'section':colToCheck.requiresUpdate=_hasSectionPageChanged(colToCheck.pageIdentifier,_structure,newstructure);
break;default:colToCheck.requiresUpdate=false;
break}}};
if(_screenColumns.left.requiresUpdate)_screenColumns.left.pageType=false;
if(_screenColumns.right.requiresUpdate)_screenColumns.right.pageType=false;
if(removeOldItemsAndRecreateLimits&&structureEdition=='latest'){
if(newstructure&&newstructure.mbird){
if(!_mbirdoverride)_mbird.limits.loggedout=newstructure.mbird['default'].loggedout;
_mbird.limits.loggedin=newstructure.mbird['default'].loggedin;
var screenspecificlimits=newstructure.mbird[_screensizemode];
if(screenspecificlimits){
if(typeof screenspecificlimits.loggedout!='undefined')_mbird.limits.loggedout=screenspecificlimits.loggedout;
if(typeof screenspecificlimits.loggedin!='undefined')_mbird.limits.loggedin=screenspecificlimits.loggedin};
localStorage.setItem('mockingbird',JSON.stringify(_mbird))};
_storePortfolioSummary(newstructure.portfolio);
if(oldstructureexisted){
for(var aUserID in _readcontent){
var userReadArticles=_readcontent[aUserID];
for(var articleid in userReadArticles)if(!newstructure.storylist[articleid])delete userReadArticles[articleid]};
localStorage.removeItem('readcontent');
localStorage.setItem('readcontent',JSON.stringify(_readcontent));
if(_bigdatabasemode){
if(Object.keys){
var storylistids=Object.keys(newstructure.storylist)}
else{
var storylistids=[];
for(var i in newstructure.storylist)storylistids.push(i)}}
else{
var storylistids=[];
for(var storyid in newstructure.storylist)if(newstructure.storylist[storyid].fetch)storylistids.push(storyid)};
_localdb.removeStoriesExcept(storylistids)};
_calculateFetchList(newstructure.storylist)};
if(_currentstructuretype==structureEdition){
_structure=newstructure;
_updateSortedPrimaryNav();
if(document.body){
var bodyclasses=document.body.className.replace(/ ?weekend/g,'');
if(_structure.weekend)bodyclasses+=' weekend';
document.body.className=bodyclasses}};
newstructure=null;
if(structureReadyCallback){
structureReadyCallback()}
else if(_barrierdisplaying||_wrapperInBackground)if(_screenColumns.center.requiresUpdate){
_screenColumns.center.requiresUpdate=false;
loadPage(_currentPageAnchor)};
return true}
function _constructMarketsDataFromString(marketsDataString,updateStorage,updatePageElements){
if(!marketsDataString)return false;
var decodedMarketsData=JSON.parse(marketsDataString);
if(!decodedMarketsData)return false;
_marketdata=decodedMarketsData[localStorage.marketsdataregion||'EUR'];
if(updateStorage){
_lastmarketdataupdate=new Date().getTime();
localStorage.marketsdatadownloadtime=_lastmarketdataupdate;
var keystoprocess=['macromap','worldmarkets','macromapbackground','macromapforeground','worldmarketschart','currencieschart'];
for(var i in keystoprocess){
var marketkey=keystoprocess[i];
if(marketkey=='macromap'||marketkey=='worldmarkets'){
localStorage['markets'+marketkey]=JSON.stringify(decodedMarketsData[marketkey])}
else localStorage['markets'+marketkey]=decodedMarketsData[marketkey];
delete (decodedMarketsData[marketkey])};
localStorage.marketsdata=JSON.stringify(decodedMarketsData)}
else _lastmarketdataupdate=localStorage.marketsdatadownloadtime;
if(updatePageElements){
if(_screenColumns.center.pageType=='marketsdata'&&!_screenColumns.center.pageIdentifier){
mFT.router.loadMarketsData()}
else{
Array.prototype.forEach.call(document.querySelectorAll('.macromapbackgroundcontainer'),function(ele){
ele.innerHTML='<img src="data:'+localStorage.marketsmacromapbackground+'" />'});
Array.prototype.forEach.call(document.querySelectorAll('.macromapforegroundcontainer'),function(ele){
ele.innerHTML='<img src="data:'+localStorage.marketsmacromapforeground+'" />'});
Array.prototype.forEach.call(document.querySelectorAll('.worldmarkets'),function(ele){
_buildWorldMarkets(ele)});
Array.prototype.forEach.call(document.querySelectorAll('.marketsmoversrailmodule'),function(ele){
ele.querySelector('.contentswitcher').innerHTML=_buildMarketMovers(ele.querySelector('.sectionmarketsdata .tablerows'),1,ele.querySelector('.exchanges .previous'),ele.querySelector('.exchanges .next'),ele.querySelector('.exchanges .title'),ele.querySelector('.exchanges .x-of-y'));
ele.style.display='block'})};
updateContentHeight();
if(_screenColumns.center.pageType=='section'||_screenColumns.center.pageType=='home')_respaceSectionPageContent('center')};
return true}
function _updateLastUpdatedHTML(){
var lastUpdatedAreas={updateRequired:[],noUpdateRequired:[]},centerUpdateAreas=document.querySelectorAll('#'+_screenColumns.center.id+' .last-updated');
if(centerUpdateAreas&&centerUpdateAreas.length){
var centerUpdateKey=_screenColumns.center.requiresUpdate?'updateRequired':'noUpdateRequired';
Array.prototype.forEach.call(centerUpdateAreas,function(newArea){
lastUpdatedAreas[centerUpdateKey].push(newArea)})};
var sidePages=['left','right'];
Array.prototype.forEach.call(sidePages,function(direction){
var screenCol=_screenColumns[direction];
if(!screenCol.pageType)return;
var dirUpdateAreas=document.querySelectorAll('#'+screenCol.id+' .last-updated');
if(dirUpdateAreas&&dirUpdateAreas.length){
var dirUpdateKey=screenCol.requiresUpdate?'updateRequired':'noUpdateRequired';
Array.prototype.forEach.call(dirUpdateAreas,function(newArea){
lastUpdatedAreas[dirUpdateKey].push(newArea)})}});
if(lastUpdatedAreas.updateRequired.length){
var lastUpdatedHTML=_getLastUpdatedHTML(true);
Array.prototype.forEach.call(lastUpdatedAreas.updateRequired,function(lastUpdatedElement){
lastUpdatedElement.innerHTML=lastUpdatedHTML})};
if(lastUpdatedAreas.noUpdateRequired.length){
var lastUpdatedHTML=_getLastUpdatedHTML(false);
Array.prototype.forEach.call(lastUpdatedAreas.noUpdateRequired,function(lastUpdatedElement){
lastUpdatedElement.innerHTML=lastUpdatedHTML})}}
function _getLastUpdatedHTML(newArticlesAvailable){
if(typeof newArticlesAvailable=='undefined')newArticlesAvailable=false;
var useShortText=(_screensizemode=='small'||_screensizemode=='medium'),theHTML;
if(_resourcesupdating){
if(useShortText){
theHTML='<h5>Updating resources...</h5>'}
else theHTML='<h5 class="withprogress">Storing resources for offline use...</h5>';
if(_resourcesprogress){
theHTML+='<div class="progress"><div style="width: '+Math.round(100*_resourcesprogress)+'%"></div></div>'}
else theHTML+='<div class="progressbar standardprogressbar uses3d"></div>';
return theHTML};
if(_structureupdating){
if(useShortText){
theHTML='<h5>Updating content</h5>'}
else theHTML='<h5 class="withprogress">Checking for new stories</h5>';
theHTML+='<div class="progressbar cancelable standardprogressbar uses3d"></div>';
theHTML+='<div class="progresscancel" onclick="mFT.cancelDownloadProcess()"><div></div></div>';
return theHTML};
if(_marketsdataupdating){
if(useShortText){
theHTML='<h5>Updating markets</h5>'}
else theHTML='<h5 class="withprogress">Updating markets data</h5>';
theHTML+='<div class="progressbar cancelable standardprogressbar uses3d"></div>';
theHTML+='<div class="progresscancel" onclick="mFT.cancelDownloadProcess()"><div></div></div>';
return theHTML};
if(_articlesupdating){
theHTML='<h5 class="withprogress">Downloading articles</h5>';
if(_articlesfetched&&_articlesfetched<_articlestofetch){
theHTML+='<div class="progress cancelable"><div style="width: ';
theHTML+=Math.round(100*_articlesfetched/_articlestofetch);
theHTML+='%"></div></div>'}
else theHTML+='<div class="progressbar cancelable standardprogressbar uses3d"></div>';
theHTML+='<div class="progresscancel" onclick="mFT.cancelDownloadProcess()"><div></div></div>';
return theHTML};
if(_imagesupdating){
theHTML='<h5 class="withprogress">Downloading images</h5>';
if(_imagesfetched&&_imagesfetched<_imagestofetch){
theHTML+='<div class="progress cancelable"><div style="width: ';
theHTML+=Math.round(100*_imagesfetched/_imagestofetch);
theHTML+='%"></div></div>'}
else theHTML+='<div class="progressbar cancelable standardprogressbar uses3d"></div>';
theHTML+='<div class="progresscancel" onclick="mFT.cancelDownloadProcess()"><div></div></div>';
return theHTML};
if(_currentstructuretype=='previous'&&'structure' in localStorage)return'<div class="smallscreenpadder"><button class="refresh" onclick="mFT.loadEdition(\'latest\');">Display latest edition<span class="refreshdate">'+_formatUpdateDate(localStorage.structuredate)+'</span></button></div>';
if(newArticlesAvailable)return'<div class="smallscreenpadder"><button class="refresh" onclick="mFT.loadPage(\''+_currentPageAnchor+'\');">Display</button><h5 class="old">New articles</h5><p>available</p></div>';
if(_currentstructuretype=='latest'&&'previousstructure' in localStorage)return'<div class="smallscreenpadder"><button class="refresh previousversion" onclick="mFT.loadEdition(\'previous\');">Last saved version<span class="refreshdate">'+_formatUpdateDate(localStorage.previousstructuredate)+'</span></button><button class="refresh" onclick="mFT.refreshStructureAction()"><span>Refresh</span></button></div>';
var theHTML='<button class="refresh" onclick="mFT.refreshStructureAction()"><span>Refresh</span></button><h5',dayBoundary=new Date();
dayBoundary.setHours(0);
dayBoundary.setMinutes(0);
dayBoundary.setSeconds(0);
var dateIsOld=(new Date().getTime()>_laststructureupdate+24*60*60*1000),theHTML='<div class="smallscreenpadder"><button class="refresh" onclick="mFT.refreshStructureAction()"><span>Refresh</span></button><h5';
if(dateIsOld)theHTML+=' class="old"';
theHTML+='>Last updated:</h5><p>'+_formatUpdateDate(parseInt(_laststructureupdate))+'</p></div>';
return theHTML}
function refreshStructureAction(){
if(_structureupdating)return;
if(uaIsOffline()){
offlineWarningPopOver();
return};
_structureupdating=true;
_updateLastUpdatedHTML();
if(_inWrapper){
var appUpdatedDate=parseInt(window.appBridge.structureDate());
if(appUpdatedDate==_laststructureupdate||appUpdatedDate<(new Date().getTime()-120000)){
window.appBridge.updateData()}
else if(!_waitgetstructactive)_waitGetStruct()}
else _updateStructureFromServer(false);
_updateLastUpdatedHTML()};
mFT.refreshStructureAction=refreshStructureAction
function loadEdition(editionName){
if(editionName!='latest'&&editionName!='previous')return;
var storagekey=(editionName=='latest')?'structure':'previousstructure';
if(!(storagekey in localStorage))return;
_currentstructuretype=editionName;
_constructStructureFromString(localStorage.getItem(storagekey),editionName,false);
localStorage.setItem('activeedition',editionName);
_screenColumns.center.requiresUpdate=false;
_screenColumns.left.requiresUpdate=false;
_screenColumns.right.requiresUpdate=false;
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false;
loadPage(_currentPageAnchor)};
mFT.loadEdition=loadEdition
function _checkStructureUpdateOnStartup(){
if(localStorage.forceNextStructureUpdate&&!uaIsOffline()){
localStorage.removeItem('forceNextStructureUpdate')}
else{
if(_laststructureupdate+(5*60*1000)>new Date().getTime())return;
if(!_inWrapper&&'onLine' in navigator&&navigator.onLine===false)return};
if(_laststructureupdate+(30*60*1000)<new Date().getTime()){
Assanka.$(document.body).addClass("structureloading");
_barrierdisplaying=true;
document.querySelector('#splashloadtext').innerHTML='Updating content...';
if(!_inWrapper){
_initialstructurestarttime=new Date().getTime();
_initialstructuretimer=window.setInterval(_updateStructureProgress,200)}};
if(_inWrapper){
setDataToSend();
window.appBridge.updateData()}
else{
var enableEditionChange=(_laststructureupdate+(30*60*1000)<new Date().getTime());
window.setTimeout(function _anon_checkStructureBackgroundUpdate(){
_updateStructureFromServer(enableEditionChange,function(){
if(_initialstructuretimer){
window.clearInterval(_initialstructuretimer);
_initialstructuretimer=false}})},100)}}
function _updateStructureFromServer(enableEditionChange,structureReadyCallback){
if(typeof (structureReadyCallback)=='undefined')structureReadyCallback=false;
_downloadprocesscancelled=false;
_structureupdating=true;
_updateLastUpdatedHTML()
function _anon_updateStructureFromServerErrorCallback(){
_structureupdating=false;
_updateLastUpdatedHTML();
console.log("Up-to-date structure could not be retrieved from the server");
if(_barrierdisplaying)if(_laststructureupdate){
loadPage(_currentPageAnchor);
_eleWithId('splashloadtext').innerHTML='<span class="warning"></span>Content update failed!';
_eleWithId('hidebarrierbuttontext').innerHTML='Load saved version <span class="updatedate">'+_formatUpdateDate(_laststructureupdate)+'</span>';
hideBarrier(5)}
else{
document.querySelector('.splashloadimage').style.display='none';
_eleWithId('splashloadtext').innerHTML='<span class="warning"></span>Content update failed!<br /><br />The application content could not be retrieved, and you have no cached edition. Please try again later.'};
if(structureReadyCallback)structureReadyCallback()};
if(uaIsOffline()){
_anon_updateStructureFromServerErrorCallback();
return};
if(enableEditionChange){
if(_currentstructuretype=='previous')loadEdition('latest');
_currentstructuretype='previous';
if('structure' in localStorage){
localStorage.previousstructure=localStorage.structure;
localStorage.previousstructuredate=localStorage.structuredate||_laststructureupdate;
localStorage.removeItem('structure');
localStorage.removeItem('structuredate')}};
var requestData={v:2,stats:JSON.stringify({user:_ftuser}),lookupRegion:!_currentregion};
if(localStorage.forceWeekendStructure)requestData.forceweekend=1;
Assanka.$.ajax({url:sourceURL+"structure",type:"POST",dataType:"text",data:requestData,success:function _anon_updateStructureFromServerCallback(structureData){
if(_downloadprocesscancelled)return;
if(!_constructStructureFromString(structureData,'latest',true)){
_anon_updateStructureFromServerErrorCallback();
return};
_laststructureupdate=new Date().getTime();
localStorage.setItem('structureupdated',_laststructureupdate);
localStorage.structure=structureData;
localStorage.structuredate=_laststructureupdate;
if(_structure.region)setRegion(_structure.region);
_structureupdating=false;
_updateLastUpdatedHTML();
if(_barrierdisplaying&&_pageinited){
loadEdition('latest');
_showDiscountPopoverIfNecessary();
hideBarrier()};
if(structureReadyCallback)structureReadyCallback()},error:_anon_updateStructureFromServerErrorCallback})}
function _updateMarketsDataFromServer(dataReadyCallback){
if(typeof (dataReadyCallback)=='undefined')dataReadyCallback=false;
if(!dataReadyCallback&&(_structureupdating||_articlesupdating||_imagesupdating||_marketsdataupdating))return;
_marketsdataupdating=true
function _updateMarketsDataFromServerError(){
_marketsdataupdating=false;
_updateLastUpdatedHTML();
if(dataReadyCallback)dataReadyCallback()};
Assanka.$.ajax({url:sourceURL+'marketsdata/',cache:false,dataType:'text',data:{v:2},success:function _anon_updateMarketsDataFromServerCallback(encodedMarketsData){
if(_downloadprocesscancelled)return;
var parseSuccess=_constructMarketsDataFromString(encodedMarketsData,true,true);
if(!parseSuccess)return _updateMarketsDataFromServerError();
_marketsdataupdating=false;
_updateLastUpdatedHTML();
if(dataReadyCallback)dataReadyCallback()},error:_updateMarketsDataFromServerError})}
function _calculateFetchList(storyListToProcess){
if(_inWrapper||_articlesupdating)return;
_articlesupdating=true;
_articlestofetch=1;
_articlesfetched=0;
_updateLastUpdatedHTML();
var idstofetch={},subsequentidstofetch={};
for(var storyid in storyListToProcess)if(storyListToProcess[storyid].fetch){
idstofetch[storyid]=true}
else if(_bigdatabasemode)subsequentidstofetch[storyid]=true;
if(_bigdatabasemode)for(var storyid in subsequentidstofetch)idstofetch[storyid]=true;
_localdb.getArticleList(function _anon_getArticleListCallback(tx,rs){
if(_downloadprocesscancelled)return;
for(var i=0;i<rs.rows.length;i++){
var storyid=String(rs.rows.item(i).id);
if(idstofetch[storyid])delete idstofetch[storyid]};
if(Object.keys){
idstofetch=Object.keys(idstofetch)}
else{
var idkeys=[];
for(var i in idstofetch)idkeys.push(i);
idstofetch=idkeys};
_articlestofetch=idstofetch.length;
var processingLastIterationTime=new Date().getTime(),processingBatchSize=20,processingFirstIteration=true,processingFunction=function _anon_articleListProcessingCallback(){
if(!idstofetch.length){
_articlesupdating=false;
if(_bigdatabasemode&&!_disableImages){
_calculateImageFetchList(storyListToProcess)}
else{
_updateMarketsDataFromServer();
_updateLastUpdatedHTML()};
return};
_articlesfetched=_articlestofetch-idstofetch.length;
_updateLastUpdatedHTML();
if(processingFirstIteration){
processingFirstIteration=false}
else{
var curTime=new Date().getTime();
if(curTime-processingLastIterationTime<5000){
processingBatchSize*=2}
else if(curTime-processingLastIterationTime>15000)processingBatchSize=Math.ceil(processingBatchSize/2);
processingBatchSize=Math.max(10,Math.min(100,processingBatchSize));
processingLastIterationTime=curTime};
var storiesToFetch=idstofetch.splice(0,processingBatchSize);
_fetchbatch(storiesToFetch.join(','),processingFunction)};
processingFunction()})}
function _fetchbatch(getargs,callback){
if(_inWrapper||_downloadprocesscancelled)return;
var fetchBatchErrorHandler=function _anon_articleFetchBackErrorCallback(){
console.log("ajax fetch article request failed");
if(callback)callback()};
Assanka.$.ajax({url:sourceURL+"articles?v=2&artids="+getargs,dataType:'json',success:function _anon_articleFetchSuccessCallback(articles){
if(_downloadprocesscancelled)return;
if(!articles)return fetchBatchErrorHandler();
_localdb.insertArticles(articles,function _anon_successCallback(){
if(callback)callback()},fetchBatchErrorHandler)},error:fetchBatchErrorHandler})}
function _calculateImageFetchList(storyListToProcess){
if(_downloadprocesscancelled)return;
_imagesupdating=true;
_imagestofetch=1;
_imagesfetched=0;
_updateLastUpdatedHTML();
var imagestofetch={},additionalimagestofetch=[];
for(var skylineid in _structure.skyline)imagestofetch[_structure.skyline[skylineid].linkid+'.skyline']=true;
for(var storyid in storyListToProcess){
var storydetails=storyListToProcess[storyid];
if('img' in storydetails)imagestofetch[storyid]=true;
if('bigimg' in storydetails)additionalimagestofetch.push(storyid+'.large');
if('fullimg' in storydetails)additionalimagestofetch.push(storyid+'.full')};
for(var videoid in _structure.video.videos)imagestofetch[videoid+'.video']=true;
for(var addid in additionalimagestofetch)imagestofetch[additionalimagestofetch[addid]]=true;
_localdb.getImageList(function _anon_getImagesListCallback(tx,rs){
if(_downloadprocesscancelled)return;
var imagestodelete=[];
for(var i=0;i<rs.rows.length;i++){
var imageid=String(rs.rows.item(i).id);
if(imagestofetch[imageid]){
delete imagestofetch[imageid]}
else imagestodelete.push(imageid)};
if(imagestodelete.length)_localdb.removeImages(imagestodelete);
if(Object.keys){
imagestofetch=Object.keys(imagestofetch)}
else{
var imagekeys=[];
for(var i in imagestofetch)imagekeys.push(i);
imagestofetch=imagekeys};
_imagestofetch=imagestofetch.length;
var processingLastIterationTime=new Date().getTime(),processingBatchSize=15,processingFirstIteration=true,processingFunction=function _anon_imageListProcessingCallback(){
if(!imagestofetch.length){
_imagesupdating=false;
_updateMarketsDataFromServer();
_updateLastUpdatedHTML();
return};
_imagesfetched=_imagestofetch-imagestofetch.length;
_updateLastUpdatedHTML();
if(processingFirstIteration){
processingFirstIteration=false}
else{
var curTime=new Date().getTime();
if(curTime-processingLastIterationTime<5000){
processingBatchSize*=2}
else if(curTime-processingLastIterationTime>15000)processingBatchSize=Math.ceil(processingBatchSize/2);
processingBatchSize=Math.max(10,Math.min(30,processingBatchSize));
processingLastIterationTime=curTime};
var iterationImagesToFetch=imagestofetch.splice(0,processingBatchSize);
_fetchImageBatch(iterationImagesToFetch.join(','),processingFunction)};
processingFunction()})}
function _fetchImageBatch(imageidlist,callback){
if(_downloadprocesscancelled)return;
var fetchImageBatchErrorHandler=function _anon_imageFetchBatchErrorCallback(){
console.log("ajax fetch image request failed");
if(callback)callback()};
Assanka.$.ajax({url:sourceURL+'articleimages',data:{id:imageidlist},dataType:'json',success:function _anon_imageFetchSuccessCallback(images){
if(_downloadprocesscancelled)return;
if(!images)return fetchImageBatchErrorHandler();
_localdb.insertImages(images,function _anon_successCallback(){
if(callback)callback()},fetchImageBatchErrorHandler)},error:fetchImageBatchErrorHandler})}
function cancelDownloadProcess(){
_downloadprocesscancelled=true;
_structureupdating=false;
_marketsdataupdating=false;
_articlesupdating=false;
_imagesupdating=false;
_updateLastUpdatedHTML()};
mFT.cancelDownloadProcess=cancelDownloadProcess
function _waitGetStruct(callbackFunction){
if(typeof (callbackFunction)=='undefined')callbackFunction=false;
_structureupdating=true;
_waitgetstructactive=true;
if(_waitgetstructtimer){
clearTimeout(_waitgetstructtimer);
_waitgetstructtimer=false};
_updateLastUpdatedHTML();
var structureData='';
structureData+=window.appBridge.readData();
if(structureData=='NULL'||structureData==''){
_waitgetstructtimer=setTimeout(function _anon_delayedWaitGetStructCall(){
_waitGetStruct(callbackFunction)},1000)}
else{
_laststructureupdate=parseInt(window.appBridge.structureDate());
localStorage.setItem('structureupdated',_laststructureupdate);
_constructStructureFromString(structureData,'latest',true);
localStorage.structure=structureData;
localStorage.structuredate=_laststructureupdate;
_structureupdating=false;
_waitgetstructactive=false;
_updateLastUpdatedHTML();
if(_barrierdisplaying&&_pageinited){
_eleWithId('splashloadtext').innerHTML='';
hideBarrier(3)};
if(callbackFunction)callbackFunction()}}
function _updateStructureProgress(){
var currentTimestamp=new Date().getTime();
if(!_initialstructurecancancel&&(currentTimestamp-_initialstructurestarttime)>15000)if(_laststructureupdate){
_initialstructurecancancel=true;
_eleWithId('splashloadtext').innerHTML='<span class="warning"></span>You are on a slow connection, continue to download or press to load last saved version';
_eleWithId('hidebarrierbuttontext').innerHTML='Load saved version <span class="updatedate">'+_formatUpdateDate(_laststructureupdate)+'</span>';
hideBarrier(30)}
else{
_initialstructurecancancel=true;
_eleWithId('splashloadtext').innerHTML='<span class="warning"></span>You are on a slow connection, but no previous edition is available. Please wait...'}}
function appBridgeNotification(notification){
var var1=false;
notification=notification.replace(', ',',');
var notificationargs=notification.split(','),notificationname=notificationargs.shift();
if(notificationargs.length)var1=notificationargs[0];
switch(notificationname){case"app_pause":_structureupdating=false;
_articlesupdating=false;
_updateLastUpdatedHTML();
if(_floatingAdvertTimer)floatAdvert('outnow');
_wrapperInBackground=true;
break;case"app_resume":_wrapperInBackground=false;
if(document.body.scrollTop)window.scrollTo(0,0);
if(_updateftuseronnextload){
_updateSubscription();
_updateftuseronnextload=false};
_checkStructureUpdateOnStartup();
_checkResourcesVersion();
break;case"button_back":if(_popoverShowing||_sectionSelectorOpen){
hidePopover();
hideSectionSelector();
return};
if(parseInt(var1)){
goBack()}
else window.appBridge.moveTaskToBack();
break;case"button_search":if(document.querySelector('#popover .searchform')){
hidePopover();
hideSectionSelector();
return};
showSectionSelector();
searchDisplay(document.querySelector('#sectionselector .searchbutton'));
break;case"ds_defer":if(_barrierdisplaying){
_eleWithId('splashloadtext').innerHTML='Update deferred due to internet settings';
hideBarrier(2)};
if(_waitgetstructtimer){
clearTimeout(_waitgetstructtimer);
_waitgetstructtimer=false};
_articlesupdating=false;
_structureupdating=false;
_waitgetstructactive=false;
_updateLastUpdatedHTML();
break;case"ds_start":if(_barrierdisplaying)_eleWithId('splashloadtext').innerHTML='Updating latest news';
break;case"ds_in_progress":break;case"ds_struct_start":_structureupdating=true;
if(_barrierdisplaying)_eleWithId('splashloadtext').innerHTML='Getting headlines<br />Loading&hellip; If you are not on Wi-Fi this may take a while';
break;case"ds_struct_fin":if(!_waitgetstructactive)if(parseInt(window.appBridge.structureDate())!=_laststructureupdate){
_waitGetStruct()}
else _structureupdating=false;
break;case"ds_art_start":_articlesupdating=true;
_articlesfetched=0;
_articlestofetch=parseInt(var1);
_updateLastUpdatedHTML();
break;case"ds_art_progress":_articlesfetched=parseInt(var1);
_updateLastUpdatedHTML();
break;case"ds_art_fin":_structureupdating=false;
_articlesupdating=false;
_updateLastUpdatedHTML();
break;case"ds_fin":if(_structureupdating){
_structureupdating=false;
_articlesupdating=false;
_updateLastUpdatedHTML()};
break;case"ds_err":if(_waitgetstructtimer){
clearTimeout(_waitgetstructtimer);
_waitgetstructtimer=false};
_waitgetstructactive=false;
_structureupdating=false;
_articlesupdating=false;
_updateLastUpdatedHTML();
if(_barrierdisplaying){
_eleWithId('splashloadtext').innerHTML='<span style="color: red;">Update failed!<br />('+(var1?var1:'-1')+')</span>';
hideBarrier(2)};
break;case"authclosed":_ftuser=false;
var storedUserDetails=localStorage.getItem('user');
if(storedUserDetails){
storedUserDetails=JSON.parse(storedUserDetails);
if(storedUserDetails)_ftuser=storedUserDetails};
if(_ftuser){
_updateSubscription();
window.appBridge.setSignedIn()}
else{
localStorage.removeItem('portfoliodetails');
_storePortfolioSummary();
window.appBridge.setSignedOut()};
loadPage(_currentPageAnchor);
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false;
break;case"transition_ended":break;default:console.log("Unhandled app bridge notification: '"+notificationname+"' received");
break}};
mFT.appBridgeNotification=appBridgeNotification
function setDataToSend(){
if(!_inWrapper||_inFragment)return;
var d={};
d.user=_ftuser;
window.appBridge.setDataToSend(JSON.stringify(d))};
mFT.setDataToSend=setDataToSend
function _checkResourcesVersion(){
var structureResourcesVersion=_structure.resourcesversion?parseFloat(_structure.resourcesversion):0;
if(!_inWrapper||resourcesVersion==structureResourcesVersion||!structureResourcesVersion)return;
Assanka.$.ajax({url:sourceURL+'onlinecheck',dataType:'json',success:function(isonlinecheck){
if(isonlinecheck&&isonlinecheck.success&&isonlinecheck.isonline){
document.querySelector('#splash .standalonebutton').style.display='none';
document.body.className+=' structureloading';
var structureProcessedFunction=function(){
window.appBridge.clearCache()};
if(structureResourcesVersion<resourcesVersion){
window.appBridge.updateData();
if(_waitgetstructactive){
window.setTimeout(structureProcessedFunction,5000)}
else _waitGetStruct(structureProcessedFunction)}
else structureProcessedFunction()}}})}
function loadHome(){
var homePageCategoryID=_structure.homepages[_currentregion];
if(!homePageCategoryID)homePageCategoryID=_structure.homepages['uk'];
var sectionScrollPosition=0;
if(_wrapperUsesGallery||!_screenColumns.center.pageType||_screenColumns.center.pageType=='home'){
_buildSectionPage(homePageCategoryID,'center');
updateContentHeight();
_addHistoryEntry('home');
doAdverts('home','home')}
else{
var targetpane='left';
if(_screenColumns.center.pageType=='content'||_screenColumns.center.pageType=='portfolio'){
var _sectionScrollLength=_sectionScrollPositions.length;
if(_sectionScrollLength&&_sectionScrollPositions[_sectionScrollLength-1].id==homePageCategoryID)sectionScrollPosition=_sectionScrollPositions[_sectionScrollLength-1].y};
var centerColumnKey=_getPrimaryContentKeyForCenterPage();
if(centerColumnKey){
var homeIndex=_primarynavlookup[homePageCategoryID],curIndex=_primarynavlookup[centerColumnKey];
if(curIndex==_sortedprimarynav.length-1&&homeIndex==0&&(!_sectionSelectorOpen||_sectionSelectorClosing)){
targetpane='right'}
else if(homeIndex>curIndex)targetpane='right'};
if(_screenColumns[targetpane].pageType!='home'||_screenColumns[targetpane].genBaseTime<_laststructureupdate)_buildSectionPage(homePageCategoryID,targetpane);
if(_preloadcontentmode)return;
if(sectionScrollPosition){
_restoreScrollPositionInColumn(-sectionScrollPosition,targetpane);
window.setTimeout(function(){
_slideView(targetpane)},10)}
else _slideView(targetpane);
_addHistoryEntry('home')};
if(!_preloadcontentmode)_currentcategory=_structure.homepages[_currentregion]};
mFT.loadHome=loadHome
function _insertHomePageSkyline(homepagesectionid,headerelement){
var headerhtml='<div class="headertitle" onclick="mFT.showSectionSelector()"><div><img class="masthead-main" src="/lib/img/masthead_main.gif" /><h2>Financial Times</h2><h1><span>FT</span> Weekend</h1></div></div></div>';
headerhtml+='<div class="headerbuttons"><div onclick="mFT.showSectionSelector()" class="sectionbutton"><div><span>Menu</span></div></div></div>';
if(_screensizemode!='small'||!_structure.weekend){
headerhtml+='<div class="skyline"><div class="skyline-inner uses3d">';
for(i=0;i<2;i++){
var skyline=_structure.skyline[i];
if(!skyline)continue;
headerhtml+='<div class="skylineitem-'+i+'" onclick="mFT.router.loadArticle('+skyline.linkid+', false, '+homepagesectionid+')"><h3><span class="imageloading articlethumb" data-id="'+skyline.linkid+'.skyline"></span><strong>'+skyline.title+'</strong><br />'+skyline.snip+'</h3></div>'};
if(_screensizemode!='small'&&_screensizemode!='medium')window.setTimeout(function(){
_requestHomePageSkylineMarketsData()},10);
headerhtml+='</div></div>'};
var regiontext=_regionlist[_currentregion],editiontext='HTML app';
if(_isAndroid){
editiontext='Android'}
else if(_isiOS)if(_userAgentString.search('ipad')>-1){
editiontext='iPad'}
else if(_userAgentString.search('iphone')>-1){
editiontext='iPhone'}
else editiontext='iOS';
headerhtml+='<div class="location-edition">'+regiontext+' '+editiontext+' edition</div>';
headerelement.className+=' homepageheaderbar';
headerelement.innerHTML=headerhtml}
function _requestHomePageSkylineMarketsData(){
Assanka.$.ajax({url:sourceURL+'topmarkets',dataType:'json',cache:false,success:function _anon_skylineMarketsDataSuccessCallback(marketsData){
if(!marketsData||!marketsData.length)return;
var o='';
for(var i=0;i<marketsData.length;i++){
var marketDetails=marketsData[i];
o+='<div class="marketdata"><h3><strong>'+marketsData[i].title+'</strong><br />'+marketsData[i].closesText+'<div class="valuesummary">'+marketsData[i].changeHTML+'</div></h3></div>'};
Array.prototype.forEach.call(document.querySelectorAll('.skyline-inner'),function(skyline){
var renderdiv=document.createElement('DIV');
renderdiv.innerHTML=o;
while(renderdiv.firstChild)skyline.appendChild(renderdiv.firstChild)})}})}
function _buildWeekendHighlights(){
var ophtml='<h1>Weekend highlights</h1>';
for(i=0;i<4;i++){
var highlight=_structure.weekendhighlights[i];
if(!highlight)continue;
ophtml+='<div class="skylineitem-'+i+' highlight" onclick="mFT.router.loadArticle('+highlight.linkid+')"><div class="thumb" '+((i==1||i==3)?'style="float:right;"':'')+'><span class="imageloading articlethumb" data-id="'+highlight.linkid+'.highlight"></span></div><h4>'+highlight.title+'</h4><p>'+highlight.snip+'</p></div>'};
return ophtml}
function _hasHomePageChanged(oldstructure,newstructure){
if(!oldstructure)return true;
var homePageCategoryID=_structure.homepages[_currentregion];
if(!homePageCategoryID)homePageCategoryID=_structure.homepages['uk'];
if(!areObjectsEqual(newstructure.skyline,oldstructure.skyline))return true;
if(!areObjectsEqual(newstructure.categories[homePageCategoryID].cids,oldstructure.categories[homePageCategoryID].cids))return true;
if(_screensizemode!='small'&&_screensizemode!='medium')if(newstructure.homepagedetails&&newstructure.homepagedetails.toprail)if(!areObjectsEqual(newstructure.homepagedetails.toprail,oldstructure.homepagedetails.toprail))return true;
return false}
function floatTip(device){
var tipDiv=document.getElementById('homescreentip');
if(tipDiv)tipDiv.parentNode.removeChild(tipDiv);
if(!device)device=/iPad|iPhone/.exec(navigator.userAgent);
setTimeout(function(){
tipDiv=document.createElement('div');
tipDiv.id='homescreentip';
tipDiv.innerHTML='<div class="close">&times;</div><div class="message"><p>To get full offline access to the FT Web App straight from your home screen, tap the button '+(device=='iPad'?'above':'below')+' and click <strong>\'Add to Home Screen\'</strong></p></div>';
tipDiv.querySelector('.close').onclick=function(){
tipDiv.parentNode.removeChild(tipDiv);
showSystemMessage('never-added-to-homescreen-message');
window.removeEventListener('orientationchange',positionTip,false);
window.removeEventListener('scroll',positionTip,false);
window.removeEventListener('webkitTransitionEnd',positionTip,false)};
_eleWithId('columnscontainer').appendChild(tipDiv);
window.addEventListener('orientationchange',positionTip,false);
window.addEventListener('scroll',positionTip,false);
window.addEventListener('webkitTransitionEnd',positionTip,false);
positionTip()},500)};
mFT.floatTip=floatTip
function positionTip(){
var tipDiv=_eleWithId('homescreentip');
if(!tipDiv)return;
if(navigator.userAgent.indexOf('iPad')!=-1){
tipDiv.style.top=(window.scrollY-16)+'px'}
else{
tipDiv.style.left=(Math.abs(window.orientation)==90)?'91px':'11px';
tipDiv.style.top=(window.scrollY+window.innerHeight-tipDiv.clientHeight+16)+'px'}}
function loadSection(linkitem){
if(typeof linkitem=='object'){
var sectionid=linkitem.getAttribute('data-id')}
else var sectionid=linkitem;
if(!_structure.categories[sectionid]){
alert('Sorry, but the section you tried to load could not be found.\n(Section '+sectionid+')');
loadHome();
return};
var sectionScrollPosition=0,currentPageType=_screenColumns.center.pageType,targetColumn='right';
if(_wrapperUsesGallery||!currentPageType){
targetColumn='center'}
else if(currentPageType=='content'||currentPageType=='account'||currentPageType=='portfolio'){
targetColumn='left';
var _sectionScrollLength=_sectionScrollPositions.length;
if(_sectionScrollLength&&_sectionScrollPositions[_sectionScrollLength-1].id==sectionid)sectionScrollPosition=_sectionScrollPositions[_sectionScrollLength-1].y}
else{
var processPrimaryNav=true,newPID=sectionid;
if(currentPageType=='section'){
var oldSectionID=_screenColumns.center.pageIdentifier,oldPID=oldSectionID;
if(oldSectionID==sectionid){
targetColumn='center';
processPrimaryNav=false}
else{
var catList=_structure.categories;
if(catList[sectionid].pid&&catList[sectionid].pid==catList[oldSectionID].pid){
targetColumn='center';
processPrimaryNav=false}
else{
while(catList[newPID].pid)newPID=catList[newPID].pid;
if(newPID==oldPID){
targetColumn='center';
processPrimaryNav=false}
else while(catList[oldPID].pid&&catList[oldPID].pid in catList){
oldPID=catList[oldPID].pid;
if(oldPID==sectionid){
targetColumn='center';
processPrimaryNav=false;
break}}}}};
if(processPrimaryNav){
var centerColumnKey=_getPrimaryContentKeyForCenterPage();
if(centerColumnKey){
var sectionIndex=_primarynavlookup[newPID],curIndex=_primarynavlookup[centerColumnKey];
if(curIndex==0&&sectionIndex==_sortedprimarynav.length-1&&(!_sectionSelectorOpen||_sectionSelectorClosing)){
targetColumn='left'}
else if(sectionIndex<curIndex)targetColumn='left'}}};
if(targetColumn=='center'||_screenColumns[targetColumn].pageType!='section'||_screenColumns[targetColumn].pageIdentifier!=sectionid||_screenColumns[targetColumn].genBaseTime<_laststructureupdate)_buildSectionPage(sectionid,targetColumn);
if(_preloadcontentmode)return;
if(targetColumn!='center'){
if(sectionScrollPosition){
_restoreScrollPositionInColumn(-sectionScrollPosition,targetColumn);
window.setTimeout(function(){
_slideView(targetColumn)},10)}
else _slideView(targetColumn)}
else{
updateContentHeight();
doAdverts('ros','section')};
_currentcategory=sectionid;
_addHistoryEntry('category',sectionid)};
mFT.loadSection=loadSection
function updatePaginatedSectionNavigator(container,listPageIndicator,previousButton,nextButton,titleArea,xofyArea,sectionID,topSectionID){
if(typeof listPageIndicator=='undefined')listPageIndicator=1;
if(typeof previousButton=='undefined')previousButton=false;
if(typeof nextButton=='undefined')nextButton=false;
if(typeof titleArea=='undefined')titleArea=false;
if(typeof sectionID=='undefined')sectionID=_screenColumns.center.pageIdentifier;
if(typeof topSectionID=='undefined')topSectionID=_screenColumns.center.pageIdentifier;
var sourcedatakey=container.getAttribute('data-key'),sourcedataindex=container.getAttribute('data-key-index'),uniqueID=container.getAttribute('data-uid'),itemsPerPage=Math.floor((window.innerWidth+4)/190),itemWidth=Math.floor((window.innerWidth+4-(itemsPerPage*20))/itemsPerPage);
if(typeof (listPageIndicator)=='object'){
var listPage=parseInt(listPageIndicator.getAttribute('data-page'))}
else var listPage=parseInt(listPageIndicator);
var categorydetails=_structure.pcatlist[sectionID];
if(!categorydetails||!categorydetails[sourcedatakey]||!categorydetails[sourcedatakey][sourcedataindex])return'';
var catfeeddata=categorydetails[sourcedatakey][sourcedataindex];
if(catfeeddata.type!='pagedrss'||!catfeeddata.feeds[listPage-1])return'';
var targetsectionid=catfeeddata.feeds[listPage-1],targetsection=_structure.categories[targetsectionid];
if(!targetsection||!targetsection.cids)return'';
var readContentStore=_readcontent[_ftuser?_ftuser.eid:'loggedout'];
if(!readContentStore)readContentStore={};
var o='<ul data-page="'+listPage+'">';
for(var i=0;i<itemsPerPage;i++){
var storyID=targetsection.cids[i];
if(storyID)var theStory=_structure.storylist[storyID];
if(!storyID||!theStory){
o+='<li style="width: '+itemWidth+'px"></li>';
continue};
o+='<li style="width: '+itemWidth+'px" data-id="'+storyID+'" data-cat="'+targetsectionid+'" data-topcat="'+topSectionID+'" onclick="mFT.router.loadArticle(this)"'+(readContentStore[storyID]?' class="read"':'')+'><span class="date">'+_formatDate(theStory.date,false,false)+'</span><h4>'+theStory.title+'</h4><p>'+theStory.snip+'</p></li>'};
o+='</ul>';
if(previousButton)if(listPage<=1){
previousButton.onclick=null;
previousButton.className=previousButton.className+' disabled'}
else{
previousButton.onclick=function(){
mFT.pageInChildContent('#'+uniqueID+' .navigatorcontentcontainer','slideright','updatePaginatedSectionNavigator',listPage-1,'#'+uniqueID+' .previous','#'+uniqueID+' .next','#'+uniqueID+' .navigatorheader h4','#'+uniqueID+' .x-of-y')};
previousButton.className=previousButton.className.replace(/\b ?disabled\b/g,'')};
if(nextButton)if(listPage>=catfeeddata.feeds.length){
nextButton.onclick=null;
nextButton.className=nextButton.className+' disabled'}
else{
nextButton.onclick=function(){
mFT.pageInChildContent('#'+uniqueID+' .navigatorcontentcontainer','slideleft','updatePaginatedSectionNavigator',listPage+1,'#'+uniqueID+' .previous','#'+uniqueID+' .next','#'+uniqueID+' .navigatorheader h4','#'+uniqueID+' .x-of-y')};
nextButton.className=nextButton.className.replace(/\b ?disabled\b/g,'')};
if(xofyArea)xofyArea.innerHTML=listPage+' of '+Math.ceil(catfeeddata.feeds.length);
if(titleArea)titleArea.innerHTML=(targetsection.name)?targetsection.name:'';
return o};
mFT.updatePaginatedSectionNavigator=updatePaginatedSectionNavigator
function _buildPaginatedSectionNavigator(targetNode,sectionID,targetArea,targetAreaIndex){
var uniqueID='paged'+Math.floor(1000000*Math.random()),newNavigator=document.querySelector('#paginatednavigatortemplate').cloneNode(true);
newNavigator.id=uniqueID;
var contentContainer=newNavigator.querySelector('.navigatorcontentcontainer');
contentContainer.setAttribute('data-key',targetArea);
contentContainer.setAttribute('data-key-index',targetAreaIndex);
contentContainer.setAttribute('data-uid',uniqueID);
contentContainer.childNodes[0].innerHTML=updatePaginatedSectionNavigator(contentContainer,1,newNavigator.querySelector('.previous'),newNavigator.querySelector('.next'),newNavigator.querySelector('.navigatorheader h4'),newNavigator.querySelector('.x-of-y'),sectionID,sectionID);
targetNode.innerHTML='';
targetNode.appendChild(newNavigator)}
function _buildTabbedSectionNavigator(targetNode,sectionsList,topSectionID,selectedTab){
var uniqueID='tabbed'+Math.floor(1000000*Math.random()),o='<div class="navigatorheader"><ul class="tabs" data-parentid="'+uniqueID+'" data-top="'+topSectionID+'" data-list="['+sectionsList.join(',')+']">',tabNum=1;
Array.prototype.forEach.call(sectionsList,function(sectionID){
var sectionDetails=_structure.categories[sectionID];
if(!sectionDetails)return;
o+='<li'+(selectedTab==tabNum?' class="active"':'')+' onclick="mFT.rebuildTabbedSectionNavigator(this)" data-num="'+tabNum+'">'+sectionDetails.name+'</li>';
tabNum++});
o+='</ul></div>';
o+='<div class="navigatorcontent">';
o+='<button class="previous disabled" id="previoussub'+uniqueID+'"><div class="arrow">&nbsp;</div></button>';
o+='<button class="next disabled" id="nextsub'+uniqueID+'"><div class="arrow">&nbsp;</div></button>';
o+='<div class="navigatorcontentcontainer" id="sub'+uniqueID+'" data-uid="sub'+uniqueID+'" data-startitem="1" data-sectionid="'+sectionsList[selectedTab-1]+'" data-topid="'+topSectionID+'"><div class="uses3d">';
o+='</div></div></div>';
var navigatorDiv=document.createElement('DIV');
navigatorDiv.id=uniqueID;
navigatorDiv.className='contentnavigator tabbednavigator';
navigatorDiv.innerHTML=o;
var contentContainer=navigatorDiv.querySelector('.navigatorcontentcontainer');
contentContainer.childNodes[0].innerHTML=updateTabbedSectionNavigatorPage(contentContainer,1,navigatorDiv.querySelector('.previous'),navigatorDiv.querySelector('.next'));
targetNode.innerHTML='';
targetNode.appendChild(navigatorDiv)}
function updateTabbedSectionNavigatorPage(container,listPageIndicator,previousButton,nextButton,titleArea,xofyArea,sectionID,topSectionID){
if(typeof listPageIndicator=='undefined')listPageIndicator=1;
if(typeof previousButton=='undefined')previousButton=false;
if(typeof nextButton=='undefined')nextButton=false;
var uniqueID=container.getAttribute('data-uid'),sectionID=container.getAttribute('data-sectionid'),topSectionID=container.getAttribute('data-topid'),itemsPerPage=Math.floor((window.innerWidth-123)/190),itemWidth=Math.floor((window.innerWidth-123-(itemsPerPage*20))/itemsPerPage);
if(typeof (listPageIndicator)=='object'){
var previousFirstItem=listPageIndicator.getAttribute('data-startitem'),listPage=Math.floor(previousFirstItem/itemsPerPage)+1}
else var listPage=parseInt(listPageIndicator);
var o='<ul class="pageablecontent" data-startitem="'+(itemsPerPage*(listPage-1)+1)+'">',sectionDetails=_structure.categories[sectionID],readContentStore=_readcontent[_ftuser?_ftuser.eid:'loggedout'];
if(!readContentStore)readContentStore={};
if(sectionDetails)for(var i=(listPage-1)*itemsPerPage;i<listPage*itemsPerPage;i++){
var storyID=sectionDetails.cids[i];
if(storyID)var theStory=_structure.storylist[storyID];
if(!storyID||!theStory){
o+='<li style="width: '+itemWidth+'px"></li>';
continue};
o+='<li style="width: '+itemWidth+'px" data-id="'+storyID+'" data-cat="'+sectionID+'" data-topcat="'+topSectionID+'" onclick="mFT.router.loadArticle(this)"'+(readContentStore[storyID]?' class="read"':'')+'><h4>'+theStory.title+'</h4><p>'+theStory.snip+'</p></li>'};
o+='</ul>';
if(previousButton)if(listPage<=1){
previousButton.onclick=null;
previousButton.className=previousButton.className+' disabled'}
else{
previousButton.onclick=function(){
mFT.pageInChildContent('#'+uniqueID,'slideright','updateTabbedSectionNavigatorPage',listPage-1,'#previous'+uniqueID,'#next'+uniqueID)};
previousButton.className=previousButton.className.replace(/\b ?disabled\b/g,'')};
if(nextButton)if(!sectionDetails||listPage*itemsPerPage>=sectionDetails.cids.length){
nextButton.onclick=null;
nextButton.className=nextButton.className+' disabled'}
else{
nextButton.onclick=function(){
mFT.pageInChildContent('#'+uniqueID,'slideleft','updateTabbedSectionNavigatorPage',listPage+1,'#previous'+uniqueID,'#next'+uniqueID)};
nextButton.className=nextButton.className.replace(/\b ?disabled\b/g,'')};
return o};
mFT.updateTabbedSectionNavigatorPage=updateTabbedSectionNavigatorPage
function rebuildTabbedSectionNavigator(element){
var parentElement=element.parentNode,containerNode=document.querySelector('#'+parentElement.getAttribute('data-parentID')).parentNode;
_buildTabbedSectionNavigator(containerNode,JSON.parse(parentElement.getAttribute('data-list')),parentElement.getAttribute('data-top'),element.getAttribute('data-num'))};
mFT.rebuildTabbedSectionNavigator=rebuildTabbedSectionNavigator
function _buildSectionPage(sectionID,targetview){
var section=_structure.categories[sectionID],useReducedLayout=(_screensizemode=='small'||_screensizemode=='medium');
siteMapTerm=section.name;
var newPage=_eleWithId('sectiontemplate').cloneNode(true);
newPage.id=null;
newPage.className+=" section"+section.name.toLowerCase().substring(0,4)+(_structure.weekend?' weekendsection':'');
var categorydetails=_structure.pcatlist[section.is_front?0:sectionID]||{};
if(categorydetails.reverse)newPage.className+=' reverse';
var hideTopContent=(!useReducedLayout&&categorydetails.hidecontent=='top');
if(hideTopContent)newPage.querySelector('.sectionabovemidriff').style.display='none';
var hideBottomContent=(categorydetails.hidecontent=='bottom');
if(hideBottomContent)newPage.querySelector('.sectionbelowmidriff').style.display='none';
var contentCount=(categorydetails.contentcount)?categorydetails.contentcount:10,topSectionID=sectionID,topSection=section;
while(topSection.pid&&topSection.pid in _structure.categories){
topSectionID=topSection.pid;
topSection=_structure.categories[topSectionID]};
newPage.querySelector('.sectiontitle').innerHTML=topSection.name;
var readContentStore=_readcontent[_ftuser?_ftuser.eid:'loggedout'];
if(!readContentStore)readContentStore={};
if(categorydetails.customheader)switch(categorydetails.customheader){case'homepageskyline':_insertHomePageSkyline(sectionID,newPage.querySelector('.headerbar'));
break;case'lifeandarts':newPage.querySelector('.headertitle').innerHTML='<div class="weekend-page"><h2><span>FT</span> Weekend</h2><h1>Life & Arts</h1></div>';
break;case'houseandhome':newPage.querySelector('.headertitle').innerHTML='<div class="weekend-page"><h2><span>FT</span> Weekend</h2><h1>House & Home</h1></div>';
break;case'magazine':newPage.querySelector('.headertitle').innerHTML='<div class="weekend-page"><h2><span>FT</span> Weekend</h2><h1>Magazine</h1></div>';
break};
if(useReducedLayout&&topSection.sub&&!topSection.is_home){
var idtohighlight=section.pid?sectionID:topSectionID,subsectionshtml='<li onclick="mFT.router.loadSection(this)" data-id="'+topSectionID+'" '+((topSectionID==idtohighlight)?'class="active"':'')+'><p>Top stories</p></li>';
for(var i in topSection.sub){
var subSectionID=topSection.sub[i],subSection=_structure.categories[subSectionID];
if(!subSection)continue;
subsectionshtml+='<li onclick="mFT.router.loadSection(this)" data-id="'+subSectionID+'" '+((subSectionID==idtohighlight)?'class="active"':'')+'><p>'+subSection.name+'</p></li>'};
newPage.querySelector('.sectionsubsections').innerHTML=subsectionshtml}
else newPage.querySelector('.sectionsubsectioncontainer').style.display='none';
var featuredarticleid=false,featuredarticle=false;
if(useReducedLayout&&categorydetails.reducedfeature)categorydetails.feature=categorydetails.reducedfeature;
if(categorydetails.feature){
var featureimagekey=(categorydetails.feature=='full')?'fullimg':'bigimg';
for(var i in section.cids){
var theStory=_structure.storylist[section.cids[i]];
if(theStory&&theStory[featureimagekey]){
featuredarticleid=section.cids[i];
featuredarticle=theStory;
break}}};
if(featuredarticle){
var isfullfeature=(categorydetails.feature=='full'||useReducedLayout),featurehtml='<div class="feature'+(isfullfeature?' fullfeature':'')+(hideTopContent?'':' bottomborder')+(readContentStore[featuredarticleid]?' read':'')+'" data-id="'+featuredarticleid+'" data-cat="'+sectionID+'" data-topcat="'+sectionID+'" onclick="mFT.router.loadArticle(this)">';
if(!_disableImages){
featurehtml+='<div class="hero resizeheight imageloading '+((categorydetails.feature=='full')?'fullimage':'largeimage')+'" data-id="'+featuredarticleid+((categorydetails.feature=='full')?'.full':'.large')+'"';
if(categorydetails.feature=='full')featurehtml+=' style="width: 100%; height: '+Math.ceil(((window.innerWidth-20)/748)*300)+'px;" data-widthmod="20" data-sizeratio="0.4011"';
featurehtml+='></div>'};
if(!isfullfeature){
var headshot=featuredarticle.byline.replace(/[\s|By]/ig,'').toLowerCase();
featurehtml+='<div class="author"><span class="headshot '+headshot+'"></span>'+featuredarticle.byline+'<span class="date">'+_formatDate(featuredarticle.date,false,useReducedLayout)+'</span></div>'};
featurehtml+='<h1>'+featuredarticle.title+'</h1><h2>'+featuredarticle.snip+'</h2></div>';
newPage.querySelector('.featurecontainer').innerHTML=featurehtml;
contentCount--};
var contenthtmls={top:'',bottom:''},contentkey=hideTopContent?'bottom':'top',articlecount=0,removefollowingborder=!!featuredarticle;
for(var i in section.cids){
var storyID=section.cids[i],theStory=_structure.storylist[storyID];
if(!theStory||storyID==featuredarticleid)continue;
var secondaryimage='';
if(theStory.img&&!_disableImages)secondaryimage='<span class="imageloading smallimage" data-id="'+storyID+'"></span>';
var dateString='<span class="date">'+_formatDate(theStory.date,false,useReducedLayout)+'</span>';
contenthtmls[contentkey]+='<li data-id="'+storyID+'" data-cat="'+sectionID+'" data-topcat="'+sectionID+'" onclick="mFT.router.loadArticle(this)" class="'+(readContentStore[storyID]?'read':'')+((!articlecount&&!featuredarticle)?' primaryarticle':'')+(removefollowingborder?' followsborder':'')+'">'+(!useReducedLayout?dateString:'')+'<h4>'+theStory.title+'</h4><p>'+secondaryimage+theStory.snip+(useReducedLayout?' '+dateString:'')+'</p></li>';
articlecount++;
removefollowingborder=false;
if(useReducedLayout)switch(articlecount){case 2:case 8:if(_disableAdverts)break;
contenthtmls[contentkey]+='<li class="followsborder dfpadwrapper">'+_getReducedLayoutSectionAdvert(((articlecount==2)?'banlb':'banlb2'))+'</li>';
removefollowingborder=true;
break;case 3:if(categorydetails.reducedtopmidriff){
contenthtmls[contentkey]+='<li class="followsborder reducedtopmidriff"></li>';
removefollowingborder=true};
break;case 5:if(categorydetails.reducedmidriff){
_buildMidriffOrAnklet(sectionID,categorydetails.reducedmidriff,'midriff',newPage);
removefollowingborder=true};
break};
if(!hideBottomContent&&articlecount>=(useReducedLayout?5:_structure.sectionpremidriffcount))contentkey='bottom';
if(articlecount>=contentCount)break};
if(useReducedLayout&&articlecount>=4&&articlecount<=7)contenthtmls[contentkey]+=_getReducedLayoutSectionAdvert('banlb');
if(useReducedLayout)if(categorydetails.reducedanklet){
_buildMidriffOrAnklet(sectionID,categorydetails.reducedanklet,'anklet',newPage)}
else _buildMidriffOrAnklet(sectionID,[{type:'subsections'}],'anklet',newPage);
newPage.querySelector('.sectionabovemidriff .sectioncontentlist').innerHTML=contenthtmls.top;
newPage.querySelector('.sectionbelowmidriff .sectioncontentlist').innerHTML=contenthtmls.bottom;
if(categorydetails.reducedtopmidriff)_buildMidriffOrAnklet(sectionID,categorydetails.reducedtopmidriff,'reducedtopmidriff',newPage);
if(!useReducedLayout){
var rails=['toprail','bottomrail'];
Array.prototype.forEach.call(rails,function(railname){
var railhtml='';
if(railname=='toprail'^hideTopContent)railhtml+='<div class="last-updated uses3d standalonebutton">'+_getLastUpdatedHTML()+'</div>';
if(categorydetails[railname])railhtml+=_buildRail(categorydetails[railname],sectionID);
if(railhtml){
newPage.querySelector('.'+railname+'content').innerHTML=railhtml;
var mmTable=newPage.querySelector('.'+railname+'content .sectionmarketsdata');
if(mmTable){
var mmUniqueID='marketmovers'+Math.floor(1000000*Math.random()),moduleHTML=_buildMarketMovers(newPage.querySelector('.sectionmarketsdata .tablerows'),1,newPage.querySelector('.exchanges .previous'),newPage.querySelector('.exchanges .next'),newPage.querySelector('.exchanges .title'),newPage.querySelector('.exchanges .x-of-y'));
if(!moduleHTML)newPage.querySelector('.marketsmoversrailmodule').style.display='none';
mmTable.innerHTML='<div class="tableheading"><div class="columnheading" style="width: 45px">Last</div><div class="columnheading">Today\'s change</div><div class="clear">&nbsp;</div></div><div class="contentswitcher">'+(moduleHTML?moduleHTML:'')+'</div>';
newPage.querySelector('.exchanges .next').onclick=function(){
mFT.pageInChildContent('.sectionmarketsdata .tablerows','slideleft','buildMarketMoversSmall',2,'.exchanges .previous','.exchanges .next','.exchanges .title','.exchanges .x-of-y')}};
var wmZone=newPage.querySelector('.'+railname+'content .worldmarkets');
if(wmZone)_buildWorldMarkets(wmZone)}})}
else newPage.querySelector('.last-updated').innerHTML=_getLastUpdatedHTML();
if(!useReducedLayout&&categorydetails.midriff)_buildMidriffOrAnklet(sectionID,categorydetails.midriff,'midriff',newPage);
if(_enableNavigationHack)newPage.querySelector('.headerbar').style.width=window.innerWidth+'px';
if(!useReducedLayout&&categorydetails.anklet)_buildMidriffOrAnklet(sectionID,categorydetails.anklet,'anklet',newPage);
newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
var targetNode=_eleWithId(_screenColumns[targetview].id);
targetNode.innerHTML='';
targetNode.appendChild(newPage);
if(section.is_front){
_screenColumns[targetview].pageType='home'}
else _screenColumns[targetview].pageType='section';
_screenColumns[targetview].pageIdentifier=sectionID;
_screenColumns[targetview].genBaseTime=_laststructureupdate;
_screenColumns[targetview].preloaded=_preloadcontentmode;
_screenColumns[targetview].disableContentBalance=!!categorydetails.hidecontent;
_loadImagesInElement(targetNode);
if(useReducedLayout&&topSection.sub&&!topSection.is_home){
var subscroller=targetNode.querySelector('.sectionsubsectionscroller');
subscroller.touchscroll=new TouchScroll(subscroller,{elastic:true,scrollbars:false});
_updateSubsectionArrowsWithScroll(subscroller,'selected',false);
subscroller.addEventListener('scrollend',function(){
_updateSubsectionArrowsWithScroll(subscroller,false)},false)};
_respaceSectionPageContent(targetview)}
function _buildMidriffOrAnklet(sectionID,riffDetails,riffName,targetPageElement){
var riffElement=targetPageElement.querySelector('.'+riffName);
for(var riffEntryNumber=0;riffEntryNumber<riffDetails.length;riffEntryNumber++){
var riffItem=riffDetails[riffEntryNumber];
switch(riffItem.type){case'pagedrss':var navcontainer=document.createElement('DIV');
navcontainer.className='paginatedsectionnavcontainer';
_buildPaginatedSectionNavigator(navcontainer,sectionID,riffName,riffEntryNumber);
riffElement.appendChild(navcontainer);
if(riffItem.feeds.length==1)riffElement.querySelector('.pagenav').style.display='none';
break;case'tabbedrss':var navcontainer=document.createElement('DIV');
navcontainer.className='tabbedsectionnavcontainer';
_buildTabbedSectionNavigator(navcontainer,riffItem.feeds,sectionID,1);
riffElement.appendChild(navcontainer);
riffElement.className+=' tabbednavigatorcontentbar';
break;case'homepagevideo':var useReducedLayout=(_screensizemode=='small'||_screensizemode=='medium'),newNavigator=document.querySelector('#paginatednavigatortemplate').cloneNode(true);
newNavigator.id=null;
newNavigator.className+=' videomidriff';
var videoContentContainer=newNavigator.querySelector('.navigatorcontentcontainer > div');
videoContentContainer.parentNode.setAttribute('data-playlistid',riffItem.playlist);
videoContentContainer.innerHTML=buildVideoList(videoContentContainer.parentNode,1,newNavigator.querySelector('.previous'),newNavigator.querySelector('.next'),newNavigator.querySelector('h4'),newNavigator.querySelector('.x-of-y'));
riffElement.appendChild(newNavigator);
break;case'BANLB':var banlbcontainer=document.createElement('DIV');
banlbcontainer.className='banlbcontainer';
banlbcontainer.innerHTML='<div class="BANLB dfpadplaceholder" data-adcontainerid="banlb" data-adclass="banlb" data-adwidth="728" data-adheight="90" data-adcode="home;sz=728x90;pos=banlb;tile=1;ord="><span>&nbsp;</span></div>';
riffElement.appendChild(banlbcontainer);
break;case'homepagemarketsdata':var targetHeight=Math.round((window.innerWidth-14)*0.5556)+'px',marketdatacontainer=document.createElement('DIV');
marketdatacontainer.className='homescreenmarketsdata';
var midriffhtml='<div class="homescreenmarketsdata"><h4>Markets data</h4><div class="macromapwrapper resizeheight" onclick="mFT.router.loadMarketsData();" style="height: '+targetHeight+'" data-widthmod="14" data-sizeratio="0.5556" ><div class="macromapbackgroundcontainer">'+(('marketsmacromapbackground' in localStorage)?'<img src="data:'+localStorage.marketsmacromapbackground+'" />':'')+'</div><div class="macromapforegroundcontainer">'+(('marketsmacromapforeground' in localStorage)?'<img src="data:'+localStorage.marketsmacromapforeground+'" />':'')+'</div></div></div>';
marketdatacontainer.innerHTML=midriffhtml;
riffElement.appendChild(marketdatacontainer);
break;case'Subscription Status':var subscontainer=document.createElement('DIV');
subscontainer.className='subscriptionbuttoncontainer';
subscontainer.innerHTML=_getSubscriptionStatusButton();
riffElement.appendChild(subscontainer);
break;case'Action Buttons':var abcontainer=document.createElement('DIV');
abcontainer.className='actionbuttonscontainer';
abcontainer.innerHTML=_buildActionButtons();
riffElement.appendChild(abcontainer);
break;case'Weekend Highlights':var highlightscontainer=document.createElement('DIV');
highlightscontainer.className='weekend-highlights';
highlightscontainer.innerHTML=_buildWeekendHighlights();
riffElement.appendChild(highlightscontainer);
break;case'subsections':if(!_structure.categories[sectionID].pid)return;
var childSections=_structure.categories[sectionID].sub;
if(!childSections)return;
var relatedsectionscontainer=document.createElement('DIV');
relatedsectionscontainer.className='relatedsections';
var relatedhtml='<h4>Related sections</h4><ul>';
for(var i in childSections){
var thecat=_structure.categories[childSections[i]];
if(!thecat)continue;
relatedhtml+='<li onclick="mFT.showRelatedSectionsSubsection(this)" data-id="'+childSections[i]+'"><span class="arrow"></span>'+thecat.name+'</li>'};
relatedhtml+='</ul>';
relatedsectionscontainer.innerHTML=relatedhtml;
riffElement.className=riffElement.className.replace(/ ?contentbar ?/,'');
riffElement.appendChild(relatedsectionscontainer);
break;case'Portfolio':var portfoliodiv=document.createElement('DIV');
portfoliodiv.innerHTML=buildPortfolioSummary();
riffElement.appendChild(portfoliodiv);
break}}}
function _buildRail(railDetails,sectionID){
var railhtml='',readContentStore=_readcontent[_ftuser?_ftuser.eid:'loggedout'];
if(!readContentStore)readContentStore={};
for(var iptr=0;iptr<railDetails.length;iptr++){
var moduletype=railDetails[iptr].type;
if(!moduletype)moduletype='rss';
switch(moduletype){case'rss':var i=railDetails[iptr].i,category=_structure.categories[i];
if(!category||!category.cids)continue;
railhtml+='<div class="rss-'+category.name.replace(' ','').toLowerCase()+'"><h4><span class="headshot '+category.name.replace(' ','').toLowerCase()+'"></span>'+category.name+'</h4><ul class="listnav">';
var feeddetails=railDetails[iptr],feedcount=feeddetails.c||1;
for(var j=0;j<feedcount;j++){
var storyID=category.cids[j],story=_structure.storylist[storyID];
if(!story)continue;
if(feeddetails.short){
railhtml+='<li data-id="'+storyID+'" data-cat="'+i+'" data-topcat="'+sectionID+'" onclick="mFT.router.loadArticle(this)" class="short'+(readContentStore[storyID]?' read':'')+'"><h5>'+story.title+'</h5></li>'}
else railhtml+='<li data-id="'+storyID+'" data-cat="'+i+'" data-topcat="'+sectionID+'" onclick="mFT.router.loadArticle(this)"'+(readContentStore[storyID]?' class="read"':'')+'><h5>'+story.title+'</h5><p>'+story.snip+'</p></li>'};
railhtml+='</ul></div>';
break;case'Market movers':railhtml+='<div class="marketsmoversrailmodule"><h4>Market movers</h4><div class="exchange-wrapper sectionexchanges"><div class="exchanges"><div class="titlebar"><div class="title"></div><div class="pagenav uses3d"><button class="previous disabled"><div class="arrow">&nbsp;</div></button><span class="x-of-y"></span><button class="next "><div class="arrow">&nbsp;</div></button></div><div class="clear"></div></div></div><div class="render marketsdata sectionmarketsdata"></div></div></div>';
break;case'Video':if(_disableImages)break;
var playlist=_structure.video.playlists[railDetails[iptr].playlist];
if(playlist){
if(sectionID&&_structure.categories[sectionID]&&_structure.categories[sectionID].name){
railhtml+='<h4>'+_structure.categories[sectionID].name+' videos</h4>'}
else railhtml+='<h4>Videos</h4>';
railhtml+='<ul class="listnav">';
for(var i=0,l=playlist.length;i<l;i++){
var videoid=playlist[i],videodetails=_structure.video.videos[videoid];
railhtml+='<li onclick="mFT.playVideo(this)" videoid="'+videoid+'"><span class="imageloading smallimage" data-id="'+videoid+'.video"></span><h5>'+videodetails.title+'</h5><p>'+videodetails.desc+'</p></li>'};
railhtml+='</ul>'};
break;case'MPU':railhtml+='<div class="MPU dfpadplaceholder" data-adcontainerid="mpu" data-adclass="mpu" data-adwidth="300" data-adheight="250" data-adcode="ros;sz=300x250;pos=mpu;tile=1;ord="><span>&nbsp;</span></div>';
break;case'World Markets':railhtml+='<div class="worldmarkets render"></div>';
break;case'Portfolio':railhtml+=buildPortfolioSummary();
break;case'Promomessage':railhtml+=_getPromoMessage();
break;case'Macromap':railhtml+='<div class="rightrailmacromap"><h4 class="first">Global market map</h4><div class="macromapwrapper" onclick="mFT.router.loadMarketsData();"><div class="macromapbackgroundcontainer">'+(('marketsmacromapbackground' in localStorage)?'<img src="data:'+localStorage.marketsmacromapbackground+'" />':'')+'</div><div class="macromapforegroundcontainer">'+(('marketsmacromapforeground' in localStorage)?'<img src="data:'+localStorage.marketsmacromapforeground+'" />':'')+'</div></div><p class="worldmapcaption">Delayed by at least 20 minutes</p></div>';
break;case'Subscription Status':railhtml+=_getSubscriptionStatusButton();
break;case'Action Buttons':railhtml+=_buildActionButtons();
break;case'Recently viewed':railhtml+='<div class="recentlyviewed">'+_buildRecentlyViewed()+'</div>';
break;case'Weekend Highlights':railhtml+='<div class="weekend-highlights">'+_buildWeekendHighlights()+'</div>';
break;default:railhtml+='<div class="unhandledmodule"><div>['+moduletype+']</div></div>';
break}};
return railhtml}
function _buildActionButtons(){
return'<div class="action-buttons standalonebutton"><button onclick="mFT.sendFeedback();">Give feedback</button><a class="button" href="http://www.ft.com/servicestools/help/terms" target="_blank">Terms &amp; conditions</a><a class="button" href="http://www.ft.com/servicestools/help/privacy" target="_blank">Privacy policy</a></div>'}
function _buildRecentlyViewed(){
var readContentBaseKey=_ftuser?_ftuser.eid:'loggedout',readContent=localStorage.getItem('readcontent');
if(!readContent||!(readContent=JSON.parse(readContent))||!(readContent=readContent[readContentBaseKey]))return'';
var rows='',i=0,limit=10;
for(var crc in readContent){
if(i>limit)break;
var article=_structure.storylist[crc];
if(!article)return;
rows+='<li data-id="'+crc+'" data-cat="'+article.catid+'" onclick="mFT.router.loadArticle(this)">'+article.title+'</li>';
i++};
return rows?'<h4>Recently viewed</h4><ul class="listnav">'+rows+'</ul>':''}
function _buildWorldMarkets(targetNode){
if(!('marketsworldmarkets' in localStorage))return;
var wmData=JSON.parse(localStorage.marketsworldmarkets),o='<h4>World markets <span>Last 24 hours of trading</span></h4><img class="world-markets-graph" src="data:'+localStorage.marketsworldmarketschart+'" /><div class="rows">';
if(wmData)for(var i=0;i<wmData.indices.length;i++){
var wmIndex=wmData.indices[i];
o+='<div class="tablerow '+wmIndex.name.toLowerCase().replace(/ |&/g,'')+'"><div class="column chgpct '+(parseFloat(wmIndex.change)<0?'negative':((parseFloat(wmIndex.change)==0)?'neutral':'positive'))+'">'+wmIndex.change+'<br><span>'+wmIndex.chgPct+'</span></div><div class="column value">'+wmIndex.last+'</div><div class="name"><strong>'+wmIndex.name+'</strong><br><span class="opening-closing">'+wmIndex.status+'</span></div><div class="clear"></div></div>'};
o+='</div><div class="tablefooter"><div class="floatright"><div class="as-of">'+wmData.asOfDate+'</div></div><div class="notice">Data delayed at least 20 mins</div></div>';
targetNode.innerHTML=o}
function _buildMarketMovers(container,listPage,previousButton,nextButton,titleArea,xofyArea){
if(!_marketdata||!_marketdata.movers)return;
var numexchanges=_marketdata.movers['rankings'].length;
if(!numexchanges)return;
var exchangename=_marketdata.movers['rankings'][listPage-1]['exchange'],movers=_marketdata.movers['rankings'][listPage-1]['gainers'].slice(0,3).concat(_marketdata.movers['rankings'][listPage-1]['losers'].slice(0,3));
if(numexchanges==1){
if(previousButton)previousButton.style.display='none';
if(nextButton)nextButton.style.display='none';
if(xofyArea)xofyArea.style.display='none'}
else{
if(previousButton)if(listPage<=1){
previousButton.onclick=null;
previousButton.className=previousButton.className+' disabled'}
else{
previousButton.onclick=function(){
mFT.pageInChildContent('.sectionmarketsdata .tablerows','slideright','buildMarketMoversSmall',listPage-1,'.exchanges .previous','.exchanges .next','.exchanges .title','.exchanges .x-of-y')};
previousButton.className=previousButton.className.replace(/\b ?disabled\b/g,'')};
if(nextButton)if(listPage==numexchanges){
nextButton.onclick=null;
nextButton.className=nextButton.className+' disabled'}
else{
nextButton.onclick=function(){
mFT.pageInChildContent('.sectionmarketsdata .tablerows','slideleft','buildMarketMoversSmall',listPage+1,'.exchanges .previous','.exchanges .next','.exchanges .title','.exchanges .x-of-y')};
nextButton.className=nextButton.className.replace(/\b ?disabled\b/g,'')};
if(xofyArea)xofyArea.innerHTML=listPage+' of '+numexchanges};
if(titleArea)titleArea.innerHTML=exchangename;
var o='';
for(var idx=0;idx<movers.length;idx++){
var r=movers[idx];
o+='<div class="tablerow" onclick="mFT.router.loadTearsheet(\''+r.ftStandard+'\');"><div class="column value"><strong>'+r.last+'</strong><br><span>'+r.currencyCode+'</span></div><div class="column chgpct '+_getUpDownClass(r.chgPct)+'">'+r.change+'<br><span>'+r.chgPct+'</span></div><div class="name"><strong>'+r.companyName+'</strong><br><span class="as-of">'+r.ftStandard+'</span></div><div class="clear">&nbsp;</div></div>'};
return'<div class="tablerows uses3d marketspagination"><div>'+o+'</div></div><div class="tablefooter"><div class="floatright">As of '+_marketdata['as-of']+'</div><div class="notice">Data delayed at least 20 mins</div></div>'};
mFT.buildMarketMoversSmall=_buildMarketMovers
function _respaceSectionPageContent(targetview){
if(_screensizemode=='small'||_screensizemode=='medium')return;
if(_screenColumns[targetview].disableContentBalance)return;
var sectionpage=_eleWithId(_screenColumns[targetview].id),toprrheight=sectionpage.querySelector('.toprailcontent').offsetHeight+10,toplistheight=sectionpage.querySelector('.listnavtop').offsetHeight,heightdifference=Math.abs(toprrheight-toplistheight);
if(heightdifference>50){
var elementsToMove=[];
if(toprrheight>toplistheight){
var possibleElements=sectionpage.querySelectorAll('.listnavbottom li');
for(var i=0;i<possibleElements.length;i++){
var elementHeight=possibleElements[i].offsetHeight;
heightdifference-=elementHeight;
if(heightdifference<0&&Math.abs(heightdifference)>elementHeight/2)break;
elementsToMove.push(possibleElements[i])};
Array.prototype.forEach.call(elementsToMove,function(listelement){
sectionpage.querySelector('.listnavtop').appendChild(listelement)})}
else{
var possibleElements=sectionpage.querySelectorAll('.listnavtop li');
for(var i=possibleElements.length-1;i>=3;i--){
var elementHeight=possibleElements[i].offsetHeight;
heightdifference-=elementHeight;
if(heightdifference<0&&Math.abs(heightdifference)>elementHeight/2)break;
elementsToMove.push(possibleElements[i])};
var bottomList=sectionpage.querySelector('.listnavbottom');
Array.prototype.forEach.call(elementsToMove,function(listelement){
bottomList.insertBefore(listelement,bottomList.firstChild)})}}}
function _updateSubsectionArrowsWithScroll(scrollerContainer,performScroll,useAnimation){
if(typeof performScroll=='undefined')performScroll=false;
if(typeof useAnimation=='undefined')useAnimation=false;
var subsectionScroller=scrollerContainer.touchscroll,containerwidth=scrollerContainer.offsetWidth,innerwidth=scrollerContainer.querySelector('.sectionsubsections').offsetWidth,animationDuration=useAnimation?200:0;
if(innerwidth<=containerwidth){
scrollerContainer.parentNode.querySelector('.navleftcontainer').style.display='none';
scrollerContainer.parentNode.querySelector('.navrightcontainer').style.display='none';
return};
var scrollposition=subsectionScroller.scrollLeft,scrollamount=0;
if(performScroll=='left'){
scrollamount=-Math.ceil(containerwidth/3);
if(scrollposition+scrollamount<5)scrollamount=-scrollposition;
if(scrollamount)subsectionScroller.scrollBy(scrollamount,0,animationDuration)}
else if(performScroll=='right'){
scrollamount=Math.ceil(containerwidth/3);
if(scrollposition+containerwidth+scrollamount+5>innerwidth)scrollamount=innerwidth-containerwidth-scrollposition;
if(scrollamount)subsectionScroller.scrollBy(scrollamount,0,animationDuration)}
else if(performScroll=='selected'){
var selectedItem=scrollerContainer.querySelector('.active');
if(selectedItem){
var targetposition=Math.round(selectedItem.offsetLeft+(selectedItem.offsetWidth/2)-(containerwidth/2));
if(targetposition<5){
targetposition=0}
else if(targetposition+containerwidth>innerwidth-5)targetposition=innerwidth-containerwidth;
scrollamount=targetposition-scrollposition;
if(scrollamount)subsectionScroller.scrollBy(scrollamount,0,animationDuration)}};
var newposition=scrollposition+scrollamount;
scrollerContainer.parentNode.querySelector('.navleftcontainer').style.display=(newposition>0)?'block':'none';
scrollerContainer.parentNode.querySelector('.navrightcontainer').style.display=(newposition+containerwidth+5<=innerwidth)?'block':'none'}
function subsectionNavLeft(){
_updateSubsectionArrowsWithScroll(document.querySelector('#'+_screenColumns.center.id+' .sectionsubsectionscroller'),'left',true)};
mFT.subsectionNavLeft=subsectionNavLeft
function subsectionNavRight(){
_updateSubsectionArrowsWithScroll(document.querySelector('#'+_screenColumns.center.id+' .sectionsubsectionscroller'),'right',true)};
mFT.subsectionNavRight=subsectionNavRight
function _showRelatedSectionsSubsection(element){
var readContentStore=_readcontent[_ftuser?_ftuser.eid:'loggedout'];
if(!readContentStore)readContentStore={};
var sectionID=element.getAttribute('data-id'),theSection=_structure.categories[sectionID];
if(!theSection||!theSection.cids)return;
var topSectionID=sectionID;
while(_structure.categories[topSectionID].pid)topSectionID=_structure.categories[topSectionID].pid;
var sections=element.parentNode.children,l=sections.length;
for(var i=0;i<l;i++)_hideRelatedSectionsSubsection(sections[i]);
var o='<ul class="relatedstories">';
for(var i in theSection.cids){
var storyID=theSection.cids[i],theStory=_structure.storylist[storyID];
if(!theStory)continue;
o+='<li data-id="'+storyID+'" data-cat="'+sectionID+'" data-topcat="'+topSectionID+'" onclick="mFT.router.loadArticle(this); window.event.stopPropagation()" class="'+(readContentStore[storyID]?'read':'')+'">'+theStory.title+'</li>'};
o+='</ul>';
element.innerHTML+=o;
element.className+=' open';
element.onclick=function(){
mFT.hideRelatedSectionsSubsection(element)};
mFT.updateContentHeight()};
mFT.showRelatedSectionsSubsection=_showRelatedSectionsSubsection
function _hideRelatedSectionsSubsection(element){
var relatedstories=element.querySelector('.relatedstories');
if(!relatedstories)return;
element.removeChild(relatedstories);
element.className=element.className.replace(/ ?open ?/,'');
element.onclick=function(){
mFT.showRelatedSectionsSubsection(element)};
mFT.updateContentHeight()};
mFT.hideRelatedSectionsSubsection=_hideRelatedSectionsSubsection
function _getReducedLayoutSectionAdvert(adposition){
return _getAdvertisingBanner(adposition)}
function _hasSectionPageChanged(sectionID,oldstructure,newstructure){
if(!oldstructure)return true;
var oldsection=oldstructure.categories[sectionID],newsection=newstructure.categories[sectionID],oldsectiondetails=oldstructure.pcatlist[sectionID],newsectiondetails=newstructure.pcatlist[sectionID];
if(!newsectiondetails)return true;
if(typeof oldsection=='undefined')return true;
if(typeof newsection=='undefined')return true;
if(!areObjectsEqual(newsection.cids,oldsection.cids))return true;
if(_screensizemode!='small'&&_screensizemode!='medium'){
var rails=['toprail','bottomrail'];
Array.prototype.forEach.call(rails,function(railname){
var newrail=newsectiondetails[railname];
if(!areObjectsEqual(newrail,oldsectiondetails[railname]))return true;
if(newsectiondetails[railname])for(var i=0;i<newrail.length;i++)if(!areObjectsEqual(newstructure.categories[newrail[i].i],oldstructure.categories[newrail[i].i]))return true})};
if(newsection.midriff&&newsection.midriff.feeds[0])if(!areObjectsEqual(newstructure.categories[newsection.midriff.feeds[0]],oldstructure.categories[newsection.midriff.feeds[0]]))return true;
return false}
function _storeSectionScrollPosition(){
var centerCol=_screenColumns.center;
if(_isLoadingArticle)return;
if(centerCol.pageType!='section'&&centerCol.pageType!='home')return;
_sectionScrollPositions[0]={id:centerCol.pageIdentifier,y:-document.body.scrollTop}}
function _restoreScrollPositionInColumn(scrollOffset,columnName){
document.querySelector('#columnscontainer').style.height=scrollOffset+window.innerHeight+'px';
_screenPanTargetVerticalOffset=-scrollOffset;
var targetColumnStyle=document.getElementById(_screenColumns[columnName].id).style;
targetColumnStyle.webkitTransitionDuration='0s';
targetColumnStyle.webkitTransform='translate('+((columnName=='left')?'-':'')+'100%,-'+scrollOffset+'px)'}
function loadArticle(linkitem,fromsection,topSection,article,isinarticlelink){
if(typeof linkitem=='object'){
var articleid=linkitem.getAttribute('data-id');
fromsection=linkitem.getAttribute('data-cat');
topSection=linkitem.getAttribute('data-topcat')||false}
else var articleid=linkitem;
_storeSectionScrollPosition();
_isLoadingArticle=true;
if(typeof article=='object'&&article!=null){
var theArticle=article}
else var theArticle=_structure.storylist[articleid];
if(!theArticle){
if(linkitem[0]=='r'&&linkitem[1]=='_'){
router.loadHome();
_isLoadingArticle=false;
return};
var downloadfailed=function(){
alert('Sorry, but the article you tried to load could no longer be found. (x'+articleid+')');
router.loadHome();
_isLoadingArticle=false;
return};
Assanka.$.ajax({url:sourceURL+'articles',dataType:'json',data:{v:2,articleid:articleid,returnextras:true},success:function(data){
theArticle=data;
if(data==null||data==""){
downloadfailed();
_isLoadingArticle=false;
return};
theArticle.isPlaceholderContent=false;
theArticle.byline=data.byline;
theArticle.guid=data.name;
theArticle.date=data.datepublished;
theArticle.content=data.content;
theArticle.stocks=data.stocks;
theArticle.image=data.details.image;
theArticle.webappshare=data.details.webappshare;
theArticle.webappemail=data.details.webappemail;
theArticle.protectionlevel=data.protectionlevel?data.protectionlevel:'normal';
mFT.router.loadArticle(articleid,null,null,theArticle,isinarticlelink)},error:function(error){
downloadfailed();
_isLoadingArticle=false;
return}});
return};
if(!theArticle)return;
if(!article)theArticle.id=articleid;
FT.env.startPage('ros','article');
var targetColumn='right';
if(_wrapperUsesGallery||!_screenColumns.center.pageType||(_screenColumns.center.pageType=='content'&&_screenColumns.center.pageIdentifier==articleid)){
targetColumn='center'}
else if((_screenColumns.center.pageType=='marketsdata'&&(!_screenColumns.left.pageType||_screenColumns.left.pageType=='content'))||(_screenColumns.center.pageType=='content'&&_historyGoingBack))targetColumn='left';
if(targetColumn!='center'&&(_screenColumns.center.pageType=='section'||_screenColumns.center.pageType=='home'))if(_prepareCenterColumnForTransitionToTop()){
window.setTimeout(function(){
loadArticle(linkitem,fromsection,topSection,article,isinarticlelink)},10);
return};
if(!_currentcategory)_currentcategory=theArticle.catid;
var articleShouldReturnToSection=false;
if(!isinarticlelink||isinarticlelink==false)if(_historyLastEntry!='category/'+_currentcategory)articleShouldReturnToSection=_currentcategory;
theArticle.guid=theArticle.guid.replace(/^f:/,'http://www.ft.com/cms/s/').replace(/^b:/,'http://blogs.ft.com/').replace(/^a:/,'http://ftalphaville.ft.com/');
if(theArticle.guid.indexOf('://')==-1)theArticle.guid='http://'+theArticle.guid;
HurdleType='undefined';
if(!_mockingbirdCheckUserHasAccess(articleid)){
HurdleType='h1';
var statusText='';
if(_mbird.limits.loggedout==0){
statusText='FT articles are only available to registered users and subscribers. To see further content, sign in, register for limited access or subscribe for unlimited articles on desktop, tablet and mobile.'}
else statusText='You have reached your limit of '+_mbird.limits.loggedout+' free articles within 30 days. To see further content, sign in, subscribe, or register for free.';
if(_campaignreference==20419)statusText='<strong>Claim your 25% discount</strong><br />FT articles are only available to registered users and subscribers. To get unlimited access on desktop, tablet and mobile, take up our reduced price subscription offer.';
var buttonText='Sign in or register';
if(_mbird.limits.loggedin==-1){
statusText='<strong>Register now for free access.</strong><br>FT articles are only available to registered users and subscribers. To see further content, please register now to take advantage of our free launch week offer or subscribe to secure ongoing access.';
buttonText='Register or Sign in'}
else if(theArticle.mbird=='premium'){
HurdleType='h3';
statusText='This section is exclusively for Premium subscribers. To continue reading please upgrade your subscription.';
buttonText='Upgrade your account'}
else if(_ftuser){
HurdleType='h2';
buttonText='Upgrade your account';
statusText='You have reached your limit of '+_mbird.limits.loggedin+' free articles within 30 days. To see further content, please subscribe.';
if(_campaignreference==20419)statusText='<strong>Claim your 25% discount</strong><br />You have reached your limit of '+_mbird.limits.loggedin+' free articles within 30 days. To get unlimited access on desktop, tablet and mobile, take up our reduced price subscription offer.'};
theArticle.placeholderContent='<div class="subscriberblock"><p>'+statusText+'</p><div class="standalonebutton"><button onclick="mFT.showAccount()">'+buttonText+'</button></div></div>';
theArticle.isPlaceholderContent=true;
if(theArticle.guid!=null){
_addHistoryEntry('content',articleid,theArticle.title,null,theArticle)}
else _addHistoryEntry('content',articleid,theArticle.title);
_buildArticlePage(articleid,theArticle,targetColumn,fromsection,articleShouldReturnToSection,topSection);
if(targetColumn!='center'){
_slideView(targetColumn)}
else{
updateContentHeight();
doAdverts('ros','content')};
_isLoadingArticle=false;
return};
if(theArticle.guid!=null){
_addHistoryEntry('content',articleid,theArticle.title,null,theArticle)}
else _addHistoryEntry('content',articleid,theArticle.title);
if(typeof linkitem=='object')linkitem.className+=' read';
if(typeof article=='object'&&article!=null){
theArticle.isPlaceholderContent=false;
_buildArticlePage(theArticle.id,theArticle,targetColumn,fromsection,articleShouldReturnToSection,topSection);
if(targetColumn!='center'){
_slideView(targetColumn)}
else updateContentHeight();
_isLoadingArticle=false;
return};
theArticle.placeholderContent='<div class="contentloading"><p>Loading article...</p><p class="contentloadingimage"><span class="progressbar standardprogressbar"></span></p></div>';
theArticle.isPlaceholderContent=true;
_buildArticlePage(articleid,theArticle,targetColumn,fromsection,articleShouldReturnToSection,topSection);
if(targetColumn!='center'){
_slideView(targetColumn)}
else updateContentHeight();
_localdb.fetchArticle(articleid,function(transaction,response){
var returnedArticle=false,storeArticleFromWrapper=false;
if(response.rows.length)returnedArticle=response.rows.item(0);
if(!returnedArticle&&_inWrapper){
var articleDetails=window.appBridge.getResource(articleid.toString());
if(articleDetails){
returnedArticle=JSON.parse(articleDetails);
storeArticleFromWrapper=true}};
if(returnedArticle){
theArticle.isPlaceholderContent=false;
theArticle.byline=returnedArticle.byline;
theArticle.guid=returnedArticle.name;
theArticle.content=returnedArticle.content;
theArticle.stocks=null;
theArticle.protectionlevel="normal";
try{theArticle.details=JSON.parse(returnedArticle.details);
if(theArticle.details.stocks)theArticle.stocks=theArticle.details.stocks;
if(theArticle.details.webappshare)theArticle.webappshare=theArticle.details.webappshare;
if(theArticle.details.webappemail)theArticle.webappemail=theArticle.details.webappemail;
if(theArticle.details.protectionlevel){
theArticle.protectionlevel=theArticle.details.protectionlevel}
else theArticle.protectionlevel="normal";
if(theArticle.details.image)theArticle.image=theArticle.details.image}catch(error){theArticle.details=null};
if(_screenColumns.center.pageType!='content'||_screenColumns.center.pageIdentifier!=articleid)return;
_buildArticlePage(articleid,theArticle,'center',fromsection,articleShouldReturnToSection,topSection);
updateContentHeight();
doAdverts('ros','content');
_isLoadingArticle=false;
return};
if(!_loadingContent['article/'+articleid]){
_loadingContent['article/'+articleid]=true;
var articleErrorHandler=function(){
delete _loadingContent['article/'+articleid];
if(_screenColumns.center.pageType=='content'&&_screenColumns.center.pageIdentifier==articleid){
if(typeof linkitem=='object')linkitem.className=linkitem.className.replace(/\b ?read\b/,'');
alert('Article content could not be retrieved from the server; please check your connection and try again.');
_isLoadingArticle=false;
goBack()}};
Assanka.$.ajax({url:sourceURL+'articles',data:{v:2,articleid:articleid},dataType:'json',success:function(returnedArticle){
if(!returnedArticle)return articleErrorHandler();
if(_bigdatabasemode)_localdb.insertArticle(returnedArticle);
delete _loadingContent['article/'+articleid];
if(_screenColumns.center.pageType=='content'&&_screenColumns.center.pageIdentifier==articleid){
theArticle.isPlaceholderContent=false;
theArticle.webappshare=returnedArticle.details.webappshare;
theArticle.webappemail=returnedArticle.details.webappemail;
theArticle.byline=returnedArticle.byline;
theArticle.guid=returnedArticle.name;
theArticle.content=returnedArticle.content;
theArticle.stocks=returnedArticle.details.stocks;
theArticle.image=returnedArticle.details.image;
theArticle.protectionlevel=returnedArticle.protectionlevel?returnedArticle.protectionlevel:'normal';
_buildArticlePage(articleid,theArticle,'center',fromsection,articleShouldReturnToSection,topSection);
doAdverts('ros','content');
updateContentHeight();
_isLoadingArticle=false}},error:articleErrorHandler})}})};
mFT.loadArticle=loadArticle
function fontSizeChange(sizeModification){
sizeModification=sizeModification.toString();
var newSize=sizeModification;
if(sizeModification.length)if(newSize.substring(0,1)=='-'||newSize.substring(0,1)=='+')newSize=parseFloat(_currentFontSize)+parseFloat(sizeModification);
if(_fontSizeClasses[newSize]){
var bodyClass=document.body.className,re=new RegExp('\\b'+_fontSizeClasses[_currentFontSize]+'\\b');
bodyClass=bodyClass.replace(re,'');
bodyClass+=' '+_fontSizeClasses[newSize];
document.body.className=bodyClass;
updateContentHeight();
_currentFontSize=newSize;
localStorage.setItem('fontsize',newSize);
if(mFT.reflowArticleColumns)mFT.reflowArticleColumns()}};
mFT.fontSizeChange=fontSizeChange
function cycleFontSize(){
if(_currentFontSize+1>=_fontSizeClasses.length){
fontSizeChange('0')}
else fontSizeChange('+1')};
mFT.cycleFontSize=cycleFontSize
function _buildArticlePage(articleID,theArticle,targetView,displayedFromSection,backButtonShouldReturnToSectionID,topSection){
var articlehtml,newPage,articleContent,titlesectionid,articleTemplate=null,useReducedLayout=(_screensizemode=='small'||_screensizemode=='medium');
_screenColumns[targetView].disableContentBalance=true;
newPage=_eleWithId('contenttemplate').cloneNode(true);
newPage.id=null;
articleContent=newPage.querySelector('.content');
if(typeof (backButtonShouldReturnToSectionID)!='undefined'&&backButtonShouldReturnToSectionID)newPage.querySelector('.backbuttonwrapper').onclick=function(){
if(_structure.categories[backButtonShouldReturnToSectionID].is_front){
mFT.router.loadHome()}
else mFT.router.loadSection(backButtonShouldReturnToSectionID)};
if(!theArticle.guid){
mFT.sendArticle=function(){
alert('You cannot share this article.');
return false}}
else mFT.sendArticle=function(linkElement){
var shareHtml=document.querySelector('#articlesharing .articles-sharing').cloneNode(true);
shareHtml.id="";
if(theArticle.webappshare!=null){
var link='http://on.ft.com/'+theArticle.webappshare}
else var link=theArticle.guid;
shareHtml.querySelector(".twitter a").href="http://twitter.com/intent/tweet?status="+encodeURIComponent(theArticle.title+': '+link+' #FT');
shareHtml.querySelector(".facebook a").href='http://'+((_screensizemode=='large'||_screensizemode=='largewide')?'':'m.')+'facebook.com/sharer.php?u='+link;
if(theArticle.webappemail!=null){
var emaillink='http://on.ft.com/'+theArticle.webappemail}
else var emaillink=theArticle.guid;
shareHtml.querySelector(".email").onclick=function(){
var emailBody="I saw this article when using the Financial Times app and thought you might be interested:\n\nFinancial Times, "+_formatDate(theArticle.date,true,true)+"\n"+theArticle.title+"\n--\n"+(theArticle.byline?(theArticle.byline+"\n--\n"):'')+theArticle.snip+"\n\nRead the full article at: "+emaillink;
parent.location="mailto:?subject="+encodeURIComponent(theArticle.title)+"&body="+encodeURIComponent(emailBody);
return false};
_showPopover(shareHtml,false,linkElement,300)};
titlesectionid=displayedFromSection||theArticle.catid;
if(titlesectionid){
var titlesection=_structure.categories[titlesectionid];
if(titlesection){
newPage.querySelector('.contenttitle').innerText=titlesection.name}
else titlesectionid=false};
if(_enableNavigationHack)newPage.querySelector('.headerbar').style.width=window.innerWidth+'px';
if(!theArticle.isPlaceholderContent&&titlesectionid)articleTemplate=_structure.categories[titlesectionid].name.toLowerCase();
var headshot="";
if(theArticle.byline!=null)headshot=theArticle.byline.replace(/[\s|By]/ig,'').toLowerCase();
switch(articleTemplate){case'editorial':case'comment':articleTemplate='comment';
articleContent.innerHTML='<div class="contentinnerwrapper"><div class="cols cols1"><div class="colA"><div class="heading">'+(theArticle.byline?'<span class="byline"><span class="headshot '+headshot+'"></span>'+theArticle.byline+'</span>':'')+'<span class="date">'+_formatDate(theArticle.date,false,false)+'</span><h4>'+theArticle.title+'</h4><span class="snip">'+theArticle.snip+'</span></div>'+_buildArticleImage('primary')+'</div><div class="colB">'+theArticle.content+'</div><div class="colC"></div></div></div>';
break;case'house & home':case'life & arts':case'magazine':case'management':articleTemplate='feature';
articleContent.innerHTML='<div class="contentinnerwrapper"><div class="cols cols1"><div class="colA">'+_buildArticleImage('primary')+'<div class="heading"><h4>'+theArticle.title+'</h4><span class="snip">'+theArticle.snip+'</span><span class="date">'+_formatDate(theArticle.date,true,false)+'</span></div></div><div class="colB">'+theArticle.content+'</div><div class="colC"></div></div></div>';
break;case'beyond-brics':case'brussels blog':case'business blog':case'energy source':case'ft alphaville':case'gavyn davies':case'martin wolf\'s exchange':case'material world':case'money supply':case'tech blog':case'ft tech hub':case'westminster blog':articleTemplate='blog';
theArticle.content=theArticle.content.replace(/\<img /g,'<img onerror="this.style.display=\'none\'" ');
articleContent.innerHTML='<div class="contentinnerwrapper"><div class="heading"><span class="date">'+_formatDate(theArticle.date,false,false)+'</span><h4>'+theArticle.title+'</h4>'+(theArticle.byline?'<p class="byline">'+theArticle.byline+'</p>':'')+'</div><div class="articlebody">'+theArticle.content+'</div></div>';
break;default:articleTemplate='default';
if(theArticle.isPlaceholderContent){
articleContent.innerHTML='<div class="contentinnerwrapper"><div class="cols cols1"><div class="heading"><span class="date">'+_formatDate(theArticle.date,false,false)+'</span><h4>'+theArticle.title+'</h4></div><div class="colA">'+(theArticle.byline?'<p class="byline"><span class="headshot '+headshot+'"></span>'+theArticle.byline+'</p>':'')+'<p>'+theArticle.snip+'</p></div>'+(theArticle.placeholderContent?theArticle.placeholderContent:'')+'</div></div>'}
else articleContent.innerHTML='<div class="contentinnerwrapper"><div class="cols cols1"><div class="heading"><span class="date">'+_formatDate(theArticle.date,false,false)+'</span><h4>'+(useReducedLayout?'':_buildArticleImage('secondary'))+theArticle.title+'<br style="clear: both;" /></h4></div><div class="colA">'+(theArticle.byline?'<p class="byline"><span class="headshot '+headshot+'"></span>'+theArticle.byline+'</p>':'')+theArticle.content+'</div>'+_buildArticleImage('primary')+(useReducedLayout?_buildArticleImage('secondary'):'')+_buildArticleStocks(theArticle.stocks)+'<div class="colB"></div><div class="colC"></div></div></div>';
break};
if(useReducedLayout&&articleTemplate!='feature'){
var articleImage=articleContent.querySelector('.articleimage');
if(articleImage){
var articleFirstParagraph=articleContent.querySelector('p');
if(!articleFirstParagraph)articleFirstParagraph=articleContent.querySelector('.colA');
if(articleFirstParagraph){
if(articleFirstParagraph.className=='byline'&&articleFirstParagraph.nextElementSibling)articleFirstParagraph=articleFirstParagraph.nextElementSibling;
var imageWidth=(articleImage.className.indexOf('primaryimg')!=-1)?272:167;
if(imageWidth>(window.innerWidth-150)){
articleFirstParagraph.parentNode.insertBefore(articleImage,articleFirstParagraph)}
else articleFirstParagraph.insertBefore(articleImage,articleFirstParagraph.firstChild)}}};
articleContent.className='content template'+articleTemplate;
if(!theArticle.isPlaceholderContent){
_addToReadContent(theArticle.id);
Array.prototype.forEach.call(articleContent.getElementsByTagName('a'),function(linkelement){
var oldonclick=false;
if(linkelement.onclick)oldonclick=linkelement.onclick;
linkelement.onclick=function(){
if(oldonclick)oldonclick()}});
var adcount=parseInt((localStorage.getItem('articleadinterval')||0),10)+1;
if(adcount==13)adcount=1;
localStorage.setItem('articleadinterval',adcount)};
if(useReducedLayout){
newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
if(!theArticle.isPlaceholderContent){
newPage.querySelector('.colC').innerHTML+=('<button class="back-to-top" onClick="window.scrollTo(0,0);">Back to top</button>');
var rel=_buildArticleRelated();
if(rel)newPage.querySelector('.colB').appendChild(rel)}};
var targetNode=_eleWithId(_screenColumns[targetView].id);
if(targetNode.firstChild){
targetNode.replaceChild(newPage,targetNode.firstChild)}
else targetNode.appendChild(newPage);
_screenColumns[targetView].pageType='content';
_screenColumns[targetView].pageIdentifier=theArticle.id;
_screenColumns[targetView].pageGUID=(theArticle.guid?theArticle.guid:'Unloaded article with ID '+theArticle.id);
_loadImagesInElement(targetNode);
if(!useReducedLayout&&articleTemplate!='blog'){
function updateArticleContentHeight(){
updateContentHeight();
articleContent.style.height=(window.innerHeight-document.querySelector('.contentheaderbar').offsetHeight-document.querySelector('.pageindicator').offsetHeight)+'px'};
mFT.updateArticleContentHeight=updateArticleContentHeight;
updateArticleContentHeight();
if(theArticle.isPlaceholderContent){
articleContent.addEventListener('orientationchange',updateArticleContentHeight,false)}
else _setupArticleColumns(articleTemplate,theArticle.id,newPage,_buildArticleRelated(),_buildArticleAd())}
else if(useReducedLayout){
var pel=newPage.querySelector('.contentinnerwrapper');
pel.insertBefore(_buildArticleAd(),pel.firstChild)}
function _buildArticleStocks(stocks){
if(!stocks)return'';
var _stocks='<div class="tableheading"><div class="columnheading graph">1 month change</div><div class="columnheading chgpct">Today\'s change</div><div class="columnheading value"><br>Last</div><div class="clear">&nbsp;</div></div>',requrl='/prices',stocksfound=0;
for(var stock in stocks){
stocksfound++;
requrl+='/'+stock;
_stocks+='<div onclick="mFT.router.loadTearsheet(\''+stock+'\')" class="tablerow stock stock-'+stock.replace(':','-').replace('.','_')+'"><div class="column graph"><img></div><div class="column chgpct"></div><div class="column value"></div><div class="name"><strong>'+stocks[stock]+'</strong><br><span class="as-of stocksloading">Loading...</span></div><div class="clear">&nbsp;</div></div>';
if(stocksfound==5)break};
if(!stocksfound)return'';
if(_disableLiveStocksInArticles)return;
Assanka.$.ajax({url:requrl,dataType:'json',success:function _populateArticleStockData(stocks){
if(!stocks){
_hideStocksLoadingSpinner();
return};
var contentContainer=_eleWithId(_screenColumns.center.id).querySelector('.contentinnerwrapper'),rowContainer,chgContainer,asOfContainer;
if(!contentContainer)return;
for(var stock in stocks){
rowContainer=contentContainer.querySelector('.stock-'+stock.replace(':','-').replace('.','_'));
rowContainer.querySelector('.column.graph img').src='http://markets.ft.com/apis/iPhone/v2.0/chart.asp?type=iPad_Spark&wsodIssues='+stocks[stock].issue;
chgContainer=rowContainer.querySelector('.column.chgpct');
chgContainer.className+=' '+_getUpDownClass(stocks[stock].chg);
chgContainer.innerHTML=stocks[stock].chg+'<br><span>'+stocks[stock].chgpct+'</span>';
rowContainer.querySelector('.column.value').innerHTML='<strong>'+stocks[stock].last+'</strong><br>'+stocks[stock].ccy;
asOfContainer=rowContainer.querySelector('.as-of');
asOfContainer.className='as-of';
asOfContainer.innerHTML=stocks[stock].asof+'</span>'};
_hideStocksLoadingSpinner()},error:_hideStocksLoadingSpinner});
return'<div class="render marketsdata contentmarketsdata">'+_stocks+'</div>'}
function _hideStocksLoadingSpinner(){
Array.prototype.forEach.call(document.querySelectorAll('.stocksloading'),function(el){
el.innerHTML='Data not available'})}
function _buildArticleImage(size){
if(_disableImages)return;
if(theArticle.isPlaceholderContent)return'';
if(size=='primary')return(!theArticle.image)?'':'<div class="imageloading articleimage primaryimg" data-id="'+articleID+'.large"></div>';
if(size=='secondary')return(!theArticle.img||theArticle.image)?'':'<div class="imageloading articleimage secondaryimg" data-id="'+articleID+'"></div>'}
function _buildArticleRelated(){
var section=displayedFromSection||theArticle.catid;
if(!section||theArticle.isPlaceholderContent)return null;
var relatedList=document.createElement('ul'),listItem,parentcategorycids=_structure.categories[section].cids,readContentStore=_readcontent[_ftuser?_ftuser.eid:'loggedout'];
if(!readContentStore)readContentStore={};
for(var eachArticleIndex in parentcategorycids){
var eachArticleID=parentcategorycids[eachArticleIndex];
if(eachArticleID==theArticle.id||!_structure.storylist[eachArticleID])continue;
listItem=relatedList.appendChild(document.createElement('li'));
listItem.setAttribute('data-id',eachArticleID);
listItem.setAttribute('data-cat',section);
listItem.setAttribute('data-topcat',topSection);
listItem.appendChild(document.createTextNode(_structure.storylist[eachArticleID].title));
listItem.addEventListener('click',function(e){
e.preventDefault();
e.stopPropagation();
mFT.router.loadArticle(this)},true);
if(readContentStore[eachArticleID])listItem.className='read';
relatedList.appendChild(listItem)};
if(!listItem)return null;
var relatedDiv=document.createElement('div');
relatedDiv.className='related-info';
relatedDiv.appendChild(document.createElement('h3').appendChild(document.createTextNode('More from '+_structure.categories[section].name)).parentNode);
return relatedDiv.appendChild(relatedList).parentNode}
function _buildArticleAd(){
var advertdiv=document.createElement('div');
advertdiv.className='adplaceholder dfpadwrapper';
advertdiv.innerHTML=_getAdvertisingBanner('article',theArticle.id);
return advertdiv}}
function _setupArticleColumns(articleTemplate,articleId,articlePage,articleRelated,articleAd){
var splitableTags=new Array('P','DIV','SPAN','BLOCKQUOTE','ADDRESS','PRE','A','EM','I','STRONG','B','CITE'),debug=false,scroller,contentInner=articlePage.querySelector('.contentinnerwrapper').cloneNode(true)
function randomId(){
var rId="";
for(var i=0;i<6;i++)rId+=String.fromCharCode(97+Math.floor((Math.random()*24)));
return rId}
function populateInner(srcel,targetHeight,overflowel){
if(debug)console.log('PopulateInner: '+targetHeight,srcel,overflowel);
lastNodeForDest=null;
splitNodeForDest=null;
findSplitPoint(srcel,targetHeight);
if(splitNodeForDest||lastNodeForDest)for(var i=0,l=srcel.childNodes.length;i<l;i++){
if(srcel.childNodes[i]!=splitNodeForDest&&srcel.childNodes[i]!=lastNodeForDest)continue;
if(splitNodeForDest)i++;
for(var l2=l-i;l2>0;l2--){
if(debug)console.log('Transferring to '+overflowel.id,srcel.childNodes[i].innerHTML.substring(0,100),srcel.childNodes[i]);
overflowel.appendChild(srcel.childNodes[i]);
l--};
break};
if(splitNodeForDest&&!lastNodeForDest){
if(debug)console.log('splitNodeForDest: ',splitNodeForDest.innerHTML);
splitElement(splitNodeForDest,targetHeight-splitNodeForDest.offsetTop,srcel,overflowel)}}
function findSplitPoint(n,newHeight){
if(debug)console.log('findSplitPoint: ',n,newHeight);
var top=false,bot=false,prevtop=false,prevbot=false;
if(n.nodeType==1){
if(debug)console.log("Examining "+n.tagName+"("+n.id+"), Type "+n.nodeType+', for height='+newHeight);
top=n.offsetTop;
bot=top+n.offsetHeight;
if(debug)console.log("findSplitPoint: "+top+' > '+newHeight+' > '+bot+' in '+n.id);
if(bot>newHeight){
if(debug)console.log("Found best split point for "+n.id+' is inside '+n.tagName+' (#'+n.id+' - '+n.innerHTML.substring(0,100)+'...)');
splitNodeForDest=n;
if(debug)console.log('splittable '+isElementSplitable(n));
if(isElementSplitable(n))for(var i=0,l=n.childNodes.length;i<l;i++){
betterfound=findSplitPoint(n.childNodes[i],newHeight);
if(betterfound){
if(debug)console.log('Found a better split inside child node',n.childNodes[i]);
return true};
if(i!=0){
if(debug)console.log("Checking between nodes: "+n.childNodes[i].offsetTop+' > '+newHeight+" > "+n.childNodes[i-1].offsetTop);
if(n.childNodes[i].offsetTop>newHeight&&n.childNodes[i-1].offsetTop<newHeight){
if(debug)console.log("Best split found between nodes "+(i-1)+" and "+i,n.childNodes[i-1],n.childNodes[i]);
lastNodeForDest=n.childNodes[i-1];
return true}}};
return true}};
return false}
function isElementSplitable(n){
if(n.tagName){
var tagName=n.tagName.toUpperCase();
for(var i=0;i<splitableTags.length;i++)if(tagName==splitableTags[i])return true};
return false}
function splitElement(n,targetHeight,col1,col2){
if(debug)console.log('splitElement: ',n,targetHeight,col1,col2);
var cn,strippedText,allStrippedText,str,wIdx;
while(cn=n.lastChild)if(cn.nodeType==3){
strippedText="dummmy";
allStrippedText="";
str=cn.data;
while(n.offsetHeight>targetHeight&&strippedText!=""){
wIdx=str.lastIndexOf(' ');
if(wIdx==-1){
wIdx=str.lastIndexOf('\n');
if(wIdx==-1)wIdx=0};
strippedText=str.substr(wIdx);
str=str.substr(0,wIdx);
cn.deleteData(wIdx,str.length);
allStrippedText=strippedText+allStrippedText};
if(allStrippedText!=""){
var insertPoint=createNodeAncestors(cn,col1,col2,'insertBefore'),insertNode=document.createTextNode(allStrippedText);
if(debug)console.log('moved text =',allStrippedText);
if(n.tagName=='P')insertNode=document.createElement('p').appendChild(insertNode).parentNode;
insertPoint.insertBefore(insertNode,insertPoint.firstChild)};
if(str==""){
n.removeChild(cn)}
else break}
else{
var insertPoint=createNodeAncestors(cn,col1,col2,'insertBefore');
insertPoint.insertBefore(n.removeChild(cn),insertPoint.firstChild)};
return strippedText}
function createNodeAncestors(n,col1,col2,method){
var ancestors=new Array(),insertNode=col2,pn=n.parentNode;
while(pn&&pn.id!=col1.id){
if(debug)console.log('Looking for parent: ',pn.id,col1.id);
ancestors[ancestors.length]=pn;
if(!pn.id)pn.id=randomId();
pn=pn.parentNode};
for(var i=ancestors.length-1;i>=0;i--){
for(var j=0;j<insertNode.childNodes.length&&(insertNode.childNodes[j].nodeType==3||!insertNode.childNodes[j].className.match(ancestors[i].id+'-css3mc'));j++);
if(j==insertNode.childNodes.length){
if(method=='append'){
insertNode=insertNode.appendChild(document.createElement(ancestors[i].tagName))}
else insertNode=insertNode.insertBefore(document.createElement(ancestors[i].tagName),insertNode.firstChild);
insertNode.className=ancestors[i].className+' '+ancestors[i].id+'-css3mc';
insertNode.style.marginTop="0";
insertNode.style.paddingTop="0";
if(insertNode.tagName.toUpperCase()=='OL'&&n.nodeType==1&&n.tagName.toUpperCase()=='LI'){
var prevsib=n.previousSibling,count=0;
while(prevsib){
if(prevsib.nodeType==1&&prevsib.tagName.toUpperCase()=='LI')count++;
prevsib=prevsib.previousSibling};
insertNode.setAttribute('start',count)}}
else{
insertNode=insertNode.childNodes[j];
if(insertNode.tagName.toUpperCase()=='OL'&&(insertNode.start==-1||insertNode.start==1)&&n.nodeType==1&&n.tagName.toUpperCase()=='LI'){
var prevsib=n.previousSibling,count=0;
while(prevsib){
if(prevsib.nodeType==1&&prevsib.tagName.toUpperCase()=='LI')count++;
prevsib=prevsib.previousSibling};
insertNode.setAttribute('start',count)}}};
return insertNode}
function flowArticleColumns(){
var colsContainerCount=1,colsContainer=articlePage.querySelector('.cols1'),colsContainerHeight=colsContainer.clientHeight,targetHeight=colsContainerHeight,colA=colsContainer.querySelector('.colA'),colB=colsContainer.querySelector('.colB');
if(articleTemplate=='default'){
if(debug)console.log('Flowing article columns with default template');
var heading=colsContainer.querySelector('.heading'),headingHeight=heading?heading.clientHeight:0,image=colsContainer.querySelector('.primaryimg'),imageHeight=image?image.clientHeight:0,stocks=colsContainer.querySelector('.contentmarketsdata'),stocksHeight=stocks?stocks.clientHeight:0;
targetHeight=colsContainerHeight-headingHeight;
if(debug)console.log('targetHeight: '+targetHeight+'; colA.offsetHeight: '+colA.offsetHeight);
if(colA.offsetHeight>targetHeight){
populateInner(colA,targetHeight,colB);
targetHeight=colsContainerHeight-headingHeight-imageHeight-stocksHeight}};
if(_screensizemode=='largewide'){
var colC=colsContainer.querySelector('.colC');
if(colB.offsetHeight>targetHeight){
populateInner(colB,targetHeight,colC);
targetHeight=colsContainerHeight;
while(colC.offsetHeight>targetHeight){
colsContainerCount++;
newColsContainer=document.createElement('div');
newColsContainer.className='cols cols'+colsContainerCount;
colsContainer.parentNode.appendChild(newColsContainer);
newColA=newColsContainer.appendChild(colA.cloneNode(false));
newColB=newColsContainer.appendChild(colB.cloneNode(false));
newColC=newColsContainer.appendChild(colC.cloneNode(false));
populateInner(colC,targetHeight,newColA);
if(newColA.offsetHeight>targetHeight){
populateInner(newColA,colsContainerHeight,newColB)}
else break;
if(newColB.offsetHeight>targetHeight){
populateInner(newColB,colsContainerHeight,newColC)}
else break;
colC=newColC}}}
else while(colB.offsetHeight>targetHeight){
colsContainerCount++;
newColsContainer=document.createElement('div');
newColsContainer.className='cols cols'+colsContainerCount;
colsContainer.parentNode.appendChild(newColsContainer);
newColA=newColsContainer.appendChild(colA.cloneNode(false));
newColB=newColsContainer.appendChild(colB.cloneNode(false));
populateInner(colB,targetHeight,newColA);
if(newColA.offsetHeight>colsContainerHeight){
populateInner(newColA,colsContainerHeight,newColB)}
else break;
colB=newColB;
targetHeight=colsContainerHeight};
if(articleRelated){
if(debug)console.log('Adding related content...',articleRelated);
var lastColsContainer=articlePage.querySelector('.cols'+colsContainerCount),emptyCol=lastColsContainer.querySelector('.colA:empty, .colB:empty, .colC:empty');
if(emptyCol&&(_screensizemode=='largewide'||emptyCol.className!='colC')){
emptyCol.appendChild(articleRelated)}
else{
newColsContainer=lastColsContainer.parentNode.appendChild(document.createElement('div'));
newColsContainer.className='cols cols'+(++colsContainerCount);
newColsContainer.appendChild(colA.cloneNode(false)).appendChild(articleRelated);
newColsContainer.appendChild(colB.cloneNode(false));
if(_screensizemode=='largewide')newColsContainer.appendChild(colC.cloneNode(false))}};
if(articleAd){
if(debug)console.log('Adding advert...',articleAd);
var lastColsContainer=articlePage.querySelector('.cols'+colsContainerCount),emptyCol=lastColsContainer.querySelector('.colA:empty, .colB:empty, .colC:empty');
if(emptyCol&&(_screensizemode=='largewide'||emptyCol.className!='colC')){
emptyCol.appendChild(articleAd.cloneNode(true))}
else{
newColsContainer=lastColsContainer.parentNode.appendChild(document.createElement('div'));
newColsContainer.className='cols cols'+(++colsContainerCount);
newColsContainer.appendChild(colA.cloneNode(false)).appendChild(articleAd)}};
scroller.setupScroller();
var oldPageIndicator=articlePage.querySelector('.pageindicator'),newPageIndicator=oldPageIndicator.cloneNode(false);
oldPageIndicator.parentNode.replaceChild(newPageIndicator,oldPageIndicator);
for(var i=0,dot;i<scroller.maxSegments.e;i++){
dot=newPageIndicator.appendChild(document.createElement('span').appendChild(document.createTextNode('•')).parentNode);
dot.className=i==scroller.currentSegment.e?'active':'inactive';
dot.setAttribute('data-page',i);
dot.addEventListener('click',function(){
var targetPage=parseInt(this.getAttribute('data-page'));
scroller.snapToGrid=false;
scroller.scrollTo(targetPage*colsContainer.clientWidth,0,1000);
scroller.scrollTo(targetPage*colsContainer.clientWidth,0,1000);
scroller.currentSegment.e=targetPage;
scroller.snapToGrid=true;
scroller._fireEvent('segmentchange',{axis:'e',segment:targetPage,numSegments:scroller.maxSegments.e})},false)};
var colContainers=articlePage.querySelectorAll('.contentinnerwrapper .cols'),colWidth=colA.clientWidth,columnScrollAction=function(e){
var offsetX=Math.abs(e.offsetX)+colWidth;
if(offsetX<colWidth*2){
scroller.scrollBy(-colsContainer.clientWidth,0,1000)}
else if(offsetX>(colsContainer.offsetWidth-colWidth))scroller.scrollBy(colsContainer.clientWidth,0,1000)};
for(var i=0;i<colContainers.length;i++)colContainers[i].addEventListener('click',columnScrollAction)};
mFT.reflowArticleColumns=function(){
scroller.scrollTo(0,0,0);
scroller.currentSegment.e=0;
var oldContentInner=articlePage.querySelector('.contentinnerwrapper'),oldStocks=contentInner.querySelector('.marketsdata.contentmarketsdata');
if(oldStocks)oldStocks.parentNode.replaceChild(oldContentInner.querySelector('.marketsdata.contentmarketsdata'),oldStocks);
if(articleAd&&!articleAd.AssankaCopied){
articleAd=oldContentInner.querySelector('.adplaceholder');
if(articleAd){
var oldScript=articleAd.querySelector('script');
if(oldScript)oldScript.parentNode.removeChild(oldScript);
articleAd.AssankaCopied=true}};
var newContentInner=contentInner.cloneNode(true);
_loadImagesInElement(newContentInner);
oldContentInner.parentNode.replaceChild(newContentInner,oldContentInner);
flowArticleColumns()};
window.addEventListener("orientationchange",function(){
if(_screenColumns.center.pageType!='content'||_screenColumns.center.pageIdentifier!=articleId){
if(debug)console.log('Not content page, removing event listener');
window.removeEventListener("orientationchange",arguments.callee,false);
return};
if(debug)console.log('Article columns orientation change');
mFT.updateArticleContentHeight();
mFT.reflowArticleColumns()},false);
scroller=new TouchScroll(articlePage.querySelector('.content'),{elastic:true,scrollbars:false,snapToGrid:true});
scroller._dom.outer.addEventListener('segmentchange',function(e){
if(debug)console.log('Scroller segment has changed',e);
var p,i=0,pageIndicator=articlePage.querySelector('.pageindicator');
while((p=pageIndicator.childNodes[i])&&p.nodeType==Node.ELEMENT_NODE){
p.className=i==e.segment?'active':'inactive';
i++}},false);
scroller._dom.scrollers.inner.removeEventListener('DOMSubtreeModified',scroller,false);
flowArticleColumns()}
function _buildContentPage(targetView,theContentObject,addFooter,removePageIndicator){
var newPage=_eleWithId('contenttemplate').cloneNode(true);
newPage.id=null;
newPage.querySelector('.headerbuttons').style.display='none';
newPage.querySelector('.content').innerHTML=theContentObject.content;
if(_enableNavigationHack)newPage.querySelector('.headerbar').style.width=window.innerWidth+'px';
if(theContentObject.title)newPage.querySelector('.contenttitle').innerHTML=theContentObject.title;
if(theContentObject.breadcrumbs){
var breadcrumbhtml='';
for(var i in theContentObject.breadcrumbs)breadcrumbhtml+='<div>'+theContentObject.breadcrumbs[i].title+'</div>';
newPage.querySelector('.breadcrumbbarinner').innerHTML=breadcrumbhtml}
else newPage.querySelector('.breadcrumbbar').style.display='none';
if(removePageIndicator)newPage.querySelector('.pageindicator').style.display='none';
if(addFooter)newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
var targetNode=_eleWithId(_screenColumns[targetView].id);
targetNode.innerHTML='';
targetNode.appendChild(newPage)}
function loadPodcastsIndex(preloading){
preloading=preloading||_preloadcontentmode;
if(uaIsOffline()){
if(!preloading)if(!_screenColumns.center.pageType){
mFT.router.loadHome()}
else{
hidePopover();
offlineWarningPopOver();
if(_screenColumns.center.pageType=='podcasts')mFT.router.loadHome()};
return};
var newPage=_eleWithId('podcaststemplate').cloneNode(true);
newPage.id=null;
var targetView='right';
if(_wrapperUsesGallery||!_screenColumns.center.pageType||(_screenColumns.center.pageType=='podcasts')){
targetView='center'}
else{
var centerColumnKey=_getPrimaryContentKeyForCenterPage();
if(centerColumnKey){
var podcastIndex=_primarynavlookup.podcasts,curIndex=_primarynavlookup[centerColumnKey];
if(curIndex==0&&podcastIndex==_sortedprimarynav.length-1&&(!_sectionSelectorOpen||_sectionSelectorClosing)){
targetView='left'}
else if(podcastIndex<curIndex)targetView='left'}};
if(!_podcasts||!_podcasts.length){
newPage.querySelector('.rail.podcasts').innerHTML='<div class="contentloading" style="padding: 20px;"><p>Loading podcasts...</p><p class="contentloadingimage"><span class="progressbar standardprogressbar" style="width: 50%"></span></p></div>';
var podcastsErrorHandler=function(){
if(_screenColumns.center.pageType=='podcasts'){
alert('Podcasts could not be retrieved from the server; please check your connection and try again.');
goBack()}};
Assanka.$.ajax({url:'/podcasts',dataType:'json',success:function(response){
if(!response||!response.length)return podcastsErrorHandler();
_podcasts=response;
if(targetView!='center'&&_screenColumns.center.pageType=='podcasts'){
targetView='center'}
else if(_screenColumns[targetView].pageType!='podcasts')return;
loadPodcastsIndex(preloading)},error:podcastsErrorHandler})}
else{
var subsections=newPage.querySelector('ul.sectionsubsections'),subsection,playlists=newPage.querySelector('.rail.podcasts'),playlist,podcast,img,latest=subsections.querySelector('.playlist-latest');
latest.addEventListener('click',showPodcastLatest);
for(var i in _podcasts){
subsection=subsections.appendChild(document.createElement('li'));
subsection.className='playlist-'+i;
subsection.setAttribute('data-playlistidx',i);
subsection.appendChild(document.createElement('p')).appendChild(document.createTextNode(_podcasts[i].name));
subsection.addEventListener('click',podcastSubsectionClickHandler)}};
newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
var targetNode=_eleWithId(_screenColumns[targetView].id);
targetNode.innerHTML='';
targetNode.appendChild(newPage);
_screenColumns[targetView].pageType='podcasts';
_screenColumns[targetView].pageIdentifier=false;
if(!preloading)_currentcategory=false;
var subsectionscroller=newPage.querySelector('.sectionsubsectionscroller');
if(_podcasts&&_podcasts.length){
showPodcastLatest(targetView);
subsectionscroller.touchscroll=new TouchScroll(subsectionscroller,{elastic:true,scrollbars:false});
_updateSubsectionArrowsWithScroll(subsectionscroller,'selected',false);
subsectionscroller.addEventListener('scrollend',function(){
_updateSubsectionArrowsWithScroll(subsectionscroller,false)},false)};
if(!preloading){
if(targetView!='center')_slideView(targetView);
_addHistoryEntry('podcasts','')}}
function podcastSubsectionClickHandler(){
var index=this.getAttribute('data-playlistidx');
if(index)showPodcastPlaylist(index)}
function _formatSectionLinks(index,targetView){
var subsectionScroller=_eleWithId(_screenColumns[targetView].id).querySelector('.sectionsubsectionscroller'),sectionLinks=subsectionScroller.querySelectorAll('li'),sectionLink=subsectionScroller.querySelector('li.playlist-'+index);
for(var i in sectionLinks)if(sectionLinks[i].className)sectionLinks[i].className=sectionLinks[i].className.replace(/active/,'');
sectionLink.className=sectionLink.className+' active'}
function showPodcastPlaylist(index){
var playlistContainer=_eleWithId(_screenColumns.center.id).querySelector('.rail.podcasts');
if(!playlistContainer)return;
_formatSectionLinks(index,'center');
playlistContainer.innerHTML='';
playlist=document.createElement('ol');
playlist.className='playlist';
if(_podcasts[index].playlist.length){
for(var i in _podcasts[index].playlist){
podcast=playlist.appendChild(_formatPodcastListItem(_podcasts[index],_podcasts[index].playlist[i]));
podcast.setAttribute('data-playlistidx',index);
podcast.setAttribute('data-podcastidx',i);
podcast.addEventListener('click',podcastClickHandler)}}
else playlist.appendChild(document.createElement('li')).appendChild(document.createTextNode('Podcasts for '+_podcasts[index].name+' are unavailable right now.'));
playlistContainer.appendChild(playlist);
updateContentHeight()}
function showPodcastLatest(targetView){
if(typeof targetView!=='string')targetView='center';
var playlistContainer=_eleWithId(_screenColumns[targetView].id).querySelector('.rail.podcasts');
if(!playlistContainer)return;
_formatSectionLinks('latest',targetView);
playlistContainer.innerHTML='';
var podcast,playlist=document.createElement('ol');
playlist.className='playlist';
for(var i in _podcasts){
if(!_podcasts[i].playlist[0])continue;
podcast=playlist.appendChild(_formatPodcastListItem(_podcasts[i],_podcasts[i].playlist[0]));
podcast.setAttribute('data-playlistidx',i);
podcast.setAttribute('data-podcastidx',0);
podcast.addEventListener('click',podcastClickHandler)};
if(!podcast)playlist.appendChild(document.createElement('li')).appendChild(document.createTextNode('Podcasts are unavailable right now.'));
playlistContainer.appendChild(playlist);
updateContentHeight()}
function _formatPodcastListItem(podcast,item){
var li=document.createElement('li'),img=li.appendChild(document.createElement('img')),desc=li.appendChild(document.createElement('div')),name=desc.appendChild(document.createElement('h5')),title=desc.appendChild(document.createElement('p')),duration=item.duration.split(':'),date=document.createElement('span');
img.src=podcast.image;
img.className='podcast-image';
desc.className='desc';
name.textContent=podcast.name;
title.textContent=item.title+' ';
duration=duration[1][1]+'m '+duration[2]+'s';
date.className='date';
date.innerHTML=item.date+' <span class="duration">'+duration+'<span>';
title.appendChild(date);
return li}
function podcastClickHandler(){
var playlistidx=this.getAttribute('data-playlistidx'),podcastidx=this.getAttribute('data-podcastidx');
if(!playlistidx||!podcastidx)return;
loadPodcast(playlistidx,podcastidx)}
function podcastAppleClickHandler(){
var uri=this.getAttribute('data-itunes');
if(!uri)return;
location.href='http://itunes.apple.com/au/podcast/'+uri}
function loadPodcast(playlistidx,podcastidx){
if(uaIsOffline()){
hidePopover();
offlineWarningPopOver();
return};
if(!_podcasts[playlistidx]||!_podcasts[playlistidx].playlist||!_podcasts[playlistidx].playlist[podcastidx])alert('The podcast cannot be loaded');
var podcast=_podcasts[playlistidx].playlist[podcastidx],newPage=_eleWithId('podcasttemplate').cloneNode(true);
newPage.id=null;
newPage.querySelector('.heading .name').innerHTML=_podcasts[playlistidx].name;
newPage.querySelector('.heading h4').innerHTML=podcast.title;
newPage.querySelector('.body .date').innerHTML=podcast.date;
newPage.querySelector('.body .description').innerHTML=podcast.description;
newPage.querySelector('.footer .description').innerHTML=_podcasts[playlistidx].description;
newPage.querySelector('.footer .podcast-image').src=_podcasts[playlistidx].image;
newPage.querySelector('.footer button').setAttribute('data-itunes',_podcasts[playlistidx].itunes);
newPage.querySelector('.footer button').addEventListener('click',podcastAppleClickHandler);
newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
var targetNode=_eleWithId(_screenColumns.right.id);
targetNode.innerHTML='';
targetNode.appendChild(newPage);
_screenColumns.right.pageType='podcast';
_slideView('right');
var audioContainer=positionAudioPlayer(),audioPlayer=audioContainer.querySelector('audio');
if(audioPlayer.getAttribute('data-playlistidx')!=playlistidx||audioPlayer.getAttribute('data-podcastidx')!=podcastidx){
audioPlayer.src=podcast.audio.url;
audioPlayer.load();
audioPlayer.play();
audioPlayer.setAttribute('data-playlistidx',playlistidx);
audioPlayer.setAttribute('data-podcastidx',podcastidx)};
var podcastVisibilityTimeout=setTimeout(function(){
audioContainer.style.visibility='visible'},1000);
newPage.querySelector('.backbuttonwrapper').addEventListener('click',function(){
if(podcastVisibilityTimeout)clearTimeout(podcastVisibilityTimeout);
audioContainer.style.visibility='hidden';
window.removeEventListener('orientationchange',positionAudioPlayer,false);
_slideView('left')});
_addHistoryEntry('podcasts',podcast.id,podcast.title,podcast.guid)};
mFT.loadPodcast=loadPodcast
function positionAudioPlayer(){
var audioContainer=_eleWithId('podcast-player');
audioContainer.style.top=document.querySelector('.audio-placeholder').offsetTop+'px';
window.addEventListener('orientationchange',positionAudioPlayer,false);
return audioContainer}
function setMarketsDataRegion(region){
var oldregion='marketsdata' in localStorage?(localStorage.marketsdataregion||'EUR'):false;
if(region!='AME'&&region!='EUR'&&region!='ASP')return;
localStorage.marketsdataregion=region;
_marketdata={};
_lastmarketdataupdate=0;
if('marketsdata' in localStorage){
_constructMarketsDataFromString(localStorage.marketsdata,false,true);
loadMarketsData()}
else{
_updateMarketsDataFromServer(function(){
if(!('marketsdata' in localStorage)){
if(uaIsOffline()){
offlineWarningPopOver('This markets data could not be loaded because you are currently offline and no cache is available. Please try again when you are online.')}
else alert('The markets data for that region could not be loaded. Please try again later.');
if(oldregion)setMarketsDataRegion(oldregion);
return}
else loadMarketsData()});
loadMarketsData()}};
mFT.setMarketsDataRegion=setMarketsDataRegion
function loadMarketsData(){
if(_wrapperUsesGallery||!_screenColumns.center.pageType||(_screenColumns.center.pageType=='marketsdata'&&!_screenColumns.center.pageIdentifier)){
_buildMarketsDataPageInit('center',_preloadcontentmode);
_addHistoryEntry('marketsdata','')}
else{
var targetpane='right',centerColumnKey=_getPrimaryContentKeyForCenterPage();
if(centerColumnKey){
var marketsIndex=_primarynavlookup.marketsdata,curIndex=_primarynavlookup[centerColumnKey];
if(curIndex==0&&marketsIndex==_sortedprimarynav.length-1&&(!_sectionSelectorOpen||_sectionSelectorClosing)){
targetpane='left'}
else if(marketsIndex<curIndex)targetpane='left'};
if(_screenColumns.center.pageType=='marketsdata'&&_screenColumns.center.pageIdentifier)targetpane='left';
if(_preloadcontentmode&&!('marketsdata' in localStorage))return;
if(_screenColumns[targetpane].pageType!='marketsdata'||_screenColumns[targetpane].pageIdentifier)_buildMarketsDataPageInit(targetpane,_preloadcontentmode);
if(_preloadcontentmode)return;
if(!_screenPanActionRequired)_slideView(targetpane);
_addHistoryEntry('marketsdata','')};
doAdverts('ros','marketsdata');
if(!_preloadcontentmode)_currentcategory=false};
mFT.loadMarketsData=loadMarketsData
function buildMarketMovers(container,listPage,previousButton,nextButton,titleArea,xofyArea){
if(typeof listPage=='undefined')listPage=1;
if(typeof previousButton=='undefined')previousButton=false;
if(typeof nextButton=='undefined')nextButton=false;
if(typeof titleArea=='undefined')titleArea=false;
if(typeof xofyArea=='undefined')xofyArea=false;
if(!_marketdata)return;
var exchangename=_marketdata.movers['rankings'][listPage-1]['exchange'],numexchanges=_marketdata.movers['rankings'].length,gainers=_marketdata.movers['rankings'][listPage-1]['gainers'],losers=_marketdata.movers['rankings'][listPage-1]['losers'];
if(numexchanges==1){
if(previousButton)previousButton.style.display='none';
if(nextButton)nextButton.style.display='none';
if(xofyArea)xofyArea.style.display='none'}
else{
if(previousButton)if(listPage<=1){
previousButton.onclick=null;
previousButton.className=previousButton.className+' disabled'}
else{
previousButton.onclick=function(){
mFT.pageInChildContent('.exchangecontentcontainer','slideright','buildMarketMovers',listPage-1,'.exchange .previous','.exchange .next','.exchange .title','.exchange .x-of-y')};
previousButton.className=previousButton.className.replace(/\b ?disabled\b/g,'')};
if(nextButton)if(listPage==numexchanges){
nextButton.onclick=null;
nextButton.className=nextButton.className+' disabled'}
else{
nextButton.onclick=function(){
mFT.pageInChildContent('.exchangecontentcontainer','slideleft','buildMarketMovers',listPage+1,'.exchange .previous','.exchange .next','.exchange .title','.exchange .x-of-y')};
nextButton.className=nextButton.className.replace(/\b ?disabled\b/g,'')};
if(xofyArea)xofyArea.innerHTML=listPage+' of '+numexchanges};
if(titleArea)titleArea.innerHTML=exchangename;
var o='<div class="onehalfwidth"><div class="gainers hr3"><div class="tableheading">';
o+='<div class="tabletitle positive">Gainers</div><div class="columnheading">Today</div>';
o+='<div class="clear">&nbsp;</div></div>';
if(gainers)for(var idx=0;idx<gainers.length;idx++){
var r=gainers[idx];
o+='<div class="tablerow" onclick="mFT.router.loadTearsheet(\''+r.ftStandard+'\')"><div class="tablecell">';
o+='<div class="companyname">'+r.companyName+'</div>';
o+='<div class="ftstandard">'+r.ftStandard+'</div>';
o+='</div><div class="tablecell">';
o+='<div class="chgpct '+_getUpDownClass(r.chgPct)+'">'+r.chgPct+'</div>';
o+='<div class="last">'+r.last+'</div>';
o+='</div></div>'};
o+='</div></div><div class="onehalfwidth">';
o+='<div class="losers hr3"><div class="tableheading">';
o+='<div class="tabletitle negative">Losers</div>';
o+='<div class="columnheading">Today</div>';
o+='<div class="clear">&nbsp;</div></div>';
if(losers)for(var idx=0;idx<losers.length;idx++){
var r=losers[idx];
o+='<div class="tablerow" onclick="mFT.router.loadTearsheet(\''+r.ftStandard+'\')"><div class="tablecell">';
o+='<div class="companyname">'+r.companyName+'</div>';
o+='<div class="ftstandard">'+r.ftStandard+'</div>';
o+='</div><div class="tablecell">';
o+='<div class="chgpct '+_getUpDownClass(r.chgPct)+'">'+r.chgPct+'</div>';
o+='<div class="last">'+r.last+'</div>';
o+='</div></div>'};
o+='</div></div><div class="clear">&nbsp;</div>';
return o};
mFT.buildMarketMovers=buildMarketMovers
function buildCurrencyList(container,listPage,previousButton,nextButton,titleArea,xofyArea){
if(typeof listPage=='undefined')listPage=1;
if(typeof previousButton=='undefined')previousButton=false;
if(typeof nextButton=='undefined')nextButton=false;
if(typeof titleArea=='undefined')titleArea=false;
if(typeof xofyArea=='undefined')xofyArea=false;
if(!_marketdata)return;
var currencydata=_marketdata.currencylist['currencies'];
if(!currencydata)return;
var thisccy=currencydata.currencyData[listPage-1],currencyname=currencydata.currencyInfo[thisccy.baseCurrency]['name'],numcurrencies=currencydata.currencyData.length;
if(numcurrencies==1){
if(previousButton)previousButton.style.display='none';
if(nextButton)previousButton.style.display='none';
if(xofyArea)xofyArea.style.display='none'}
else{
if(previousButton)if(listPage<=1){
previousButton.onclick=null;
previousButton.className=previousButton.className+' disabled'}
else{
previousButton.onclick=function(){
mFT.pageInChildContent('.currencycontentcontainer','slideright','buildCurrencyList',listPage-1,'.currency .previous','.currency .next','.currency .title','.currency .x-of-y')};
previousButton.className=previousButton.className.replace(/\b ?disabled\b/g,'')};
if(nextButton)if(listPage==numcurrencies){
nextButton.onclick=null;
nextButton.className=nextButton.className+' disabled'}
else{
nextButton.onclick=function(){
mFT.pageInChildContent('.currencycontentcontainer','slideleft','buildCurrencyList',listPage+1,'.currency .previous','.currency .next','.currency .title','.currency .x-of-y')};
nextButton.className=nextButton.className.replace(/\b ?disabled\b/g,'')};
if(xofyArea)xofyArea.innerHTML=listPage+' of '+numcurrencies};
if(titleArea)titleArea.innerHTML=currencyname;
o='<div class="tableheading"><div class="columnheading">Last</div><div class="columnheading">Change</div><div class="clear">&nbsp;</div></div>';
for(var idx=0;idx<thisccy.conversionCurrencies.length;idx++){
var r=thisccy.conversionCurrencies[idx];
o+='<div class="tablerow">';
o+=' <div class="column value">'+r.value+'</div>';
o+=' <div class="column chgpct '+_getUpDownClass(r.change)+'">'+r.change+'</div>';
o+=' <div class="name">'+r.currency+'</div>';
o+='</div>'};
o+='</div></div>';
return o};
mFT.buildCurrencyList=buildCurrencyList
function buildCommoditiesList(container,listPage,previousButton,nextButton,titleArea,xofyArea){
if(typeof listPage=='undefined')listPage=1;
if(typeof previousButton=='undefined')previousButton=false;
if(typeof nextButton=='undefined')nextButton=false;
if(typeof titleArea=='undefined')titleArea=false;
if(typeof xofyArea=='undefined')xofyArea=false;
if(!_marketdata)return;
var commoditydata=_marketdata.commodities['commodities'];
if(!commoditydata)return;
var thiscommodity=commoditydata[listPage-1],numcommodities=commoditydata.length;
if(numcommodities==1){
if(previousButton)previousButton.style.display='none';
if(nextButton)nextButton.style.display='none';
if(xofyArea)xofyArea.style.display='none'}
else{
if(previousButton)if(listPage<=1){
previousButton.onclick=null;
previousButton.className=previousButton.className+' disabled'}
else{
previousButton.onclick=function(){
mFT.pageInChildContent('.commoditycontentcontainer','slideright','buildCommoditiesList',listPage-1,'.commodity .previous','.commodity .next','.commodity .title','.commodity .x-of-y')};
previousButton.className=previousButton.className.replace(/\b ?disabled\b/g,'')};
if(nextButton)if(listPage==numcommodities){
nextButton.onclick=null;
nextButton.className=nextButton.className+' disabled'}
else{
nextButton.onclick=function(){
mFT.pageInChildContent('.commoditycontentcontainer','slideleft','buildCommoditiesList',listPage+1,'.commodity .previous','.commodity .next','.commodity .title','.commodity .x-of-y')};
nextButton.className=nextButton.className.replace(/\b ?disabled\b/g,'')};
if(xofyArea)xofyArea.innerHTML=listPage+' of '+numcommodities};
if(titleArea)titleArea.innerHTML=thiscommodity.category;
o='<div class="tableheading"><div class="columnheading bar">Low &nbsp; 52-week &nbsp; High</div><div class="columnheading">Last price</div><div class="columnheading">Today\'s change</div><div class="clear">&nbsp;</div></div>';
for(var idx=0;idx<thiscommodity.commoditiesInCategory.length;idx++){
var r=thiscommodity.commoditiesInCategory[idx],p=Math.floor(100*(r.last.replace(',','')-r.low52Week.replace(',',''))/(r.high52Week.replace(',','')-r.low52Week.replace(',','')));
o+='<div class="tablerow">';
o+=' <div class="column bar"><div class="sliderbox"><div class="slider" style="left:'+p+'%;">&nbsp;</div></div></div>';
o+=' <div class="column value">'+r.last+'</div>';
o+=' <div class="column chgpct '+_getUpDownClass(r.chgPct)+'">'+r.change+'<br />';
o+=' <span>'+r.chgPct+'</span></div>';
o+=' <div class="name"><strong>'+r.name+'</strong><br />';
o+=' <span class="as-of">'+r.date+'</span></div>';
o+=' <div class="clear">&nbsp;</div>';
o+='</div>'};
o+='</div></div>';
return o};
mFT.buildCommoditiesList=buildCommoditiesList
function _buildMarketsDataPageInit(targetview,ispreloading){
var newPage=_eleWithId('marketsdatatemplate').cloneNode(true);
newPage.id=null;
var region=localStorage.marketsdataregion||'EUR';
newPage.querySelector('.region-label.'+region).className+=' selectedregion';
newPage.querySelector('.map-button.'+region).className+=' selectedregion';
if(_enableNavigationHack)newPage.querySelector('.headerbar').style.width=window.innerWidth+'px';
newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
var targetNode=_eleWithId(_screenColumns[targetview].id);
targetNode.innerHTML='';
targetNode.appendChild(newPage);
_screenColumns[targetview].pageType='marketsdata';
_screenColumns[targetview].pageIdentifier=false;
updateContentHeight();
if(_lastmarketdataupdate)if(new Date().getTime()<_lastmarketdataupdate+30*60*1000){
_buildMarketsDataPage(targetview,ispreloading);
return};
var _prebuildMarketsViewPage=function(){
var contentLoadView=false;
if(_screenColumns.center.pageType=='marketsdata'&&!_screenColumns.center.pageIdentifier){
contentLoadView='center'}
else if(_screenColumns[targetview].pageType=='marketsdata'&&!_screenColumns[targetview].pageIdentifier)contentLoadView=targetview;
if(!contentLoadView)return;
_buildMarketsDataPage(contentLoadView,ispreloading)};
_updateMarketsDataFromServer(_prebuildMarketsViewPage)}
function _buildMarketsDataPage(targetview,ispreloading){
var newPage=_eleWithId('marketsdatatemplate').cloneNode(true);
newPage.id=null;
_screenColumns[targetview].disableContentBalance=true;
var region=localStorage.marketsdataregion||'EUR';
newPage.querySelector('.region-label.'+region).className+=' selectedregion';
newPage.querySelector('.map-button.'+region).className+=' selectedregion';
if(!_marketdata||!('headlines' in _marketdata)){
if(!ispreloading){
alert("The markets data you requested is not available offline");
window.setTimeout(function(){
goBack();
preloadAdjacentContent()},_screenPanActionRequired?1000:10)};
if(_screenColumns[targetview].pageType=='marketsdata'&&!_screenColumns[targetview].pageIdentifier)_screenColumns[targetview].pageType=false;
return};
_buildMarketsDataMacroMap(newPage.querySelector('.markers'));
var headlineIndices=_marketdata.headlines['overview']['indices'],el=newPage.querySelector('.wsodindices');
for(var idx in headlineIndices)_buildMarketsDataHeadlineIndices(headlineIndices[idx],el);
var el=newPage.querySelector('.benchmark.bonds');
for(var dataidx in _marketdata.benchmarks['Bonds']){
var data=_marketdata.benchmarks['Bonds'][dataidx];
el.innerHTML+='<div class="tablerow"><div class="column chgpct '+_getUpDownClass(data.chgPct)+'">'+data.chgPct+'</div><div class="column divyield">'+data.divYield+'</div><div class="name">'+data.name+'</div></div>'};
var el=newPage.querySelector('.benchmark.currencies');
for(var dataidx in _marketdata.benchmarks['Currencies']){
var data=_marketdata.benchmarks['Currencies'][dataidx];
el.innerHTML+='<div class="tablerow"><div class="column chgpct '+_getUpDownClass(data.change)+'">'+data.change+'</div><div class="column divyield">'+data.value+'</div><div class="name">'+data.currencyDisplay+'</div></div>'};
var el=Array();
el[0]=newPage.querySelector('.benchmark.commodities-crude');
el[1]=el[0];
el[2]=newPage.querySelector('.benchmark.commodities-gold');
el[3]=newPage.querySelector('.benchmark.commodities-crops');
el[4]=el[3];
for(var dataidx in _marketdata.benchmarks['Commodities']){
var data=_marketdata.benchmarks['Commodities'][dataidx];
el[dataidx].innerHTML+='<div class="tablerow"><div class="column chgpct '+_getUpDownClass(data.chgPct)+'">'+data.chgPct+'</div><div class="column divyield">'+data.last+'</div><div class="name">'+data.name+'</div></div>'};
newPage.querySelector('.currencyperformancechartcontainer').innerHTML='<img src="data:'+localStorage.marketscurrencieschart+'" />';
newPage.querySelector('.bondschartcontainer').innerHTML='<img src="data:'+_marketdata.bondschart+'" />';
var bonds=_marketdata.bonds['bonds'][0],bonds=_marketdata.bonds['bonds'][0];
newPage.querySelector('.yield .tabletitle').innerText=bonds.tableName;
var el=newPage.querySelector('.yield');
for(var i=0;i<bonds.periods.length;i++){
var p=bonds.periods[i];
el.innerHTML+='<div class="tablerow"><div class="column 1monthago">'+p.oneMonth+'</div><div class="column 1weekago">'+p.oneWeek+'</div><div class="column change '+_getUpDownClass(p.change)+'">'+p.change+'</div><div class="column yield">'+p.last+'</div><div class="name"><strong>'+p.time+'</strong></div><div class="clear">&nbsp;</div></div>'};
var marketmoverhtml=buildMarketMovers('.exchangecontentcontainer',1,newPage.querySelector('.exchange .previous'),newPage.querySelector('.exchange .next'),newPage.querySelector('.exchange .title'),newPage.querySelector('.exchange .x-of-y'));
newPage.querySelector('.exchangecontentcontainer > div').innerHTML=marketmoverhtml;
var currencyhtml=buildCurrencyList('.currencycontentcontainer',1,false,false,newPage.querySelector('.currency .title'),newPage.querySelector('.currency .x-of-y'));
newPage.querySelector('.currencycontentcontainer > div').innerHTML=currencyhtml;
var commodityhtml=buildCommoditiesList('.commoditycontentcontainer',1,false,false,newPage.querySelector('.commodity .title'),newPage.querySelector('.commodity .x-of-y'));
newPage.querySelector('.commoditycontentcontainer > div').innerHTML=commodityhtml;
var asofs=newPage.querySelectorAll('.as-of');
for(var thisIdx in asofs)asofs[thisIdx].innerText=_marketdata['as-of'];
newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
if(_enableNavigationHack)newPage.querySelector('.headerbar').style.width=window.innerWidth+'px';
newPage.querySelector('.spinner').style.display='none';
newPage.querySelector('.fulldata').style.display='block';
var targetNode=_eleWithId(_screenColumns[targetview].id);
targetNode.innerHTML='';
targetNode.appendChild(newPage);
_screenColumns[targetview].pageType='marketsdata';
_screenColumns[targetview].pageIdentifier=false;
updateContentHeight();
_notifyIfDataIsStale(targetview,region)}
function _buildMarketsDataHeadlineIndices(data,parentel){
var el=document.createElement('div');
el.className='indices';
var updown='down';
if(data.chgPct.replace('%','')>0)updown='up';
if(data.chgPct.replace('%','')==0)updown='nochange';
data.chgPct=data.chgPct.replace('+','');
data.chgPct=data.chgPct.replace('-','');
el.innerHTML='<div class="chgpct '+updown+'"><div class="icon">&nbsp;</div>'+data.chgPct+'</div><div class="name">'+data.name+'</div><div class="last">'+data.last+'</div>';
el.innerHTML+='<div class="wsodchart"><img width="153" height="125" src="data:'+_marketdata.indexcharts[data.wsodIssue]+'"></div>';
parentel.appendChild(el)}
function _buildMarketsDataMacroMap(wrapperel){
if(!('marketsmacromap' in localStorage))return;
var mapWidth=document.width,mapHeight=Math.floor(mapWidth*284/600);
mapdef=JSON.parse(localStorage.marketsmacromap);
var o="",scalefactorW=0.91,scalefactorH=0.8,scalefactorW2=mapWidth/600,scalefactorH2=mapHeight/284,thisview=mapdef.views['global'];
for(var countrycode in thisview){
var thislabel='<div class="markers" style="',top=Math.floor(scalefactorH*(thisview[countrycode]['y']+10)*scalefactorH2),left=Math.floor((scalefactorW*(thisview[countrycode]['x'])-100)*scalefactorW2);
thislabel+='top:'+top+'px; left:'+left+'px">';
for(var exidx in thisview[countrycode]['indexKeys']){
exname=thisview[countrycode]['indexKeys'][exidx];
var thisex=mapdef.indexList[exname],updown='down';
if(thisex.pctChg.replace('%','')>0)updown='up';
if(thisex.pctChg.replace('%','')==0)updown='nochange';
var thisprice=thisex.pctChg;
thislabel+='<div class="label size'+thisex.size+'"><span class="name '+updown+'">'+thisex.name+' <span class="price '+updown+'">'+thisprice+'</span></div>'};
thislabel+='</div>';
o+=thislabel};
wrapperel.innerHTML=o}
function _notifyIfDataIsStale(targetview){
var now=new Date();
if(_lastmarketdataupdate){
marketsdatadltime=new Date(parseInt(_lastmarketdataupdate));
var dlinterval=(now.getTime()/1000/60/60)-(marketsdatadltime.getTime()/1000/60/60);
if(dlinterval>24){
_showStaleDataNotice(targetview,'You last updated your Market Data on <strong>'+marketsdatadltime.toLocaleString()+'</strong>','red')}
else if(dlinterval>0.5)_showStaleDataNotice(targetview,'You last updated your Market Data on <strong>'+marketsdatadltime.toLocaleString()+'</strong>','yellow')}}
function _showStaleDataNotice(targetview,message,colour){
var noticeDiv=document.createElement('div');
noticeDiv.id='staledatanotice';
noticeDiv.className=colour;
noticeDiv.innerHTML=message;
var oldDiv=document.getElementById(noticeDiv.id);
if(oldDiv)oldDiv.parentNode.removeChild(oldDiv);
var targetel='#'+_screenColumns[targetview].id+((_screensizemode=='small'||_screensizemode=='medium')?' .marketsdata':''),mdcol=document.querySelector(targetel);
if(!mdcol)return;
mdcol.insertBefore(noticeDiv,mdcol.firstChild)}
function loadTearsheet(linkitem){
if(typeof linkitem=='object'){
var symbol=linkitem.getAttribute('data-id')}
else var symbol=linkitem;
var targetColumn='right';
if(_wrapperUsesGallery||!_screenColumns.center.pageType||(_screenColumns.center.pageType=='marketsdata'&&_screenColumns.center.pageIdentifier==symbol))targetColumn='center';
if(targetColumn=='center'||_screenColumns[targetColumn].pageType!='marketsdata'||_screenColumns.center.pageIdentifier!=symbol)_buildTearsheetPage(symbol,targetColumn);
if(targetColumn!='center'){
_slideView(targetColumn)}
else updateContentHeight();
_addHistoryEntry('tearsheet',symbol);
_currentCategory=false};
mFT.loadTearsheet=loadTearsheet
function _buildTearsheetPage(symbol,targetview){
var placeholderPage=_eleWithId('contenttemplate').cloneNode(true);
placeholderPage.id=null;
placeholderPage.querySelector('.content').innerHTML='<p class="contentloading">Loading tearsheet...</p><p class="contentloadingimage"><span class="progressbar standardprogressbar" style="width: 50%"></span></p>';
placeholderPage.querySelector('.breadcrumbbar').style.display='none';
placeholderPage.querySelector('.headerbuttons').style.display='none';
placeholderPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
if(_enableNavigationHack)placeholderPage.querySelector('.headerbar').style.width=window.innerWidth+'px';
var targetNode=_eleWithId(_screenColumns[targetview].id);
targetNode.innerHTML='';
targetNode.appendChild(placeholderPage);
_screenColumns[targetview].pageType='marketsdata';
_screenColumns[targetview].pageIdentifier=symbol;
var tearsheetFetchErrorHandler=function(){
if(_screenColumns.center.pageType!='marketsdata'||_screenColumns.center.pageIdentifier!=symbol)return;
alert("Data about this company could not be loaded. ");
goBack()};
Assanka.$.ajax({url:"/tearsheetdata/"+symbol,dataType:"json",success:function(tearsheetdata){
if(!tearsheetdata||isObjectEmpty(tearsheetdata))return tearsheetFetchErrorHandler();
if(_screenColumns.center.pageType!='marketsdata'||_screenColumns.center.pageIdentifier!=symbol)return;
var tearsheetPage=_eleWithId('tearsheettemplate').cloneNode(true);
tearsheetPage.id=null;
for(var tearsheetsection in tearsheetdata)for(var tearsheetdatakey in tearsheetdata[tearsheetsection]){
key='tearsheet-'+tearsheetsection+'-'+tearsheetdatakey;
value=tearsheetdata[tearsheetsection][tearsheetdatakey];
var tearsheetobj=tearsheetPage.querySelector('.'+key);
if(tearsheetobj){
tearsheetobj.innerText=value;
if(key=="tearsheet-profile-revenue"|key=="tearsheet-snapshot-chgPct"|key=="tearsheet-snapshot-change"|key=="tearsheet-snapshot-oneYearChgPct"|key=="tearsheet-snapshot-oneYearChg"|key=="tearsheet-profile-netIncome"){
var num=parseFloat(value);
if(num!=NaN){
if(num<0)tearsheetobj.className+=" negative";
if(num==0)tearsheetobj.className+=" neutral";
if(num>0)tearsheetobj.className+=" positive"}}}};
var relatedStroiesErrorHandler=function(){
tearsheetPage.querySelector('.company-news').style.display="none";
updateContentHeight()};
Assanka.$.ajax({url:"/companiesnews",dataType:"json",data:{symbol:symbol},success:function(relatedstories){
if(!relatedstories||isObjectEmpty(relatedstories))return relatedStroiesErrorHandler();
var relatedlist="";
for(i in relatedstories.stories)relatedlist+="<li class = "+i+" id='related-story-"+relatedstories.stories[i].DocumentKey+"'>"+relatedstories.stories[i].Headline+"</li>";
tearsheetPage.querySelector('.related-news-list').innerHTML=relatedlist;
for(i in relatedstories.stories){
var clickFunc=function(id){
var i=id.className,theArticle=relatedstories.stories[i];
theArticle.isPlaceholderContent=false;
theArticle.byline=relatedstories.stories[i].Author;
theArticle.guid=relatedstories.stories[i].URL;
theArticle.protectionlevel='normal';
theArticle.content=relatedstories.stories[i].Body;
theArticle.title=relatedstories.stories[i].Headline;
theArticle.snip=relatedstories.stories[i].Teaser;
mFT.router.loadArticle('r_'+i,null,null,theArticle)};
tearsheetPage.querySelector('.related-news-list #related-story-'+relatedstories.stories[i].DocumentKey).onclick=function(){
clickFunc(this)}};
updateContentHeight()},error:relatedStroiesErrorHandler});
var lastPrice=parseFloat(tearsheetdata.snapshot['last'].replace(',','')),lowPrice=parseFloat(tearsheetdata.snapshot['low52Week'].replace(',','')),highPrice=parseFloat(tearsheetdata.snapshot['high52Week'].replace(',','')),price52=100*(lastPrice-lowPrice)/(highPrice-lowPrice);
tearsheetPage.querySelector('.slider').style.left=price52+"%";
if(tearsheetdata.profile['incorporationDate'].length>4){
tearsheetPage.querySelector('.tearsheet-profile-incorporationDate').innerText=tearsheetdata.profile['incorporationDate'].substring(0,4)}
else tearsheetPage.querySelector('.tearsheet-profile-incorporationDate').innerText="--";
var maxagreement=0,consensus="";
for(var opiniontype in tearsheetdata.estimates){
if(opiniontype=='analystsWithOpinion')continue;
if(tearsheetdata.estimates[opiniontype]>maxagreement){
maxagreement=tearsheetdata.estimates[opiniontype];
consensus=opiniontype}};
if(consensus){
var optitle=tearsheetPage.querySelector('.'+consensus.toLowerCase()+'title');
optitle.className+=" consensus";
var opqty=tearsheetPage.querySelector('.tearsheet-estimates-'+consensus);
opqty.className+=" consensus";
opqty.parentNode.className+=" consensus"};
Array.prototype.forEach.call(tearsheetPage.querySelectorAll("img"),function(imageelement){
imageelement.setAttribute('src',imageelement.getAttribute('templatesrc').replace('*****',tearsheetdata.companyInfo['ftStandard']))});
tearsheetPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
if(_enableNavigationHack)tearsheetPage.querySelector('.headerbar').style.width=window.innerWidth+'px';
targetNode.innerHTML='';
targetNode.appendChild(tearsheetPage);
updateContentHeight()},error:tearsheetFetchErrorHandler})}
function loadPortfolio(){
if(!_ftuser){
mFT.router.loadHome();
return};
var targetColumn='right';
if(_wrapperUsesGallery||!_screenColumns.center.pageType||_screenColumns.center.pageType=='portfolio'){
targetColumn='center'}
else if(_screenColumns.center.pageType=='marketsdata')targetColumn='left';
_addHistoryEntry('portfolio','');
_currentcategory=false;
var dummyContent={title:'My Portfolio',content:'<p class="contentloading">Loading portfolio...</p><p class="contentloadingimage"><span class="progressbar standardprogressbar" style="width: 50%"></span></p>'};
_buildContentPage(targetColumn,dummyContent,true,true);
var screenColumnElement=document.querySelector('#'+_screenColumns[targetColumn].id);
_expandElementWithinElementToFillElement(screenColumnElement.querySelector('.content'),screenColumnElement,screenColumnElement.parentNode);
if(targetColumn!='center')_slideView(targetColumn);
_screenColumns.center.pageType='portfolio';
_screenColumns.center.genBaseTime=_laststructureupdate;
var portfolioFetchErrorHandler=function(){
var portfoliodetails=localStorage.portfoliodetails;
if(!portfoliodetails){
alert('Your portfolio cannot currently be retrieved, and no old versions are available. Please try again later (or check your internet connectivity).');
router.loadHome();
return};
portfoliodetails=JSON.parse(portfoliodetails);
if(_screenColumns.center.pageType!='portfolio')return;
var portfolioage=new Date().getTime()/1000-parseInt(portfoliodetails.dateupdated),portfolioagestring='';
if(portfolioage<90){
portfolioagestring='a minute'}
else if(portfolioage<1800){
portfolioagestring=Math.round(portfolioage/60)+' minutes'}
else if(portfolioage<5400){
portfolioagestring='an hour'}
else if(portfolioage<72000){
portfolioagestring=Math.round(portfolioage/3600)+' hours'}
else if(portfolioage<129600){
portfolioagestring='a day'}
else portfolioagestring=Math.round(portfolioage/86400)+' days';
_buildContentPage('center',{content:'<div class="portfolioagewarning system-message">This data was last updated '+portfolioagestring+' ago.</div>'+portfoliodetails.content},true,true);
updateContentHeight();
var screenColumnElement=document.querySelector('#'+_screenColumns.center.id);
_expandElementWithinElementToFillElement(screenColumnElement.querySelector('.content'),screenColumnElement,screenColumnElement.parentNode)},portfolioFetcher=function(){
Assanka.$.ajax({url:sourceURL+'portfolio',type:'POST',dataType:'json',data:{user:JSON.stringify(_ftuser)},success:function(portfolio){
if(!portfolio||!portfolio.success)return portfolioFetchErrorHandler();
var portfoliodetails={dateupdated:(new Date().getTime()/1000),content:portfolio.content};
localStorage.portfoliodetails=JSON.stringify(portfoliodetails);
if(_screenColumns.center.pageType!='portfolio')return;
_buildContentPage('center',{content:portfolio.content,title:'My portfolio'},true,true);
updateContentHeight();
var screenColumnElement=document.querySelector('#'+_screenColumns.center.id);
_expandElementWithinElementToFillElement(screenColumnElement.querySelector('.content'),screenColumnElement,screenColumnElement.parentNode)},error:portfolioFetchErrorHandler})},portfoliodetails=localStorage.portfoliodetails;
if(portfoliodetails)portfoliodetails=JSON.parse(portfoliodetails);
if(portfoliodetails){
var portfolioage=new Date().getTime()/1000-parseInt(portfoliodetails.dateupdated);
if(portfolioage<1800){
portfolioFetchErrorHandler()}
else portfolioFetcher()}
else portfolioFetcher()};
mFT.loadPortfolio=loadPortfolio
function buildPortfolioSummary(){
if(!_ftuser)return'<div class="portfolio-notloggedin"><h4>My portfolio summary</h4><div class="rail last-upated standalonebutton"><button class="narrow" onclick="mFT.showAccount();">Sign in</button><p>Sign in to view your FT.com portfolio</p></div></div>';
var portfolio=_retrievePortfolioSummary();
if(!portfolio)return'<div class="portfolio-noportfolio"><h4>My portfolio summary</h4><div class="rail last-upated standalonebutton"><a class="button" onclick="if(mFT.uaIsOffline()){mFT.offlineWarningPopOver();return false;}" href="http://markets.ft.com/portfolio/all.asp">Set up</a><p>Visit FT.com to set up your portfolio</p></div></div>'
function getPortfolioField(portfolio,f){
var num=parseFloat(portfolio[f].replace(',',''));
if(isNaN(num))return'<span class="'+f+'">'+portfolio[f]+'</span>';
var fieldclass='';
if(f!='currentValue'){
if(num<0)fieldclass="negative";
if(num==0)fieldclass="neutral";
if(num>0)fieldclass="positive"};
var percentsign='';
if(f.indexOf('Percent')!=-1)percentsign='%';
return'<span class="'+f+' '+fieldclass+'">'+num+percentsign+'</span>'};
var op='';
op+='<div class="portfolio-widget render" onclick="mFT.router.loadPortfolio()">';
op+=' <h4>My portfolio summary</h4>';
op+=' <div class="tablerow">';
op+=' <div class="column value">';
op+=' <h5>Total return</h5>';
op+=' '+getPortfolioField(portfolio,'totalReturnDecimal')+'<br>';
op+=' <strong>'+getPortfolioField(portfolio,'totalReturnPercent')+'</strong>';
op+=' </div>';
op+=' <div class="column value">';
op+=' <h5>Current value</h5>';
op+=' '+getPortfolioField(portfolio,'currentValue')+'<br>';
op+=' <strong>'+getPortfolioField(portfolio,'currency')+'</strong>';
op+=' <div class="columnborder"></div>';
op+=' </div>';
op+=' <div class="column chgpct value">';
op+=' <h5>Today\'s change</h5>';
op+=' '+getPortfolioField(portfolio,'todaysChangeDecimal')+'<br>';
op+=' <strong>'+getPortfolioField(portfolio,'todaysChangePercent')+'</strong>';
op+=' <div class="columnborder"></div>';
op+=' </div>';
op+=' <div class="clear">&nbsp;</div>';
op+=' </div>';
op+=' <div class="tablefooter">';
op+=' <div class="notice floatleft">Data delayed at least 20 mins</div>';
if(portfolio['as-of'])op+='<div class="as-of floatright">'+portfolio['as-of']+'</div>';
op+=' <div class="clear"></div>';
op+=' </div>';
op+='</div>';
return op}
function _storePortfolioSummary(portfolioSummary){
if(typeof (portfolioSummary)=='undefined'||!portfolioSummary){
localStorage.removeItem('portfolio')}
else localStorage.setItem('portfolio',JSON.stringify(portfolioSummary))}
function _retrievePortfolioSummary(){
var storedDetails=localStorage.portfolio;
if(!storedDetails)return false;
return JSON.parse(storedDetails)}
function loadCurrencyConverter(){
var dummyContent={title:'Converter',content:'<p class="contentloading">Loading currency converter...</p><p class="contentloadingimage"><span class="progressbar standardprogressbar" style="width: 50%"></span></p>'};
if(_wrapperUsesGallery||!_screenColumns.center.pageType||(_screenColumns.center.pageType=='currencyconverter'&&!_screenColumns.center.pageIdentifier)){
_buildContentPage('center',dummyContent,true,true);
_screenColumns.center.pageType='currencyconverter';
_screenColumns.center.pageIdentifier=false;
updateContentHeight();
_buildCurrencyConverterPageInit(_screenColumns.center,_preloadcontentmode)}
else{
var targetpane='right',centerColumnKey=_getPrimaryContentKeyForCenterPage();
if(centerColumnKey){
var currencyIndex=_primarynavlookup.currencyconverter,curIndex=_primarynavlookup[centerColumnKey];
if(curIndex==0&&currencyIndex==_sortedprimarynav.length-1&&(!_sectionSelectorOpen||_sectionSelectorClosing)){
targetpane='left'}
else if(currencyIndex<curIndex)targetpane='left'};
_buildContentPage(targetpane,dummyContent,true,true);
_screenColumns[targetpane].pageType='currencyconverter';
_screenColumns[targetpane].pageIdentifier=false;
updateContentHeight();
_buildCurrencyConverterPageInit(_screenColumns[targetpane],_preloadcontentmode);
if(_preloadcontentmode)return;
if(!_screenPanActionRequired)_slideView(targetpane)};
updateContentHeight();
if(!_preloadcontentmode)_currentcategory=false};
mFT.loadCurrencyConverter=loadCurrencyConverter
function currencySetValue(value){
currencyHideInstructions();
document.querySelector('#'+_screenColumns.center.id+' .currency-in').value=value+".00";
currencyDoConversion()};
mFT.currencySetValue=currencySetValue
function currencyIn(e,elem){
key=e.which;
fromamount=elem.value;
if(fromamount.length>13&&key!=8)return false;
if(key>47&&key<60){
return true}
else if(key==8){
return true}
else if(key==190&&fromamount.indexOf('.')==-1){
return true}
else return false};
mFT.currencyIn=currencyIn
function currencyFormat(elem){
currencyDoConversion(elem);
var current=elem.value;
current=_tidyCommas(current.replace(/[^0-9\.-]/g,"")+'');
elem.value=current};
mFT.currencyFormat=currencyFormat
function _tidyCommas(nStr){
nStr=nStr.toString();
nStr=nStr.replace(/[\,]/g,"");
nStr=nStr.replace(/(.+)-/,'$1');
x=nStr.indexOf('.');
if(x==-1)x=nStr.length;
x1=nStr.substring(0,x);
x2=nStr.substring(x);
x1=x1.replace(/^(s?0)+s?([\dz])/,'$2');
var rgx=/(([\dz]s?)+)(([\dz]s?){3})/;
while(rgx.test(x1))x1=x1.replace(rgx,'$1,$3');
if((x1==''||x1=='s')&&x2!='')x1=0+x1;
return x1+x2}
function changeSelect(elem){
var currency=elem.querySelector('#'+_screenColumns.center.id+' .currency-select').value,currencydata=JSON.parse(localStorage.getItem('currencydata'));
elem.querySelector('#'+_screenColumns.center.id+' .currency-flag').className="currency-flag "+currency.toString().toLowerCase();
elem.querySelector('#'+_screenColumns.center.id+' .currency-name').innerHTML=currencydata[currency]["ccyname"];
elem.querySelector('#'+_screenColumns.center.id+' .currency-code').innerHTML=currency;
if(currency!="GBP"&&currency!="USD"&&currency!="EUR"){
var recentcurrencies=localStorage.getItem('recentcurrencies'),option="<option value='"+currency+"'>"+currencydata[currency]["ccyname"]+'</option>';
if(recentcurrencies==null){
recentcurrencies=new Array(option)}
else{
recentcurrencies=JSON.parse(recentcurrencies);
if(recentcurrencies.length>2)recentcurrencies.shift();
recentcurrencies.push(option)};
localStorage.setItem('recentcurrencies',JSON.stringify(recentcurrencies));
elem.querySelector(' .recent-currencies').innerHTML=_buildRecentCurrenciesOpt();
elem.querySelector('#'+_screenColumns.center.id+' .currency-select').value=currency};
currencyDoConversion()};
mFT.changeSelect=changeSelect
function _buildRecentCurrenciesOpt(){
currencyjson=JSON.parse(localStorage.getItem('currencydata'));
html='<optgroup label= "Recently used" class="recent-currencies">';
html+='<option value="GBP">British Pound</option>';
html+='<option value="USD">US Dollar</option>';
html+='<option value="EUR">Euro</option>';
recentcurrencyjson=JSON.parse(localStorage.getItem('recentcurrencies'));
if(recentcurrencyjson!=null)for(i in recentcurrencyjson)html+=recentcurrencyjson[i];
html+='</optgroup>';
return html}
function _buildCurrencyConverterPageInit(targetview,preloading){
var _prebuildCurrencyConverterPage=function(){
if(!localStorage.currencydatadownloadtime){
if(!preloading){
mFT.router.loadHome();
if(uaIsOffline()){
offlineWarningPopOver('The currency converter is not available because you are offline. Please try again when you are online.')}
else offlineWarningPopOver('The currency converter is not available at this time. Please try again later.')};
return};
_buildCurrencyConverterPage(targetview,preloading)};
Assanka.$.ajax({url:sourceURL+'currencyconverter',timeout:5000,dataType:'json',success:function(data){
if(data&&data.success){
localStorage.currencydata=JSON.stringify(data.rates);
localStorage.currencydatadownloadtime=new Date().getTime()};
_prebuildCurrencyConverterPage()},error:function(){
if(!localStorage.currencydatadownloadtime){
Assanka.$.ajax({url:sourceURL+'currencyconverter',timeout:5000,dataType:'json',success:function(data){
if(data&&data.success){
localStorage.currencydata=JSON.stringify(data.rates);
localStorage.currencydatadownloadtime=new Date().getTime()};
_prebuildCurrencyConverterPage()},error:function(){
_prebuildCurrencyConverterPage()}})}
else _buildCurrencyConverterPage(targetview,preloading)}})}
function _buildCurrencyConverterPage(targetview,preloading){
var newPage=_eleWithId('currencyconvertertemplate').cloneNode(true);
newPage.id=null;
var currencyhtml=_buildCurrencyList();
newPage.querySelector('.in .currency-select').innerHTML=currencyhtml;
newPage.querySelector('.in .currency-select').value="USD";
newPage.querySelector('.out .currency-select').innerHTML=currencyhtml;
newPage.querySelector('.out .currency-select').value="GBP";
currencydata=JSON.parse(localStorage.getItem('currencydata'));
lastfrom=localStorage.getItem('currencylastfrom');
lastto=localStorage.getItem('currencylastto');
if(lastfrom!=null){
newPage.querySelector('#'+_screenColumns.center.id+'.convert-from .currency-country').innerHTML=currencydata[lastfrom]["ccyname"].split(" ")[0];
newPage.querySelector('#'+_screenColumns.center.id+'.convert-from .currency-type').innerHTML=currencydata[lastfrom]["ccyname"].split(" ")[1]};
if(lastto!=null){
newPage.querySelector('#'+_screenColumns.center.id+'.convert-to .currency-country').innerHTML=currencydata[lastto]["ccyname"].split(" ")[0];
newPage.querySelector('#'+_screenColumns.center.id+'.convert-to .currency-type').innerHTML=currencydata[lastto]["ccyname"].split(" ")[1]};
newPage.appendChild(_eleWithId('footertemplate').cloneNode(true));
var targetNode=_eleWithId(targetview.id);
targetNode.innerHTML='';
targetNode.appendChild(newPage);
targetview.pageType='currencyconverter';
targetview.pageIdentifier=false;
updateContentHeight();
if(!preloading)_addHistoryEntry('currencyconverter','')}
function _buildCurrencyList(){
currencyjson=JSON.parse(localStorage.getItem('currencydata'));
html=_buildRecentCurrenciesOpt();
html+='<optgroup label= "All currencies">';
for(i in currencyjson){
if(currencyjson[i]["ccyname"]==null)continue;
html+='<option value="'+i+'">'+currencyjson[i]["ccyname"]+'</option>'};
html+='</optgroup>';
return html}
function currencyDoConversion(fromelem){
var result,topcurrency=document.querySelector('#'+_screenColumns.center.id+' .in .currency-select').value,bottomcurrency=document.querySelector('#'+_screenColumns.center.id+' .out .currency-select').value;
if(fromelem==null)var fromelem=document.querySelector('#'+_screenColumns.center.id+' .in .quantity-in');
if(fromelem.className=='quantity-in input'){
result=document.querySelector('#'+_screenColumns.center.id+' .out .quantity-out')}
else result=document.querySelector('#'+_screenColumns.center.id+' .in .quantity-in');
var fromquantity=fromelem.value;
if(fromquantity=="")fromquantity="0";
fromquantity=fromquantity.replace(/,/g,"");
fromquantity=parseFloat(fromquantity);
var currencydata=JSON.parse(localStorage.getItem('currencydata'));
frommid=(parseFloat(currencydata[topcurrency]["bid"])+parseFloat(currencydata[topcurrency]["ask"]))/2;
tomid=(parseFloat(currencydata[bottomcurrency]["bid"])+parseFloat(currencydata[bottomcurrency]["ask"]))/2;
result.value=_currencyFormat((tomid/frommid)*fromquantity);
if(tomid/frommid<0.001){
document.querySelector('#'+_screenColumns.center.id+' span.exchange-rate span').innerHTML=_twodp(frommid/tomid);
document.querySelector('#'+_screenColumns.center.id+' .warning').innerHTML="As this exchange rate less than 0.001, it's inverse has been shown"}
else{
document.querySelector('#'+_screenColumns.center.id+' span.exchange-rate span').innerHTML=_twodp(tomid/frommid);
document.querySelector('#'+_screenColumns.center.id+' .warning').innerHTML=""};
(currencydata[topcurrency]['timestamp']<currencydata[bottomcurrency]['timestamp'])?datestr=currencydata[topcurrency]['date']:datestr=currencydata[bottomcurrency]['date'];
document.querySelector('#'+_screenColumns.center.id+' .as-of').innerHTML='As of '+datestr+".&nbsp;";
updateContentHeight()};
mFT.currencyDoConversion=currencyDoConversion
function _twodp(number){
number=number*1000;
number=Math.round(number);
number=number/1000;
number=number.toString();
var decimalpt=number.indexOf(".");
if(decimalpt==-1){
number=number+".00"}
else if((number.substr(decimalpt)).length==2)number=number+"0";
return number}
function _currencyFormat(number){
return _tidyCommas(_twodp(number))}
function showAccount(element,justsignedin){
if(uaIsOffline()){
offlineWarningPopOver();
return};
if(_inWrapper&&'showAuthPopover' in window.appBridge)return window.appBridge.showAuthPopover();
if(!_ftuser){
var loginForm=document.querySelector('#templates .signin').cloneNode(true);
if(/iPad/.test(navigator.userAgent)){
loginForm.querySelector('p.call-now').style.display='block'}
else loginForm.querySelector('button.call-now').style.display='block';
if(_updateftuseronnextload)loginForm.querySelector('h4').style.display='block';
_showPopover(loginForm,false,element,454,false,'authpopover')}
else if(justsignedin){
if(_mbird.limits.loggedin==-1&&_ftuser.level=='registered'){
var justLoggedInForm=document.querySelector('#templates .justsignedin').cloneNode(true);
justLoggedInForm.querySelector('.signedinunlimited').style.display='block';
justLoggedInForm.querySelector('.signedinname').innerHTML=_ftuser.email;
_showPopover(justLoggedInForm,false,element,454,false,'authpopover')}
else{
var justLoggedInForm=document.querySelector('#templates .justsignedin').cloneNode(true);
justLoggedInForm.querySelector('.signedin'+_ftuser.level).style.display='block';
justLoggedInForm.querySelector('.signedinname').innerHTML=_ftuser.email;
if(_campaignreference==20419)justLoggedInForm.querySelector('.signedinregistered p').innerHTML='<strong>Claim your 25% discount</strong><br />Get unlimited access on desktop, tablet and mobile with a standard Financial Times subscription at a reduced price.';
_showPopover(justLoggedInForm,false,element,454,false,'authpopover')}}
else{
var logoutForm=document.querySelector('#templates .signout').cloneNode(true);
logoutForm.querySelector('.signedin'+_ftuser.level).style.display='block';
logoutForm.querySelector('.signedinname').innerHTML=_ftuser.email;
if(_mbird.limits.loggedin==-1&&_ftuser.level=='registered')logoutForm.querySelector('.signedinregistered p').innerHTML='Your registered user account allows you free unlimited access to articles for the FT Web App launch week. Subscribe now to maintain full access when the offer ends';
if(_campaignreference==20419)logoutForm.querySelector('.signedinregistered p').innerHTML='<strong>Claim your 25% discount</strong><br />Get unlimited access on desktop, tablet and mobile with a standard Financial Times subscription at a reduced price.';
_showPopover(logoutForm,false,element,454,false,'authpopover')}};
mFT.showAccount=showAccount
function accountLogin(cb,cbargs){
if(document.activeElement)document.activeElement.blur();
var username=document.querySelector('#popover .signinusername').value,password=document.querySelector('#popover .signinpassword').value;
document.querySelector('#popover .waitmarker').style.display='block';
_repositionAuthWaitMarker();
Assanka.$.post(sourceURL.replace('http://app.ft.com','https://app.ft.com')+'login',{username:username,password:password,inwebapp:!!window.navigator.standalone,w:screen.width,h:screen.height},function(data,textStatus){
document.querySelector('#popover .waitmarker').style.display='none';
if(!data||!data.success){
if(data&&data.error){
if(data.regf){
_mbird.limits.loggedout=-1;
_mbirdoverride=true;
loadPage(_currentPageAnchor);
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false};
if(_inWrapper){
setTimeout(function(){
document.querySelector('#popover .registrationdescription').innerHTML=data.error},20)}
else document.querySelector('#popover .registrationdescription').innerHTML=data.error}
else if(_inWrapper){
setTimeout(function(){
document.querySelector('#popover .registrationdescription').innerHTML='<div class="loginfailure"><h3 style="color: red;">Login failed</h3><p>The login server could not be contacted. Please try again later.</p></div>'},20)}
else document.querySelector('#popover .registrationdescription').innerHTML='<div class="loginfailure"><h3 style="color: red;">Login failed</h3><p>The login server could not be contacted. Please try again later.</p></div>';
_showPopover();
return};
_ftuser=data.user;
localStorage.setItem('user',JSON.stringify(_ftuser));
_storePortfolioSummary(data.portfolio);
document.querySelector('.sectionstatustext').innerHTML='You are signed in';
document.querySelector('.sectionstatusbutton').innerHTML='Your account';
loadPage(_currentPageAnchor);
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false;
if(typeof cb=='undefined'){
showAccount(_sectionSelectorOpen?document.querySelector('.sectionstatusbutton'):false,true)}
else{
cbargs.username=username;
cbargs.password=password;
cb.call(null,cbargs)};
if(_inWrapper&&'setSignedIn' in window.appBridge)window.appBridge.setSignedIn()},'json').error(function(){
if(uaIsOffline()){
hidePopover();
offlineWarningPopOver();
return};
if(_inWrapper&&'dismiss' in window.appBridge){
window.appBridge.dismiss();
window.appBridge.loginFailedWarning();
return}
else{
hidePopover();
loginFailedPopOver();
return}})};
mFT.accountLogin=accountLogin
function accountLogout(){
_ftuser=false;
localStorage.removeItem('user');
localStorage.removeItem('portfoliodetails');
_storePortfolioSummary();
loadPage(_currentPageAnchor);
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false;
document.querySelector('.sectionstatustext').innerHTML='You are signed out';
document.querySelector('.sectionstatusbutton').innerHTML='Sign in';
showAccount(_sectionSelectorOpen?document.querySelector('.sectionstatusbutton'):false);
if(_inWrapper&&'setSignedOut' in window.appBridge)window.appBridge.setSignedOut()};
mFT.accountLogout=accountLogout
function accountRegister(el){
var segid='90136';
if(_inWrapper){
switch(_screensizemode){case'small':segid=90155;
break;case'medium':segid=90157;
break;case'large':segid=90159;
break;case'largewide':segid=90161;
break}}
else{
switch(_screensizemode){case'small':segid=90147;
break;case'medium':segid=90149;
break;case'large':segid=90151;
break;case'largewide':segid=90153;
break};
var device=/iPad|iPhone/.exec(navigator.userAgent);
if(device=='iPad')segid=90145;
if(device=='iPhone')segid=90143};
if(_onSamsungTab)segid='90140';
if(_campaignreference)segid=_campaignreference;
_accountPageHistoryStart=window.history.length;
_updateftuseronnextload=true;
var url='https://registration.ft.com/registration/subscription-service/register?segid='+segid+'&segsrc=html5&countryCode=GBR&term=annually&origin=ftandroid'+(_isiOS?'&scrollthrough=0':'')+'&simigvis='+_getFTUserTrack();
url='https://registration.ft.com/registration/login/logout?location='+encodeURIComponent(url);
if(_isiOS){
var reghtml='<div class="registrationarea iframecontainer">';
reghtml+='<iframe class="registrationiframe accountiframe" src="'+url+'"></iframe></div>';
reghtml+='</div><div class="waitmarker"><div class="waitinner"><div class="progressbar standardprogressbar"></div><br />Please wait...</div></div>';
_showPopover(reghtml,false,undefined,332,300,'authpopover');
document.querySelector('#popover .waitmarker').style.display='block';
_repositionAuthWaitMarker();
_popoverScroller=_makePopoverScroller(document.querySelector('#popover .iframecontainer'),document.querySelector('#popover .accountiframe'));
return false};
el.href=url;
return true};
mFT.accountRegister=accountRegister
function accountSubscribe(el,subscriptionChoice){
if(_ftuser&&_ftuser.level=='subscribed')subscriptionChoice='premium';
if(!subscriptionChoice){
var subscriptionSelectForm=document.querySelector('#templates .subscribelevel').cloneNode(true);
_showPopover(subscriptionSelectForm,'<button class="button backbutton" onclick="mFT.showAccount()"><div class="arrow"></div>Back</button>',undefined,454,false,'authpopover');
_localdb.trackAnalytics('psp','');
return};
if(subscriptionChoice!='subscription'&&subscriptionChoice!='premium')return alert('Subscription choice not recognised.');
var cpgid='0302';
if(subscriptionChoice=='premium')cpgid='0303';
var segid='90137';
if(_inWrapper){
switch(_screensizemode){case'small':segid=90154;
break;case'medium':segid=90156;
break;case'large':segid=90158;
break;case'largewide':segid=90160;
break}}
else{
switch(_screensizemode){case'small':segid=90146;
break;case'medium':segid=90148;
break;case'large':segid=90150;
break;case'largewide':segid=90152;
break};
var device=/iPad|iPhone/.exec(navigator.userAgent);
if(device=='iPad')segid=90144;
if(device=='iPhone')segid=90142};
if(_onSamsungTab)segid='90141';
if(_campaignreference)segid=_campaignreference;
if(segid==20419)cpgid='0460';
_accountPageHistoryStart=window.history.length;
_updateftuseronnextload=true;
var hideWaitMessage=false,url='https://registration.ft.com/registration/subscription-service/'+subscriptionChoice+'?cpgid='+cpgid+'&segid='+segid+'&segsrc=html5&countryCode=GBR&term=annually&origin=ftandroid'+(_isiOS?'&scrollthrough=0':'')+'&simigvis='+_getFTUserTrack();
if(_ftuser){
url='https://registration.ft.com/registration/barrier/mobile/login?username='+encodeURIComponent(_ftuser.email)+'&location='+encodeURIComponent(url);
hideWaitMessage=true};
url='https://registration.ft.com/registration/login/logout?location='+encodeURIComponent(url);
if(_isiOS){
var subshtml='<div class="subscriptionarea iframecontainer">';
subshtml+='<iframe class="subscriptioniframe accountiframe" src="'+url+'"></iframe></div>';
subshtml+='</div><div class="waitmarker"><div class="waitinner"><div class="progressbar standardprogressbar"></div><br />Please wait...</div></div>';
_showPopover(subshtml,false,undefined,332,300,'authpopover');
if(!hideWaitMessage)document.querySelector('#popover .waitmarker').style.display='block';
_popoverScroller=_makePopoverScroller(document.querySelector('#popover .iframecontainer'),document.querySelector('#popover .accountiframe'));
return false};
el.href=url;
return true};
mFT.accountSubscribe=accountSubscribe
function accountDirectSubscription(args){
var segid=args.segid,cpgid=args.cpgid;
_accountPageHistoryStart=window.history.length;
_updateftuseronnextload=true;
var url='https://registration.ft.com/registration/subscription-service/subscription?segid='+segid+'&segsrc=html5&countryCode=GBR&term=annually&origin=ftandroid'+(_isiOS?'&scrollthrough=0':'')+'&simigvis='+_getFTUserTrack();
if(true||_isiOS){
var reghtml='<div class="registrationarea iframecontainer">';
reghtml+='<iframe id="directsubscriptionframe" class="registrationiframe accountiframe" src=""></iframe></div>';
reghtml+='</div><div class="waitmarker"><div class="waitinner"><div class="progressbar standardprogressbar"></div><br />Please wait...</div></div>';
_showPopover(reghtml,false,undefined,332,300,'authpopover');
document.querySelector('#popover .waitmarker').style.display='block';
_repositionAuthWaitMarker();
_popoverScroller=_makePopoverScroller(document.querySelector('#popover .iframecontainer'),document.querySelector('#popover .accountiframe'));
var frm=document.createElement('form');
frm.setAttribute("action","https://registration.ft.com/registration/barrier/mobile/login?username="+encodeURIComponent(args.username)+"&location="+encodeURIComponent(url));
frm.setAttribute("method","post");
frm.style.display='none';
frm.setAttribute("target","directsubscriptionframe");
var pwinput=document.createElement("input");
pwinput.type="hidden";
pwinput.name="password";
pwinput.value=args.password;
frm.appendChild(pwinput);
document.body.appendChild(frm);
frm.submit();
return false};
window.open(url);
return true};
mFT.accountDirectSubscription=accountDirectSubscription
function accountForgotPassword(){
_showPopover('<div class="forgotpasswordloadwait"></div><iframe class="forgotpasswordiframe" allowtransparency="true" src="https://registration.ft.com/registration/login/mobile/forgottenpassword?'+(_isiOS?'scrollthrough=0':'')+'"></iframe>','<button class="button backbutton" onclick="mFT.showAccount()"><div class="arrow"></div>Back</button>',_popoverReferenceElement,335,341,'authpopover')};
mFT.accountForgotPassword=accountForgotPassword
function processFormKeyPress(event,inputelement){
if(!event.keyCode||event.keyCode!=13)return true;
var eachNode=inputelement;
while(eachNode=eachNode.parentNode)if(eachNode.tagName=='FORM'){
if(eachNode.onsubmit){
eachNode.onsubmit()}
else eachNode.submit();
return false};
return true};
mFT.processFormKeyPress=processFormKeyPress
function _showDiscountPopoverIfNecessary(){
if(_campaignreference&&_campaignreference.length==2){
_campaignreference=_campaignreference[1];
discountPopOver()}}
function _mockingbirdCheckUserHasAccess(articleid){
var article=_structure.storylist[articleid],articlembird='normal',userlevel=_ftuser.level;
if(article)if(article.mbird)articlembird=article.mbird;
if(articlembird=='free')return true;
if(userlevel=='premium')return true;
if(userlevel=='subscribed'&&articlembird=='normal')return true;
var mbirdTrackingKey=_ftuser?_ftuser.eid:'loggedout',mbirdLimit=_mbird.limits[_ftuser?'loggedin':'loggedout'];
if(!_mbird.tracking[mbirdTrackingKey])_mbird.tracking[mbirdTrackingKey]={anniversary:(new Date().getTime()),count:0,l:{}};
var trackingDetails=_mbird.tracking[mbirdTrackingKey];
if(trackingDetails.l[articleid])return true;
if(mbirdLimit==-1)return true;
if(trackingDetails.count>=mbirdLimit)return false;
trackingDetails.count++;
trackingDetails.l[articleid]=true;
localStorage.setItem('mockingbird',JSON.stringify(_mbird));
return true}
function _updateSubscription(ignoreloggedout){
if(!_ftuser&&!ignoreloggedout){
showAccount();
return};
Assanka.$.post(sourceURL+'getsubslevel',{eid:_ftuser.eid,hash:_ftuser.hash,inwebapp:!!window.navigator.standalone,w:screen.width,h:screen.height},function(data,textStatus){
if(!data||!data.level)return;
if(data.level!=_ftuser.level){
_ftuser.level=data.level;
localStorage.setItem('user',JSON.stringify(_ftuser));
loadPage(_currentPageAnchor);
if(document.querySelector('#popover .signout'))showAccount();
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false}},'json')}
function _receiveWindowMessage(event){
var message=event.data;
try{message=JSON.parse(message)}catch(e){};
if(!message||!message.type)return;
switch(message.type){case'registration':if(!message.height)return;
var targetContainedHeight=(message.height+10);
document.body.scrollTop=document.querySelector('#popover').style.top;
document.querySelector('#popover .accountiframe').style.height=targetContainedHeight+'px';
_updateAuthPopoverHeight();
var waitlayer=document.querySelector('#popover .waitmarker');
if(waitlayer)waitlayer.style.display='none';
break;case'touch':switch(message.t){case'start':_popoverScroller.scrollStart(message.y);
break;case'move':_popoverScroller.scrollMove(message.y);
break;case'end':_popoverScroller.scrollEnd();
break};
break;case'formsubmitted':var waitlayer=document.querySelector('#popover .waitmarker');
if(waitlayer){
waitlayer.style.display='block';
_repositionAuthWaitMarker()};
break;case'regdone':loadPage(_currentPageAnchor);
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false;
showAccount(_sectionSelectorOpen?document.querySelector('.sectionstatusbutton'):false);
break}}
function _getFTUserTrack(){
var re=/FTUserTrack=([0-9\.]*);/,ms=re.exec(document.cookie);
if(ms){
return ms[1]}
else return''}
function _getSubscriptionStatusButton(){
var regstatus='signedout';
if(_ftuser)regstatus='signedin'+_ftuser.level;
if(_mbird.limits.loggedin==-1){
return'<div class="calltoaction" onclick="mFT.showAccount()"><div class="signedout"'+(regstatus=='signedout'?' style="display: block"':'')+'><h5><strong>Register now for free access</strong></h5>Take advantage of our launch offer or sign in to your account</div><div class="signedinregistered"'+(regstatus=='signedinregistered'?' style="display: block"':'')+'><h5><strong>Subscribe now to maintain unlimited access</strong></h5>Don\'t miss out when the free period ends </div><div class="signedinsubscribed"'+(regstatus=='signedinsubscribed'?' style="display: block"':'')+'><h5>Upgrade your FT account</h5>Premium subscribers get more benefits</div><div class="signedinpremium"'+(regstatus=='signedinpremium'?' style="display: block"':'')+'>Your premium FT.com subscription entitles you to unlimited access</div></div>'}
else return'<div class="calltoaction" onclick="mFT.showAccount()"><div class="signedout"'+(regstatus=='signedout'?' style="display: block"':'')+'><h5>Subscribe now for unlimited access</h5>Get the latest news on tablet, mobile and PC</div><div class="signedinregistered"'+(regstatus=='signedinregistered'?' style="display: block"':'')+'><h5>Subscribe now for unlimited access</h5>Get the latest news on tablet, mobile and PC</div><div class="signedinsubscribed"'+(regstatus=='signedinsubscribed'?' style="display: block"':'')+'><h5>Upgrade your FT account</h5>Premium subscribers get more benefits</div><div class="signedinpremium"'+(regstatus=='signedinpremium'?' style="display: block"':'')+'>Your premium FT.com subscription entitles you to unlimited access</div></div>'}
function _getPromoMessage(){
if((!_ftuser||_ftuser.level=='registered')&&_campaignreference==20419)return'<div class="system-message" onclick="mFT.showAccount()" style="display: block;">Claim your 25% subscription discount</div>';
return''}
function _updateAuthPopoverHeight(){
var authcontainer=document.querySelector('#popover .iframecontainer');
if(!authcontainer)return;
var contentheight=parseInt(document.querySelector('#popover .accountiframe').offsetHeight),availablewindowheight=window.innerHeight-document.querySelector('#popover').offsetTop-(_inFragment?30:70);
if(_popoverScroller){
var targetHeight=Math.max(250,Math.min(contentheight,availablewindowheight));
document.querySelector('#popover .iframecontainer').style.height=targetHeight+'px';
_popoverScroller.updateScrollableHeight()}
else{
var targetHeight=contentheight;
document.querySelector('#popover .iframecontainer').style.height=targetHeight+'px'};
_showPopover()}
function _repositionAuthWaitMarker(){
var waitInnerOnScreen=true,waitMarker=document.querySelector('#popover .waitmarker'),waitMarkerInner=waitMarker.querySelector('.waitinner'),waitMarkerTop=waitMarker.offsetTop,offsetNode=waitMarker;
while(offsetNode=offsetNode.offsetParent)waitMarkerTop+=offsetNode.offsetTop;
var waitMarkerHeight=waitMarker.offsetHeight,innerHeight=90,topVisibleBoundary=Math.max(document.body.scrollTop,waitMarkerTop),bottomVisibleBoundary=Math.min(document.body.scrollTop+window.innerHeight,waitMarkerTop+waitMarkerHeight),innerTop=Math.floor((topVisibleBoundary+bottomVisibleBoundary)/2)-Math.floor(innerHeight/2)-waitMarkerTop;
waitMarkerInner.style.margin='0 auto';
waitMarkerInner.style.bottom='auto';
waitMarkerInner.style.top=innerTop+'px'}
function searchDisplay(element){
if(uaIsOffline()){
offlineWarningPopOver('Search is not available because you are offline. Please try again when you are online.');
return};
if(element.querySelector('.search-in'))var searchterm=element.querySelector('.search-in').value;
var searchInterface=document.querySelector('#searchtemplate .search').cloneNode(true),lastSearchType=localStorage.getItem('lastsearchtype');
if(!lastSearchType)lastSearchType='news';
searchInterface.querySelector('.'+lastSearchType+'button').className+=' selected';
searchInterface.querySelector('.searchtext').placeholder=((lastSearchType=='news')?'Find news':'Find quotes');
var resultsArea=searchInterface.querySelector('.searchresultsarea');
resultsArea.innerHTML=_getSearchContentHTML(lastSearchType).html;
if(document.body.scrollTop)window.scrollTo(0,0);
_showPopover(searchInterface,false,element,400);
if(searchterm)document.querySelector('#popover .searchtext').value=searchterm;
_searchScroller=new TouchScroll(document.querySelector('#popover .searchresultsarea'),{elastic:true});
searchSubmit()};
mFT.searchDisplay=searchDisplay
function searchChangeMode(modename){
var selectedbutton=document.querySelector('#popover .button.selected');
if(selectedbutton)selectedbutton.className=selectedbutton.className.replace(/\b ?selected\b/,'');
document.querySelector('#popover .'+modename+'button').className+=' selected';
document.querySelector('#popover .searchtext').placeholder=((modename=='news')?'Find news':'Find quotes');
localStorage.setItem('lastsearchtype',modename);
var touchScrollEle=document.querySelector('#popover .-ts-inner');
touchScrollEle.innerHTML=_getSearchContentHTML(modename).html};
mFT.searchChangeMode=searchChangeMode
function searchSubmit(){
if(uaIsOffline()){
offlineWarningPopOver('Search is not available because you are offline. Please try again when you are online.');
return};
var searchMode=localStorage.getItem('lastsearchtype');
if(!searchMode)searchMode='news';
var searchTerm=document.querySelector('#popover .searchtext').value;
if(!searchTerm)return;
document.querySelector('#popover .-ts-inner').innerHTML='<div class="waitmarker" searchterm="'+encodeURI(searchTerm)+'"><div class="waitinner"><div class="progressbar standardprogressbar"></div><br />Searching...</div></div>';
document.querySelector('#popover .searchtext').blur();
_showPopover();
_localdb.trackAnalytics('search',{mode:searchMode,searchterm:searchTerm});
switch(searchMode){case'news':siteMapTerm='Search';
var previoussearches=localStorage.getItem('previousnewssearches');
if(previoussearches)previoussearches=JSON.parse(previoussearches);
if(!previoussearches)previoussearches=[];
for(var i=0;i<previoussearches.length;i++)if(previoussearches[i]==searchTerm)previoussearches.splice(i,1);
if(previoussearches.unshift(searchTerm)>10)previoussearches.splice(10);
localStorage.setItem('previousnewssearches',JSON.stringify(previoussearches));
var newsFetchErrorHandler=function(){
if(!_popoverShowing||document.querySelector('#popover .searchresultsarea .waitmarker').getAttribute('searchterm')!=encodeURI(searchTerm))return;
_updateSearchAreaWithContent('<h4>Search failed</h4><p>Please try again later</p>')};
Assanka.$.ajax({url:sourceURL+'newssearch/'+encodeURIComponent(searchTerm),dataType:'json',success:function(data){
if(!_popoverShowing||document.querySelector('#popover .searchresultsarea .waitmarker').getAttribute('searchterm')!=encodeURI(searchTerm))return;
if(data===false){
newsFetchErrorHandler()}
else{
var results=_getSearchContentHTML('news',data.results);
_updateSearchAreaWithContent(results.html,results.missed)}},error:newsFetchErrorHandler});
break;case'quotes':var quotesFetchErrorHandler=function(){
if(!_popoverShowing||document.querySelector('#popover .searchresultsarea .waitmarker').getAttribute('searchterm')!=encodeURI(searchTerm))return;
_updateSearchAreaWithContent('<h4>Search failed</h4><p>Please try again later</p>')},previousquotesearches=localStorage.getItem('previousquotesearches');
if(previousquotesearches)previousquotesearches=JSON.parse(previousquotesearches);
if(!previousquotesearches)previousquotesearches=[];
for(var i=0;i<previousquotesearches.length;i++)if(previousquotesearches[i]==searchTerm)previousquotesearches.splice(i,1);
if(previousquotesearches.unshift(searchTerm)>10)previousquotesearches.splice(10);
localStorage.setItem('previousquotesearches',JSON.stringify(previousquotesearches));
Assanka.$.ajax({url:sourceURL+'quotesearch/'+encodeURIComponent(searchTerm),dataType:'json',success:function(data){
if(!_popoverShowing||document.querySelector('#popover .searchresultsarea .waitmarker').getAttribute('searchterm')!=encodeURI(searchTerm))return;
if(!data||!data.results)return quotesFetchErrorHandler();
_updateSearchAreaWithContent(_getSearchContentHTML('quotes',data.results).html)},error:quotesFetchErrorHandler});
break}};
mFT.searchSubmit=searchSubmit
function searchForTerm(aTerm){
document.querySelector('#popover .searchtext').value=aTerm;
searchSubmit()};
mFT.searchForTerm=searchForTerm
function androidInputFix(turnOn){
if(turnOn){
mFT.enable3d()}
else mFT.disable3d()};
mFT.androidInputFix=androidInputFix
function setShowSearch(){
_showSearch=true;
return true};
mFT.setShowSearch=setShowSearch
function _getSearchContentHTML(mode,currentresultset,searchterm){
var html='',failed=Array();
switch(mode){case'news':if(currentresultset){
if(!currentresultset.length){
html+='<h4>No search results</h4>'}
else{
var articlelist=_structure.storylist;
html+='<h4>Search results</h4><ul class="listnav">';
for(var i=0;i<currentresultset.length;i++){
if(currentresultset[i]=="")continue;
var theArticle=articlelist[currentresultset[i]];
if(!theArticle){
html+='<li data-id="'+currentresultset[i]+'" class="ph-id-'+currentresultset[i]+'"></li>';
failed.push(currentresultset[i])}
else{
html+='<li data-id="'+currentresultset[i]+'" onclick=" mFT.setShowSearch(); mFT.router.loadArticle('+currentresultset[i]+');">';
html+='<span class="date">'+_formatDate(theArticle.date,false,false)+'</span>';
html+='<h4>'+theArticle.title+'</h4><p>'+theArticle.snip+'</p></li>'}};
html+='</ul>'}}
else{
var previoussearches=localStorage.getItem('previousnewssearches');
if(previoussearches)previoussearches=JSON.parse(previoussearches);
if(previoussearches){
html+='<h4>Recently searched</h4><ul class="listnav">';
for(var i=0;i<previoussearches.length;i++)html+='<li onclick="mFT.searchForTerm(\''+previoussearches[i].replace("'","\\'")+'\')" class="previoussearch">'+previoussearches[i]+'</li>';
html+='</ul>'}
else html+='<h4>No recent searches</h4>'};
break;case'quotes':if(currentresultset){
if(!currentresultset.length){
html+='<h4>No search results</h4>'}
else{
html+='<h4>Search results</h4>';
for(var i=0;i<currentresultset.length;i++){
var match=currentresultset[i];
html+='<div onclick="mFT.router.loadTearsheet(\''+match.id+'\')" class="quotematch">';
html+='<span>'+match.title+'</span>';
html+='<span class="quoteidentifier">'+match.dispid+'</span>';
html+='</div>'}}}
else{
var previousquotesearches=localStorage.getItem('previousquotesearches');
if(previousquotesearches)previousquotesearches=JSON.parse(previousquotesearches);
if(previousquotesearches){
html+='<h4>Recently searched</h4><ul class="listnav">';
for(var i=0;i<previousquotesearches.length;i++)html+='<li onclick="mFT.setShowSearch(); mFT.searchForTerm(\''+previousquotesearches[i].replace("'","\\'")+'\')" class="previoussearch">'+previousquotesearches[i]+'</li>';
html+='</ul>'}
else html+='<h4>No recent searches</h4>'};
break};
return{html:html,missed:failed}}
function _updateSearchAreaWithContent(content,failedIds){
var resultsArea=document.querySelector('#popover .searchresultsarea'),touchScrollEle=resultsArea.querySelector('.-ts-inner');
touchScrollEle.innerHTML=content;
if(failedIds!=null)for(var i=0;i<failedIds.length;i++)_asyncDownloadStories(failedIds[i]);
touchScrollEle.parentNode.style.webkitTransitionDuration='0s';
touchScrollEle.parentNode.style.webkitTransform='translate(0 ,0)';
_searchScroller.setupScroller()}
function _asyncDownloadStories(id){
var removePlaceHolder=function(){
placeholder=document.querySelector('#popover .searchresultsarea li.ph-id-'+id);
if(placeholder!=null)document.querySelector('#popover .searchresultsarea .-ts-inner ul').removeChild(placeholder);
if(document.querySelector('#popover .searchresultsarea li')==null)document.querySelector('#popover .searchresultsarea .-ts-inner').innerHTML='<h4>No search results</h4>';
return};
Assanka.$.ajax({url:sourceURL+'articles',dataType:'json',data:{v:2,articleid:id,returnextras:true},success:function(data){
var theArticle=data;
if(data==null||data==""){
removePlaceHolder();
return};
theArticle.isPlaceholderContent=false;
theArticle.byline=data.byline;
theArticle.guid=data.name;
theArticle.date=data.datepublished;
theArticle.content=data.content;
theArticle.stocks=data.stocks;
theArticle.image=data.details.image;
theArticle.protectionlevel=data.protectionlevel?data.protectionlevel:'normal';
theArticle.snip=data.snippet;
var html="",clickFunc=function(){
_showSearch=true;
mFT.router.loadArticle(id,null,null,theArticle)};
html+='<span class="date">'+_formatDate(theArticle.datepublished,false,false)+'</span>';
html+='<h4>'+theArticle.title+'</h4><p>'+theArticle.snippet+'</p>';
document.querySelector('#popover .searchresultsarea li.ph-id-'+id).innerHTML=html;
document.querySelector('#popover .searchresultsarea li.ph-id-'+id).onclick=clickFunc},error:function(error){
removePlaceHolder()}})}
function offlineWarningPopOver(offlineWarningText){
if(typeof (offlineWarningText)=='undefined')offlineWarningText='Some features and content may not be available because you are offline.';
_showPopover('<div class="sans"><p style="margin:1em;">'+offlineWarningText+'</p></div>','You are offline',false,300)};
mFT.offlineWarningPopOver=offlineWarningPopOver
function loginFailedPopOver(){
_showPopover('<div class="sans"><p style="margin:1em;">Sign in was unsuccessful due to a network error. Please try again later.</p></div>','Error',false,300,100)}
function discountPopOver(){
if(_campaignreference==20419)_showPopover('<div class="signin discount"><form method="post" action="/#" onsubmit="mFT.accountLogin(mFT.accountDirectSubscription, {segid:20419,cpgid:\'0460\'}); return false;" name="loginform" novalidate><fieldset><h2>To claim your 25% discount on a standard subscription</h2><h3>Please verify your account</h3><hr><div class="signinformcontrols"><div><label>Username or email address</label><input name="username" class="signinusername" value="" type="email" autocapitalize="off" autocorrect="off"></div><div><label>Password</label><input name="password" class="signinpassword" type="password" value="" autocapitalize="off"></div><div class="signinbuttons standalonebutton"><label>&nbsp;<!-- leave this here for layout. --></label><button class="signin" type="submit">Sign in</button><a target="_blank" style="text-decoration: none;" href="https://registration.ft.com/registration/login/forgottenpassword"><button class="forgotpassword" onclick="return false">Forgot password</button></a><br><h5 onclick="mFT.hidePopover()">Ignore this offer</h5></div></div></fieldset></form><div class="registrationdescription sans"></div><div class="waitmarker"><div class="waitinner"><div class="progressbar standardprogressbar"></div><br>Please wait...</div></div></div>','',false,400)}
function welcomePopover(){
var html='<div class="welcome sans"><h3>Welcome to the FT Web App</h3><hr><p>To get the most out of the FT Web App please tap \'Go\' and select \'Increase\' on the pop-up as shown below.</p><img src="/lib/img/ios-welcome.png"><p>This will give you the best offline access on your FT Web App.</p><p class="buttons standalonebutton"><button class="info" onclick="if (this.textContent.indexOf(\'More\') !== -1) { this.textContent = \'Less information\'; document.querySelector(\'#popover .welcome p.info\').style.display = \'block\'; } else { this.textContent = \'More information\'; document.querySelector(\'#popover .welcome p.info\').style.display = \'none\'; } mFT.reformatPopover();">More information</button><button class="go" onclick="mFT.enableBigDatabaseMode(); localStorage.hasShownWelcome = true;">Go</button></p><p></p><p class="info" style="display: none;">By doing this you are giving us a little extra memory space so we can store the full FT for your offline reading. It will not affect your device and can be undone at any time. Go to the FAQ for instructions on how to undo this.</p><p style="clear: both;">&nbsp;</p><div>',popover=_showPopover(html,null,null,500),doneButton=popover.querySelector('.donebutton');
doneButton.textContent='Cancel';
doneButton.addEventListener('click',function(){
localStorage.hasShownWelcome=true;
showSystemMessage('small-database-message')},false)}
function showSystemMessage(messageClass){
var messageContainers=document.querySelectorAll('.system-messages'),message;
if(!messageContainers||!messageClass)return;
switch(messageClass){case'small-database-message':message='<div class="system-message small-database-message" onclick="mFT.enableBigDatabaseMode();mFT.hideSystemMessage(\'small-database-message\');">You\'ve chosen not to increase the space for FT to store the entire edition offline. Some content and features will be unavailable. <strong>Tap here to change.</strong></div>';
break;case'never-added-to-homescreen-message':message='<div class="system-message never-added-to-homescreen-message" onclick="mFT.floatTip(); mFT.hideSystemMessage(\'never-added-to-homescreen-message\');">Some content and features are unavailable because you haven\'t yet added the FT Web App to your home screen. <strong>Tap here to see how.</strong></div>';
break;case'added-to-homescreen-but-since-forgotten-message':message='<div class="system-message never-added-to-homescreen-message">You\'ve added the FT Web App to your homescreen but are not using it. Launch the FT Web App from your homescreen to get the best out of its features and content.</strong></div>';
break};
for(l=messageContainers.length-1;l>=0;l--)messageContainers[l].innerHTML=message;
if(_screensizemode=='small')updateContentHeight()};
mFT.showSystemMessage=showSystemMessage
function hideSystemMessage(messageClass){
var messages=document.querySelectorAll('.system-messages .'+messageClass);
if(!messages)return;
for(l=messages.length-1;l>=0;l--)messages[l].parentNode.removeChild(messages[l]);
if(_screensizemode=='small')updateContentHeight()};
mFT.hideSystemMessage=hideSystemMessage
function hidePopover(){
if(!_popoverShowing)return;
_enable3d();
_eleWithId('columnscontainer').removeEventListener('touchstart',hidePopover,true);
var popover=document.querySelector('#popover');
if(popover&&(popover.className.indexOf('authpopover')!=-1))_updateSubscription(true);
_lastSearch=popover.querySelector('.popovercontent');
popover.parentNode.removeChild(popover);
popover.style.display="none";
var popoverbg=_eleWithId('popoverbg');
popoverbg.parentNode.removeChild(popoverbg);
_popoverShowing=false;
_popoverScroller=false;
_popoverReferenceElement=false;
if(document.body.scrollTop<150)document.body.scrollTop=0;
if(_screensizemode=='small')updateContentHeight()};
mFT.hidePopover=hidePopover
function _showPopover(content,title,anchorElement,width,height,popoverextraclasses){
if(typeof (popoverextraclasses)=='undefined')popoverextraclasses=false;
if(_floatingAdvertTimer)floatAdvert('outnow');
if(typeof (anchorElement)!='undefined')_popoverReferenceElement=anchorElement;
if(!_popoverShowing){
var thePopover=_eleWithId('popovertemplate').cloneNode(true);
thePopover.id='popover'}
else var thePopover=_eleWithId('popover');
if(content){
if(_popoverScroller)_popoverScroller=false;
if(typeof content=='object'){
if(_popoverShowing)thePopover.querySelector('.popovercontent').innerHTML='';
thePopover.querySelector('.popovercontent').appendChild(content)}
else thePopover.querySelector('.popovercontent').innerHTML=content}
else if(_popoverShowing){
var contentContainer=thePopover.querySelector('.popovercontent');
if(!width)width=contentContainer.offsetWidth+(_inFragment?0:12);
if(!height)height=contentContainer.offsetHeight+7};
if(!title)title='';
thePopover.querySelector('.title').innerHTML=title;
var popoverPosition=_getPopoverPosition(width,height);
if(_popoverReferenceElement){
thePopover.querySelector('.popoverarrow').style.left=popoverPosition.arrowX+'px'}
else if(!_popoverShowing)thePopover.querySelector('.popoverarrow').style.display='none';
if(width)thePopover.style.width=width+'px';
thePopover.style.left=popoverPosition.x+'px';
thePopover.style.top=popoverPosition.y+'px';
if(typeof (content)!='undefined')thePopover.className='popover'+(_disable3dForInteraction?' no3d':'')+(popoverextraclasses?' '+popoverextraclasses:'');
if(!_popoverShowing){
var backgroundDiv=document.createElement('div');
backgroundDiv.id='popoverbg';
if(_disable3dForInteraction)backgroundDiv.className='no3d';
_disable3d();
thePopover.style.visibility='hidden';
document.body.appendChild(thePopover)};
if(height){
thePopover.style.height=(height+(_inFragment?0:40))+'px';
if(!_popoverReferenceElement)thePopover.style.top=Math.max(popoverPosition.y-Math.floor(Math.min(height,window.innerHeight)/2),0)+'px'}
else{
var heightToRender=thePopover.querySelector('.popovercontent').offsetHeight+(_inFragment?7:47);
thePopover.style.height=heightToRender+'px';
if(!_popoverReferenceElement)thePopover.style.top=Math.max(popoverPosition.y-Math.floor(Math.min(heightToRender,window.innerHeight)/2),0)+'px'};
var backgroundHeight=Math.max(_eleWithId('columnscontainer').offsetHeight+(_sectionSelectorOpen?_eleWithId('sectionselector').offsetHeight:0),window.innerHeight);
if(!_popoverShowing){
backgroundDiv.style.height=backgroundHeight+'px';
backgroundDiv.style.opacity='0';
document.body.appendChild(backgroundDiv);
thePopover.style.visibility='visible';
backgroundDiv.style.webkitTransition='opacity 500ms linear';
setTimeout(function(){
backgroundDiv.style.opacity=(popoverextraclasses&&/\bdarkbg\b/.test(popoverextraclasses))?'0.8':'0.4'},0)}
else _eleWithId('popoverbg').style.height=backgroundHeight+'px';
var popoverTop=parseInt(thePopover.style.top);
if(popoverTop<document.body.scrollTop||popoverTop>document.body.scrollTop+window.innerHeight)document.body.scrollTop=popoverTop;
_popoverShowing=true;
if(_screensizemode=='small')updateContentHeight();
return thePopover};
mFT.reformatPopover=function(){
_showPopover()}
function _getPopoverPosition(width,height){
var windowWidth=document.body.offsetWidth;
if(_screensizemode=='small')width=windowWidth;
if(_popoverReferenceElement){
var anEle=_popoverReferenceElement,elementX=_popoverReferenceElement.offsetWidth/2,elementY=_popoverReferenceElement.offsetHeight;
do{elementX+=anEle.offsetLeft;
elementY+=anEle.offsetTop}while(anEle=anEle.offsetParent);
var popoverX=Math.floor(elementX-width/2);
if(_screensizemode=='small'&&((popoverX<6)||(width+6>windowWidth))){
popoverX=0}
else if(popoverX<6){
popoverX=6}
else if(popoverX+width+6>windowWidth)popoverX=windowWidth-width-6;
var popoverY=elementY+13,arrowX=elementX-popoverX-12}
else{
var popoverX=Math.floor((document.body.offsetWidth/2)-(width/2));
if(_screensizemode=='small'&&popoverX<0)popoverX=0;
var popoverY=document.body.scrollTop+Math.floor((_samsungTabInnerHeight?_samsungTabInnerHeight:window.innerHeight)/2)};
if(_screensizemode=='small')popoverY=0;
return{x:popoverX,y:popoverY,arrowX:(arrowX?arrowX:0)}}
function _makePopoverScroller(scrollFrameElement,elementToScroll){
return false;
var o={},frameHeight=scrollFrameElement.offsetHeight,scrollableHeight=0,maxScrollPosition=0,scrollStartOffset=0,scrollPosition=0,representedScrollPosition=0,trackedOffset=0,lastOffsetDirection=false,dejitterBoundary=3,directionDejitterCount=dejitterBoundary,scrollPermittedToStart=false,scrollInProgress=false,scrollIncomplete=false,ignoreNextLargeMoveCounter=0;
o.scrollStart=function(moveOffset){
if(scrollIncomplete)return;
scrollPermittedToStart=true;
scrollInProgress=true;
var scrolledOffset=parseInt(elementToScroll.style.top)||0;
trackedOffset=scrollStartOffset=(moveOffset+scrolledOffset)};
o.scrollMove=function(moveOffset){
if(!scrollInProgress||scrollIncomplete)return;
var offsetChange=trackedOffset-moveOffset;
if(ignoreNextLargeMoveCounter&&Math.abs(offsetChange)>50){
ignoreNextLargeMoveCounter--;
return};
if(scrollPermittedToStart){
scrollPermittedToStart=false;
var scrolledOffset=parseInt(elementToScroll.style.top)||0;
elementToScroll.style.webkitTransform='translate(0px, '+ -representedScrollPosition+'px)';
elementToScroll.style.top='0px';
ignoreNextMoveCounter=3;
return};
var moveDirection=(offsetChange>0);
if(moveDirection!=lastOffsetDirection){
directionDejitterCount--;
if(directionDejitterCount>0)return;
lastOffsetDirection=moveDirection;
directionDejitterCount=dejitterBoundary}
else directionDejitterCount=Math.min(directionDejitterCount+1,dejitterBoundary);
scrollPosition+=offsetChange;
trackedOffset=moveOffset;
if(scrollPosition<0){
representedScrollPosition=Math.ceil(scrollPosition/2)}
else if(scrollPosition>maxScrollPosition){
representedScrollPosition=maxScrollPosition+Math.ceil((scrollPosition-maxScrollPosition)/2)}
else representedScrollPosition=scrollPosition;
elementToScroll.style.webkitTransform='translate(0px, '+ -representedScrollPosition+'px)'};
o.scrollEnd=function(){
if(scrollIncomplete||!scrollInProgress||scrollPermittedToStart)return;
scrollInProgress=false;
if(scrollPosition<0){
scrollIncomplete=true;
elementToScroll.style.webkitTransitionDuration='0.3s';
elementToScroll.style.webkitTransform='translate(0px, 0px)'}
else if(scrollPosition>maxScrollPosition){
scrollIncomplete=true;
elementToScroll.style.webkitTransitionDuration='0.3s';
elementToScroll.style.webkitTransform='translate(0px, -'+maxScrollPosition+'px)'}
else o.completeScroll()};
o.completeScroll=function(){
elementToScroll.style.webkitTransitionDuration='0s';
representedScrollPosition=scrollPosition=Math.max(0,Math.min(maxScrollPosition,scrollPosition));
window.setTimeout(function(){
elementToScroll.style.webkitTransform='translate(0px, 0px)';
elementToScroll.style.top=-scrollPosition+'px';
scrollIncomplete=false},10)};
o.updateScrollableHeight=function(){
frameHeight=scrollFrameElement.offsetHeight;
scrollableHeight=elementToScroll.offsetHeight;
maxScrollPosition=scrollableHeight-frameHeight;
elementToScroll.style.top='0px';
scrollPosition=0;
representedScrollPosition=0};
elementToScroll.addEventListener('webkitTransitionEnd',o.completeScroll,false);
o.updateScrollableHeight();
return o}
function showSectionSelector(){
if(_sectionSelectorOpen||_wrapperProvidesNavigation)return;
var sectionSelector=document.querySelector('#sectionselector');
sectionSelector.style.display='block';
var parentCategoryID=false;
if(_currentcategory){
parentCategoryID=_currentcategory;
var categoryLooper;
while(categoryLooper=_structure.categories[parentCategoryID]){
if(!categoryLooper.pid)break;
parentCategoryID=categoryLooper.pid}};
var sectionhtml='';
for(var sortkey=0;sortkey<_sortedprimarynav.length;sortkey++){
var pcatkey=_sortedprimarynav[sortkey],pridetails=_structure.pcatlist[pcatkey];
if(!pridetails.type){
var isactivesection=(pcatkey==parentCategoryID),thesection=_structure.categories[pcatkey],sectionkey=thesection.name.toLowerCase().substring(0,4);
sectionhtml+='<li data-id="'+pcatkey+'" onclick="mFT.updateSelectorHighlight(this); mFT.router.'+(thesection.is_front?'loadHome':'loadSection')+'(this)" '+(isactivesection?'class="active"':'')+'><div>'+thesection.name+'<span class="'+sectionkey+'"></span><span class="'+sectionkey+' wbanner"></span></div></li>'}
else{
var isactivesection=(_screenColumns.center.pageType==pridetails.type),sectionkey=pridetails.name.toLowerCase().substring(0,4);
sectionhtml+='<li onclick="mFT.updateSelectorHighlight(this); location.hash=\''+pridetails.type+'\'" '+(isactivesection?'class="active"':'')+'><div>'+pridetails.name+'<span class="'+sectionkey+'"></span><span class="'+sectionkey+' wbanner"></span></div></li>'}};
if(_screensizemode=='small'||_screensizemode=='medium'){
var audioPlayer=document.querySelector('#podcast-player audio'),playlistIdx=audioPlayer.getAttribute('data-playlistidx'),podcastIdx=audioPlayer.getAttribute('data-podcastidx');
if(playlistIdx&&podcastIdx)sectionhtml+='<li onclick="mFT.loadPodcast('+playlistIdx+', '+podcastIdx+'); mFT.updateSelectorHighlight(this);"><div>Now Playing</div></li>'};
_eleWithId('sectionlist').innerHTML=sectionhtml;
document.querySelector('.sectionstatustext').innerHTML=_ftuser?'You are signed in':'You are signed out';
document.querySelector('.sectionstatusbutton').innerHTML=_ftuser?'Your account':'Sign in or subscribe';
_updateSectionSelectorArrowsWithScroll('selected');
var newHeight=sectionSelector.offsetHeight,columnsContainerElement=_eleWithId('columnscontainer');
columnsContainerElement.addEventListener('touchstart',hideSectionSelector,true);
columnsContainerElement.style.webkitTransform='translate(0,'+newHeight+'px)';
_sectionSelectorOpen=true};
mFT.showSectionSelector=showSectionSelector
function hideSectionSelector(event){
if(!_sectionSelectorOpen||_sectionSelectorClosing||_wrapperProvidesNavigation)return;
_sectionSelectorClosing=true;
_eleWithId('columnscontainer').removeEventListener('touchstart',hideSectionSelector,true);
setTimeout(function(){
_sectionSelectorOpen=false;
_sectionSelectorClosing=false},300);
_eleWithId('columnscontainer').style.webkitTransform='translate(0,0)';
return false};
mFT.hideSectionSelector=hideSectionSelector
function sectionNavLeft(){
_updateSectionSelectorArrowsWithScroll('left')};
mFT.sectionNavLeft=sectionNavLeft
function sectionNavRight(){
_updateSectionSelectorArrowsWithScroll('right')};
mFT.sectionNavRight=sectionNavRight
function updateSelectorHighlight(element){
var activeSelection=document.querySelector('#sectionlist .active');
if(activeSelection)activeSelection.className='';
element.className='active'};
mFT.updateSelectorHighlight=updateSelectorHighlight
function _updateSortedPrimaryNav(){
if(!_structure||!_structure.pcatseq)return;
var useReducedLayout=(_screensizemode=='small'||_screensizemode=='medium'),isOffline=uaIsOffline();
_sortedprimarynavofflinestate=isOffline;
_sortedprimarynav=[];
for(var sortkey=0;sortkey<_structure.pcatseq.length;sortkey++){
var pcatkey=_structure.pcatseq[sortkey];
if(pcatkey==0)continue;
if(isOffline&&(pcatkey=='podcasts'||pcatkey=='currencyconverter'))continue;
var pridetails=_structure.pcatlist[pcatkey];
if(!pridetails.type){
var thesection=_structure.categories[pcatkey];
if(thesection.reg&&thesection.reg!=_currentregion)continue}
else if(pridetails.reducedonly&&!useReducedLayout||pridetails.fullonly&&useReducedLayout)continue;
_sortedprimarynav.push(pcatkey)};
_primarynavlookup={};
for(var sortkey=0;sortkey<_sortedprimarynav.length;sortkey++)_primarynavlookup[_sortedprimarynav[sortkey]]=sortkey}
function _updateSectionSelectorArrowsWithScroll(performScroll){
if(typeof performScroll=='undefined')performScroll=false;
var containerwidth=document.querySelector('#sectionscroller').offsetWidth,innerwidth=document.querySelector('#sectionlist').offsetWidth;
if(innerwidth<=containerwidth){
document.querySelector('#sectionselector .navleftcontainer').style.display='none';
document.querySelector('#sectionselector .navrightcontainer').style.display='none';
return};
var scrollposition=_sectionSelectorScroller.scrollLeft,scrollamount=0;
if(performScroll=='left'){
scrollamount=-90;
if(scrollposition+scrollamount<5)scrollamount=-scrollposition;
if(scrollamount)_sectionSelectorScroller.scrollBy(scrollamount,0,200)}
else if(performScroll=='right'){
scrollamount=90;
if(scrollposition+containerwidth+scrollamount+5>innerwidth)scrollamount=innerwidth-containerwidth-scrollposition;
if(scrollamount)_sectionSelectorScroller.scrollBy(scrollamount,0,200)}
else if(performScroll=='selected'){
var selectedItem=document.querySelector('#sectionlist .active');
if(selectedItem){
var targetposition=Math.round(selectedItem.offsetLeft+(selectedItem.offsetWidth/2)-(containerwidth/2));
if(targetposition<5){
targetposition=0}
else if(targetposition+containerwidth>innerwidth-5)targetposition=innerwidth-containerwidth;
scrollamount=targetposition-scrollposition;
if(scrollamount)_sectionSelectorScroller.scrollBy(scrollamount,0,_sectionSelectorOpen?200:0)}};
var newposition=scrollposition+scrollamount;
document.querySelector('#sectionselector .navleftcontainer').style.display=(newposition>0)?'block':'none';
document.querySelector('#sectionselector .navrightcontainer').style.display=(newposition+containerwidth+5<=innerwidth)?'block':'none'}
function buildVideoList(container,listPageIndicator,previousButton,nextButton,titleArea,xofyArea){
if(typeof listPageIndicator=='undefined')listPageIndicator=1;
if(typeof previousButton=='undefined')previousButton=false;
if(typeof nextButton=='undefined')nextButton=false;
if(typeof xofyArea=='undefined')xofyArea=false;
var useReducedLayout=(_screensizemode=='small'||_screensizemode=='medium'),playlistID=container.getAttribute('data-playlistid');
if(!playlistID)return"";
var videobandwidth='medium';
if(_screensizemode=='small'){
var videoelementcontainer=document.querySelector('#currentvideocontainer');
if(videoelementcontainer){
videoelementcontainer.querySelector('video').pause();
videoelementcontainer.parentNode.removeChild(videoelementcontainer)}};
var containerWidth=document.documentElement.clientWidth-14;
if(useReducedLayout){
var itemWidth=Math.min(170,Math.floor(containerWidth/Math.round(containerWidth/170)));
itemWidth-=3}
else var itemWidth=175;
var itemsPerPage=Math.floor(containerWidth/itemWidth);
if(typeof (listPageIndicator)=='object'){
var previousFirstItem=listPageIndicator.getAttribute('data-startitem'),listPage=Math.floor(previousFirstItem/itemsPerPage)+1}
else var listPage=parseInt(listPageIndicator);
if(!_structure||!_structure.video||!_structure.video.playlists)return"";
var playlist=_structure.video.playlists[playlistID];
if(!playlist)return"";
var o='<ul class="videolist" data-startitem="'+(itemsPerPage*(listPage-1)+1)+'">';
for(var i=(listPage-1)*itemsPerPage;i<listPage*itemsPerPage;i++){
var videoID=playlist[i];
if(!videoID){
o+='<li'+(useReducedLayout?' style="width: '+itemWidth+'px;"':'')+'></li>';
continue};
var videodetails=_structure.video.videos[videoID];
o+='<li onclick="mFT.playVideo(this)" videoid="'+videoID+'"'+(useReducedLayout?' style="width: '+itemWidth+'px;"':'')+'><span class="imageloading videocontainer" data-id="'+videoID+'.video"'+(useReducedLayout?' style="width: '+itemWidth+'px; height: '+Math.round(96*itemWidth/167)+'px"':'')+'></span><div class="title">'+videodetails.title+'</div>'+videodetails.desc+'</li>'};
o+='</ul>';
if(previousButton)if(listPage<=1){
previousButton.onclick=null;
previousButton.className=previousButton.className+' disabled'}
else{
previousButton.onclick=function(){
mFT.pageInChildContent('.videomidriff .navigatorcontentcontainer','slideright','buildVideoList',listPage-1,'.previous','.next',false,'.x-of-y');
_loadImagesInElement(container)};
previousButton.className=previousButton.className.replace(/\b ?disabled\b/g,'')};
if(nextButton)if(listPage*itemsPerPage>=playlist.length){
nextButton.onclick=null;
nextButton.className=nextButton.className+' disabled'}
else{
nextButton.onclick=function(){
mFT.pageInChildContent('.videomidriff .navigatorcontentcontainer','slideleft','buildVideoList',listPage+1,'.previous','.next',false,'.x-of-y');
_loadImagesInElement(container)};
nextButton.className=nextButton.className.replace(/\b ?disabled\b/g,'')};
if(xofyArea)xofyArea.innerHTML=listPage+' of '+Math.ceil(playlist.length/itemsPerPage);
if(titleArea)titleArea.innerText='Videos';
return o};
mFT.buildVideoList=buildVideoList
function playVideo(el){
if(uaIsOffline()){
offlineWarningPopOver();
return};
var id=el.getAttribute('videoid');
if(_inWrapper){
window.appBridge.playVideo(id)}
else{
var theVideo=_structure.video.videos[id],theVideoSrc=theVideo.versions.medium;
if(_screensizemode=='small'){
var videoelementcontainer=document.querySelector('#currentvideocontainer');
if(videoelementcontainer){
videoelementcontainer.querySelector('video').pause();
videoelementcontainer.parentNode.removeChild(videoelementcontainer)};
var imagethumbnail=el.querySelector('img')||{},offsetLeft=el.offsetLeft,offsetTop=el.offsetTop,parentItem=el.offsetParent;
while(parentItem.className.indexOf('videomidriff')==-1){
offsetLeft+=parentItem.offsetLeft;
offsetTop+=parentItem.offsetTop;
parentItem=parentItem.offsetParent};
var videocontainer=document.createElement('DIV');
videocontainer.id='currentvideocontainer';
videocontainer.style.width=imagethumbnail.offsetWidth+'px';
videocontainer.style.height=imagethumbnail.offsetHeight+'px';
videocontainer.style.top=offsetTop+'px';
videocontainer.style.left=offsetLeft+'px';
if(_isiOS3){
var videohtml='<embed id="currentvideo" src="'+theVideoSrc+'" width="'+imagethumbnail.offsetWidth+'" height="'+imagethumbnail.offsetHeight+'" onerror="mFT.videoError(event)" '+(_isiOS?'':'controls')+' style="left: '+imagethumbnail.offsetLeft+'px" />'}
else var videohtml='<video id="currentvideo" src="'+theVideoSrc+'" width="'+imagethumbnail.offsetWidth+'" height="'+imagethumbnail.offsetHeight+'" onerror="mFT.videoError(event)" onplaying="mFT.videoPlaying(event)" '+(_isiOS?'':'controls')+' style="left: '+imagethumbnail.offsetLeft+'px"></video>';
videohtml+='<div class="videoload">Please wait,<br />loading...</div>';
videocontainer.innerHTML=videohtml;
parentItem.appendChild(videocontainer)}
else{
var targetPlayerWidth=document.body.offsetWidth-100,targetPlayerHeight=Math.ceil(targetPlayerWidth*theVideo.medheight/theVideo.medwidth),videohtml='<div class="videoplayer"><div class="videoclose"><div></div></div>';
videohtml+='<h3>'+theVideo.title+'</h3>';
videohtml+='<div class="placeholder">Loading video, please wait...</div>';
videohtml+='<video id="currentvideo" src="'+theVideoSrc+'" width="'+targetPlayerWidth+'" height="'+targetPlayerHeight+'" onerror="mFT.videoError(event)" onplaying="mFT.videoPlaying(event)" '+(_isiOS?'':'controls')+' data-origwidth="'+theVideo.medwidth+'" data-origheight="'+theVideo.medheight+'"></video>';
_showPopover(videohtml,false,false,(targetPlayerWidth+50),false,'darkpopover darkbg hidetitlebar');
document.querySelector('#popover .videoclose').onclick=mFT.hidePopover};
var videoelement=document.querySelector('#currentvideo');
if(videoelement)videoelement.play();
var analyticsDetail={id:id,src:theVideoSrc,title:theVideo.title};
if(theVideo.section)analyticsDetail.section=theVideo.section;
if(theVideo.brand)analyticsDetail.brand=theVideo.brand;
if(theVideo.indepth)analyticsDetail.indepth=theVideo.indepth;
_localdb.trackAnalytics('video',JSON.stringify(analyticsDetail))}};
mFT.playVideo=playVideo
function _resizeVideoPopover(){
var theVideo=document.querySelector('#currentvideo'),targetPlayerWidth=document.body.offsetWidth-100,targetPlayerHeight=Math.ceil(targetPlayerWidth*theVideo.getAttribute('data-origheight')/theVideo.getAttribute('data-origwidth'));
_showPopover(false,false,false,targetPlayerWidth+50,targetPlayerHeight+50,'darkpopover hidetitlebar');
theVideo.width=targetPlayerWidth;
theVideo.height=targetPlayerHeight}
function videoError(e){
if(uaIsOffline()){
hidePopover();
offlineWarningPopOver();
return};
var placeholder=document.querySelector('#popover .videoplayer .placeholder');
if(!placeholder)return;
placeholder.className='errormessage';
switch(e.target.error.code){case e.target.error.MEDIA_ERR_ABORTED:placeholder.innerHTML='Video playback cancelled';
break;case e.target.error.MEDIA_ERR_NETWORK:placeholder.innerHTML='A network error prevented video playback';
break;case e.target.error.MEDIA_ERR_DECODE:placeholder.innerHTML='Video corrupted and unplayable';
break;case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:placeholder.innerHTML='Video format not supported';
break;default:placeholder.innerHTML='Sorry, but this video could not be played';
break};
placeholder.style.display='block'};
mFT.videoError=videoError
function videoPlaying(e){
var videoelement=event.target;
videoelement.style.opacity=1;
videoelement.controls=true;
var placeholder=document.querySelector('#popover .videoplayer .placeholder');
if(placeholder)placeholder.style.display='none';
var waittext=document.querySelector('.videoload');
if(waittext)waittext.parentNode.removeChild(waittext)};
mFT.videoPlaying=videoPlaying
function showPreferences(linkElement){
var preferencesInterface=document.querySelector('#prefstemplate .prefs').cloneNode(true),regiondropdown=preferencesInterface.querySelector('.regionselector select'),regionoptionhtml='';
for(var regionkey in _regionlist)regionoptionhtml+='<option value="'+regionkey+'" '+((regionkey==_currentregion)?'selected="selected" ':'')+'>'+_regionlist[regionkey]+'</option>';
regiondropdown.innerHTML=regionoptionhtml;
preferencesInterface.querySelector('.regionselector .displayvalue').innerHTML=_regionlist[_currentregion];
regiondropdown.onchange=function(e){
mFT.setRegion(e.target.value);
document.querySelector('#popover .regionselector .displayvalue').innerHTML=_regionlist[_currentregion]};
preferencesInterface.querySelector('.fontselector .displayvalue').innerHTML=_fontSizeNames[_currentFontSize];
var portfoliobuttonarea=preferencesInterface.querySelector('.portfoliobutton'),portfolio=_retrievePortfolioSummary();
if(!_ftuser){
portfoliobuttonarea.innerHTML='<button onclick="mFT.showAccount();">Sign in to view your FT.com portfolio</button>'}
else if(!portfolio){
portfoliobuttonarea.innerHTML='<a class="button" onclick="if (mFT.uaIsOffline()) { mFT.offlineWarningPopOver(\'Setting up a portfolio requires internet access; please try again when you are online.\'); return false; }" href="http://markets.ft.com/portfolio/all.asp" target="_blank">Set up an FT.com portfolio</a>'}
else portfoliobuttonarea.innerHTML='<button onclick="mFT.loadPortfolio();">Portfolio</button>';
_showPopover(preferencesInterface,false,linkElement,300)};
mFT.showPreferences=showPreferences
function setRegion(newregion){
if(!(newregion in _regionlist)){
alert('Unrecognised region!');
return};
_currentregion=newregion;
localStorage.setItem('region',_currentregion);
_updateSortedPrimaryNav();
loadPage(_currentPageAnchor);
_screenColumns.left.pageType=false;
_screenColumns.right.pageType=false};
mFT.setRegion=setRegion
function setFontSize(size,returntoprefs){
if(size>_fontSizeClasses.length-1||size<0){
alert('Unrecognised font size!');
return};
fontSizeChange(size);
if(returntoprefs===false){
hidePopover()}
else showPreferences()};
mFT.setFontSize=setFontSize
function showFontSizePopover(includebackbutton,anchorElement){
var fontPrefs=document.querySelector('#fontprefstemplate .fontpreferences').cloneNode(true),fontoptshtml="";
for(var i in _fontSizeClasses){
fontoptshtml+='<div class="'+_fontSizeClasses[i];
if(i==_fontSizeClasses.length-1)fontoptshtml+=' bottom ';
fontoptshtml+='" onclick="mFT.setFontSize('+i+', '+includebackbutton+')"';
fontoptshtml+='>'+_fontSizeNames[i];
if(i==_currentFontSize){
fontoptshtml+='<span class="tick"></span>'}
else fontoptshtml+='<span></span>';
fontoptshtml+='</div>'};
fontPrefs.innerHTML=fontoptshtml;
if(includebackbutton===false){
_showPopover(fontPrefs,'',anchorElement,300,false)}
else _showPopover(fontPrefs,'<button class="button backbutton" onclick="mFT.showPreferences()"><div class="arrow"></div>Back</button>',anchorElement,300,false)};
mFT.showFontSizePopover=showFontSizePopover
function floatAdvert(opt){
if(!_onSamsungTab||!_positionFixedSupport)return;
if(typeof opt=='undefined')opt='';
if(_popoverShowing&&opt!='outnow')return;
if(_floatingAdvertTimer){
window.clearTimeout(_floatingAdvertTimer);
_floatingAdvertTimer=false};
switch(opt){case'in':var adPlaceholder=document.querySelector('#'+_screenColumns.center.id+' .adplaceholder');
if(adPlaceholder&&adPlaceholder.innerHTML.length)adPlaceholder.style.visibility='hidden';
_eleWithId('floatingadvert').style.webkitTransform='translate(0,0)';
_floatingAdvertTimer=window.setTimeout('mFT.floatAdvert("out")',10000);
_localdb.trackAdImpression(_currentPageGUID);
break;case'outnow':var floatingAdvertElement=_eleWithId('floatingadvert');
floatingAdvertElement.style.webkitTransitionDuration=0;
floatingAdvertElement.style.webkitTransform='translate(0,100px)';
window.setTimeout(function(){
floatingAdvertElement.style.webkitTransitionDuration='1s'},10);
var adPlaceholder=document.querySelector('#'+_screenColumns.center.id+' .adplaceholder');
if(adPlaceholder)adPlaceholder.style.visibility='visible';
break;case'out':var floatingAd=_eleWithId('floatingadvert');
window.setTimeout(function(){
var adPlaceholder=document.querySelector('#'+_screenColumns.center.id+' .adplaceholder');
if(adPlaceholder)adPlaceholder.style.visibility='visible'},1000);
floatingAd.style.webkitTransform='translate(0,100px)';
break;default:_floatingAdvertTimer=window.setTimeout('mFT.floatAdvert("in")',3000)}};
mFT.floatAdvert=floatAdvert
function activateDFPAdverts(zone,pageType){
var pageAdverts=document.querySelectorAll('#'+_screenColumns.center.id+' .dfpadplaceholder');
if(!pageAdverts||!pageAdverts.length)return;
pageType=pageType||_screenColumns.center.pageType;
zone=zone||(pageType=='home'?'home':'ros');
FT.env.startPage(zone,pageType);
for(var i=0,l=pageAdverts.length;i<l;i++){
var thisAd=pageAdverts[i];
if(!thisAd.parentNode)continue;
var adCode=thisAd.getAttribute('data-adcode'),adContainerId=thisAd.getAttribute('data-adcontainerid'),adClass=thisAd.getAttribute('data-adclass'),adWidth=thisAd.getAttribute('data-adwidth'),adHeight=thisAd.getAttribute('data-adheight');
if(adCode&&adContainerId&&adClass&&adWidth&&adHeight)_buildDFPAdvert(thisAd,adClass,adWidth,adHeight,adCode,adContainerId,i+1)}}
function _buildDFPAdvert(el,adClass,adWidth,adHeight,adCode,adContainerId,adTile){
if(_disableAdverts)return;
var oldiframe=false;
if(oldiframe=el.querySelector('iframe')){
oldiframe.style.display='block';
return};
var collapseadverts=!(_screensizemode=='large'||_screensizemode=='largewide'),randint=Math.floor(Math.random()*10000000);
adCode+=randint;
var articleCount=localStorage.getItem('articleadinterval')||'1',userId=_ftuser.eid||'loggedout';
FT.env.targeting=";eid="+userId;
try{var adCall=FT.env.getURL(adClass)}catch(e){};
if(typeof (adCall)=="undefined"||adCall=="undefined")return;
if(uaIsOffline()&&collapseadverts){
el.parentNode.className=el.parentNode.className.replace('dfpadwrapper','dfpadwrappercollapsed');
return};
var ifr=document.createElement("iframe");
ifr.setAttribute("class",adClass);
ifr.setAttribute("style",(collapseadverts?"display:none;":"")+"border:none;padding-top:10px;padding-bottom:10px;width:"+adWidth+"px;height:"+adHeight+"px;");
ifr.setAttribute("id","adifr"+randint);
ifr.setAttribute("vspace",10);
el.innerHTML="";
el.appendChild(ifr);
if(!ifr.contentWindow)return;
doc=ifr.contentWindow.document;
if(!doc)return;
doc.open();
doc.writeln('<html><head><title>Advert</title><style>* {padding:0;margin:0}</style>');
if(collapseadverts)doc.writeln('<script> var targetWidth='+adWidth+'; var targetHeight='+adHeight+'; </script>');
doc.writeln('</head><body><div id="'+adContainerId+'"'+((_screensizemode=='large'||_screensizemode=='largewide')?' style="-webkit-transform-style: preserve-3d"':'')+'>');
doc.writeln('<script language="javascript" src="'+adCall+'"></script>');
doc.writeln('</div><script>');
if(collapseadverts){
doc.writeln('if (document.body.innerHTML.indexOf("NO AD" + "VERT") >= 0) { targetWidth = 0; targetHeight = 0; }');
doc.writeln('window.parent.mFT.setElementSize("adifr'+randint+'", targetWidth, targetHeight);')};
if(adContainerId=='hlfmpu'){
doc.writeln('function breakoutofiframe() {');
doc.writeln(' window.parent.mFT.breakAdvertOutOfIframe("adifr'+randint+'", document.getElementById("hlfmpu").innerHTML)');
doc.writeln('}');
doc.writeln('setTimeout(breakoutofiframe,500);')};
doc.writeln('</script>');
doc.writeln('</body></html>');
doc.close()}
function breakAdvertOutOfIframe(elid,newhtml){
var el=document.getElementById(elid);
if(!el)return;
el.parentNode.innerHTML=newhtml;
updateContentHeight()};
mFT.breakAdvertOutOfIframe=breakAdvertOutOfIframe
function setElementSize(elid,targetWidth,targetHeight){
var el=document.getElementById(elid);
if(!el)return;
el.width=targetWidth;
el.height=targetHeight;
el.style.display='block';
if(targetHeight==0)el.parentNode.parentNode.className=el.parentNode.parentNode.className.replace('dfpadwrapper','dfpadwrappercollapsed');
updateContentHeight()};
mFT.setElementSize=setElementSize
function doAdverts(zone,pageType){
if(_disableAdverts)return;
_advertsShowing=true;
floatAdvert();
activateDFPAdverts(zone,pageType);
switch(_screenColumns.center.pageType){case'home':_respaceSectionPageContent('center');
break;case'section':_respaceSectionPageContent('center');
break};
updateContentHeight()};
mFT.doAdverts=doAdverts
function _hideAdverts(){
if(!_advertsShowing)return;
Array.prototype.forEach.call(document.querySelectorAll('#'+_screenColumns.center.id+' .dfpadplaceholder'),function(adplaceholder){
adplaceholder.style.height=adplaceholder.offsetHeight+'px';
var adiframe=adplaceholder.querySelector('iframe');
if(adiframe)adiframe.style.display='none'});
_advertsShowing=false}
function _removeAdverts(parentelement){
Array.prototype.forEach.call(parentelement.querySelectorAll('.dfpadplaceholder'),function(adplaceholder){
adplaceholder.style.height=adplaceholder.offsetHeight+'px';
adplaceholder.innerHTML=''})}
function _getAdvertisingBanner(adposition){
if(_screensizemode=='small'||_screensizemode=='medium'){
if(typeof adposition=='undefined'||adposition!='banlb2')adposition='banlb';
return'<div class="banlb dfpadplaceholder" data-adcontainerid='+adposition+' data-adclass="'+adposition+'" data-adwidth="300" data-adheight="50" data-adcode="ros;sz=300x50;pos='+adposition+';tile=6;ord="><span>&nbsp;</span></div>'};
return'<div class="MPU dfpadplaceholder" data-adcontainerid="hlfmpu" data-adclass="hlfmpu" data-adwidth="300" data-adheight="600" data-adcode="ros;sz=300x600,300x250;pos=hlfmpu;tile=1;ord="><span>&nbsp;</span></div>'}
function _trackView(section,id,article){
if(!section)section='home';
var _currentPageGUID='/#untracked-page',_type=section,_detail='';
switch(section){case'home':_currentPageGUID='/';
_type='homepage';
break;case'category':_currentPageGUID='/#section/'+id+'/'+encodeURIComponent(_structure.categories[id].name);
_type='section';
_detail={id:id,name:_structure.categories[id].name};
break;case'content':if(typeof article=='object'&&article!=null){
var thisitem=article}
else var thisitem=_structure.storylist[id];
if(thisitem==null||thisitem.guid==null)return;
_currentPageGUID=thisitem.guid;
var _protectionlevel=thisitem.mbird?thisitem.mbird:'normal';
_detail={guid:thisitem.guid,protectionlevel:_protectionlevel,title:thisitem.title};
break;case'tearsheet':_currentPageGUID='/#tearsheets/'+encodeURIComponent(id);
_detail=id;
break;case'portfolio':_currentPageGUID='/#portfolio';
break;case'marketsdata':_currentPageGUID='/#marketsdata/'+id;
_detail=id;
break;case'podcasts':_detail={guid:id,protectionlevel:'free'};
break};
if(_disableAnalytics)return;
_localdb.trackAnalytics(_type,_detail,_ftuser)}
function _addToReadContent(articleid){
var readbase=false,readContentBaseKey=_ftuser?_ftuser.eid:'loggedout';
if(!(readbase=_readcontent[readContentBaseKey])){
_readcontent[readContentBaseKey]={};
readbase=_readcontent[readContentBaseKey]};
readbase[articleid]=true;
localStorage.setItem('readcontent',JSON.stringify(_readcontent))}
function router(){
};
if(_inWrapper&&window.appBridge.loadHome){
router.loadHome=function(){
window.appBridge.loadHome()};
router.loadSection=function(id){
if(typeof id=='object')id=id.getAttribute('data-id');
window.appBridge.loadSection(id)};
router.loadArticle=function(id,fromsection,topsection){
if(typeof id=='object'){
var articleid=id.getAttribute('data-id');
fromsection=id.getAttribute('data-cat')||'false';
topsection=id.getAttribute('data-topcat')||'false'}
else var articleid=id;
window.appBridge.loadArticle(articleid,fromsection,topsection)};
router.loadPortfolio=function(){
window.appBridge.loadPortfolio()};
router.loadMarketsData=function(){
window.appBridge.loadMarketsData()};
router.loadPodcastsIndex=function(){
window.appBridge.loadPodcastsIndex()};
router.loadCurrencyConverter=function(){
window.appBridge.loadCurrencyConverter()};
router.loadTearsheet=function(id){
if(typeof id=='object')id=id.getAttribute('data-id');
window.appBridge.loadTearsheet(id)};
router.loadBlankPage=function(){
window.appBridge.loadBlankPage()}}
else{
router.loadHome=loadHome;
router.loadSection=loadSection;
router.loadArticle=loadArticle;
router.loadPortfolio=loadPortfolio;
router.loadMarketsData=loadMarketsData;
router.loadPodcastsIndex=loadPodcastsIndex;
router.loadCurrencyConverter=loadCurrencyConverter;
router.loadTearsheet=loadTearsheet;
router.loadBlankPage=loadBlankPage;
router.loadCurrencyConverter=loadCurrencyConverter};
mFT.router=router
function loadPage(navdata){
if(!_structureinited)return;
if(!navdata||navdata=='false'){
loadHome();
return};
var navdataparts=navdata.split('/');
switch(navdataparts[0]){case'home':loadHome();
break;case'category':loadSection(navdataparts[1]);
break;case'content':loadArticle(navdataparts[1],false,false);
break;case'portfolio':loadPortfolio();
break;case'currencyconverter':loadCurrencyConverter();
break;case'marketsdata':if(!navdataparts[1])loadMarketsData();
break;case'podcasts':loadPodcastsIndex();
break;case'tearsheet':loadTearsheet(navdataparts[1]);
break;case'fragment':switch(navdataparts[1]){case'auth':showAccount();
break;case'search':searchDisplay();
break};
if(_inWrapper&&'fragmentLoaded' in window.appBridge){
var thePopover=document.querySelector('#popover');
window.appBridge.fragmentLoaded(thePopover.offsetWidth,thePopover.offsetHeight)};
break;case'blank':loadBlankPage();
break}};
mFT.loadPage=loadPage
function goBack(){
if(window.history.length>1){
if(_screenColumns.center.pageType=='account'&&_accountPageHistoryStart!==false){
if(_accountPageHistoryStart==window.history.length){
router.loadHome()}
else window.history.go(_accountPageHistoryStart-window.history.length)}
else window.history.back()}
else router.loadHome()};
mFT.goBack=goBack
function _setupHistoryHandler(){
var _onHashChange=function(){
if(window.location.hash!=_currentPageAnchor){
var newPageAnchor=window.location.hash;
if(newPageAnchor)newPageAnchor=newPageAnchor.substring(1);
if(newPageAnchor!=_currentPageAnchor){
_currentPageAnchor=newPageAnchor;
loadPage(newPageAnchor)};
localStorage.setItem('lastaccesstime',new Date().getTime());
localStorage.setItem('lastaccesslocation',newPageAnchor)}};
if(window.history.pushState){
window.addEventListener('popstate',function(event){
if(event.state){
_currentPageAnchor=event.state.slug;
_historyGoingBack=true;
loadPage(event.state.slug);
_historyGoingBack=false}},false)}
else window.setInterval(_onHashChange,100);
window.addEventListener('hashchange',_onHashChange)}
function _checkNewHistoryEntry(){
if(window.location.hash!=_currentPageAnchor){
var newPageAnchor=window.location.hash;
if(newPageAnchor)newPageAnchor=newPageAnchor.substring(1);
if(newPageAnchor!=_currentPageAnchor){
_currentPageAnchor=newPageAnchor;
loadPage(newPageAnchor)}}}
function _addHistoryEntry(section,id,title,guid,article){
if(_preloadcontentmode)return;
var navdata='';
if(section&&section!='home'){
navdata=section+'/'+id}
else section=navdata='home';
_historyLastEntry=navdata;
var currentnavdata=window.location.hash;
if(currentnavdata)currentnavdata=currentnavdata.substring(1);
if(currentnavdata==navdata)return;
if(section=='podcasts')_trackView(section,guid);
if(typeof article=='object'&&article!=null){
_trackView(section,id,article)}
else _trackView(section,id);
_currentPageAnchor=navdata;
if(window.history.pushState){
window.history.pushState({slug:navdata},title,'#'+navdata)}
else window.location.hash=navdata;
localStorage.setItem('lastaccesstime',new Date().getTime());
localStorage.setItem('lastaccesslocation',navdata)}
function preloadAdjacentContent(){
if(_wrapperUsesGallery)return;
if(uaIsOffline()!=_sortedprimarynavofflinestate)_updateSortedPrimaryNav();
_loadContentInDirection('right',true);
_loadContentInDirection('left',true);
_swipingReady=true};
mFT.preloadAdjacentContent=preloadAdjacentContent
function _loadContentInDirection(direction,preload){
if(typeof (preload)=='undefined')preload=false;
if(preload)_preloadcontentmode=true;
var useReducedLayout=(_screensizemode=='small'||_screensizemode=='medium'),activePageType=_screenColumns.center.pageType,primaryContentKey=_getPrimaryContentKeyForCenterPage();
if(!primaryContentKey){
if(activePageType=='content'&&direction=='left'&&!_preloadcontentmode)goBack();
_preloadcontentmode=false;
return};
var contentKeyToLoad=false,firstContentKey=false,previousContentKey=false,loadNextKey=false,loadLastKey=false;
for(var sortkey=0;sortkey<_sortedprimarynav.length;sortkey++){
var pcatkey=_sortedprimarynav[sortkey];
if(pcatkey==primaryContentKey){
if(direction=='left'){
if(previousContentKey){
contentKeyToLoad=previousContentKey;
break};
loadLastKey=true}
else loadNextKey=true;
continue};
previousContentKey=pcatkey;
if(!firstContentKey)firstContentKey=pcatkey;
if(loadNextKey){
contentKeyToLoad=pcatkey;
break}};
if(loadLastKey)contentKeyToLoad=previousContentKey;
if(direction=='right'&&!contentKeyToLoad)contentKeyToLoad=firstContentKey;
if(contentKeyToLoad){
var itemtoload=_structure.pcatlist[contentKeyToLoad];
if(!itemtoload.type){
var theSection=_structure.categories[contentKeyToLoad];
if(theSection.is_front){
router.loadHome()}
else router.loadSection(contentKeyToLoad)}
else switch(itemtoload.type){case'marketsdata':router.loadMarketsData();
break;case'podcasts':router.loadPodcastsIndex();
break;case'currencyconverter':router.loadCurrencyConverter();
break}};
_preloadcontentmode=false}
function _getPrimaryContentKeyForCenterPage(){
var activePageType=_screenColumns.center.pageType,activePageIdentifier=_screenColumns.center.pageIdentifier,primaryContentKey=false;
switch(activePageType){case'home':primaryContentKey=activePageIdentifier;
break;case'section':primaryContentKey=activePageIdentifier;
break;case'marketsdata':if(activePageIdentifier)break;case'currencyconverter':case'podcasts':primaryContentKey=activePageType;
break};
if(activePageType=='section'){
var eachSection=_structure.categories[primaryContentKey];
while(eachSection.pid&&eachSection.pid in _structure.categories){
primaryContentKey=eachSection.pid;
eachSection=_structure.categories[primaryContentKey]}};
return primaryContentKey}
window.addEventListener('orientationchange',function(){
if(_enableNavigationHack){
window.setTimeout(_updateWindowOrientation,10)}
else _updateWindowOrientation()},false)
function _updateWindowOrientation(){
if(!document.body)return;
var neworientation=_getWindowOrientation();
if(neworientation==_lastorientation)return;
_lastorientation=neworientation;
var bodyclass=document.body.className;
bodyclass=bodyclass.replace(/\w+screen/,'').replace(/ +/,' ');
bodyclass+=' '+_classNameForScreenSize(_updateScreenSize());
document.body.className=bodyclass}
function updateContentHeight(){
if(_inWrapper&&'hideWait' in window.appBridge)window.appBridge.hideWait();
if(_barrierdisplaying||(_inWrapper&&!_wrapperSplashClosed)||_wrapperUsesGallery)return;
var columnsContainer=document.querySelector('#columnscontainer'),elementToMeasure=document.querySelector('#'+_screenColumns.center.id);
if(_popoverShowing&&_screensizemode=='small')elementToMeasure=document.querySelector('#popover');
var targetHeight=elementToMeasure.offsetHeight;
if((_samsungTabInnerHeight?_samsungTabInnerHeight:window.innerHeight)>targetHeight)targetHeight=(_samsungTabInnerHeight?_samsungTabInnerHeight:window.innerHeight);
columnsContainer.style.height=targetHeight+'px';
if(_popoverShowing)document.querySelector('#popoverbg').style.height=targetHeight+'px'};
mFT.updateContentHeight=updateContentHeight
function _updateScreenSize(){
var oldSize=_screensizemode;
if(_wrapperProvidesNavigation){
var webviewSize=window.appBridge.getWidth();
if(webviewSize>500)_screensizemode='large'}
else{
var detectorFontSize=parseInt(window.getComputedStyle(document.querySelector('#sizedetector'))['font-size']);
switch(detectorFontSize){case 30:_screensizemode='largewide';
break;case 20:_screensizemode='medium';
break;case 10:_screensizemode='small';
break;default:_screensizemode='large'}};
if(_screensizemode!=oldSize){
_articlecolumnsmode=(_screensizemode=='large'||_screensizemode=='largewide');
_updateSortedPrimaryNav()};
return _screensizemode}
function _classNameForScreenSize(screensize){
var bodyclass='';
if(screensize=='medium'){
bodyclass='smallscreen mediumscreen'}
else bodyclass=screensize+'screen';
return bodyclass}
function _performWindowResizeTasks(){
if(_resizeActionTimer)window.clearTimeout(_resizeActionTimer);
_resizeActionTimer=window.setTimeout(_resizeContentForWindow,(_isiOS?10:50))}
function _resizeContentForWindow(){
_resizeActionTimer=false;
for(var colname in _screenColumns)switch(_screenColumns[colname].pageType){case'home':_respaceSectionPageContent(colname);
var theColumn=document.querySelector('#'+_screenColumns[colname].id),videoContentContainer=theColumn.querySelector('.navigatorcontentcontainer > div');
if(videoContentContainer){
if(_screensizemode=='small'){
var currentVideoContainer=theColumn.querySelector('#currentvideocontainer');
if(currentVideoContainer)currentVideoContainer.style.display='none'};
videoContentContainer.innerHTML=buildVideoList(videoContentContainer.parentNode,theColumn.querySelector('.videolist'),theColumn.querySelector('.videomidriff .previous'),theColumn.querySelector('.videomidriff .next'),false,theColumn.querySelector('.videomidriff .x-of-y'));
_loadImagesInElement(videoContentContainer.parentNode)};
break;case'section':_respaceSectionPageContent(colname);
Array.prototype.forEach.call(document.querySelectorAll('#'+_screenColumns[colname].id+' .paginatednavigator'),function(paginatednav){
var contentContainer=paginatednav.querySelector('.navigatorcontentcontainer');
contentContainer.childNodes[0].innerHTML=updatePaginatedSectionNavigator(contentContainer,paginatednav.querySelector('ul'),false,false,false,false,_screenColumns[colname].pageIdentifier,_screenColumns[colname].pageIdentifier)});
Array.prototype.forEach.call(document.querySelectorAll('#'+_screenColumns[colname].id+' .tabbednavigator'),function(tabbednav){
var contentContainer=tabbednav.querySelector('.navigatorcontentcontainer');
contentContainer.childNodes[0].innerHTML=updateTabbedSectionNavigatorPage(contentContainer,tabbednav.querySelector('.pageablecontent'),tabbednav.querySelector('.previous'),tabbednav.querySelector('.next'))});
break};
if(_popoverShowing)if(document.querySelector('#popover #currentvideo')){
_resizeVideoPopover()}
else if(_popoverScroller){
_updateAuthPopoverHeight()}
else{
var popover=document.querySelector('#popover');
_showPopover(false,popover.querySelector('.title').innerHTML,_popoverReferenceElement,false,false,popover.className.replace('popover ',''))};
Array.prototype.forEach.call(document.querySelectorAll('.resizeheight'),function(elementtoresize){
var sizeratio=elementtoresize.getAttribute('data-sizeratio'),widthmodifier=elementtoresize.getAttribute('data-widthmod')||0;
if(!sizeratio)return;
elementtoresize.style.height=Math.round((window.innerWidth-widthmodifier)*sizeratio)+'px'});
updateContentHeight()}
function _getWindowOrientation(){
if(_inWrapper&&'getOrientation' in window.appBridge)return window.appBridge.getOrientation();
if(!window.orientation)return'portrait';
if(window.orientation==90||window.orientation==-90)return'landscape';
return'portrait'}
function _setupFastTouchClick(){
var touchSupport=true;
if(!('createTouch' in document))try{var touchevent=document.createEvent('TouchEvent');
if(!touchevent.initTouchEvent)touchSupport=false}catch(error){touchSupport=false};
if(touchSupport){
document.body.addEventListener('touchstart',onTouchStart,true);
document.body.addEventListener('touchmove',onTouchMove,true);
document.body.addEventListener('touchend',onTouchEnd,true);
document.body.addEventListener('touchcancel',onTouchCancel,true)};
document.body.addEventListener('click',onClick,true);
var clickStart={x:0,y:0,scroll:0},trackingClick=false
function onTouchStart(event){
trackingClick=true;
clickStart.x=event.targetTouches[0].clientX;
clickStart.y=event.targetTouches[0].clientY;
clickStart.scroll=window.pageYOffset;
return true}
function onTouchMove(event){
if(trackingClick)if(Math.abs(event.targetTouches[0].clientX-clickStart.x)>10||Math.abs(event.targetTouches[0].clientY-clickStart.y)>10)trackingClick=false;
return true}
function onTouchEnd(event){
if(!trackingClick||_columnsAnimating||Math.abs(window.pageYOffset-clickStart.scroll)>5)return true;
var targetElement=document.elementFromPoint(clickStart.x,clickStart.y+((_isAndroid&&!_positionFixedSupport)?window.pageYOffset:0));
if(targetElement.nodeType==Node.TEXT_NODE)targetElement=targetElement.parentNode;
var clickEvent=document.createEvent('MouseEvents');
clickEvent.initEvent('click',true,true);
clickEvent.forwardedTouchEvent=true;
targetElement.dispatchEvent(clickEvent);
if(targetElement.className.indexOf('needsclick')!=-1)return false;
if(targetElement.nodeName!='SELECT')event.preventDefault()}
function onTouchCancel(event){
trackingClick=false}
function onClick(event){
if(!window.event)return true;
var allowClick=true,targetElement=document.elementFromPoint(clickStart.x,clickStart.y+((_isAndroid&&!_positionFixedSupport)?window.pageYOffset:0));
if(targetElement.className.indexOf('needsclick')!=-1)return true;
if(!window.event.forwardedTouchEvent&&touchSupport){
allowClick=false}
else if(_sectionSelectorOpen&&!_popoverShowing)if(_sectionSelectorClosing){
allowClick=false}
else{
var targetElement=window.event.target,columnsContainerElement=_eleWithId('columnscontainer');
do{if(targetElement==columnsContainerElement){
hideSectionSelector();
allowClick=false;
break}}while(targetElement=targetElement.parentNode)};
if(allowClick)return true;
event.stopPropagation();
event.preventDefault();
return false}}
function addSwipeListenerToPagesContainer(pagesContainer){
var yBoundary=50,gestureStart={x:0,y:0},lastX=preLastX=0,lastTime=preLastTime=0,trackingSwipe=false,lastSwipeDirection=false,swipeToDragEnabled=false,swipeToFlickEnabled=false,centercolstyle=null,leftcolstyle=null,rightcolstyle=null,parentElementWidth=0,dragStartOffset=0
function isSwipeToDragAllowedOnPagesContainer(){
switch(_screenColumns.center.pageType){case'home':case'section':case'currencyconverter':return true;
break;case'podcasts':case'marketsdata':return !_screenColumns.center.pageIdentifier;
break};
return false}
function isSwipeToFlickAllowedOnPagesContainer(){
return !(_screenColumns.center.pageType=='content'&&_articlecolumnsmode)}
function dragPageWhileSwiping(clientX,swipeX){
if(!_screenIsPanning){
_screenIsPanning=true;
if(_columnsAnimating){
var currentTransform=window.getComputedStyle(_eleWithId(_screenColumns.center.id),null)['-webkit-transform'];
if(currentTransform.indexOf('matrix')>=0){
var currentOffset=currentTransform.replace(/matrix\([^,]+,[^,]+,[^,]+,[^,]+,\s(-?\d+),.*/i,'$1');
if(parseInt(currentOffset)==currentOffset&&Math.abs(currentOffset)>0)dragStartOffset=parseInt(currentOffset*0.7)};
if(dragStartOffset<0){
_screenColumns.left.pageType=false}
else if(dragStartOffset>0){
_screenColumns.right.pageType=false}
else completeSlide()}
else _completeGallerySlide();
parentElementWidth=pagesContainer.offsetWidth;
leftcolstyle=_eleWithId(_screenColumns.left.id).style;
centercolstyle=_eleWithId(_screenColumns.center.id).style;
rightcolstyle=_eleWithId(_screenColumns.right.id).style;
leftcolstyle.webkitTransitionDuration='0s';
centercolstyle.webkitTransitionDuration='0s';
rightcolstyle.webkitTransitionDuration='0s';
if(!_screenColumns.left.pageType)_loadContentInDirection('left',true);
if(!_screenColumns.right.pageType)_loadContentInDirection('right',true);
if(!_columnsAnimating&&document.body.scrollTop){
_screenPanVerticalOffset=-document.body.scrollTop;
window.scrollTo(0,0)}
else _screenPanVerticalOffset=0};
preLastX=lastX;
preLastTime=lastTime;
lastX=clientX;
lastTime=new Date().getTime();
leftcolstyle.webkitTransform='translate('+(Math.max(0,swipeX+dragStartOffset)-parentElementWidth)+'px,0)';
centercolstyle.webkitTransform='translate('+(swipeX+dragStartOffset)+'px,'+_screenPanVerticalOffset+'px)';
rightcolstyle.webkitTransform='translate('+(parentElementWidth+Math.min(0,swipeX+dragStartOffset))+'px,0)'}
function triggerFlickToPageOnSwipe(clientX,clientY,swipeX){
var swipeSpeed=Math.round((new Date().getTime()-lastTime)/(Math.abs(lastX-clientX)/document.body.offsetWidth))/1000;
if(swipeSpeed>0.6){
swipeSpeed=0.6}
else if(swipeSpeed<0.2)swipeSpeed=0.2;
var newSwipeDirection=(swipeX>0)?'right':'left';
if(newSwipeDirection==lastSwipeDirection){
gestureStart.x=clientX}
else{
lastSwipeDirection=newSwipeDirection;
flickToLeftOrRightPageAfterSwipe(newSwipeDirection,pagesContainer,swipeSpeed)};
gestureStart.y=clientY}
function flickToLeftOrRightPageAfterSwipe(direction,swipedElement,swipeSpeed){
var activePageType=_screenColumns.center.pageType,loadDirection=(direction=='left')?'right':'left';
_eleWithId(_screenColumns.center.id).style.webkitTransitionDuration=swipeSpeed+'s';
_eleWithId(_screenColumns[loadDirection].id).style.webkitTransitionDuration=swipeSpeed+'s';
_loadContentInDirection(loadDirection,false)}
function scrollPagesContainerWithSyntheticTouchEvent(touchEvent){
var syntheticTouchEvent=document.createEvent('TouchEvent');
syntheticTouchEvent.initTouchEvent('touchmove',true,true,window,touchEvent.detail,touchEvent.screenX,touchEvent.screenY,touchEvent.clientX,touchEvent.clientY,touchEvent.ctrlKey,touchEvent.altKey,touchEvent.shiftKey,touchEvent.metaKey,touchEvent.touches,touchEvent.targetTouches,touchEvent.changedTouches,touchEvent.scale,touchEvent.rotation);
pagesContainer.dispatchEvent(syntheticTouchEvent)}
function onTouchStart(touchStartEvent){
if(trackingSwipe)return;
_screenIsPanning=false;
dragStartOffset=0;
gestureStart.x=touchStartEvent.touches[0].clientX;
gestureStart.y=touchStartEvent.touches[0].clientY;
lastSwipeDirection=false;
lastTime=preLastTime=new Date().getTime();
lastX=preLastX=gestureStart.x;
swipeToDragEnabled=isSwipeToDragAllowedOnPagesContainer();
swipeToFlickEnabled=isSwipeToFlickAllowedOnPagesContainer();
trackingSwipe=true;
if(_columnsAnimating)scrollPagesContainerWithSyntheticTouchEvent(touchStartEvent)}
function onTouchMove(touchMoveEvent){
if(!trackingSwipe)return true;
var swipeY=touchMoveEvent.touches[0].clientY-gestureStart.y,swipeX=touchMoveEvent.touches[0].clientX-gestureStart.x,yMove=Math.abs(swipeY),xMove=Math.abs(swipeX);
if(_isiOS){
if(_sectionSelectorOpen)hideSectionSelector();
if(_sectionSelectorClosing||!_swipingReady){
touchMoveEvent.preventDefault();
trackingSwipe=false;
return false}
else if(!_screenIsPanning&&yMove>xMove){
trackingSwipe=false;
return true}
else if(swipeToDragEnabled){
if(_advertsShowing)_hideAdverts();
dragPageWhileSwiping(touchMoveEvent.touches[0].clientX,swipeX);
touchMoveEvent.preventDefault()}
else if(swipeToFlickEnabled){
if(_advertsShowing)_hideAdverts();
touchMoveEvent.preventDefault();
if(xMove<50){
lastX=touchMoveEvent.touches[0].clientX;
lastTime=new Date().getTime();
return true};
triggerFlickToPageOnSwipe(touchMoveEvent.touches[0].clientX,touchMoveEvent.touches[0].clientY,swipeX);
touchMoveEvent.stopPropagation()}}
else if(yMove>yBoundary){
trackingSwipe=false;
return true}
else if(yMove>xMove||xMove<50){
lastX=touchMoveEvent.touches[0].clientX;
lastTime=new Date().getTime();
return true}
else{
triggerFlickToPageOnSwipe(touchMoveEvent.touches[0].clientX,touchMoveEvent.touches[0].clientY,swipeX);
touchMoveEvent.stopPropagation()}}
function onTouchEnd(event){
trackingSwipe=false;
if(!_screenIsPanning)return;
if(lastX-gestureStart.x==0&&!dragStartOffset){
if(_screenPanVerticalOffset){
centercolstyle.webkitTransform='translate(0,0)';
window.scrollTo(0,Math.abs(_screenPanVerticalOffset))};
window.setTimeout(function(){
leftcolstyle.webkitTransitionDuration='0.5s';
centercolstyle.webkitTransitionDuration='0.5s';
rightcolstyle.webkitTransitionDuration='0.5s'},10);
_screenIsPanning=false;
_screenPanVerticalOffset=0;
return};
var pagesContainerWidth=pagesContainer.offsetWidth;
_swipingReady=false;
var moveSpeed=((lastX-preLastX)/pagesContainerWidth)/(lastTime-preLastTime)*1000,targetSnap='tocenter',transitionSpeed=0.5;
if(Math.abs(moveSpeed)<0.05){
if(lastX-gestureStart.x>pagesContainerWidth/2){
targetSnap='toright'}
else if(gestureStart.x-lastX>pagesContainerWidth/2)targetSnap='toleft'}
else{
transitionSpeed=1/Math.abs(moveSpeed);
transitionSpeed=Math.max(0.25,Math.min(1,transitionSpeed));
var targetPane=false;
if(lastX<preLastX&&lastX<gestureStart.x&&dragStartOffset<=0){
targetSnap='toleft'}
else if(lastX>preLastX&&lastX>gestureStart.x&&dragStartOffset>=0)targetSnap='toright'};
if(targetSnap=='toright'||targetSnap=='toleft')_removeAdverts(document.querySelector('#'+_screenColumns.center.id));
leftcolstyle.webkitTransitionDuration=transitionSpeed+'s';
centercolstyle.webkitTransitionDuration=transitionSpeed+'s';
rightcolstyle.webkitTransitionDuration=transitionSpeed+'s';
if(targetSnap=='toright'){
_screenPanActionRequired=true;
if(!_screenColumns.left.pageType)_loadContentInDirection('left',false);
if(!_screenColumns.left.pageType){
targetSnap='tocenter'}
else _slideView('left')}
else if(targetSnap=='toleft'){
_screenPanActionRequired=true;
if(!_screenColumns.right.pageType)_loadContentInDirection('right',false);
if(!_screenColumns.right.pageType){
targetSnap='tocenter'}
else _slideView('right')};
if(!targetSnap||targetSnap=='tocenter'){
_columnsAnimating=true;
_screenPanActionRequired=dragStartOffset?true:'center';
leftcolstyle.webkitTransform='translate(-100%,0)';
centercolstyle.webkitTransform='translate(0,'+_screenPanVerticalOffset+'px)';
rightcolstyle.webkitTransform='translate(100%,0)'};
_screenIsPanning=false};
pagesContainer.addEventListener('touchstart',onTouchStart,false);
pagesContainer.addEventListener('touchmove',onTouchMove,false);
pagesContainer.addEventListener('touchend',onTouchEnd,false)};
mFT.addSwipeListenerToPagesContainer=addSwipeListenerToPagesContainer
function _completeGallerySlide(){
if(!_screenPanActionRequired)return;
if(_screenPanActionRequired=='center'){
if(_screenPanVerticalOffset){
var centerColumnStyle=_eleWithId(_screenColumns.center.id).style;
centerColumnStyle.webkitTransitionDuration='0s';
centerColumnStyle.webkitTransform='translate(0px,0px)';
window.scrollTo(0,Math.abs(_screenPanVerticalOffset));
window.setTimeout(function(){
centerColumnStyle.webkitTransitionDuration='0.5s'},10);
_screenPanVerticalOffset=0};
window.setTimeout(function(){
doAdverts()},10);
_screenPanActionRequired=false;
return};
if(_screenPanActionRequired){
_eleWithId(_screenColumns.left.id).style.webkitTransform='translate(-100%,0)';
_eleWithId(_screenColumns.right.id).style.webkitTransform='translate(100%,0)'};
var newPageType=_screenColumns.center.pageType;
if(newPageType=='section'){
_currentcategory=_screenColumns.center.pageIdentifier;
_addHistoryEntry('category',_currentcategory);
doAdverts('ros','section')}
else if(newPageType=='home'){
_currentcategory=_structure.homepages[_currentregion];
_addHistoryEntry('home');
doAdverts('home','home')}
else if(newPageType=='marketsdata'||newPageType=='podcasts'||newPageType=='currencyconverter'){
_currentcategory=false;
_addHistoryEntry(newPageType,'');
doAdverts('ros',newPageType)};
_screenPanActionRequired=false}
function pageInChildContent(containerselector,transition,contentgenerationfunction,newpage,previousbuttonselector,nextbuttonselector,titleselector,xofyselector){
var currentPage=document.querySelector('#'+_screenColumns.center.id),container=currentPage.querySelector(containerselector),previousButton=false,nextButton=false,titleArea=false,xofyArea=false;
if(previousbuttonselector)previousButton=currentPage.querySelector(previousbuttonselector);
if(nextbuttonselector)nextButton=currentPage.querySelector(nextbuttonselector);
if(titleselector)titleArea=currentPage.querySelector(titleselector);
if(xofyselector)xofyArea=currentPage.querySelector(xofyselector);
var newContent=mFT[contentgenerationfunction](container,newpage,previousButton,nextButton,titleArea,xofyArea);
if(transition=='slideleft'){
var oldDiv=container.lastChild,newDiv=document.createElement('div');
newDiv.className='uses3d';
newDiv.innerHTML=newContent;
newDiv.style.webkitTransform='translate(100%,0)';
Array.prototype.forEach.call(container.childNodes,function(anotherOldDiv){
if(anotherOldDiv!=oldDiv)container.removeChild(anotherOldDiv)});
container.appendChild(newDiv);
var triggerRender=newDiv.offsetHeight;
oldDiv.addEventListener('webkitTransitionEnd',function(){
if(this.parentNode)this.parentNode.removeChild(this)});
window.setTimeout(function(){
oldDiv.style.webkitTransform='translate(-100%,0)';
newDiv.style.webkitTransform='translate(0,0)'},10)}
else if(transition=='slideright'){
var oldDiv=container.firstChild,newDiv=document.createElement('div');
newDiv.className='uses3d';
newDiv.innerHTML=newContent;
newDiv.style.webkitTransform='translate(-100%,0)';
Array.prototype.forEach.call(container.childNodes,function(anotherOldDiv){
if(anotherOldDiv!=oldDiv)container.removeChild(anotherOldDiv)});
container.insertBefore(newDiv,container.firstChild);
var triggerRender=newDiv.offsetHeight;
oldDiv.addEventListener('webkitTransitionEnd',function(){
if(this.parentNode)this.parentNode.removeChild(this)});
window.setTimeout(function(){
oldDiv.style.webkitTransform='translate(100%,0)';
newDiv.style.webkitTransform='translate(0,0)'},10)}
else container.innerHTML='<div>'+newContent+'</div>'};
mFT.pageInChildContent=pageInChildContent
function _slideView(direction){
if(direction!='left'&&direction!='right')return console.log('Invalid slide');
_columnsAnimating=true;
if(_disable3dForInteraction&&!_3daccelerated){
_enable3d();
window.setTimeout(function(){
_slideView(direction)},10);
return};
if(_floatingAdvertTimer)floatAdvert('outnow');
var centerView=_eleWithId(_screenColumns.center.id),leftView=_eleWithId(_screenColumns.left.id),rightView=_eleWithId(_screenColumns.right.id);
if(direction=='right'){
var temp=_screenColumns.left;
_screenColumns.left=_screenColumns.center;
_screenColumns.center=_screenColumns.right;
_screenColumns.right=temp;
if(!_screenIsPanning){
leftView.innerHTML='';
temp.pageType=false};
leftView.style.webkitTransitionDuration='0s';
leftView.style.webkitTransform='translate(100%,0)';
rightView.style.webkitTransitionDuration='0.5s';
rightView.style.webkitTransform='translate(0,'+_screenPanTargetVerticalOffset+'px)';
centerView.style.webkitTransitionDuration='0.5s';
centerView.style.webkitTransform='translate(-100%,'+_screenPanVerticalOffset+'px)'}
else{
var temp=_screenColumns.right;
_screenColumns.right=_screenColumns.center;
_screenColumns.center=_screenColumns.left;
_screenColumns.left=temp;
if(!_screenIsPanning){
rightView.innerHTML='';
temp.pageType=false};
rightView.style.webkitTransitionDuration='0s';
rightView.style.webkitTransform='translate(-100%,0)';
leftView.style.webkitTransitionDuration='0.5s';
leftView.style.webkitTransform='translate(0,'+_screenPanTargetVerticalOffset+'px)';
centerView.style.webkitTransitionDuration='0.5s';
centerView.style.webkitTransform='translate(100%,'+_screenPanVerticalOffset+'px)'};
if(document.body.scrollTop)window.scrollTo(0,0);
if(_popoverShowing)hidePopover()}
function keyboardTransitions(event){
var keyCode=event.which;
if(keyCode==undefined)keyCode=event.keyCode;
if(keyCode==39){
_loadContentInDirection('right')}
else if(keyCode==37)_loadContentInDirection('left')};
window.addEventListener("keydown",keyboardTransitions,false)
function completeSlide(){
if(!_columnsAnimating)return;
_columnsAnimating=false;
hideSectionSelector();
if(!_screenIsPanning)updateContentHeight();
if(!_screenIsPanning&&(_screenPanVerticalOffset||_screenPanTargetVerticalOffset)){
var leftStyle=_eleWithId(_screenColumns.left.id).style,rightStyle=_eleWithId(_screenColumns.right.id).style,centerStyle=_eleWithId(_screenColumns.center.id).style;
leftStyle.webkitTransitionDuration='0s';
leftStyle.webkitTransform='translate(-100%,0)';
rightStyle.webkitTransitionDuration='0s';
rightStyle.webkitTransform='translate(100%,0)';
centerStyle.webkitTransitionDuration='0s';
centerStyle.webkitTransform='translate(0,0)';
var scrollOffset=-_screenPanTargetVerticalOffset;
window.setTimeout(function(){
if(scrollOffset)window.scrollTo(0,scrollOffset);
leftStyle.webkitTransitionDuration='0.5s';
rightStyle.webkitTransitionDuration='0.5s';
centerStyle.webkitTransitionDuration='0.5s'},10)};
if(_screenTransitionEndFunction){
_screenTransitionEndFunction();
_screenTransitionEndFunction=false};
if(_screenColumns.right.pageType=='account'){
_screenColumns.right.pageType=false;
var accountiframe=document.querySelector('#'+_screenColumns.right.id+' .accountiframe');
if(accountiframe)accountiframe.parentNode.removeChild(accountiframe)};
_completeGallerySlide();
preloadAdjacentContent();
doAdverts();
if(_screenColumns.center.pageType=='section'){
siteMapTerm=_structure.categories[_screenColumns.center.pageIdentifier].name}
else if(_screenColumns.center.pageType=='home')siteMapTerm='homepage';
_screenPanVerticalOffset=0;
_screenPanTargetVerticalOffset=0;
if(_showSearch==true&&(_screenColumns.center.pageType=='section'||_screenColumns.center.pageType=='home'||_screenColumns.center.pageType=='markets')){
_showSearch=false;
_showPopover(_lastSearch,null,document.querySelector('.searchbutton'),400)}};
mFT.completeSlide=completeSlide
function _enable3d(){
if(!_disable3dForInteraction||_3daccelerated)return;
Array.prototype.forEach.call(document.querySelectorAll(".uses3d"),function(a3DElement){
});
_3daccelerated=true};
mFT.enable3d=_enable3d
function _disable3d(){
if(!_disable3dForInteraction||!_3daccelerated)return;
Array.prototype.forEach.call(document.querySelectorAll(".uses3d"),function(a3DElement){
a3DElement.style.webkitTransformStyle='flat'});
_3daccelerated=false};
mFT.disable3d=_disable3d
function _prepareCenterColumnForTransitionToTop(){
var centerColumnStyle=document.getElementById(_screenColumns.center.id).style,scrollOffset=-document.body.scrollTop;
if(!scrollOffset)return false;
_screenPanVerticalOffset=scrollOffset;
centerColumnStyle.webkitTransitionDuration='0s';
window.scrollTo(0,0);
centerColumnStyle.webkitTransform='translate(0px,'+scrollOffset+'px)';
return true}
function uaIsOffline(){
return('onLine' in navigator&&navigator.onLine===false)};
mFT.uaIsOffline=uaIsOffline
function enableBigDatabaseMode(){
localStorage.useBigDatabaseMode=true;
localStorage.forceNextStructureUpdate=true;
window.location.reload()};
mFT.enableBigDatabaseMode=enableBigDatabaseMode
function sendFeedback(){
if(_inWrapper){
window.location='mailto:appfeedback@ft.com?subject=Feedback from the FT Android application&body='+encodeURIComponent('\n\n\n\n\n\n\n====\nTechnical information:\nUser-agent: '+navigator.userAgent)}
else window.location='mailto:appfeedback@ft.com?subject=Feedback from the FT HTML5 application&body='+encodeURIComponent('\n\n\n\n\n\n\n====\nTechnical information:\nUser-agent: '+navigator.userAgent)};
mFT.sendFeedback=sendFeedback
function dialNumber(number){
if(navigator.userAgent.indexOf('iPad')>-1)return;
window.location='tel:'+number};
mFT.dialNumber=dialNumber
function getStackTrace(){
var callstack=[],currentFunction=arguments.callee.caller;
while(currentFunction){
var fn=currentFunction.toString(),fname=fn.substring(fn.indexOf('function')+9,fn.indexOf('('))||'anonymous';
callstack.push(fname);
currentFunction=currentFunction.caller};
return callstack.reverse().join(' > ')};
mFT.getStackTrace=getStackTrace
function _eleWithId(id){
return document.getElementById(id)}
function _loadImagesInElement(theelement){
if(_disableImages)return;
var imagestoload=[],imageelementstoload=theelement.querySelectorAll('.imageloading');
Array.prototype.forEach.call(imageelementstoload,function(imagetoload){
var imagename=imagetoload.getAttribute('data-id');
if(imagename)imagestoload.push(imagename)});
if(imagestoload.length){
function _replacePlaceholdersWithImages(imagelist,fallbackFromServer){
for(var i=imageelementstoload.length-1;i>=0;i--){
var imagetoload=imageelementstoload[i],imagename=imagetoload.getAttribute('data-id');
if(imagename&&imagename in imagelist){
imagetoload.innerHTML='<img class="uses3d" src="data:'+imagelist[imagename]+'" />';
imagetoload.className=imagetoload.className.replace(/imageloading/,'')}};
if(fallbackFromServer){
var imagesstilltoload=[];
Array.prototype.forEach.call(imagestoload,function(imageid){
if(!(imageid in imagelist))imagesstilltoload.push(imageid)});
if(imagesstilltoload.length)_retrieveImagesFromServer(imagesstilltoload)}
else if(_bigdatabasemode)_localdb.insertImages(imagelist)};
function _retrieveImagesFromServer(imageidlist){
Assanka.$.ajax({url:sourceURL+'articleimages',data:{id:imageidlist.join(',')},dataType:'json',success:function(returnedImages){
_replacePlaceholdersWithImages(returnedImages,false)}})};
if(_bigdatabasemode){
_localdb.getImages(imagestoload,function(returnedImages){
_replacePlaceholdersWithImages(returnedImages,true)})}
else _retrieveImagesFromServer(imagestoload)}}
function _formatDate(aDate,alwaysUseLong,useIntegratedTimePeriods){
var formattedDate='';
if(typeof aDate!='object')aDate=new Date(aDate);
var minutes=aDate.getMinutes();
if(minutes<10)minutes='0'+minutes;
var hours=aDate.getHours();
if(hours>=12){
formattedDate=((hours==12)?12:(hours-12))+':'+minutes+(useIntegratedTimePeriods?'pm':'<small> PM</small>')+' '}
else formattedDate=((hours==0)?12:hours)+':'+minutes+(useIntegratedTimePeriods?'am':'<small> AM</small>')+' ';
if(aDate>_shortDateCutoffDate&&!alwaysUseLong){
formattedDate+=_dateConstants.days[aDate.getDay()]}
else{
var dayNumber=aDate.getDate();
if(alwaysUseLong)formattedDate+=_dateConstants.days[aDate.getDay()]+' ';
if(dayNumber==1||dayNumber==21||dayNumber==31){
formattedDate+=dayNumber+'st '}
else if(dayNumber==2||dayNumber==22){
formattedDate+=dayNumber+'nd '}
else if(dayNumber==3||dayNumber==23){
formattedDate+=dayNumber+'rd '}
else formattedDate+=dayNumber+'th ';
formattedDate+=_dateConstants.months[aDate.getMonth()];
if(alwaysUseLong)formattedDate+=' '+aDate.getFullYear()};
return formattedDate}
function _formatUpdateDate(aDate){
var formattedDate='';
if(typeof aDate!='object')aDate=new Date(parseInt(aDate));
if(aDate>_shortDateCutoffDate){
var minutes=aDate.getMinutes();
if(minutes<10)minutes='0'+minutes;
var hours=aDate.getHours();
if(hours>=12){
formattedDate=((hours==12)?12:(hours-12))+':'+minutes+'pm'}
else formattedDate=((hours==0)?12:hours)+':'+minutes+'am';
if(aDate.getDay()!=new Date().getDay())formattedDate+=' '+_dateConstants.days[aDate.getDay()].substring(0,3)}
else{
formattedDate+=_dateConstants.months[aDate.getMonth()].substring(0,3);
formattedDate+=' '+aDate.getDate();
formattedDate+=', '+aDate.getFullYear()};
return formattedDate}
function _expandElementWithinElementToFillElement(elementToExpand,wrappingElement,containerElement){
elementToExpand.style.minHeight=(containerElement.offsetHeight-(wrappingElement.offsetHeight-elementToExpand.offsetHeight))+'px'}
function _getTransparentOnePx(){
return'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAkAAAEALAAAAAABAAEAAAICTAEAOw=='}
function _getUpDownClass(d){
var updown='negative';
if(d.replace('%','')>0)updown='positive';
if(d.replace('%','')==0)updown='neutral';
return updown}
function isObjectEmpty(anObject){
for(var i in anObject)if(anObject.hasOwnProperty(i))return false;
return true}
function areObjectsEqual(a,b){
if(typeof (a)!=='object'||typeof (b)!=='object')return(a===b);
for(var i in a){
if(typeof (a[i])!==typeof (b[i]))return false;
switch(typeof (a[i])){case'object':if(!areObjectsEqual(a[i],b[i]))return false;
break;case'function':if(typeof (b[i])=='undefined'||a[i].toString()!=b[i].toString())return false;
break;default:if(a[i]!==b[i])return false}};
for(i in b)if(typeof (a[i])=='undefined')return false;
return true}
return mFT;
}());
@rwaldron
Copy link

rwaldron commented Jun 8, 2011

How did that jQuery header get in there?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment