
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;

if(typeof jwplayer=="undefined"){var jwplayer=function(a){if(jwplayer.api){return jwplayer.api.selectPlayer(a)}};var $jw=jwplayer;jwplayer.version="5.7.1864";jwplayer.vid=document.createElement("video");jwplayer.audio=document.createElement("audio");jwplayer.source=document.createElement("source");(function(b){b.utils=function(){};b.utils.typeOf=function(d){var c=typeof d;if(c==="object"){if(d){if(d instanceof Array){c="array"}}else{c="null"}}return c};b.utils.extend=function(){var c=b.utils.extend["arguments"];if(c.length>1){for(var e=1;e<c.length;e++){for(var d in c[e]){c[0][d]=c[e][d]}}return c[0]}return null};b.utils.clone=function(f){var c;var d=b.utils.clone["arguments"];if(d.length==1){switch(b.utils.typeOf(d[0])){case"object":c={};for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;case"array":c=[];for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;default:return d[0];break}}return c};b.utils.extension=function(c){if(!c){return""}c=c.substring(c.lastIndexOf("/")+1,c.length);c=c.split("?")[0];if(c.lastIndexOf(".")>-1){return c.substr(c.lastIndexOf(".")+1,c.length).toLowerCase()}return};b.utils.html=function(c,d){c.innerHTML=d};b.utils.wrap=function(c,d){if(c.parentNode){c.parentNode.replaceChild(d,c)}d.appendChild(c)};b.utils.ajax=function(g,f,c){var e;if(window.XMLHttpRequest){e=new XMLHttpRequest()}else{e=new ActiveXObject("Microsoft.XMLHTTP")}e.onreadystatechange=function(){if(e.readyState===4){if(e.status===200){if(f){f(e)}}else{if(c){c(g)}}}};try{e.open("GET",g,true);e.send(null)}catch(d){if(c){c(g)}}return e};b.utils.load=function(d,e,c){d.onreadystatechange=function(){if(d.readyState===4){if(d.status===200){if(e){e()}}else{if(c){c()}}}}};b.utils.find=function(d,c){return d.getElementsByTagName(c)};b.utils.append=function(c,d){c.appendChild(d)};b.utils.isIE=function(){return((!+"\v1")||(typeof window.ActiveXObject!="undefined"))};b.utils.isLegacyAndroid=function(){var c=navigator.userAgent.toLowerCase();return(c.match(/android 2.[012]/i)!==null)};b.utils.isIOS=function(d){if(typeof d=="undefined"){d=/iP(hone|ad|od)/i}var c=navigator.userAgent.toLowerCase();return(c.match(d)!==null)};b.utils.isIPad=function(){return b.utils.isIOS(/iPad/i)};b.utils.isIPod=function(){return b.utils.isIOS(/iP(hone|od)/i)};b.utils.getFirstPlaylistItemFromConfig=function(c){var d={};var e;if(c.playlist&&c.playlist.length){e=c.playlist[0]}else{e=c}d.file=e.file;d.levels=e.levels;d.streamer=e.streamer;d.playlistfile=e.playlistfile;d.provider=e.provider;if(!d.provider){if(d.file&&(d.file.toLowerCase().indexOf("youtube.com")>-1||d.file.toLowerCase().indexOf("youtu.be")>-1)){d.provider="youtube"}if(d.streamer&&d.streamer.toLowerCase().indexOf("rtmp://")==0){d.provider="rtmp"}if(e.type){d.provider=e.type.toLowerCase()}}if(d.provider=="audio"){d.provider="sound"}return d};b.utils.getOuterHTML=function(c){if(c.outerHTML){return c.outerHTML}else{try{return new XMLSerializer().serializeToString(c)}catch(d){return""}}};b.utils.setOuterHTML=function(f,e){if(f.outerHTML){f.outerHTML=e}else{var g=document.createElement("div");g.innerHTML=e;var c=document.createRange();c.selectNodeContents(g);var d=c.extractContents();f.parentNode.insertBefore(d,f);f.parentNode.removeChild(f)}};b.utils.hasFlash=function(){if(typeof navigator.plugins!="undefined"&&typeof navigator.plugins["Shockwave Flash"]!="undefined"){return true}if(typeof window.ActiveXObject!="undefined"){try{new ActiveXObject("ShockwaveFlash.ShockwaveFlash");return true}catch(c){}}return false};b.utils.getPluginName=function(c){if(c.lastIndexOf("/")>=0){c=c.substring(c.lastIndexOf("/")+1,c.length)}if(c.lastIndexOf("-")>=0){c=c.substring(0,c.lastIndexOf("-"))}if(c.lastIndexOf(".swf")>=0){c=c.substring(0,c.lastIndexOf(".swf"))}if(c.lastIndexOf(".js")>=0){c=c.substring(0,c.lastIndexOf(".js"))}return c};b.utils.getPluginVersion=function(c){if(c.lastIndexOf("-")>=0){if(c.lastIndexOf(".js")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".js"))}else{if(c.lastIndexOf(".swf")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".swf"))}else{return c.substring(c.lastIndexOf("-")+1)}}}return""};b.utils.getAbsolutePath=function(j,h){if(!b.utils.exists(h)){h=document.location.href}if(!b.utils.exists(j)){return undefined}if(a(j)){return j}var k=h.substring(0,h.indexOf("://")+3);var g=h.substring(k.length,h.indexOf("/",k.length+1));var d;if(j.indexOf("/")===0){d=j.split("/")}else{var e=h.split("?")[0];e=e.substring(k.length+g.length+1,e.lastIndexOf("/"));d=e.split("/").concat(j.split("/"))}var c=[];for(var f=0;f<d.length;f++){if(!d[f]||!b.utils.exists(d[f])||d[f]=="."){continue}else{if(d[f]==".."){c.pop()}else{c.push(d[f])}}}return k+g+"/"+c.join("/")};function a(d){if(!b.utils.exists(d)){return}var e=d.indexOf("://");var c=d.indexOf("?");return(e>0&&(c<0||(c>e)))}b.utils.pluginPathType={ABSOLUTE:"ABSOLUTE",RELATIVE:"RELATIVE",CDN:"CDN"};b.utils.getPluginPathType=function(d){if(typeof d!="string"){return}d=d.split("?")[0];var e=d.indexOf("://");if(e>0){return b.utils.pluginPathType.ABSOLUTE}var c=d.indexOf("/");var f=b.utils.extension(d);if(e<0&&c<0&&(!f||!isNaN(f))){return b.utils.pluginPathType.CDN}return b.utils.pluginPathType.RELATIVE};b.utils.mapEmpty=function(c){for(var d in c){return false}return true};b.utils.mapLength=function(d){var c=0;for(var e in d){c++}return c};b.utils.log=function(d,c){if(typeof console!="undefined"&&typeof console.log!="undefined"){if(c){console.log(d,c)}else{console.log(d)}}};b.utils.css=function(d,g,c){if(b.utils.exists(d)){for(var e in g){try{if(typeof g[e]==="undefined"){continue}else{if(typeof g[e]=="number"&&!(e=="zIndex"||e=="opacity")){if(isNaN(g[e])){continue}if(e.match(/color/i)){g[e]="#"+b.utils.strings.pad(g[e].toString(16),6)}else{g[e]=Math.ceil(g[e])+"px"}}}d.style[e]=g[e]}catch(f){}}}};b.utils.isYouTube=function(c){return(c.indexOf("youtube.com")>-1||c.indexOf("youtu.be")>-1)};b.utils.transform=function(c,d){c.style.webkitTransform=d;c.style.MozTransform=d;c.style.OTransform=d};b.utils.stretch=function(h,n,m,f,l,g){if(typeof m=="undefined"||typeof f=="undefined"||typeof l=="undefined"||typeof g=="undefined"){return}var d=m/l;var e=f/g;var k=0;var j=0;n.style.overflow="hidden";b.utils.transform(n,"");var c={};switch(h.toUpperCase()){case b.utils.stretching.NONE:c.width=l;c.height=g;break;case b.utils.stretching.UNIFORM:if(d>e){c.width=l*e;c.height=g*e}else{c.width=l*d;c.height=g*d}break;case b.utils.stretching.FILL:if(d>e){c.width=l*d;c.height=g*d}else{c.width=l*e;c.height=g*e}break;case b.utils.stretching.EXACTFIT:b.utils.transform(n,["scale(",d,",",e,")"," translate(0px,0px)"].join(""));c.width=l;c.height=g;break;default:break}c.top=(f-c.height)/2;c.left=(m-c.width)/2;b.utils.css(n,c)};b.utils.stretching={NONE:"NONE",FILL:"FILL",UNIFORM:"UNIFORM",EXACTFIT:"EXACTFIT"};b.utils.deepReplaceKeyName=function(h,e,c){switch(b.utils.typeOf(h)){case"array":for(var g=0;g<h.length;g++){h[g]=b.utils.deepReplaceKeyName(h[g],e,c)}break;case"object":for(var f in h){var d=f.replace(new RegExp(e,"g"),c);h[d]=b.utils.deepReplaceKeyName(h[f],e,c);if(f!=d){delete h[f]}}break}return h};b.utils.isInArray=function(e,d){if(!(e)||!(e instanceof Array)){return false}for(var c=0;c<e.length;c++){if(d===e[c]){return true}}return false};b.utils.exists=function(c){switch(typeof(c)){case"string":return(c.length>0);break;case"object":return(c!==null);case"undefined":return false}return true};b.utils.empty=function(c){if(typeof c.hasChildNodes=="function"){while(c.hasChildNodes()){c.removeChild(c.firstChild)}}};b.utils.parseDimension=function(c){if(typeof c=="string"){if(c===""){return 0}else{if(c.lastIndexOf("%")>-1){return c}else{return parseInt(c.replace("px",""),10)}}}return c};b.utils.getDimensions=function(c){if(c&&c.style){return{x:b.utils.parseDimension(c.style.left),y:b.utils.parseDimension(c.style.top),width:b.utils.parseDimension(c.style.width),height:b.utils.parseDimension(c.style.height)}}else{return{}}};b.utils.timeFormat=function(c){str="00:00";if(c>0){str=Math.floor(c/60)<10?"0"+Math.floor(c/60)+":":Math.floor(c/60)+":";str+=Math.floor(c%60)<10?"0"+Math.floor(c%60):Math.floor(c%60)}return str}})(jwplayer);(function(a){a.events=function(){};a.events.COMPLETE="COMPLETE";a.events.ERROR="ERROR"})(jwplayer);(function(jwplayer){jwplayer.events.eventdispatcher=function(debug){var _debug=debug;var _listeners;var _globallisteners;this.resetEventListeners=function(){_listeners={};_globallisteners=[]};this.resetEventListeners();this.addEventListener=function(type,listener,count){try{if(!jwplayer.utils.exists(_listeners[type])){_listeners[type]=[]}if(typeof(listener)=="string"){eval("listener = "+listener)}_listeners[type].push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeEventListener=function(type,listener){if(!_listeners[type]){return}try{for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){if(_listeners[type][listenerIndex].listener.toString()==listener.toString()){_listeners[type].splice(listenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.addGlobalListener=function(listener,count){try{if(typeof(listener)=="string"){eval("listener = "+listener)}_globallisteners.push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeGlobalListener=function(listener){if(!_globallisteners[type]){return}try{for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){if(_globallisteners[globalListenerIndex].listener.toString()==listener.toString()){_globallisteners.splice(globalListenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.sendEvent=function(type,data){if(!jwplayer.utils.exists(data)){data={}}if(_debug){jwplayer.utils.log(type,data)}if(typeof _listeners[type]!="undefined"){for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){try{_listeners[type][listenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_listeners[type][listenerIndex].listener)}if(_listeners[type][listenerIndex]){if(_listeners[type][listenerIndex].count===1){delete _listeners[type][listenerIndex]}else{if(_listeners[type][listenerIndex].count>0){_listeners[type][listenerIndex].count=_listeners[type][listenerIndex].count-1}}}}}for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){try{_globallisteners[globalListenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_globallisteners[globalListenerIndex].listener)}if(_globallisteners[globalListenerIndex]){if(_globallisteners[globalListenerIndex].count===1){delete _globallisteners[globalListenerIndex]}else{if(_globallisteners[globalListenerIndex].count>0){_globallisteners[globalListenerIndex].count=_globallisteners[globalListenerIndex].count-1}}}}}}})(jwplayer);(function(a){var b={};a.utils.animations=function(){};a.utils.animations.transform=function(c,d){c.style.webkitTransform=d;c.style.MozTransform=d;c.style.OTransform=d;c.style.msTransform=d};a.utils.animations.transformOrigin=function(c,d){c.style.webkitTransformOrigin=d;c.style.MozTransformOrigin=d;c.style.OTransformOrigin=d;c.style.msTransformOrigin=d};a.utils.animations.rotate=function(c,d){a.utils.animations.transform(c,["rotate(",d,"deg)"].join(""))};a.utils.cancelAnimation=function(c){delete b[c.id]};a.utils.fadeTo=function(m,f,e,j,h,d){if(b[m.id]!=d&&a.utils.exists(d)){return}if(m.style.opacity==f){return}var c=new Date().getTime();if(d>c){setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},d-c)}if(m.style.display=="none"){m.style.display="block"}if(!a.utils.exists(j)){j=m.style.opacity===""?1:m.style.opacity}if(m.style.opacity==f&&m.style.opacity!==""&&a.utils.exists(d)){if(f===0){m.style.display="none"}return}if(!a.utils.exists(d)){d=c;b[m.id]=d}if(!a.utils.exists(h)){h=0}var k=(e>0)?((c-d)/(e*1000)):0;k=k>1?1:k;var l=f-j;var g=j+(k*l);if(g>1){g=1}else{if(g<0){g=0}}m.style.opacity=g;if(h>0){b[m.id]=d+h*1000;a.utils.fadeTo(m,f,e,j,0,b[m.id]);return}setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},10)}})(jwplayer);(function(a){a.utils.arrays=function(){};a.utils.arrays.indexOf=function(c,d){for(var b=0;b<c.length;b++){if(c[b]==d){return b}}return -1};a.utils.arrays.remove=function(c,d){var b=a.utils.arrays.indexOf(c,d);if(b>-1){c.splice(b,1)}}})(jwplayer);(function(a){a.utils.extensionmap={"3gp":{html5:"video/3gpp",flash:"video"},"3gpp":{html5:"video/3gpp"},"3g2":{html5:"video/3gpp2",flash:"video"},"3gpp2":{html5:"video/3gpp2"},flv:{flash:"video"},f4a:{html5:"audio/mp4"},f4b:{html5:"audio/mp4",flash:"video"},f4v:{html5:"video/mp4",flash:"video"},mov:{html5:"video/quicktime",flash:"video"},m4a:{html5:"audio/mp4",flash:"video"},m4b:{html5:"audio/mp4"},m4p:{html5:"audio/mp4"},m4v:{html5:"video/mp4",flash:"video"},mp4:{html5:"video/mp4",flash:"video"},rbs:{flash:"sound"},aac:{html5:"audio/aac",flash:"video"},mp3:{html5:"audio/mp3",flash:"sound"},ogg:{html5:"audio/ogg"},oga:{html5:"audio/ogg"},ogv:{html5:"video/ogg"},webm:{html5:"video/webm"},m3u8:{html5:"audio/x-mpegurl"},gif:{flash:"image"},jpeg:{flash:"image"},jpg:{flash:"image"},swf:{flash:"image"},png:{flash:"image"},wav:{html5:"audio/x-wav"}}})(jwplayer);(function(e){e.utils.mediaparser=function(){};var g={element:{width:"width",height:"height",id:"id","class":"className",name:"name"},media:{src:"file",preload:"preload",autoplay:"autostart",loop:"repeat",controls:"controls"},source:{src:"file",type:"type",media:"media","data-jw-width":"width","data-jw-bitrate":"bitrate"},video:{poster:"image"}};var f={};e.utils.mediaparser.parseMedia=function(j){return d(j)};function c(k,j){if(!e.utils.exists(j)){j=g[k]}else{e.utils.extend(j,g[k])}return j}function d(n,j){if(f[n.tagName.toLowerCase()]&&!e.utils.exists(j)){return f[n.tagName.toLowerCase()](n)}else{j=c("element",j);var o={};for(var k in j){if(k!="length"){var m=n.getAttribute(k);if(e.utils.exists(m)){o[j[k]]=m}}}var l=n.style["#background-color"];if(l&&!(l=="transparent"||l=="rgba(0, 0, 0, 0)")){o.screencolor=l}return o}}function h(n,k){k=c("media",k);var l=[];var j=e.utils.selectors("source",n);for(var m in j){if(!isNaN(m)){l.push(a(j[m]))}}var o=d(n,k);if(e.utils.exists(o.file)){l[0]={file:o.file}}o.levels=l;return o}function a(l,k){k=c("source",k);var j=d(l,k);j.width=j.width?j.width:0;j.bitrate=j.bitrate?j.bitrate:0;return j}function b(l,k){k=c("video",k);var j=h(l,k);return j}f.media=h;f.audio=h;f.source=a;f.video=b})(jwplayer);(function(a){a.utils.loaderstatus={NEW:"NEW",LOADING:"LOADING",ERROR:"ERROR",COMPLETE:"COMPLETE"};a.utils.scriptloader=function(c){var d=a.utils.loaderstatus.NEW;var b=new a.events.eventdispatcher();a.utils.extend(this,b);this.load=function(){if(d==a.utils.loaderstatus.NEW){d=a.utils.loaderstatus.LOADING;var e=document.createElement("script");e.onload=function(f){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)};e.onerror=function(f){d=a.utils.loaderstatus.ERROR;b.sendEvent(a.events.ERROR)};e.onreadystatechange=function(){if(e.readyState=="loaded"||e.readyState=="complete"){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)}};document.getElementsByTagName("head")[0].appendChild(e);e.src=c}};this.getStatus=function(){return d}}})(jwplayer);(function(a){a.utils.selectors=function(b,e){if(!a.utils.exists(e)){e=document}b=a.utils.strings.trim(b);var c=b.charAt(0);if(c=="#"){return e.getElementById(b.substr(1))}else{if(c=="."){if(e.getElementsByClassName){return e.getElementsByClassName(b.substr(1))}else{return a.utils.selectors.getElementsByTagAndClass("*",b.substr(1))}}else{if(b.indexOf(".")>0){var d=b.split(".");return a.utils.selectors.getElementsByTagAndClass(d[0],d[1])}else{return e.getElementsByTagName(b)}}}return null};a.utils.selectors.getElementsByTagAndClass=function(e,h,g){var j=[];if(!a.utils.exists(g)){g=document}var f=g.getElementsByTagName(e);for(var d=0;d<f.length;d++){if(a.utils.exists(f[d].className)){var c=f[d].className.split(" ");for(var b=0;b<c.length;b++){if(c[b]==h){j.push(f[d])}}}}return j}})(jwplayer);(function(a){a.utils.strings=function(){};a.utils.strings.trim=function(b){return b.replace(/^\s*/,"").replace(/\s*$/,"")};a.utils.strings.pad=function(c,d,b){if(!b){b="0"}while(c.length<d){c=b+c}return c};a.utils.strings.serialize=function(b){if(b==null){return null}else{if(b=="true"){return true}else{if(b=="false"){return false}else{if(isNaN(Number(b))||b.length>5||b.length==0){return b}else{return Number(b)}}}}};a.utils.strings.seconds=function(d){d=d.replace(",",".");var b=d.split(":");var c=0;if(d.substr(-1)=="s"){c=Number(d.substr(0,d.length-1))}else{if(d.substr(-1)=="m"){c=Number(d.substr(0,d.length-1))*60}else{if(d.substr(-1)=="h"){c=Number(d.substr(0,d.length-1))*3600}else{if(b.length>1){c=Number(b[b.length-1]);c+=Number(b[b.length-2])*60;if(b.length==3){c+=Number(b[b.length-3])*3600}}else{c=Number(d)}}}}return c};a.utils.strings.xmlAttribute=function(b,c){for(var d in b.attributes){if(b.attributes[d].name&&b.attributes[d].name.toLowerCase()==c.toLowerCase()){return b.attributes[d].value.toString()}}return""};a.utils.strings.jsonToString=function(f){var h=h||{};if(h&&h.stringify){return h.stringify(f)}var c=typeof(f);if(c!="object"||f===null){if(c=="string"){f='"'+f+'"'}else{return String(f)}}else{var g=[],b=(f&&f.constructor==Array);for(var d in f){var e=f[d];switch(typeof(e)){case"string":e='"'+e+'"';break;case"object":if(a.utils.exists(e)){e=a.utils.strings.jsonToString(e)}break}if(b){if(typeof(e)!="function"){g.push(String(e))}}else{if(typeof(e)!="function"){g.push('"'+d+'":'+String(e))}}}if(b){return"["+String(g)+"]"}else{return"{"+String(g)+"}"}}}})(jwplayer);(function(c){var d=new RegExp(/^(#|0x)[0-9a-fA-F]{3,6}/);c.utils.typechecker=function(g,f){f=!c.utils.exists(f)?b(g):f;return e(g,f)};function b(f){var g=["true","false","t","f"];if(g.toString().indexOf(f.toLowerCase().replace(" ",""))>=0){return"boolean"}else{if(d.test(f)){return"color"}else{if(!isNaN(parseInt(f,10))&&parseInt(f,10).toString().length==f.length){return"integer"}else{if(!isNaN(parseFloat(f))&&parseFloat(f).toString().length==f.length){return"float"}}}}return"string"}function e(g,f){if(!c.utils.exists(f)){return g}switch(f){case"color":if(g.length>0){return a(g)}return null;case"integer":return parseInt(g,10);case"float":return parseFloat(g);case"boolean":if(g.toLowerCase()=="true"){return true}else{if(g=="1"){return true}}return false}return g}function a(f){switch(f.toLowerCase()){case"blue":return parseInt("0000FF",16);case"green":return parseInt("00FF00",16);case"red":return parseInt("FF0000",16);case"cyan":return parseInt("00FFFF",16);case"magenta":return parseInt("FF00FF",16);case"yellow":return parseInt("FFFF00",16);case"black":return parseInt("000000",16);case"white":return parseInt("FFFFFF",16);default:f=f.replace(/(#|0x)?([0-9A-F]{3,6})$/gi,"$2");if(f.length==3){f=f.charAt(0)+f.charAt(0)+f.charAt(1)+f.charAt(1)+f.charAt(2)+f.charAt(2)}return parseInt(f,16)}return parseInt("000000",16)}})(jwplayer);(function(a){a.utils.parsers=function(){}})(jwplayer);(function(a){a.utils.parsers.jwparser=function(){};a.utils.parsers.jwparser.PREFIX="jwplayer";a.utils.parsers.jwparser.parseEntry=function(c,d){for(var b in c.childNodes){if(c.childNodes[b].prefix==a.utils.parsers.jwparser.PREFIX){d[c.childNodes[b].localName]=a.utils.strings.serialize(c.childNodes[b].textContent)}if(!d.file&&String(d.link).toLowerCase().indexOf("youtube")>-1){d.file=d.link}}return d};a.utils.parsers.jwparser.getProvider=function(c){if(c.type){return c.type}else{if(c.file.indexOf("youtube.com/w")>-1||c.file.indexOf("youtube.com/v")>-1||c.file.indexOf("youtu.be/")>-1){return"youtube"}else{if(c.streamer&&c.streamer.indexOf("rtmp")==0){return"rtmp"}else{if(c.streamer&&c.streamer.indexOf("http")==0){return"http"}else{var b=a.utils.strings.extension(c.file);if(extensions.hasOwnProperty(b)){return extensions[b]}}}}}return""}})(jwplayer);(function(a){a.utils.parsers.mediaparser=function(){};a.utils.parsers.mediaparser.PREFIX="media";a.utils.parsers.mediaparser.parseGroup=function(d,f){var e=false;for(var c in d.childNodes){if(d.childNodes[c].prefix==a.utils.parsers.mediaparser.PREFIX){if(!d.childNodes[c].localName){continue}switch(d.childNodes[c].localName.toLowerCase()){case"content":if(!e){f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}if(d.childNodes[c].attributes.duration){f.duration=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"duration"))}if(d.childNodes[c].attributes.start){f.start=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"start"))}if(d.childNodes[c].childNodes&&d.childNodes[c].childNodes.length>0){f=a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f)}if(d.childNodes[c].attributes.width||d.childNodes[c].attributes.bitrate||d.childNodes[c].attributes.url){if(!f.levels){f.levels=[]}f.levels.push({width:a.utils.strings.xmlAttribute(d.childNodes[c],"width"),bitrate:a.utils.strings.xmlAttribute(d.childNodes[c],"bitrate"),file:a.utils.strings.xmlAttribute(d.childNodes[c],"url")})}break;case"title":f.title=d.childNodes[c].textContent;break;case"description":f.description=d.childNodes[c].textContent;break;case"keywords":f.tags=d.childNodes[c].textContent;break;case"thumbnail":f.image=a.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"credit":f.author=d.childNodes[c].textContent;break;case"player":var b=d.childNodes[c].url;if(b.indexOf("youtube.com")>=0||b.indexOf("youtu.be")>=0){e=true;f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}break;case"group":a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f);break}}}return f}})(jwplayer);(function(b){b.utils.parsers.rssparser=function(){};b.utils.parsers.rssparser.parse=function(f){var c=[];for(var e in f.childNodes){if(f.childNodes[e].localName&&f.childNodes[e].localName.toLowerCase()=="channel"){for(var d in f.childNodes[e].childNodes){if(f.childNodes[e].childNodes[d].localName&&f.childNodes[e].childNodes[d].localName.toLowerCase()=="item"){c.push(a(f.childNodes[e].childNodes[d]))}}}}return c};function a(d){var e={};for(var c in d.childNodes){if(!d.childNodes[c].localName){continue}switch(d.childNodes[c].localName.toLowerCase()){case"enclosure":e.file=b.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"title":e.title=d.childNodes[c].textContent;break;case"pubdate":e.date=d.childNodes[c].textContent;break;case"description":e.description=d.childNodes[c].textContent;break;case"link":e.link=d.childNodes[c].textContent;break;case"category":if(e.tags){e.tags+=d.childNodes[c].textContent}else{e.tags=d.childNodes[c].textContent}break}}e=b.utils.parsers.mediaparser.parseGroup(d,e);e=b.utils.parsers.jwparser.parseEntry(d,e);return new b.html5.playlistitem(e)}})(jwplayer);(function(a){var c={};var b={};a.plugins=function(){};a.plugins.loadPlugins=function(e,d){b[e]=new a.plugins.pluginloader(new a.plugins.model(c),d);return b[e]};a.plugins.registerPlugin=function(h,f,e){var d=a.utils.getPluginName(h);if(c[d]){c[d].registerPlugin(h,f,e)}else{a.utils.log("A plugin ("+h+") was registered with the player that was not loaded. Please check your configuration.");for(var g in b){b[g].pluginFailed()}}}})(jwplayer);(function(a){a.plugins.model=function(b){this.addPlugin=function(c){var d=a.utils.getPluginName(c);if(!b[d]){b[d]=new a.plugins.plugin(c)}return b[d]}}})(jwplayer);(function(a){a.plugins.pluginmodes={FLASH:"FLASH",JAVASCRIPT:"JAVASCRIPT",HYBRID:"HYBRID"};a.plugins.plugin=function(b){var d="http://plugins.longtailvideo.com";var j=a.utils.loaderstatus.NEW;var k;var h;var l;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function e(){switch(a.utils.getPluginPathType(b)){case a.utils.pluginPathType.ABSOLUTE:return b;case a.utils.pluginPathType.RELATIVE:return a.utils.getAbsolutePath(b,window.location.href);case a.utils.pluginPathType.CDN:var n=a.utils.getPluginName(b);var m=a.utils.getPluginVersion(b);return d+"/"+a.version.split(".")[0]+"/"+n+"/"+n+(m!==""?("-"+m):"")+".js"}}function g(m){l=setTimeout(function(){j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)},1000)}function f(m){j=a.utils.loaderstatus.ERROR;c.sendEvent(a.events.ERROR)}this.load=function(){if(j==a.utils.loaderstatus.NEW){if(b.lastIndexOf(".swf")>0){k=b;j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE);return}j=a.utils.loaderstatus.LOADING;var m=new a.utils.scriptloader(e());m.addEventListener(a.events.COMPLETE,g);m.addEventListener(a.events.ERROR,f);m.load()}};this.registerPlugin=function(o,n,m){if(l){clearTimeout(l);l=undefined}if(n&&m){k=m;h=n}else{if(typeof n=="string"){k=n}else{if(typeof n=="function"){h=n}else{if(!n&&!m){k=o}}}}j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)};this.getStatus=function(){return j};this.getPluginName=function(){return a.utils.getPluginName(b)};this.getFlashPath=function(){if(k){switch(a.utils.getPluginPathType(k)){case a.utils.pluginPathType.ABSOLUTE:return k;case a.utils.pluginPathType.RELATIVE:if(b.lastIndexOf(".swf")>0){return a.utils.getAbsolutePath(k,window.location.href)}return a.utils.getAbsolutePath(k,e());case a.utils.pluginPathType.CDN:if(k.indexOf("-")>-1){return k+"h"}return k+"-h"}}return null};this.getJS=function(){return h};this.getPluginmode=function(){if(typeof k!="undefined"&&typeof h!="undefined"){return a.plugins.pluginmodes.HYBRID}else{if(typeof k!="undefined"){return a.plugins.pluginmodes.FLASH}else{if(typeof h!="undefined"){return a.plugins.pluginmodes.JAVASCRIPT}}}};this.getNewInstance=function(n,m,o){return new h(n,m,o)};this.getURL=function(){return b}}})(jwplayer);(function(a){a.plugins.pluginloader=function(h,e){var g={};var k=a.utils.loaderstatus.NEW;var d=false;var b=false;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function f(){if(!b){b=true;k=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)}}function j(){if(!b){var m=0;for(plugin in g){var l=g[plugin].getStatus();if(l==a.utils.loaderstatus.LOADING||l==a.utils.loaderstatus.NEW){m++}}if(m==0){f()}}}this.setupPlugins=function(n,l,s){var m={length:0,plugins:{}};var p={length:0,plugins:{}};for(var o in g){var q=g[o].getPluginName();if(g[o].getFlashPath()){m.plugins[g[o].getFlashPath()]=l.plugins[o];m.plugins[g[o].getFlashPath()].pluginmode=g[o].getPluginmode();m.length++}if(g[o].getJS()){var r=document.createElement("div");r.id=n.id+"_"+q;r.style.position="absolute";r.style.zIndex=p.length+10;p.plugins[q]=g[o].getNewInstance(n,l.plugins[o],r);p.length++;if(typeof p.plugins[q].resize!="undefined"){n.onReady(s(p.plugins[q],r,true));n.onResize(s(p.plugins[q],r))}}}n.plugins=p.plugins;return m};this.load=function(){k=a.utils.loaderstatus.LOADING;d=true;for(var l in e){if(a.utils.exists(l)){g[l]=h.addPlugin(l);g[l].addEventListener(a.events.COMPLETE,j);g[l].addEventListener(a.events.ERROR,j)}}for(l in g){g[l].load()}d=false;j()};this.pluginFailed=function(){f()};this.getStatus=function(){return k}}})(jwplayer);(function(b){var a=[];b.api=function(d){this.container=d;this.id=d.id;var n={};var s={};var q={};var c=[];var h=undefined;var l=false;var j=[];var p=b.utils.getOuterHTML(d);var r={};var k={};this.getBuffer=function(){return this.callInternal("jwGetBuffer")};this.getContainer=function(){return this.container};function e(u,t){return function(z,v,w,x){if(this.renderingMode=="flash"||this.renderingMode=="html5"){var y;if(v){k[z]=v;y="jwplayer('"+u.id+"').callback('"+z+"')"}else{if(!v&&k[z]){delete k[z]}}h.jwDockSetButton(z,y,w,x)}return t}}this.getPlugin=function(t){var v=this;var u={};if(t=="dock"){return b.utils.extend(u,{setButton:e(v,u),show:function(){v.callInternal("jwDockShow");return u},hide:function(){v.callInternal("jwDockHide");return u},onShow:function(w){v.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{if(t=="controlbar"){return b.utils.extend(u,{show:function(){v.callInternal("jwControlbarShow");return u},hide:function(){v.callInternal("jwControlbarHide");return u},onShow:function(w){v.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{if(t=="display"){return b.utils.extend(u,{show:function(){v.callInternal("jwDisplayShow");return u},hide:function(){v.callInternal("jwDisplayHide");return u},onShow:function(w){v.componentListener("display",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("display",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{return this.plugins[t]}}}};this.callback=function(t){if(k[t]){return k[t]()}};this.getDuration=function(){return this.callInternal("jwGetDuration")};this.getFullscreen=function(){return this.callInternal("jwGetFullscreen")};this.getHeight=function(){return this.callInternal("jwGetHeight")};this.getLockState=function(){return this.callInternal("jwGetLockState")};this.getMeta=function(){return this.getItemMeta()};this.getMute=function(){return this.callInternal("jwGetMute")};this.getPlaylist=function(){var u=this.callInternal("jwGetPlaylist");if(this.renderingMode=="flash"){b.utils.deepReplaceKeyName(u,"__dot__",".")}for(var t=0;t<u.length;t++){if(!b.utils.exists(u[t].index)){u[t].index=t}}return u};this.getPlaylistItem=function(t){if(!b.utils.exists(t)){t=this.getCurrentItem()}return this.getPlaylist()[t]};this.getPosition=function(){return this.callInternal("jwGetPosition")};this.getRenderingMode=function(){return this.renderingMode};this.getState=function(){return this.callInternal("jwGetState")};this.getVolume=function(){return this.callInternal("jwGetVolume")};this.getWidth=function(){return this.callInternal("jwGetWidth")};this.setFullscreen=function(t){if(!b.utils.exists(t)){this.callInternal("jwSetFullscreen",!this.callInternal("jwGetFullscreen"))}else{this.callInternal("jwSetFullscreen",t)}return this};this.setMute=function(t){if(!b.utils.exists(t)){this.callInternal("jwSetMute",!this.callInternal("jwGetMute"))}else{this.callInternal("jwSetMute",t)}return this};this.lock=function(){return this};this.unlock=function(){return this};this.load=function(t){this.callInternal("jwLoad",t);return this};this.playlistItem=function(t){this.callInternal("jwPlaylistItem",t);return this};this.playlistPrev=function(){this.callInternal("jwPlaylistPrev");return this};this.playlistNext=function(){this.callInternal("jwPlaylistNext");return this};this.resize=function(u,t){if(this.renderingMode=="html5"){h.jwResize(u,t)}else{this.container.width=u;this.container.height=t}return this};this.play=function(t){if(typeof t=="undefined"){t=this.getState();if(t==b.api.events.state.PLAYING||t==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPlay",t)}return this};this.pause=function(t){if(typeof t=="undefined"){t=this.getState();if(t==b.api.events.state.PLAYING||t==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPause",t)}return this};this.stop=function(){this.callInternal("jwStop");return this};this.seek=function(t){this.callInternal("jwSeek",t);return this};this.setVolume=function(t){this.callInternal("jwSetVolume",t);return this};this.onBufferChange=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER,t)};this.onBufferFull=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,t)};this.onError=function(t){return this.eventListener(b.api.events.JWPLAYER_ERROR,t)};this.onFullscreen=function(t){return this.eventListener(b.api.events.JWPLAYER_FULLSCREEN,t)};this.onMeta=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_META,t)};this.onMute=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_MUTE,t)};this.onPlaylist=function(t){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_LOADED,t)};this.onPlaylistItem=function(t){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,t)};this.onReady=function(t){return this.eventListener(b.api.events.API_READY,t)};this.onResize=function(t){return this.eventListener(b.api.events.JWPLAYER_RESIZE,t)};this.onComplete=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,t)};this.onSeek=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_SEEK,t)};this.onTime=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_TIME,t)};this.onVolume=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_VOLUME,t)};this.onBuffer=function(t){return this.stateListener(b.api.events.state.BUFFERING,t)};this.onPause=function(t){return this.stateListener(b.api.events.state.PAUSED,t)};this.onPlay=function(t){return this.stateListener(b.api.events.state.PLAYING,t)};this.onIdle=function(t){return this.stateListener(b.api.events.state.IDLE,t)};this.remove=function(){n={};j=[];if(b.utils.getOuterHTML(this.container)!=p){b.api.destroyPlayer(this.id,p)}};this.setup=function(u){if(b.embed){var t=this.id;this.remove();var v=b(t);v.config=u;return new b.embed(v)}return this};this.registerPlugin=function(v,u,t){b.plugins.registerPlugin(v,u,t)};this.setPlayer=function(t,u){h=t;this.renderingMode=u};this.stateListener=function(t,u){if(!s[t]){s[t]=[];this.eventListener(b.api.events.JWPLAYER_PLAYER_STATE,g(t))}s[t].push(u);return this};function g(t){return function(v){var u=v.newstate,x=v.oldstate;if(u==t){var w=s[u];if(w){for(var y=0;y<w.length;y++){if(typeof w[y]=="function"){w[y].call(this,{oldstate:x,newstate:u})}}}}}}this.componentListener=function(t,u,v){if(!q[t]){q[t]={}}if(!q[t][u]){q[t][u]=[];this.eventListener(u,m(t,u))}q[t][u].push(v);return this};function m(t,u){return function(w){if(t==w.component){var v=q[t][u];if(v){for(var x=0;x<v.length;x++){if(typeof v[x]=="function"){v[x].call(this,w)}}}}}}this.addInternalListener=function(t,u){t.jwAddEventListener(u,'function(dat) { jwplayer("'+this.id+'").dispatchEvent("'+u+'", dat); }')};this.eventListener=function(t,u){if(!n[t]){n[t]=[];if(h&&l){this.addInternalListener(h,t)}}n[t].push(u);return this};this.dispatchEvent=function(v){if(n[v]){var u=f(v,arguments[1]);for(var t=0;t<n[v].length;t++){if(typeof n[v][t]=="function"){n[v][t].call(this,u)}}}};function f(v,t){var x=b.utils.extend({},t);if(v==b.api.events.JWPLAYER_FULLSCREEN&&!x.fullscreen){x.fullscreen=x.message=="true"?true:false;delete x.message}else{if(typeof x.data=="object"){x=b.utils.extend(x,x.data);delete x.data}}var u=["position","duration","offset"];for(var w in u){if(x[u[w]]){x[u[w]]=Math.round(x[u[w]]*1000)/1000}}return x}this.callInternal=function(u,t){if(l){if(typeof h!="undefined"&&typeof h[u]=="function"){if(b.utils.exists(t)){return(h[u])(t)}else{return(h[u])()}}return null}else{j.push({method:u,parameters:t})}};this.playerReady=function(v){l=true;if(!h){this.setPlayer(document.getElementById(v.id))}this.container=document.getElementById(this.id);for(var t in n){this.addInternalListener(h,t)}this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,function(w){r={}});this.eventListener(b.api.events.JWPLAYER_MEDIA_META,function(w){b.utils.extend(r,w.metadata)});this.dispatchEvent(b.api.events.API_READY);while(j.length>0){var u=j.shift();this.callInternal(u.method,u.parameters)}};this.getItemMeta=function(){return r};this.getCurrentItem=function(){return this.callInternal("jwGetPlaylistIndex")};function o(v,x,w){var t=[];if(!x){x=0}if(!w){w=v.length-1}for(var u=x;u<=w;u++){t.push(v[u])}return t}return this};b.api.selectPlayer=function(d){var c;if(!b.utils.exists(d)){d=0}if(d.nodeType){c=d}else{if(typeof d=="string"){c=document.getElementById(d)}}if(c){var e=b.api.playerById(c.id);if(e){return e}else{return b.api.addPlayer(new b.api(c))}}else{if(typeof d=="number"){return b.getPlayers()[d]}}return null};b.api.events={API_READY:"jwplayerAPIReady",JWPLAYER_READY:"jwplayerReady",JWPLAYER_FULLSCREEN:"jwplayerFullscreen",JWPLAYER_RESIZE:"jwplayerResize",JWPLAYER_ERROR:"jwplayerError",JWPLAYER_COMPONENT_SHOW:"jwplayerComponentShow",JWPLAYER_COMPONENT_HIDE:"jwplayerComponentHide",JWPLAYER_MEDIA_BUFFER:"jwplayerMediaBuffer",JWPLAYER_MEDIA_BUFFER_FULL:"jwplayerMediaBufferFull",JWPLAYER_MEDIA_ERROR:"jwplayerMediaError",JWPLAYER_MEDIA_LOADED:"jwplayerMediaLoaded",JWPLAYER_MEDIA_COMPLETE:"jwplayerMediaComplete",JWPLAYER_MEDIA_SEEK:"jwplayerMediaSeek",JWPLAYER_MEDIA_TIME:"jwplayerMediaTime",JWPLAYER_MEDIA_VOLUME:"jwplayerMediaVolume",JWPLAYER_MEDIA_META:"jwplayerMediaMeta",JWPLAYER_MEDIA_MUTE:"jwplayerMediaMute",JWPLAYER_PLAYER_STATE:"jwplayerPlayerState",JWPLAYER_PLAYLIST_LOADED:"jwplayerPlaylistLoaded",JWPLAYER_PLAYLIST_ITEM:"jwplayerPlaylistItem"};b.api.events.state={BUFFERING:"BUFFERING",IDLE:"IDLE",PAUSED:"PAUSED",PLAYING:"PLAYING"};b.api.playerById=function(d){for(var c=0;c<a.length;c++){if(a[c].id==d){return a[c]}}return null};b.api.addPlayer=function(c){for(var d=0;d<a.length;d++){if(a[d]==c){return c}}a.push(c);return c};b.api.destroyPlayer=function(g,d){var f=-1;for(var j=0;j<a.length;j++){if(a[j].id==g){f=j;continue}}if(f>=0){var c=document.getElementById(a[f].id);if(document.getElementById(a[f].id+"_wrapper")){c=document.getElementById(a[f].id+"_wrapper")}if(c){if(d){b.utils.setOuterHTML(c,d)}else{var h=document.createElement("div");var e=c.id;if(c.id.indexOf("_wrapper")==c.id.length-8){newID=c.id.substring(0,c.id.length-8)}h.setAttribute("id",e);c.parentNode.replaceChild(h,c)}}a.splice(f,1)}return null};b.getPlayers=function(){return a.slice(0)}})(jwplayer);var _userPlayerReady=(typeof playerReady=="function")?playerReady:undefined;playerReady=function(b){var a=jwplayer.api.playerById(b.id);if(a){a.playerReady(b)}else{jwplayer.api.selectPlayer(b.id).playerReady(b)}if(_userPlayerReady){_userPlayerReady.call(this,b)}};(function(a){a.embed=function(g){var j={width:400,height:300,components:{controlbar:{position:"over"}}};var f=a.utils.mediaparser.parseMedia(g.container);var e=new a.embed.config(a.utils.extend(j,f,g.config),this);var h=a.plugins.loadPlugins(g.id,e.plugins);function c(m,l){for(var k in l){if(typeof m[k]=="function"){(m[k]).call(m,l[k])}}}function d(){if(h.getStatus()==a.utils.loaderstatus.COMPLETE){for(var m=0;m<e.modes.length;m++){if(e.modes[m].type&&a.embed[e.modes[m].type]){var k=e;if(e.modes[m].config){k=a.utils.extend(a.utils.clone(e),e.modes[m].config)}var l=new a.embed[e.modes[m].type](document.getElementById(g.id),e.modes[m],k,h,g);if(l.supportsConfig()){l.embed();c(g,e.events);return g}}}a.utils.log("No suitable players found");new a.embed.logo(a.utils.extend({hide:true},e.components.logo),"none",g.id)}}h.addEventListener(a.events.COMPLETE,d);h.addEventListener(a.events.ERROR,d);h.load();return g};function b(){if(!document.body){return setTimeout(b,15)}var c=a.utils.selectors.getElementsByTagAndClass("video","jwplayer");for(var d=0;d<c.length;d++){var e=c[d];a(e.id).setup({})}}b()})(jwplayer);(function(e){function h(){return[{type:"flash",src:"/jwplayer/player.swf"},{type:"html5"},{type:"download"}]}var a={players:"modes",autoplay:"autostart"};function b(n){var m=n.toLowerCase();var l=["left","right","top","bottom"];for(var k=0;k<l.length;k++){if(m==l[k]){return true}}return false}function c(l){var k=false;k=(l instanceof Array)||(typeof l=="object"&&!l.position&&!l.size);return k}function j(k){if(typeof k=="string"){if(parseInt(k).toString()==k||k.toLowerCase().indexOf("px")>-1){return parseInt(k)}}return k}var g=["playlist","dock","controlbar","logo","display"];function f(k){var n={};switch(e.utils.typeOf(k.plugins)){case"object":for(var m in k.plugins){n[e.utils.getPluginName(m)]=m}break;case"string":var o=k.plugins.split(",");for(var l=0;l<o.length;l++){n[e.utils.getPluginName(o[l])]=o[l]}break}return n}function d(o,n,m,k){if(e.utils.typeOf(o[n])!="object"){o[n]={}}var l=o[n][m];if(e.utils.typeOf(l)!="object"){o[n][m]=l={}}if(k){if(n=="plugins"){var p=e.utils.getPluginName(m);l[k]=o[p+"."+k];delete o[p+"."+k]}else{l[k]=o[m+"."+k];delete o[m+"."+k]}}}e.embed.deserialize=function(l){var m=f(l);for(var k in m){d(l,"plugins",m[k])}for(var p in l){if(p.indexOf(".")>-1){var o=p.split(".");var n=o[0];var p=o[1];if(e.utils.isInArray(g,n)){d(l,"components",n,p)}else{if(m[n]){d(l,"plugins",m[n],p)}}}}return l};e.embed.config=function(k,u){var t=e.utils.extend({},k);var r;if(c(t.playlist)){r=t.playlist;delete t.playlist}t=e.embed.deserialize(t);t.height=j(t.height);t.width=j(t.width);if(typeof t.plugins=="string"){var l=t.plugins.split(",");if(typeof t.plugins!="object"){t.plugins={}}for(var p=0;p<l.length;p++){var q=e.utils.getPluginName(l[p]);if(typeof t[q]=="object"){t.plugins[l[p]]=t[q];delete t[q]}else{t.plugins[l[p]]={}}}}for(var s=0;s<g.length;s++){var o=g[s];if(e.utils.exists(t[o])){if(typeof t[o]!="object"){if(!t.components[o]){t.components[o]={}}if(o=="logo"){t.components[o].file=t[o]}else{t.components[o].position=t[o]}delete t[o]}else{if(!t.components[o]){t.components[o]={}}e.utils.extend(t.components[o],t[o]);delete t[o]}}if(typeof t[o+"size"]!="undefined"){if(!t.components[o]){t.components[o]={}}t.components[o].size=t[o+"size"];delete t[o+"size"]}}if(typeof t.icons!="undefined"){if(!t.components.display){t.components.display={}}t.components.display.icons=t.icons;delete t.icons}for(var n in a){if(t[n]){if(!t[a[n]]){t[a[n]]=t[n]}delete t[n]}}var m;if(t.flashplayer&&!t.modes){m=h();m[0].src=t.flashplayer;delete t.flashplayer}else{if(t.modes){if(typeof t.modes=="string"){m=h();m[0].src=t.modes}else{if(t.modes instanceof Array){m=t.modes}else{if(typeof t.modes=="object"&&t.modes.type){m=[t.modes]}}}delete t.modes}else{m=h()}}t.modes=m;if(r){t.playlist=r}return t}})(jwplayer);(function(a){a.embed.download=function(c,g,b,d,f){this.embed=function(){var k=a.utils.extend({},b);var q={};var j=b.width?b.width:480;if(typeof j!="number"){j=parseInt(j,10)}var m=b.height?b.height:320;if(typeof m!="number"){m=parseInt(m,10)}var u,o,n;var s={};if(b.playlist&&b.playlist.length){s.file=b.playlist[0].file;o=b.playlist[0].image;s.levels=b.playlist[0].levels}else{s.file=b.file;o=b.image;s.levels=b.levels}if(s.file){u=s.file}else{if(s.levels&&s.levels.length){u=s.levels[0].file}}n=u?"pointer":"auto";var l={display:{style:{cursor:n,width:j,height:m,backgroundColor:"#000",position:"relative",textDecoration:"none",border:"none",display:"block"}},display_icon:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:0,left:0,border:0,margin:0,padding:0,zIndex:3,width:50,height:50,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNrs18ENgjAYhmFouDOCcQJGcARHgE10BDcgTOIosAGwQOuPwaQeuFRi2p/3Sb6EC5L3QCxZBgAAAOCorLW1zMn65TrlkH4NcV7QNcUQt7Gn7KIhxA+qNIR81spOGkL8oFJDyLJRdosqKDDkK+iX5+d7huzwM40xptMQMkjIOeRGo+VkEVvIPfTGIpKASfYIfT9iCHkHrBEzf4gcUQ56aEzuGK/mw0rHpy4AAACAf3kJMACBxjAQNRckhwAAAABJRU5ErkJggg==)"}},display_iconBackground:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:((m-50)/2),left:((j-50)/2),border:0,width:50,height:50,margin:0,padding:0,zIndex:2,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNrszwENADAIA7DhX8ENoBMZ5KR10EryckCJiIiIiIiIiIiIiIiIiIiIiIh8GmkRERERERERERERERERERERERGRHSPAAPlXH1phYpYaAAAAAElFTkSuQmCC)"}},display_image:{style:{width:j,height:m,display:o?"block":"none",position:"absolute",cursor:n,left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1,border:"none"}}};var h=function(v,x,y){var w=document.createElement(v);if(y){w.id=y}else{w.id=c.id+"_jwplayer_"+x}a.utils.css(w,l[x].style);return w};q.display=h("a","display",c.id);if(u){q.display.setAttribute("href",a.utils.getAbsolutePath(u))}q.display_image=h("img","display_image");q.display_image.setAttribute("alt","Click to download...");if(o){q.display_image.setAttribute("src",a.utils.getAbsolutePath(o))}if(true){q.display_icon=h("div","display_icon");q.display_iconBackground=h("div","display_iconBackground");q.display.appendChild(q.display_image);q.display_iconBackground.appendChild(q.display_icon);q.display.appendChild(q.display_iconBackground)}_css=a.utils.css;_hide=function(v){_css(v,{display:"none"})};function r(v){_imageWidth=q.display_image.naturalWidth;_imageHeight=q.display_image.naturalHeight;t()}function t(){a.utils.stretch(a.utils.stretching.UNIFORM,q.display_image,j,m,_imageWidth,_imageHeight)}q.display_image.onerror=function(v){_hide(q.display_image)};q.display_image.onload=r;c.parentNode.replaceChild(q.display,c);var p=(b.plugins&&b.plugins.logo)?b.plugins.logo:{};q.display.appendChild(new a.embed.logo(b.components.logo,"download",c.id));f.container=document.getElementById(f.id);f.setPlayer(q.display,"download")};this.supportsConfig=function(){if(b){var j=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof j.file=="undefined"&&typeof j.levels=="undefined"){return true}else{if(j.file){return e(j.file,j.provider,j.playlistfile)}else{if(j.levels&&j.levels.length){for(var h=0;h<j.levels.length;h++){if(j.levels[h].file&&e(j.levels[h].file,j.provider,j.playlistfile)){return true}}}}}}else{return true}};function e(j,l,h){if(h){return false}var k=["image","sound","youtube","http"];if(l&&(k.toString().indexOf(l)>-1)){return true}if(!l||(l&&l=="video")){var m=a.utils.extension(j);if(m&&a.utils.extensionmap[m]){return true}}return false}}})(jwplayer);(function(a){a.embed.flash=function(f,g,l,e,j){function m(o,n,p){var q=document.createElement("param");q.setAttribute("name",n);q.setAttribute("value",p);o.appendChild(q)}function k(o,p,n){return function(q){if(n){document.getElementById(j.id+"_wrapper").appendChild(p)}var s=document.getElementById(j.id).getPluginConfig("display");o.resize(s.width,s.height);var r={left:s.x,top:s.y};a.utils.css(p,r)}}function d(p){if(!p){return{}}var r={};for(var o in p){var n=p[o];for(var q in n){r[o+"."+q]=n[q]}}return r}function h(q,p){if(q[p]){var s=q[p];for(var o in s){var n=s[o];if(typeof n=="string"){if(!q[o]){q[o]=n}}else{for(var r in n){if(!q[o+"."+r]){q[o+"."+r]=n[r]}}}}delete q[p]}}function b(q){if(!q){return{}}var t={},s=[];for(var n in q){var p=a.utils.getPluginName(n);var o=q[n];s.push(n);for(var r in o){t[p+"."+r]=o[r]}}t.plugins=s.join(",");return t}function c(p){var n=p.netstreambasepath?"":"netstreambasepath="+encodeURIComponent(window.location.href.split("#")[0])+"&";for(var o in p){if(typeof(p[o])=="object"){n+=o+"="+encodeURIComponent("[[JSON]]"+a.utils.strings.jsonToString(p[o]))+"&"}else{n+=o+"="+encodeURIComponent(p[o])+"&"}}return n.substring(0,n.length-1)}this.embed=function(){l.id=j.id;var y;var q=a.utils.extend({},l);var n=q.width;var w=q.height;if(f.id+"_wrapper"==f.parentNode.id){y=document.getElementById(f.id+"_wrapper")}else{y=document.createElement("div");y.id=f.id+"_wrapper";a.utils.wrap(f,y);a.utils.css(y,{position:"relative",width:n,height:w})}var o=e.setupPlugins(j,q,k);if(o.length>0){a.utils.extend(q,b(o.plugins))}else{delete q.plugins}var r=["height","width","modes","events"];for(var u=0;u<r.length;u++){delete q[r[u]]}var p="opaque";if(q.wmode){p=q.wmode}h(q,"components");h(q,"providers");if(typeof q["dock.position"]!="undefined"){if(q["dock.position"].toString().toLowerCase()=="false"){q.dock=q["dock.position"];delete q["dock.position"]}}var x="#000000";var t;if(a.utils.isIE()){var v='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" bgcolor="'+x+'" width="100%" height="100%" id="'+f.id+'" name="'+f.id+'" tabindex=0"">';v+='<param name="movie" value="'+g.src+'">';v+='<param name="allowfullscreen" value="true">';v+='<param name="allowscriptaccess" value="always">';v+='<param name="seamlesstabbing" value="true">';v+='<param name="wmode" value="'+p+'">';v+='<param name="flashvars" value="'+c(q)+'">';v+="</object>";a.utils.setOuterHTML(f,v);t=document.getElementById(f.id)}else{var s=document.createElement("object");s.setAttribute("type","application/x-shockwave-flash");s.setAttribute("data",g.src);s.setAttribute("width","100%");s.setAttribute("height","100%");s.setAttribute("bgcolor","#000000");s.setAttribute("id",f.id);s.setAttribute("name",f.id);s.setAttribute("tabindex",0);m(s,"allowfullscreen","true");m(s,"allowscriptaccess","always");m(s,"seamlesstabbing","true");m(s,"wmode",p);m(s,"flashvars",c(q));f.parentNode.replaceChild(s,f);t=s}j.container=t;j.setPlayer(t,"flash")};this.supportsConfig=function(){if(a.utils.hasFlash()){if(l){var o=a.utils.getFirstPlaylistItemFromConfig(l);if(typeof o.file=="undefined"&&typeof o.levels=="undefined"){return true}else{if(o.file){return flashCanPlay(o.file,o.provider)}else{if(o.levels&&o.levels.length){for(var n=0;n<o.levels.length;n++){if(o.levels[n].file&&flashCanPlay(o.levels[n].file,o.provider)){return true}}}}}}else{return true}}return false};flashCanPlay=function(n,p){var o=["video","http","sound","image"];if(p&&(o.toString().indexOf(p<0))){return true}var q=a.utils.extension(n);if(!q){return true}if(a.utils.exists(a.utils.extensionmap[q])&&!a.utils.exists(a.utils.extensionmap[q].flash)){return false}return true}}})(jwplayer);(function(a){a.embed.html5=function(c,g,b,d,f){function e(j,k,h){return function(l){var m=document.getElementById(c.id+"_displayarea");if(h){m.appendChild(k)}var n=m.style;j.resize(parseInt(n.width.replace("px","")),parseInt(n.height.replace("px","")));k.left=n.left;k.top=n.top}}this.embed=function(){if(a.html5){d.setupPlugins(f,b,e);c.innerHTML="";var j=a.utils.extend({screencolor:"0x000000"},b);var h=["plugins","modes","events"];for(var k=0;k<h.length;k++){delete j[h[k]]}if(j.levels&&!j.sources){j.sources=b.levels}if(j.skin&&j.skin.toLowerCase().indexOf(".zip")>0){j.skin=j.skin.replace(/\.zip/i,".xml")}var l=new (a.html5(c)).setup(j);f.container=document.getElementById(f.id);f.setPlayer(l,"html5")}else{return null}};this.supportsConfig=function(){var h=document.createElement("video");if(!!h.canPlayType){if(b){var k=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof k.file=="undefined"&&typeof k.levels=="undefined"){return true}else{if(k.file){return html5CanPlay(h,k.file,k.provider,k.playlistfile)}else{if(k.levels&&k.levels.length){for(var j=0;j<k.levels.length;j++){if(k.levels[j].file&&html5CanPlay(h,k.levels[j].file,k.provider,k.playlistfile)){return true}}}}}}else{return true}}return false};html5CanPlay=function(k,j,l,h){if(h){return false}if(l&&l=="youtube"){return true}if(l&&l!="video"&&l!="http"&&l!="sound"){return false}var m=a.utils.extension(j);if(!a.utils.exists(m)||!a.utils.exists(a.utils.extensionmap[m])){return true}if(!a.utils.exists(a.utils.extensionmap[m].html5)){return false}if(a.utils.isLegacyAndroid()&&m.match(/m4v|mp4/)){return true}return browserCanPlay(k,a.utils.extensionmap[m].html5)};browserCanPlay=function(j,h){if(!h){return true}if(j.canPlayType(h)){return true}else{if(h=="audio/mp3"&&navigator.userAgent.match(/safari/i)){return j.canPlayType("audio/mpeg")}else{return false}}}}})(jwplayer);(function(a){a.embed.logo=function(m,l,d){var j={prefix:"http://l.longtailvideo.com/"+l+"/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",margin:8,out:0.5,over:1,timeout:5,hide:false,position:"bottom-left"};_css=a.utils.css;var b;var h;k();function k(){o();c();f()}function o(){if(j.prefix){var q=a.version.split(/\W/).splice(0,2).join("/");if(j.prefix.indexOf(q)<0){j.prefix+=q+"/"}}h=a.utils.extend({},j)}function p(){var s={border:"none",textDecoration:"none",position:"absolute",cursor:"pointer",zIndex:10};s.display=h.hide?"none":"block";var r=h.position.toLowerCase().split("-");for(var q in r){s[r[q]]=h.margin}return s}function c(){b=document.createElement("img");b.id=d+"_jwplayer_logo";b.style.display="none";b.onload=function(q){_css(b,p());e()};if(!h.file){return}if(h.file.indexOf("http://")===0){b.src=h.file}else{b.src=h.prefix+h.file}}if(!h.file){return}function f(){if(h.link){b.onmouseover=g;b.onmouseout=e;b.onclick=n}else{this.mouseEnabled=false}}function n(q){if(typeof q!="undefined"){q.preventDefault();q.stopPropagation()}if(h.link){window.open(h.link,"_blank")}return}function e(q){if(h.link){b.style.opacity=h.out}return}function g(q){if(h.hide){b.style.opacity=h.over}return}return b}})(jwplayer);(function(a){a.html5=function(b){var c=b;this.setup=function(d){a.utils.extend(this,new a.html5.api(c,d));return this};return this}})(jwplayer);(function(b){var d=b.utils;var c=d.css;b.html5.view=function(r,q,f){var u=r;var n=q;var x=f;var w;var g;var C;var s;var D;var p;var A;function z(){w=document.createElement("div");w.id=n.id;w.className=n.className;_videowrapper=document.createElement("div");_videowrapper.id=w.id+"_video_wrapper";n.id=w.id+"_video";c(w,{position:"relative",height:x.height,width:x.width,padding:0,backgroundColor:E(),zIndex:0});function E(){if(u.skin.getComponentSettings("display")&&u.skin.getComponentSettings("display").backgroundcolor){return u.skin.getComponentSettings("display").backgroundcolor}return parseInt("000000",16)}c(n,{width:x.width,height:x.height,top:0,left:0,zIndex:1,margin:"auto",display:"block"});c(_videowrapper,{overflow:"hidden",position:"absolute",top:0,left:0,bottom:0,right:0});d.wrap(n,w);d.wrap(n,_videowrapper);s=document.createElement("div");s.id=w.id+"_displayarea";w.appendChild(s)}function k(){for(var E=0;E<x.plugins.order.length;E++){var F=x.plugins.order[E];if(d.exists(x.plugins.object[F].getDisplayElement)){x.plugins.object[F].height=d.parseDimension(x.plugins.object[F].getDisplayElement().style.height);x.plugins.object[F].width=d.parseDimension(x.plugins.object[F].getDisplayElement().style.width);x.plugins.config[F].currentPosition=x.plugins.config[F].position}}v()}function m(E){c(s,{display:x.getMedia().hasChrome()?"none":"block"})}function v(F){var H=x.getMedia()?x.getMedia().getDisplayElement():null;if(d.exists(H)){if(A!=H){if(A&&A.parentNode){A.parentNode.replaceChild(H,A)}A=H}for(var E=0;E<x.plugins.order.length;E++){var G=x.plugins.order[E];if(d.exists(x.plugins.object[G].getDisplayElement)){if(x.getMedia().hasChrome()){x.plugins.config[G].currentPosition=b.html5.view.positions.NONE}else{x.plugins.config[G].currentPosition=x.plugins.config[G].position}}}}j(x.width,x.height)}this.setup=function(){if(x&&x.getMedia()){n=x.getMedia().getDisplayElement()}z();k();u.jwAddEventListener(b.api.events.JWPLAYER_PLAYER_STATE,m);u.jwAddEventListener(b.api.events.JWPLAYER_MEDIA_LOADED,v);u.jwAddEventListener(b.api.events.JWPLAYER_MEDIA_META,function(){y()});var E;if(d.exists(window.onresize)){E=window.onresize}window.onresize=function(F){if(d.exists(E)){try{E(F)}catch(H){}}if(u.jwGetFullscreen()){var G=document.body.getBoundingClientRect();x.width=Math.abs(G.left)+Math.abs(G.right);x.height=window.innerHeight}j(x.width,x.height)}};function h(E){switch(E.keyCode){case 27:if(u.jwGetFullscreen()){u.jwSetFullscreen(false)}break;case 32:if(u.jwGetState()!=b.api.events.state.IDLE&&u.jwGetState()!=b.api.events.state.PAUSED){u.jwPause()}else{u.jwPlay()}break}}function j(H,E){if(w.style.display=="none"){return}var G=[].concat(x.plugins.order);G.reverse();D=G.length+2;if(!x.fullscreen){x.width=H;x.height=E;g=H;C=E;c(s,{top:0,bottom:0,left:0,right:0,width:H,height:E,position:"relative"});c(w,{height:C,width:g});var F=o(t,G);if(F.length>0){D+=F.length;var J=F.indexOf("playlist"),I=F.indexOf("controlbar");if(J>=0&&I>=0){F[J]=F.splice(I,1,F[J])[0]}o(l,F,true)}}else{if(navigator.vendor.indexOf("Apple")!==0){o(B,G,true)}}y()}function o(J,G,H){var F=[];for(var E=0;E<G.length;E++){var K=G[E];if(d.exists(x.plugins.object[K].getDisplayElement)){if(x.plugins.config[K].currentPosition!=b.html5.view.positions.NONE){var I=J(K,D--);if(!I){F.push(K)}else{x.plugins.object[K].resize(I.width,I.height);if(H){delete I.width;delete I.height}c(x.plugins.object[K].getDisplayElement(),I)}}else{c(x.plugins.object[K].getDisplayElement(),{display:"none"})}}}return F}function t(F,G){if(d.exists(x.plugins.object[F].getDisplayElement)){if(x.plugins.config[F].position&&a(x.plugins.config[F].position)){if(!d.exists(x.plugins.object[F].getDisplayElement().parentNode)){w.appendChild(x.plugins.object[F].getDisplayElement())}var E=e(F);E.zIndex=G;return E}}return false}function l(G,H){if(!d.exists(x.plugins.object[G].getDisplayElement().parentNode)){s.appendChild(x.plugins.object[G].getDisplayElement())}var E=x.width,F=x.height;if(typeof x.width=="string"&&x.width.lastIndexOf("%")>-1){percentage=parseFloat(x.width.substring(0,x.width.lastIndexOf("%")))/100;E=Math.round(window.innerWidth*percentage)}if(typeof x.height=="string"&&x.height.lastIndexOf("%")>-1){percentage=parseFloat(x.height.substring(0,x.height.lastIndexOf("%")))/100;F=Math.round(window.innerHeight*percentage)}return{position:"absolute",width:(E-d.parseDimension(s.style.left)-d.parseDimension(s.style.right)),height:(F-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom)),zIndex:H}}function B(E,F){return{position:"fixed",width:x.width,height:x.height,zIndex:F}}function y(){if(!d.exists(x.getMedia())){return}s.style.position="absolute";var G=x.getMedia().getDisplayElement();if(G&&G.tagName.toLowerCase()=="video"){G.style.position="absolute";var E,H;if(s.style.width.toString().lastIndexOf("%")>-1||s.style.width.toString().lastIndexOf("%")>-1){var F=s.getBoundingClientRect();E=Math.abs(F.left)+Math.abs(F.right);H=Math.abs(F.top)+Math.abs(F.bottom)}else{E=d.parseDimension(s.style.width);H=d.parseDimension(s.style.height)}if(G.parentNode){G.parentNode.style.left=s.style.left;G.parentNode.style.top=s.style.top}d.stretch(u.jwGetStretching(),G,E,H,G.videoWidth?G.videoWidth:400,G.videoHeight?G.videoHeight:300)}else{x.getMedia().resize(d.parseDimension(s.style.width),d.parseDimension(s.style.height))}}function e(F){var G={position:"absolute",margin:0,padding:0,top:null};var E=x.plugins.config[F].currentPosition.toLowerCase();switch(E.toUpperCase()){case b.html5.view.positions.TOP:G.top=d.parseDimension(s.style.top);G.left=d.parseDimension(s.style.left);G.width=g-d.parseDimension(s.style.left)-d.parseDimension(s.style.right);G.height=x.plugins.object[F].height;s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].height+"px";s.style.height=d.parseDimension(s.style.height)-G.height+"px";break;case b.html5.view.positions.RIGHT:G.top=d.parseDimension(s.style.top);G.right=d.parseDimension(s.style.right);G.width=x.plugins.object[F].width;G.height=C-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom);s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].width+"px";s.style.width=d.parseDimension(s.style.width)-G.width+"px";break;case b.html5.view.positions.BOTTOM:G.bottom=d.parseDimension(s.style.bottom);G.left=d.parseDimension(s.style.left);G.width=g-d.parseDimension(s.style.left)-d.parseDimension(s.style.right);G.height=x.plugins.object[F].height;s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].height+"px";s.style.height=d.parseDimension(s.style.height)-G.height+"px";break;case b.html5.view.positions.LEFT:G.top=d.parseDimension(s.style.top);G.left=d.parseDimension(s.style.left);G.width=x.plugins.object[F].width;G.height=C-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom);s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].width+"px";s.style.width=d.parseDimension(s.style.width)-G.width+"px";break;default:break}return G}this.resize=j;this.fullscreen=function(H){if(navigator&&navigator.vendor&&navigator.vendor.indexOf("Apple")===0){if(x.getMedia().getDisplayElement().webkitSupportsFullscreen){if(H){try{x.getMedia().getDisplayElement().webkitEnterFullscreen()}catch(G){}}else{try{x.getMedia().getDisplayElement().webkitExitFullscreen()}catch(G){}}}}else{if(H){document.onkeydown=h;clearInterval(p);var F=document.body.getBoundingClientRect();x.width=Math.abs(F.left)+Math.abs(F.right);x.height=window.innerHeight;var E={position:"fixed",width:"100%",height:"100%",top:0,left:0,zIndex:2147483000};c(w,E);E.zIndex=1;c(x.getMedia().getDisplayElement(),E);E.zIndex=2;c(s,E)}else{document.onkeydown="";x.width=g;x.height=C;c(w,{position:"relative",height:x.height,width:x.width,zIndex:0})}j(x.width,x.height)}}};function a(e){return([b.html5.view.positions.TOP,b.html5.view.positions.RIGHT,b.html5.view.positions.BOTTOM,b.html5.view.positions.LEFT].toString().indexOf(e.toUpperCase())>-1)}b.html5.view.positions={TOP:"TOP",RIGHT:"RIGHT",BOTTOM:"BOTTOM",LEFT:"LEFT",OVER:"OVER",NONE:"NONE"}})(jwplayer);(function(a){var b={backgroundcolor:"",margin:10,font:"Arial,sans-serif",fontsize:10,fontcolor:parseInt("000000",16),fontstyle:"normal",fontweight:"bold",buttoncolor:parseInt("ffffff",16),position:a.html5.view.positions.BOTTOM,idlehide:false,layout:{left:{position:"left",elements:[{name:"play",type:"button"},{name:"divider",type:"divider"},{name:"prev",type:"button"},{name:"divider",type:"divider"},{name:"next",type:"button"},{name:"divider",type:"divider"},{name:"elapsed",type:"text"}]},center:{position:"center",elements:[{name:"time",type:"slider"}]},right:{position:"right",elements:[{name:"duration",type:"text"},{name:"blank",type:"button"},{name:"divider",type:"divider"},{name:"mute",type:"button"},{name:"volume",type:"slider"},{name:"divider",type:"divider"},{name:"fullscreen",type:"button"}]}}};_utils=a.utils;_css=_utils.css;_hide=function(c){_css(c,{display:"none"})};_show=function(c){_css(c,{display:"block"})};a.html5.controlbar=function(l,V){var k=l;var D=_utils.extend({},b,k.skin.getComponentSettings("controlbar"),V);if(D.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[D.position]=="undefined"){return}if(_utils.mapLength(k.skin.getComponentLayout("controlbar"))>0){D.layout=k.skin.getComponentLayout("controlbar")}var ac;var P;var ab;var E;var v="none";var g;var j;var ad;var f;var e;var y;var Q={};var p=false;var c={};var Y;var h=false;var o;var d;var S=false;var G=false;var W=new a.html5.eventdispatcher();_utils.extend(this,W);function J(){if(!Y){Y=k.skin.getSkinElement("controlbar","background");if(!Y){Y={width:0,height:0,src:null}}}return Y}function N(){ab=0;E=0;P=0;if(!p){var ak={height:J().height,backgroundColor:D.backgroundcolor};ac=document.createElement("div");ac.id=k.id+"_jwplayer_controlbar";_css(ac,ak)}var aj=(k.skin.getSkinElement("controlbar","capLeft"));var ai=(k.skin.getSkinElement("controlbar","capRight"));if(aj){x("capLeft","left",false,ac)}var al={position:"absolute",height:J().height,left:(aj?aj.width:0),zIndex:0};Z("background",ac,al,"img");if(J().src){Q.background.src=J().src}al.zIndex=1;Z("elements",ac,al);if(ai){x("capRight","right",false,ac)}}this.getDisplayElement=function(){return ac};this.resize=function(ak,ai){_utils.cancelAnimation(ac);document.getElementById(k.id).onmousemove=A;e=ak;y=ai;if(G!=k.jwGetFullscreen()){G=k.jwGetFullscreen();d=undefined}var aj=w();A();I({id:k.id,duration:ad,position:j});u({id:k.id,bufferPercent:f});return aj};this.show=function(){if(h){h=false;_show(ac);T()}};this.hide=function(){if(!h){h=true;_hide(ac);aa()}};function q(){var aj=["timeSlider","volumeSlider","timeSliderRail","volumeSliderRail"];for(var ak in aj){var ai=aj[ak];if(typeof Q[ai]!="undefined"){c[ai]=Q[ai].getBoundingClientRect()}}}function A(ai){if(h){return}if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){clearTimeout(o);switch(k.jwGetState()){case a.api.events.state.PAUSED:case a.api.events.state.IDLE:if(!D.idlehide||_utils.exists(ai)){U()}if(D.idlehide){o=setTimeout(function(){z()},2000)}break;default:if(ai){U()}o=setTimeout(function(){z()},2000);break}}}function z(ai){aa();_utils.cancelAnimation(ac);_utils.fadeTo(ac,0,0.1,1,0)}function U(){T();_utils.cancelAnimation(ac);_utils.fadeTo(ac,1,0,1,0)}function H(ai){return function(){if(S&&d!=ai){d=ai;W.sendEvent(ai,{component:"controlbar",boundingRect:O()})}}}var T=H(a.api.events.JWPLAYER_COMPONENT_SHOW);var aa=H(a.api.events.JWPLAYER_COMPONENT_HIDE);function O(){if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){return _utils.getDimensions(ac)}else{return{x:0,y:0,width:0,height:0}}}function Z(am,al,ak,ai){var aj;if(!p){if(!ai){ai="div"}aj=document.createElement(ai);Q[am]=aj;aj.id=ac.id+"_"+am;al.appendChild(aj)}else{aj=document.getElementById(ac.id+"_"+am)}if(_utils.exists(ak)){_css(aj,ak)}return aj}function M(){ah(D.layout.left);ah(D.layout.right,-1);ah(D.layout.center)}function ah(al,ai){var am=al.position=="right"?"right":"left";var ak=_utils.extend([],al.elements);if(_utils.exists(ai)){ak.reverse()}for(var aj=0;aj<ak.length;aj++){C(ak[aj],am)}}function K(){return P++}function C(am,ao){var al,aj,ak,ai,aq;if(am.type=="divider"){x("divider"+K(),ao,true,undefined,undefined,am.width,am.element);return}switch(am.name){case"play":x("playButton",ao,false);x("pauseButton",ao,true);R("playButton","jwPlay");R("pauseButton","jwPause");break;case"prev":x("prevButton",ao,true);R("prevButton","jwPlaylistPrev");break;case"stop":x("stopButton",ao,true);R("stopButton","jwStop");break;case"next":x("nextButton",ao,true);R("nextButton","jwPlaylistNext");break;case"elapsed":x("elapsedText",ao,true);break;case"time":aj=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","timeSliderCapLeft").width;ak=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapRight"))?0:k.skin.getSkinElement("controlbar","timeSliderCapRight").width;al=ao=="left"?aj:ak;ai=k.skin.getSkinElement("controlbar","timeSliderRail").width+aj+ak;aq={height:J().height,position:"absolute",top:0,width:ai};aq[ao]=ao=="left"?ab:E;var an=Z("timeSlider",Q.elements,aq);x("timeSliderCapLeft",ao,true,an,ao=="left"?0:al);x("timeSliderRail",ao,false,an,al);x("timeSliderBuffer",ao,false,an,al);x("timeSliderProgress",ao,false,an,al);x("timeSliderThumb",ao,false,an,al);x("timeSliderCapRight",ao,true,an,ao=="right"?0:al);X("time");break;case"fullscreen":x("fullscreenButton",ao,false);x("normalscreenButton",ao,true);R("fullscreenButton","jwSetFullscreen",true);R("normalscreenButton","jwSetFullscreen",false);break;case"volume":aj=!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;ak=!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapRight"))?0:k.skin.getSkinElement("controlbar","volumeSliderCapRight").width;al=ao=="left"?aj:ak;ai=k.skin.getSkinElement("controlbar","volumeSliderRail").width+aj+ak;aq={height:J().height,position:"absolute",top:0,width:ai};aq[ao]=ao=="left"?ab:E;var ap=Z("volumeSlider",Q.elements,aq);x("volumeSliderCapLeft",ao,true,ap,ao=="left"?0:al);x("volumeSliderRail",ao,true,ap,al);x("volumeSliderProgress",ao,false,ap,al);x("volumeSliderCapRight",ao,true,ap,ao=="right"?0:al);X("volume");break;case"mute":x("muteButton",ao,false);x("unmuteButton",ao,true);R("muteButton","jwSetMute",true);R("unmuteButton","jwSetMute",false);break;case"duration":x("durationText",ao,true);break}}function x(al,ao,aj,ar,am,ai,ak){if(_utils.exists(k.skin.getSkinElement("controlbar",al))||al.indexOf("Text")>0||al.indexOf("divider")===0){var an={height:J().height,position:"absolute",display:"block",top:0};if((al.indexOf("next")===0||al.indexOf("prev")===0)&&k.jwGetPlaylist().length<2){aj=false;an.display="none"}var at;if(al.indexOf("Text")>0){al.innerhtml="00:00";an.font=D.fontsize+"px/"+(J().height+1)+"px "+D.font;an.color=D.fontcolor;an.textAlign="center";an.fontWeight=D.fontweight;an.fontStyle=D.fontstyle;an.cursor="default";at=14+3*D.fontsize}else{if(al.indexOf("divider")===0){if(ai){if(!isNaN(parseInt(ai))){at=parseInt(ai)}}else{if(ak){var ap=k.skin.getSkinElement("controlbar",ak);if(ap){an.background="url("+ap.src+") repeat-x center left";at=ap.width}}else{an.background="url("+k.skin.getSkinElement("controlbar","divider").src+") repeat-x center left";at=k.skin.getSkinElement("controlbar","divider").width}}}else{an.background="url("+k.skin.getSkinElement("controlbar",al).src+") repeat-x center left";at=k.skin.getSkinElement("controlbar",al).width}}if(ao=="left"){an.left=isNaN(am)?ab:am;if(aj){ab+=at}}else{if(ao=="right"){an.right=isNaN(am)?E:am;if(aj){E+=at}}}if(_utils.typeOf(ar)=="undefined"){ar=Q.elements}an.width=at;if(p){_css(Q[al],an)}else{var aq=Z(al,ar,an);if(_utils.exists(k.skin.getSkinElement("controlbar",al+"Over"))){aq.onmouseover=function(au){aq.style.backgroundImage=["url(",k.skin.getSkinElement("controlbar",al+"Over").src,")"].join("")};aq.onmouseout=function(au){aq.style.backgroundImage=["url(",k.skin.getSkinElement("controlbar",al).src,")"].join("")}}}}}function F(){k.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,B);k.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,s);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_BUFFER,u);k.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,r);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_TIME,I);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,ag);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_VOLUME,m);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_COMPLETE,L)}function B(){N();M();w();ae()}function s(ai){ad=k.jwGetPlaylist()[ai.index].duration;I({id:k.id,duration:ad,position:0});u({id:k.id,bufferProgress:0})}function ae(){I({id:k.id,duration:k.jwGetDuration(),position:0});u({id:k.id,bufferProgress:0});ag({id:k.id,mute:k.jwGetMute()});r({id:k.id,newstate:a.api.events.state.IDLE});m({id:k.id,volume:k.jwGetVolume()})}function R(ak,al,aj){if(p){return}if(_utils.exists(k.skin.getSkinElement("controlbar",ak))){var ai=Q[ak];if(_utils.exists(ai)){_css(ai,{cursor:"pointer"});if(al=="fullscreen"){ai.onmouseup=function(am){am.stopPropagation();k.jwSetFullscreen(!k.jwGetFullscreen())}}else{ai.onmouseup=function(am){am.stopPropagation();if(_utils.exists(aj)){k[al](aj)}else{k[al]()}}}}}}function X(ai){if(p){return}var aj=Q[ai+"Slider"];_css(Q.elements,{cursor:"pointer"});_css(aj,{cursor:"pointer"});aj.onmousedown=function(ak){v=ai};aj.onmouseup=function(ak){ak.stopPropagation();af(ak.pageX)};aj.onmousemove=function(ak){if(v=="time"){g=true;var al=ak.pageX-c[ai+"Slider"].left-window.pageXOffset;_css(Q.timeSliderThumb,{left:al})}}}function af(aj){g=false;var ai;if(v=="time"){ai=aj-c.timeSliderRail.left+window.pageXOffset;var al=ai/c.timeSliderRail.width*ad;if(al<0){al=0}else{if(al>ad){al=ad-3}}if(k.jwGetState()==a.api.events.state.PAUSED||k.jwGetState()==a.api.events.state.IDLE){k.jwPlay()}k.jwSeek(al)}else{if(v=="volume"){ai=aj-c.volumeSliderRail.left-window.pageXOffset;var ak=Math.round(ai/c.volumeSliderRail.width*100);if(ak<0){ak=0}else{if(ak>100){ak=100}}if(k.jwGetMute()){k.jwSetMute(false)}k.jwSetVolume(ak)}}v="none"}function u(aj){if(_utils.exists(aj.bufferPercent)){f=aj.bufferPercent}if(c.timeSliderRail){var ak=c.timeSliderRail.width;var ai=isNaN(Math.round(ak*f/100))?0:Math.round(ak*f/100);_css(Q.timeSliderBuffer,{width:ai})}}function ag(ai){if(ai.mute){_hide(Q.muteButton);_show(Q.unmuteButton);_hide(Q.volumeSliderProgress)}else{_show(Q.muteButton);_hide(Q.unmuteButton);_show(Q.volumeSliderProgress)}}function r(ai){if(ai.newstate==a.api.events.state.BUFFERING||ai.newstate==a.api.events.state.PLAYING){_show(Q.pauseButton);_hide(Q.playButton)}else{_hide(Q.pauseButton);_show(Q.playButton)}A();if(ai.newstate==a.api.events.state.IDLE){_hide(Q.timeSliderBuffer);_hide(Q.timeSliderProgress);_hide(Q.timeSliderThumb);I({id:k.id,duration:k.jwGetDuration(),position:0})}else{_show(Q.timeSliderBuffer);if(ai.newstate!=a.api.events.state.BUFFERING){_show(Q.timeSliderProgress);_show(Q.timeSliderThumb)}}}function L(ai){u({bufferPercent:0});I(_utils.extend(ai,{position:0,duration:ad}))}function I(al){if(_utils.exists(al.position)){j=al.position}if(_utils.exists(al.duration)){ad=al.duration}var aj=(j===ad===0)?0:j/ad;var am=c.timeSliderRail;if(am){var ai=isNaN(Math.round(am.width*aj))?0:Math.round(am.width*aj);var ak=ai;if(Q.timeSliderProgress){Q.timeSliderProgress.style.width=ai+"px";if(!g){if(Q.timeSliderThumb){Q.timeSliderThumb.style.left=ak+"px"}}}}if(Q.durationText){Q.durationText.innerHTML=_utils.timeFormat(ad)}if(Q.elapsedText){Q.elapsedText.innerHTML=_utils.timeFormat(j)}}function n(){var am,aj;var ak=document.getElementById(ac.id+"_elements");if(!ak){return}var al=ak.childNodes;for(var ai in ak.childNodes){if(isNaN(parseInt(ai,10))){continue}if(al[ai].id.indexOf(ac.id+"_divider")===0&&aj&&aj.id.indexOf(ac.id+"_divider")===0&&al[ai].style.backgroundImage==aj.style.backgroundImage){al[ai].style.display="none"}else{if(al[ai].id.indexOf(ac.id+"_divider")===0&&am&&am.style.display!="none"){al[ai].style.display="block"}}if(al[ai].style.display!="none"){aj=al[ai]}am=al[ai]}}function w(){n();if(k.jwGetFullscreen()){_show(Q.normalscreenButton);_hide(Q.fullscreenButton)}else{_hide(Q.normalscreenButton);_show(Q.fullscreenButton)}var aj={width:e};var ai={};if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){aj.left=D.margin;aj.width-=2*D.margin;aj.top=y-J().height-D.margin;aj.height=J().height}var al=k.skin.getSkinElement("controlbar","capLeft");var ak=k.skin.getSkinElement("controlbar","capRight");ai.left=al?al.width:0;ai.width=aj.width-ai.left-(ak?ak.width:0);var am=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","timeSliderCapLeft").width;_css(Q.timeSliderRail,{width:(ai.width-ab-E),left:am});if(_utils.exists(Q.timeSliderCapRight)){_css(Q.timeSliderCapRight,{left:am+(ai.width-ab-E)})}_css(ac,aj);_css(Q.elements,ai);_css(Q.background,ai);q();return aj}function m(am){if(_utils.exists(Q.volumeSliderRail)){var ak=isNaN(am.volume/100)?1:am.volume/100;var al=_utils.parseDimension(Q.volumeSliderRail.style.width);var ai=isNaN(Math.round(al*ak))?0:Math.round(al*ak);var an=_utils.parseDimension(Q.volumeSliderRail.style.right);var aj=(!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapLeft")))?0:k.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;_css(Q.volumeSliderProgress,{width:ai,left:aj});if(_utils.exists(Q.volumeSliderCapLeft)){_css(Q.volumeSliderCapLeft,{left:0})}}}function t(){N();M();q();p=true;F();D.idlehide=(D.idlehide.toString().toLowerCase()=="true");if(D.position==a.html5.view.positions.OVER&&D.idlehide){ac.style.opacity=0;S=true}else{setTimeout((function(){S=true;T()}),1)}ae()}t();return this}})(jwplayer);(function(b){var a=["width","height","state","playlist","item","position","buffer","duration","volume","mute","fullscreen"];var c=b.utils;b.html5.controller=function(z,w,h,v){var C=z;var G=h;var g=v;var o=w;var J=true;var e=-1;var A=c.exists(G.config.debug)&&(G.config.debug.toString().toLowerCase()=="console");var m=new b.html5.eventdispatcher(o.id,A);c.extend(this,m);var E=[];var d=false;function r(M){if(d){m.sendEvent(M.type,M)}else{E.push(M)}}function K(M){if(!d){f(G.item);m.sendEvent(b.api.events.JWPLAYER_READY,M);if(b.utils.exists(window.playerReady)){playerReady(M)}if(b.utils.exists(window[h.config.playerReady])){window[h.config.playerReady](M)}while(E.length>0){var O=E.shift();m.sendEvent(O.type,O)}if(h.config.autostart&&!b.utils.isIOS()){controller.item(h.item)}while(p.length>0){var N=p.shift();x(N.method,N.arguments)}d=true}}G.addGlobalListener(r);G.addEventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,function(){G.getMedia().play()});G.addEventListener(b.api.events.JWPLAYER_MEDIA_TIME,function(M){if(M.position>=G.playlist[G.item].start&&e>=0){G.playlist[G.item].start=e;e=-1}});G.addEventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,function(M){setTimeout(s,25)});G.addEventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,function(M){f(G.item)});function u(){try{if(G.playlist[G.item].levels[0].file.length>0){if(J||G.state==b.api.events.state.IDLE){G.getMedia().load(G.playlist[G.item]);J=false}else{if(G.state==b.api.events.state.PAUSED){G.getMedia().play()}}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function I(){try{if(G.playlist[G.item].levels[0].file.length>0){switch(G.state){case b.api.events.state.PLAYING:case b.api.events.state.BUFFERING:G.getMedia().pause();break}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function D(M){try{if(G.playlist[G.item].levels[0].file.length>0){if(typeof M!="number"){M=parseFloat(M)}switch(G.state){case b.api.events.state.IDLE:if(e<0){e=G.playlist[G.item].start;G.playlist[G.item].start=M}u();break;case b.api.events.state.PLAYING:case b.api.events.state.PAUSED:case b.api.events.state.BUFFERING:G.seek(M);break}}return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}function n(M){if(!c.exists(M)){M=true}try{G.getMedia().stop(M);return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}function k(){try{if(G.playlist[G.item].levels[0].file.length>0){if(G.config.shuffle){f(y())}else{if(G.item+1==G.playlist.length){f(0)}else{f(G.item+1)}}}if(G.state!=b.api.events.state.IDLE){var N=G.state;G.state=b.api.events.state.IDLE;m.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:N,newstate:b.api.events.state.IDLE})}u();return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function j(){try{if(G.playlist[G.item].levels[0].file.length>0){if(G.config.shuffle){f(y())}else{if(G.item===0){f(G.playlist.length-1)}else{f(G.item-1)}}}if(G.state!=b.api.events.state.IDLE){var N=G.state;G.state=b.api.events.state.IDLE;m.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:N,newstate:b.api.events.state.IDLE})}u();return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function y(){var M=null;if(G.playlist.length>1){while(!c.exists(M)){M=Math.floor(Math.random()*G.playlist.length);if(M==G.item){M=null}}}else{M=0}return M}function t(N){if(!G.playlist||!G.playlist[N]){return false}try{if(G.playlist[N].levels[0].file.length>0){var O=G.state;if(O!==b.api.events.state.IDLE){if(G.playlist[G.item].provider==G.playlist[N].provider){n(false)}else{n()}}f(N);u()}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function f(M){if(!G.playlist[M]){return}G.setActiveMediaProvider(G.playlist[M]);if(G.item!=M){G.item=M;J=true;m.sendEvent(b.api.events.JWPLAYER_PLAYLIST_ITEM,{index:M})}}function H(N){try{switch(typeof(N)){case"number":G.getMedia().volume(N);break;case"string":G.getMedia().volume(parseInt(N,10));break}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function q(N){try{if(typeof N=="undefined"){G.getMedia().mute(!G.mute)}else{if(N.toString().toLowerCase()=="true"){G.getMedia().mute(true)}else{G.getMedia().mute(false)}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function l(N,M){try{G.width=N;G.height=M;g.resize(N,M);m.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:G.width,height:G.height});return true}catch(O){m.sendEvent(b.api.events.JWPLAYER_ERROR,O)}return false}function B(N){try{if(typeof N=="undefined"){G.fullscreen=!G.fullscreen;g.fullscreen(!G.fullscreen)}else{if(N.toString().toLowerCase()=="true"){G.fullscreen=true;g.fullscreen(true)}else{G.fullscreen=false;g.fullscreen(false)}}m.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:G.width,height:G.height});m.sendEvent(b.api.events.JWPLAYER_FULLSCREEN,{fullscreen:N});return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function L(M){try{n();G.loadPlaylist(M);f(G.item);return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}b.html5.controller.repeatoptions={LIST:"LIST",ALWAYS:"ALWAYS",SINGLE:"SINGLE",NONE:"NONE"};function s(){switch(G.config.repeat.toUpperCase()){case b.html5.controller.repeatoptions.SINGLE:u();break;case b.html5.controller.repeatoptions.ALWAYS:if(G.item==G.playlist.length-1&&!G.config.shuffle){t(0)}else{k()}break;case b.html5.controller.repeatoptions.LIST:if(G.item==G.playlist.length-1&&!G.config.shuffle){n();f(0)}else{k()}break;default:n();break}}var p=[];function F(M){return function(){if(d){x(M,arguments)}else{p.push({method:M,arguments:arguments})}}}function x(O,N){var M=[];for(i=0;i<N.length;i++){M.push(N[i])}O.apply(this,M)}this.play=F(u);this.pause=F(I);this.seek=F(D);this.stop=F(n);this.next=F(k);this.prev=F(j);this.item=F(t);this.setVolume=F(H);this.setMute=F(q);this.resize=F(l);this.setFullscreen=F(B);this.load=F(L);this.playerReady=K}})(jwplayer);(function(a){a.html5.defaultSkin=function(){this.text='<?xml version="1.0" ?><skin author="LongTail Video" name="Five" version="1.0"><settings><setting name="backcolor" value="0xFFFFFF"/><setting name="frontcolor" value="0x000000"/><setting name="lightcolor" value="0x000000"/><setting name="screencolor" value="0x000000"/></settings><components><component name="controlbar"><settings><setting name="margin" value="20"/><setting name="fontsize" value="11"/></settings><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFJJREFUeNrslLENwAAIwxLU/09j5AiOgD5hVQzNAVY8JK4qEfHMIKBnd2+BQlBINaiRtL/aV2rdzYBsM6CIONbI1NZENTr3RwdB2PlnJgJ6BRgA4hwu5Qg5iswAAAAASUVORK5CYII="/><element name="capLeft" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="capRight" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="divider" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="playButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEhJREFUeNpiYqABYBo1dNRQ+hr6H4jvA3E8NS39j4SpZvh/LJig4YxEGEqy3kET+w+AOGFQRhTJhrEQkGcczfujhg4CQwECDADpTRWU/B3wHQAAAABJRU5ErkJggg=="/><element name="pauseButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAChJREFUeNpiYBgFo2DwA0YC8v/R1P4nRu+ooaOGUtnQUTAKhgIACDAAFCwQCfAJ4gwAAAAASUVORK5CYII="/><element name="prevButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEtJREFUeNpiYBgFo2Dog/9QDAPyQHweTYwiQ/2B+D0Wi8g2tB+JTdBQRiIMJVkvEy0iglhDF9Aq9uOpHVEwoE+NJDUKRsFgAAABBgDe2hqZcNNL0AAAAABJRU5ErkJggg=="/><element name="nextButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAElJREFUeNpiYBgFo2Dog/9AfB6I5dHE/lNqKAi/B2J/ahsKw/3EGMpIhKEk66WJoaR6fz61IyqemhEFSlL61ExSo2AUDAYAEGAAiG4hj+5t7M8AAAAASUVORK5CYII="/><element name="timeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADxJREFUeNpiYBgFo2AU0Bwwzluw+D8tLWARFhKiqQ9YuLg4aWsBGxs7bS1gZ6e5BWyjSX0UjIKhDgACDABlYQOGh5pYywAAAABJRU5ErkJggg=="/><element name="timeSliderBuffer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYBgFo2AU0Bww1jc0/aelBSz8/Pw09QELOzs7bS1gY2OjrQWsrKy09gHraFIfBaNgqAOAAAMAvy0DChXHsZMAAAAASUVORK5CYII="/><element name="timeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAClJREFUeNpiYBgFo2AU0BwwAvF/WlrARGsfjFow8BaMglEwCugAAAIMAOHfAQunR+XzAAAAAElFTkSuQmCC"/><element name="timeSliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAICAYAAAA870V8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABZJREFUeNpiZICA/yCCiQEJUJcDEGAAY0gBD1/m7Q0AAAAASUVORK5CYII="/><element name="muteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiYBgFIw3MB+L/5Gj8j6yRiRTFyICJXHfTXyMLAXlGati4YDRFDj8AEGAABk8GSqqS4CoAAAAASUVORK5CYII="/><element name="unmuteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYBgFgxz8p7bm+cQa+h8LHy7GhEcjIz4bmAjYykiun/8j0fakGPIfTfPgiSr6aB4FVAcAAQYAWdwR1G1Wd2gAAAAASUVORK5CYII="/><element name="volumeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAYCAYAAADkgu3FAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGpJREFUeNpi/P//PwM9ABMDncCoRYPfIqqDZcuW1UPp/6AUDcNM1DQYKtRAlaAj1mCSLSLXYIIWUctgDItoZfDA5aOoqKhGEANIM9LVR7SymGDQUctikuOIXkFNdhHEOFrDjlpEd4sAAgwAriRMub95fu8AAAAASUVORK5CYII="/><element name="volumeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAYCAYAAADkgu3FAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFtJREFUeNpi/P//PwM9ABMDncCoRYPfIlqAeij9H5SiYZiqBqPTlFqE02BKLSLaYFItIttgQhZRzWB8FjENiuRJ7aAbsMQwYMl7wDIsWUUQ42gNO2oR3S0CCDAAKhKq6MLLn8oAAAAASUVORK5CYII="/><element name="fullscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAE5JREFUeNpiYBgFo2DQA0YC8v/xqP1PjDlMRDrEgUgxkgHIlfZoriVGjmzLsLFHAW2D6D8eA/9Tw7L/BAwgJE90PvhPpNgoGAVDEQAEGAAMdhTyXcPKcAAAAABJRU5ErkJggg=="/><element name="normalscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEZJREFUeNpiYBgFo2DIg/9UUkOUAf8JiFFsyX88fJyAkcQgYMQjNkzBoAgiezyRbE+tFGSPxQJ7auYBmma0UTAKBhgABBgAJAEY6zON61sAAAAASUVORK5CYII="/></elements></component><component name="display"><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNrszwENADAIA7DhX8ENoBMZ5KR10EryckCJiIiIiIiIiIiIiIiIiIiIiIh8GmkRERERERERERERERERERERERGRHSPAAPlXH1phYpYaAAAAAElFTkSuQmCC"/><element name="playIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNrs18ENgjAYhmFouDOCcQJGcARHgE10BDcgTOIosAGwQOuPwaQeuFRi2p/3Sb6EC5L3QCxZBgAAAOCorLW1zMn65TrlkH4NcV7QNcUQt7Gn7KIhxA+qNIR81spOGkL8oFJDyLJRdosqKDDkK+iX5+d7huzwM40xptMQMkjIOeRGo+VkEVvIPfTGIpKASfYIfT9iCHkHrBEzf4gcUQ56aEzuGK/mw0rHpy4AAACAf3kJMACBxjAQNRckhwAAAABJRU5ErkJggg=="/><element name="muteIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNrs1jEOgCAMBVAg7t5/8qaoIy4uoobyXsLCxA+0NCUAAADGUWvdQoQ41x4ixNBB2hBvBskdD3w5ZCkl3+33VqI0kjBBlh9rp+uTcyOP33TnolfsU85XX3yIRpQph8ZQY3wTZtU5AACASA4BBgDHoVuY1/fvOQAAAABJRU5ErkJggg=="/><element name="errorIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWlJREFUeNrsl+1twjAQhsHq/7BBYQLYIBmBDcoGMAIjtBPQTcII2SDtBDBBwrU6pGsUO7YbO470PtKJkz9iH++d4ywWAAAAAABgljRNsyWr2bZzDuJG1rLdZhcMbTjrBCGDyUKsqQLFciJb9bSvuG/WagRVRUVUI6gqy5HVeKWfSgRyJruKIU//TrZTSn2nmlaXThrloi/v9F2STC1W4+Aw5cBzkquRc09bofFNc6YLxEON0VUZS5FPTftO49vMjRsIF3RhOGr7/D/pJw+FKU+q0vDyq8W42jCunDqI3LC5XxNj2wHLU1XjaRnb0Lhykhqhhd8MtSF5J9tbjCv4mXGvKJz/65FF/qJryyaaIvzP2QRxZTX2nTuXjvV/VPFSwyLnW7mpH99yTh1FEVro6JBSd40/pMrRdV8vPtcKl28T2pT8TnFZ4yNosct3Q0io6JfBiz1FlGdqVQH3VHnepAEAAAAAADDzEGAAcTwB10jWgxcAAAAASUVORK5CYII="/><element name="bufferIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAuhJREFUeNrsWr9rU1EUznuNGqvFQh1ULOhiBx0KDtIuioO4pJuik3FxFfUPaAV1FTdx0Q5d2g4FFxehTnEpZHFoBy20tCIWtGq0TZP4HfkeHB5N8m6Sl/sa74XDybvv3vvOd8/Pe4lXrVZT3dD8VJc0B8QBcUAcEAfESktHGeR5XtMfqFQq/f92zPe/NbtGlKTdCY30kuxrpMGO94BlQCXs+rbh3ONgA6BlzP1p20d80gEI5hmA2A92Qua1Q2PtAFISM+bvjMG8U+Q7oA3rQGASwrYCU6WpNdLGYbA+Pq5jjXIiwi8EEa2UDbQSaKOIuV+SlkcCrfjY8XTI9EpKGwP0C2kru2hLtHqa4zoXtZRWyvi4CLwv9Opr6Hkn6A9HKgEANsQ1iqC3Ub/vRUk2JgmRkatK36kVrnt0qObunwUdUUMXMWYpakJsO5Am8tAw2GBIgwWA+G2S2dMpiw0gDioQRQJoKhRb1QiDwlHZUABYbaXWsm5ae6loTE4ZDxN4CZar8foVzOJ2iyZ2kWF3t7YIevffaMT5yJ70kQb2fQ1sE5SHr2wazs2wgMxgbsEKEAgxAvZUJbQLBGTSBMgNrncJbA6AljtS/eKDJ0Ez+DmrQEzXS2h1Ck25kAg0IZcUOaydCy4sYnN2fOA+2AP16gNoHALlQ+fwH7XO4CxLenUpgj4xr6ugY2roPMbMx+Xs18m/E8CVEIhxsNeg83XWOAN6grG3lGbk8uE5fr4B/WH3cJw+co/l9nTYsSGYCJ/lY5/qv0thn6nrIWmjeJcPSnWOeY++AkF8tpJHIMAUs/MaBBpj3znZfQo5psY+ZrG4gv5HickjEOymKjEeRpgyST6IuZcTcWbnjcgdPi5ghxciRKsl1lDSsgwA1i8fssonJgzmTSqfGUkCENndNdAL7PS6QQ7ZYISTo+1qq0LEWjTWcvY4isa4z+yfQB+7ooyHVg5RI7/i1Ijn/vnggDggDogD4oC00P4KMACd/juEHOrS4AAAAABJRU5ErkJggg=="/></elements></component><component name="dock"><elements><element name="button" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFBJREFUeNrs0cEJACAQA8Eofu0fu/W6EM5ZSAFDRpKTBs00CQQEBAQEBAQEBAQEBAQEBATkK8iqbY+AgICAgICAgICAgICAgICAgIC86QowAG5PAQzEJ0lKAAAAAElFTkSuQmCC"/></elements></component><component name="playlist"><elements><element name="item" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAIAAAC1nk4lAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHhJREFUeNrs2NEJwCAMBcBYuv/CFuIE9VN47WWCR7iocXR3pdWdGPqqwIoMjYfQeAiNh9B4JHc6MHQVHnjggQceeOCBBx77TifyeOY0iHi8DqIdEY8dD5cL094eePzINB5CO/LwcOTptNB4CP25L4TIbZzpU7UEGAA5wz1uF5rF9AAAAABJRU5ErkJggg=="/><element name="sliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAA8CAIAAADpFA0BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADhJREFUeNrsy6ENACAMAMHClp2wYxZLAg5Fcu9e3OjuOKqqfTMzbs14CIZhGIZhGIZhGP4VLwEGAK/BBnVFpB0oAAAAAElFTkSuQmCC"/><element name="sliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAA8CAIAAADpFA0BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrsy7ENACAMBLE8++8caFFKKiRffU53112SGs3ttOohGIZhGIZhGIZh+Fe8BRgAiaUGde6NOSEAAAAASUVORK5CYII="/></elements></component></components></skin>';this.xml=null;if(window.DOMParser){parser=new DOMParser();this.xml=parser.parseFromString(this.text,"text/xml")}else{this.xml=new ActiveXObject("Microsoft.XMLDOM");this.xml.async="false";this.xml.loadXML(this.text)}return this}})(jwplayer);(function(a){_utils=a.utils;_css=_utils.css;_hide=function(b){_css(b,{display:"none"})};_show=function(b){_css(b,{display:"block"})};a.html5.display=function(k,G){var j={icons:true,showmute:false};var Q=_utils.extend({},j,G);var h=k;var P={};var e;var u;var w;var N;var s;var I;var A;var J=!_utils.exists(h.skin.getComponentSettings("display").bufferrotation)?15:parseInt(h.skin.getComponentSettings("display").bufferrotation,10);var q=!_utils.exists(h.skin.getComponentSettings("display").bufferinterval)?100:parseInt(h.skin.getComponentSettings("display").bufferinterval,10);var z=-1;var t="";var K=true;var d;var g=false;var n=false;var H=new a.html5.eventdispatcher();_utils.extend(this,H);var D={display:{style:{cursor:"pointer",top:0,left:0,overflow:"hidden"},click:m},display_icon:{style:{cursor:"pointer",position:"absolute",top:((h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display","playIcon").height)/2),left:((h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display","playIcon").width)/2),border:0,margin:0,padding:0,zIndex:3,display:"none"}},display_iconBackground:{style:{cursor:"pointer",position:"absolute",top:((u-h.skin.getSkinElement("display","background").height)/2),left:((e-h.skin.getSkinElement("display","background").width)/2),border:0,backgroundImage:(["url(",h.skin.getSkinElement("display","background").src,")"]).join(""),width:h.skin.getSkinElement("display","background").width,height:h.skin.getSkinElement("display","background").height,margin:0,padding:0,zIndex:2,display:"none"}},display_image:{style:{display:"none",width:e,height:u,position:"absolute",cursor:"pointer",left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1}},display_text:{style:{zIndex:4,position:"relative",opacity:0.8,backgroundColor:parseInt("000000",16),color:parseInt("ffffff",16),textAlign:"center",fontFamily:"Arial,sans-serif",padding:"0 5px",fontSize:14}}};h.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,p);h.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,p);h.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,p);h.jwAddEventListener(a.api.events.JWPLAYER_ERROR,o);L();function L(){P.display=C("div","display");P.display_text=C("div","display_text");P.display.appendChild(P.display_text);P.display_image=C("img","display_image");P.display_image.onerror=function(R){_hide(P.display_image)};P.display_image.onload=y;P.display_icon=C("div","display_icon");P.display_iconBackground=C("div","display_iconBackground");P.display.appendChild(P.display_image);P.display_iconBackground.appendChild(P.display_icon);P.display.appendChild(P.display_iconBackground);f();setTimeout((function(){n=true;if(Q.icons.toString()=="true"){F()}}),1)}this.getDisplayElement=function(){return P.display};this.resize=function(S,R){_css(P.display,{width:S,height:R});_css(P.display_text,{width:(S-10),top:((R-P.display_text.getBoundingClientRect().height)/2)});_css(P.display_iconBackground,{top:((R-h.skin.getSkinElement("display","background").height)/2),left:((S-h.skin.getSkinElement("display","background").width)/2)});if(e!=S||u!=R){e=S;u=R;d=undefined;F()}c();p({})};this.show=function(){if(g){g=false;d=undefined;b()}};this.hide=function(){if(!g){d=undefined;B();g=true}};function y(R){w=P.display_image.naturalWidth;N=P.display_image.naturalHeight;c()}function c(){_utils.stretch(h.jwGetStretching(),P.display_image,e,u,w,N)}function C(R,T){var S=document.createElement(R);S.id=h.id+"_jwplayer_"+T;_css(S,D[T].style);return S}function f(){for(var R in P){if(_utils.exists(D[R].click)){P[R].onclick=D[R].click}}}function m(R){if(typeof R.preventDefault!="undefined"){R.preventDefault()}else{R.returnValue=false}if(h.jwGetState()!=a.api.events.state.PLAYING){h.jwPlay()}else{h.jwPause()}}function O(R){if(A){B();return}P.display_icon.style.backgroundImage=(["url(",h.skin.getSkinElement("display",R).src,")"]).join("");_css(P.display_icon,{width:h.skin.getSkinElement("display",R).width,height:h.skin.getSkinElement("display",R).height,top:(h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display",R).height)/2,left:(h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display",R).width)/2});b();if(_utils.exists(h.skin.getSkinElement("display",R+"Over"))){P.display_icon.onmouseover=function(S){P.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",R+"Over").src,")"].join("")};P.display_icon.onmouseout=function(S){P.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",R).src,")"].join("")}}else{P.display_icon.onmouseover=null;P.display_icon.onmouseout=null}}function B(){if(Q.icons.toString()=="true"){_hide(P.display_icon);_hide(P.display_iconBackground);M()}}function b(){if(!g&&Q.icons.toString()=="true"){_show(P.display_icon);_show(P.display_iconBackground);F()}}function o(R){A=true;B();P.display_text.innerHTML=R.error;_show(P.display_text);P.display_text.style.top=((u-P.display_text.getBoundingClientRect().height)/2)+"px"}function E(){P.display_image.style.display="none"}function p(R){if((R.type==a.api.events.JWPLAYER_PLAYER_STATE||R.type==a.api.events.JWPLAYER_PLAYLIST_ITEM)&&A){A=false;_hide(P.display_text)}var S=h.jwGetState();if(S==t){return}t=S;if(z>=0){clearTimeout(z)}if(K||h.jwGetState()==a.api.events.state.PLAYING||h.jwGetState()==a.api.events.state.PAUSED){r(h.jwGetState())}else{z=setTimeout(l(h.jwGetState()),500)}}function l(R){return(function(){r(R)})}function r(R){if(_utils.exists(I)){clearInterval(I);I=null;_utils.animations.rotate(P.display_icon,0)}switch(R){case a.api.events.state.BUFFERING:if(_utils.isIOS()){E();B()}else{if(h.jwGetPlaylist()[h.jwGetItem()].provider=="sound"){v()}s=0;I=setInterval(function(){s+=J;_utils.animations.rotate(P.display_icon,s%360)},q);O("bufferIcon");K=true}break;case a.api.events.state.PAUSED:if(!_utils.isIOS()){if(h.jwGetPlaylist()[h.jwGetItem()].provider!="sound"){_css(P.display_image,{background:"transparent no-repeat center center"})}O("playIcon");K=true}break;case a.api.events.state.IDLE:if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].image){v()}else{E()}O("playIcon");K=true;break;default:if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].provider=="sound"){if(_utils.isIOS()){E();K=false}else{v()}}else{E();K=false}if(h.jwGetMute()&&Q.showmute){O("muteIcon")}else{B()}break}z=-1}function v(){_css(P.display_image,{display:"block"});P.display_image.src=_utils.getAbsolutePath(h.jwGetPlaylist()[h.jwGetItem()].image)}function x(R){return function(){if(!n){return}if(!g&&d!=R){d=R;H.sendEvent(R,{component:"display",boundingRect:_utils.getDimensions(P.display_iconBackground)})}}}var F=x(a.api.events.JWPLAYER_COMPONENT_SHOW);var M=x(a.api.events.JWPLAYER_COMPONENT_HIDE);return this}})(jwplayer);(function(a){_css=a.utils.css;a.html5.dock=function(p,u){function q(){return{align:a.html5.view.positions.RIGHT}}var k=a.utils.extend({},q(),u);if(k.align=="FALSE"){return}var f={};var s=[];var g;var v;var d=false;var t=false;var e={x:0,y:0,width:0,height:0};var r;var j=new a.html5.eventdispatcher();_utils.extend(this,j);var m=document.createElement("div");m.id=p.id+"_jwplayer_dock";p.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,l);this.getDisplayElement=function(){return m};this.setButton=function(A,x,y,z){if(!x&&f[A]){a.utils.arrays.remove(s,A);m.removeChild(f[A].div);delete f[A]}else{if(x){if(!f[A]){f[A]={}}f[A].handler=x;f[A].outGraphic=y;f[A].overGraphic=z;if(!f[A].div){s.push(A);f[A].div=document.createElement("div");f[A].div.style.position="relative";m.appendChild(f[A].div);f[A].div.appendChild(document.createElement("img"));f[A].div.childNodes[0].style.position="absolute";f[A].div.childNodes[0].style.left=0;f[A].div.childNodes[0].style.top=0;f[A].div.childNodes[0].style.zIndex=10;f[A].div.childNodes[0].style.cursor="pointer";f[A].div.appendChild(document.createElement("img"));f[A].div.childNodes[1].style.position="absolute";f[A].div.childNodes[1].style.left=0;f[A].div.childNodes[1].style.top=0;if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}f[A].div.childNodes[1].style.zIndex=9;f[A].div.childNodes[1].style.cursor="pointer";f[A].div.onmouseover=function(){if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(p.skin.getSkinElement("dock","buttonOver")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","buttonOver").src}};f[A].div.onmouseout=function(){if(f[A].outGraphic){f[A].div.childNodes[0].src=f[A].outGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}};if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(f[A].outGraphic){f[A].div.childNodes[0].src=f[A].outGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}}if(x){f[A].div.onclick=function(B){B.preventDefault();a(p.id).callback(A);if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}}}}}h(g,v)};function h(x,J){if(s.length>0){var y=10;var I=y;var F=-1;var G=p.skin.getSkinElement("dock","button").height;var E=p.skin.getSkinElement("dock","button").width;var C=x-E-y;var H,B;if(k.align==a.html5.view.positions.LEFT){F=1;C=y}for(var z=0;z<s.length;z++){var K=Math.floor(I/J);if((I+G+y)>((K+1)*J)){I=((K+1)*J)+y;K=Math.floor(I/J)}var A=f[s[z]].div;A.style.top=(I%J)+"px";A.style.left=(C+(p.skin.getSkinElement("dock","button").width+y)*K*F)+"px";var D={x:a.utils.parseDimension(A.style.left),y:a.utils.parseDimension(A.style.top),width:E,height:G};if(!H||(D.x<=H.x&&D.y<=H.y)){H=D}if(!B||(D.x>=B.x&&D.y>=B.y)){B=D}I+=p.skin.getSkinElement("dock","button").height+y}e={x:H.x,y:H.y,width:B.x-H.x+B.width,height:H.y-B.y+B.height}}if(t!=p.jwGetFullscreen()||g!=x||v!=J){g=x;v=J;t=p.jwGetFullscreen();r=undefined;setTimeout(n,1)}}function b(x){return function(){if(!d&&r!=x&&s.length>0){r=x;j.sendEvent(x,{component:"dock",boundingRect:e})}}}function l(x){if(a.utils.isIOS()){switch(x.newstate){case a.api.events.state.IDLE:o();break;default:c();break}}}var n=b(a.api.events.JWPLAYER_COMPONENT_SHOW);var w=b(a.api.events.JWPLAYER_COMPONENT_HIDE);this.resize=h;var o=function(){_css(m,{display:"block"});if(d){d=false;n()}};var c=function(){_css(m,{display:"none"});if(!d){w();d=true}};this.hide=c;this.show=o;return this}})(jwplayer);(function(a){a.html5.eventdispatcher=function(d,b){var c=new a.events.eventdispatcher(b);a.utils.extend(this,c);this.sendEvent=function(e,f){if(!a.utils.exists(f)){f={}}a.utils.extend(f,{id:d,version:a.version,type:e});c.sendEvent(e,f)}}})(jwplayer);(function(a){var b={prefix:"http://l.longtailvideo.com/html5/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",margin:8,out:0.5,over:1,timeout:5,hide:true,position:"bottom-left"};_css=a.utils.css;a.html5.logo=function(m,n){var s=m;var o;var j;var c;k();function k(){q();d();f()}function q(){if(b.prefix){var u=m.version.split(/\W/).splice(0,2).join("/");if(b.prefix.indexOf(u)<0){b.prefix+=u+"/"}}if(n.position==a.html5.view.positions.OVER){n.position=b.position}j=a.utils.extend({},b)}function d(){c=document.createElement("img");c.id=s.id+"_jwplayer_logo";c.style.display="none";c.onload=function(u){_css(c,r());s.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,t);e()};if(!j.file){return}if(j.file.indexOf("http://")===0){c.src=j.file}else{c.src=j.prefix+j.file}}if(!j.file){return}this.resize=function(v,u){};this.getDisplayElement=function(){return c};function f(){if(j.link){c.onmouseover=h;c.onmouseout=e;c.onclick=p}else{this.mouseEnabled=false}}function p(u){if(typeof u!="undefined"){u.stopPropagation()}s.jwPause();s.jwSetFullscreen(false);if(j.link){window.open(j.link,"_top")}return}function e(u){if(j.link){c.style.opacity=j.out}return}function h(u){if(j.hide.toString()=="true"){c.style.opacity=j.over}return}function r(){var w={textDecoration:"none",position:"absolute",cursor:"pointer"};w.display=(j.hide.toString()=="true")?"none":"block";var v=j.position.toLowerCase().split("-");for(var u in v){w[v[u]]=j.margin}return w}function l(){if(j.hide.toString()=="true"){c.style.display="block";c.style.opacity=0;a.utils.fadeTo(c,j.out,0.1,parseFloat(c.style.opacity));o=setTimeout(function(){g()},j.timeout*1000)}}function g(){if(j.hide.toString()=="hide"){a.utils.fadeTo(c,0,0.1,parseFloat(c.style.opacity))}}function t(u){if(u.newstate==a.api.events.state.BUFFERING){clearTimeout(o);l()}}return this}})(jwplayer);(function(a){var c={ended:a.api.events.state.IDLE,playing:a.api.events.state.PLAYING,pause:a.api.events.state.PAUSED,buffering:a.api.events.state.BUFFERING};var e=a.utils;var b=e.css;var d=e.isIOS();a.html5.mediavideo=function(h,s){var r={abort:n,canplay:k,canplaythrough:k,durationchange:G,emptied:n,ended:k,error:u,loadeddata:G,loadedmetadata:G,loadstart:k,pause:k,play:D,playing:k,progress:v,ratechange:n,seeked:k,seeking:k,stalled:k,suspend:k,timeupdate:D,volumechange:n,waiting:k,canshowcurrentframe:n,dataunavailable:n,empty:n,load:z,loadedfirstframe:n};var j=new a.html5.eventdispatcher();e.extend(this,j);var y=h,l=s,m,B,A,x,f,H=false,C,p,q;o();this.load=function(J,K){if(typeof K=="undefined"){K=true}x=J;e.empty(m);q=0;if(J.levels&&J.levels.length>0){if(J.levels.length==1){m.src=J.levels[0].file}else{if(m.src){m.removeAttribute("src")}for(var I=0;I<J.levels.length;I++){var L=m.ownerDocument.createElement("source");L.src=J.levels[I].file;m.appendChild(L);q++}}}else{m.src=J.file}if(d){if(J.image){m.poster=J.image}m.controls="controls"}C=p=A=false;y.buffer=0;if(!e.exists(J.start)){J.start=0}y.duration=J.duration;j.sendEvent(a.api.events.JWPLAYER_MEDIA_LOADED);if((!d&&J.levels.length==1)||!H){m.load()}H=false;if(K){E(a.api.events.state.BUFFERING);j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});this.play()}};this.play=function(){if(B!=a.api.events.state.PLAYING){t();m.play();if(p){E(a.api.events.state.PLAYING)}else{E(a.api.events.state.BUFFERING)}}};this.pause=function(){m.pause();E(a.api.events.state.PAUSED)};this.seek=function(I){if(!(y.duration<=0||isNaN(y.duration))&&!(y.position<=0||isNaN(y.position))){m.currentTime=I;m.play()}};_stop=this.stop=function(I){if(!e.exists(I)){I=true}g();if(I){m.style.display="none";p=false;var J=navigator.userAgent;if(J.match(/chrome/i)){m.src=undefined}else{if(J.match(/safari/i)){m.removeAttribute("src")}else{m.src=""}}m.removeAttribute("controls");m.removeAttribute("poster");e.empty(m);m.load();H=true;if(m.webkitSupportsFullscreen){try{m.webkitExitFullscreen()}catch(K){}}}E(a.api.events.state.IDLE)};this.fullscreen=function(I){if(I===true){this.resize("100%","100%")}else{this.resize(y.config.width,y.config.height)}};this.resize=function(J,I){if(false){b(l,{width:J,height:I})}j.sendEvent(a.api.events.JWPLAYER_MEDIA_RESIZE,{fullscreen:y.fullscreen,width:J,hieght:I})};this.volume=function(I){if(!d){m.volume=I/100;y.volume=I;j.sendEvent(a.api.events.JWPLAYER_MEDIA_VOLUME,{volume:Math.round(I)})}};this.mute=function(I){if(!d){m.muted=I;y.mute=I;j.sendEvent(a.api.events.JWPLAYER_MEDIA_MUTE,{mute:I})}};this.getDisplayElement=function(){return m};this.hasChrome=function(){return false};function o(){m=document.createElement("video");B=a.api.events.state.IDLE;for(var I in r){m.addEventListener(I,function(J){if(e.exists(J.target.parentNode)){r[J.type](J)}},true)}if(l.parentNode){l.parentNode.replaceChild(m,l)}if(!m.id){m.id=l.id}}function E(I){if(I==a.api.events.state.PAUSED&&B==a.api.events.state.IDLE){return}if(B!=I){var J=B;y.state=B=I;j.sendEvent(a.api.events.JWPLAYER_PLAYER_STATE,{oldstate:J,newstate:I})}}function n(I){}function v(K){var J;if(e.exists(K)&&K.lengthComputable&&K.total){J=K.loaded/K.total*100}else{if(e.exists(m.buffered)&&(m.buffered.length>0)){var I=m.buffered.length-1;if(I>=0){J=m.buffered.end(I)/m.duration*100}}}if(p===false&&B==a.api.events.state.BUFFERING){j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL);p=true}if(!C){if(J==100){C=true}if(e.exists(J)&&(J>y.buffer)){y.buffer=Math.round(J);j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:Math.round(J)})}}}function D(J){if(e.exists(J)&&e.exists(J.target)){if(y.duration<=0||isNaN(y.duration)){y.duration=Math.round(J.target.duration*10)/10}if(!A&&m.readyState>0){m.style.display="block";E(a.api.events.state.PLAYING)}if(B==a.api.events.state.PLAYING){if(!A&&m.readyState>0){A=true;try{if(m.currentTime<x.start){m.currentTime=x.start}}catch(I){}m.volume=y.volume/100;m.muted=y.mute}y.position=Math.round(J.target.currentTime*10)/10;j.sendEvent(a.api.events.JWPLAYER_MEDIA_TIME,{position:J.target.currentTime,duration:y.duration});if(y.position>=y.duration&&(y.position>0||y.duration>0)){w()}}}v(J)}function z(I){}function k(I){if(c[I.type]){if(I.type=="ended"){w()}else{E(c[I.type])}}}function G(I){var J={height:I.target.videoHeight,width:I.target.videoWidth,duration:Math.round(I.target.duration*10)/10};if(y.duration===0||isNaN(y.duration)){y.duration=Math.round(I.target.duration*10)/10}j.sendEvent(a.api.events.JWPLAYER_MEDIA_META,{metadata:J})}function u(K){if(B==a.api.events.state.IDLE){return}var J="There was an error: ";if((K.target.error&&K.target.tagName.toLowerCase()=="video")||K.target.parentNode.error&&K.target.parentNode.tagName.toLowerCase()=="video"){var I=!e.exists(K.target.error)?K.target.parentNode.error:K.target.error;switch(I.code){case I.MEDIA_ERR_ABORTED:J="You aborted the video playback: ";break;case I.MEDIA_ERR_NETWORK:J="A network error caused the video download to fail part-way: ";break;case I.MEDIA_ERR_DECODE:J="The video playback was aborted due to a corruption problem or because the video used features your browser did not support: ";break;case I.MEDIA_ERR_SRC_NOT_SUPPORTED:J="The video could not be loaded, either because the server or network failed or because the format is not supported: ";break;default:J="An unknown error occurred: ";break}}else{if(K.target.tagName.toLowerCase()=="source"){q--;if(q>0){return}J="The video could not be loaded, either because the server or network failed or because the format is not supported: "}else{e.log("An unknown error occurred.  Continuing...");return}}_stop(false);J+=F();_error=true;j.sendEvent(a.api.events.JWPLAYER_ERROR,{error:J});return}function F(){var K="";for(var J in x.levels){var I=x.levels[J];var L=l.ownerDocument.createElement("source");K+=a.utils.getAbsolutePath(I.file);if(J<(x.levels.length-1)){K+=", "}}return K}function t(){if(!e.exists(f)){f=setInterval(function(){v()},100)}}function g(){clearInterval(f);f=null}function w(){if(B!=a.api.events.state.IDLE){_stop(false);j.sendEvent(a.api.events.JWPLAYER_MEDIA_COMPLETE)}}}})(jwplayer);(function(a){var c={ended:a.api.events.state.IDLE,playing:a.api.events.state.PLAYING,pause:a.api.events.state.PAUSED,buffering:a.api.events.state.BUFFERING};var b=a.utils.css;a.html5.mediayoutube=function(j,e){var f=new a.html5.eventdispatcher();a.utils.extend(this,f);var l=j;var h=document.getElementById(e.id);var g=a.api.events.state.IDLE;var o,n;m();function k(q){if(g!=q){var r=g;l.state=q;g=q;f.sendEvent(a.api.events.JWPLAYER_PLAYER_STATE,{oldstate:r,newstate:q})}}this.getDisplayElement=function(){return h};this.play=function(){if(g==a.api.events.state.IDLE){f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:100});f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL);k(a.api.events.state.PLAYING)}else{if(g==a.api.events.state.PAUSED){k(a.api.events.state.PLAYING)}}};this.pause=function(){k(a.api.events.state.PAUSED)};this.seek=function(q){};this.stop=function(q){if(!_utils.exists(q)){q=true}l.position=0;k(a.api.events.state.IDLE);if(q){b(o,{display:"none"})}};this.volume=function(q){l.volume=q;f.sendEvent(a.api.events.JWPLAYER_MEDIA_VOLUME,{volume:Math.round(q)})};this.mute=function(q){h.muted=q;l.mute=q;f.sendEvent(a.api.events.JWPLAYER_MEDIA_MUTE,{mute:q})};this.resize=function(r,q){if(r*q>0){o.width=n.width=r;o.height=n.height=q}f.sendEvent(a.api.events.JWPLAYER_MEDIA_RESIZE,{fullscreen:l.fullscreen,width:r,height:q})};this.fullscreen=function(q){if(q===true){this.resize("100%","100%")}else{this.resize(l.config.width,l.config.height)}};this.load=function(q){b(o,{display:"block"});p(q);k(a.api.events.state.BUFFERING);f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});f.sendEvent(a.api.events.JWPLAYER_MEDIA_LOADED);this.play()};this.hasChrome=function(){return(g!=a.api.events.state.IDLE)};function p(w){var t=w.levels[0].file;t=["http://www.youtube.com/v/",d(t),"&amp;hl=en_US&amp;fs=1&autoplay=1"].join("");var v={movie:t,allowfullscreen:"true",allowscriptaccess:"always"};o.innerHTML="";for(var q in v){var u=document.createElement("param");u.name=q;u.value=v[q];o.appendChild(u)}var r={src:t,type:"application/x-shockwave-flash",allowfullscreen:"true",allowscriptaccess:"always",width:o.width,height:o.height};for(var s in r){n.setAttribute(s,r[s])}o.appendChild(n);o.style.zIndex=2147483000}function m(){o=document.createElement("object");o.id=h.id;o.style.position="absolute";o.width=l.config.width;o.height=l.config.height;if(h.parentNode){h.parentNode.replaceChild(o,h)}h=o;n=document.createElement("embed");o.appendChild(n);if(a.utils.isIOS()&&l.playlist&&l.playlist[l.item]){p(l.playlist[l.item])}}function d(r){var q=r.split(/\?|\#\!/);var t="";for(var s=0;s<q.length;s++){if(q[s].substr(0,2)=="v="){t=q[s].substr(2)}}if(t==""){if(r.indexOf("/v/")>=0){t=r.substr(r.indexOf("/v/")+3)}else{if(r.indexOf("youtu.be")>=0){t=r.substr(r.indexOf("youtu.be/")+9)}else{t=r}}}if(t.indexOf("?")>-1){t=t.substr(0,t.indexOf("?"))}if(t.indexOf("&")>-1){t=t.substr(0,t.indexOf("&"))}return t}this.embed=n;return this}})(jwplayer);(function(jwplayer){var _configurableStateVariables=["width","height","start","duration","volume","mute","fullscreen","item","plugins","stretching"];jwplayer.html5.model=function(api,container,options){var _api=api;var _container=container;var _model={id:_container.id,playlist:[],state:jwplayer.api.events.state.IDLE,position:0,buffer:0,config:{width:480,height:320,item:-1,skin:undefined,file:undefined,image:undefined,start:0,duration:0,bufferlength:5,volume:90,mute:false,fullscreen:false,repeat:"",stretching:jwplayer.utils.stretching.UNIFORM,autostart:false,debug:undefined,screencolor:undefined}};var _media;var _eventDispatcher=new jwplayer.html5.eventdispatcher();var _components=["display","logo","controlbar","playlist","dock"];jwplayer.utils.extend(_model,_eventDispatcher);for(var option in options){if(typeof options[option]=="string"){var type=/color$/.test(option)?"color":null;options[option]=jwplayer.utils.typechecker(options[option],type)}var config=_model.config;var path=option.split(".");for(var edge in path){if(edge==path.length-1){config[path[edge]]=options[option]}else{if(!jwplayer.utils.exists(config[path[edge]])){config[path[edge]]={}}config=config[path[edge]]}}}for(var index in _configurableStateVariables){var configurableStateVariable=_configurableStateVariables[index];_model[configurableStateVariable]=_model.config[configurableStateVariable]}var pluginorder=_components.concat([]);if(jwplayer.utils.exists(_model.plugins)){if(typeof _model.plugins=="string"){var userplugins=_model.plugins.split(",");for(var userplugin in userplugins){if(typeof userplugins[userplugin]=="string"){pluginorder.push(userplugins[userplugin].replace(/^\s+|\s+$/g,""))}}}}if(typeof _model.config.chromeless=="undefined"&&jwplayer.utils.isIPod()){_model.config.chromeless=true}if(jwplayer.utils.isIPad()){pluginorder=["display","logo","dock","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}else{if(_model.config.chromeless){pluginorder=["logo","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}}_model.plugins={order:pluginorder,config:{},object:{}};if(typeof _model.config.components!="undefined"){for(var component in _model.config.components){_model.plugins.config[component]=_model.config.components[component]}}for(var pluginIndex in _model.plugins.order){var pluginName=_model.plugins.order[pluginIndex];var pluginConfig=!jwplayer.utils.exists(_model.plugins.config[pluginName])?{}:_model.plugins.config[pluginName];_model.plugins.config[pluginName]=!jwplayer.utils.exists(_model.plugins.config[pluginName])?pluginConfig:jwplayer.utils.extend(_model.plugins.config[pluginName],pluginConfig);if(!jwplayer.utils.exists(_model.plugins.config[pluginName].position)){if(pluginName=="playlist"){_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.NONE}else{_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.OVER}}else{_model.plugins.config[pluginName].position=_model.plugins.config[pluginName].position.toString().toUpperCase()}}if(typeof _model.plugins.config.dock!="undefined"){if(typeof _model.plugins.config.dock!="object"){var position=_model.plugins.config.dock.toString().toUpperCase();_model.plugins.config.dock={position:position}}if(typeof _model.plugins.config.dock.position!="undefined"){_model.plugins.config.dock.align=_model.plugins.config.dock.position;_model.plugins.config.dock.position=jwplayer.html5.view.positions.OVER}}function _loadExternal(playlistfile){var loader=new jwplayer.html5.playlistloader();loader.addEventListener(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,function(evt){_model.playlist=new jwplayer.html5.playlist(evt);_loadComplete(true)});loader.addEventListener(jwplayer.api.events.JWPLAYER_ERROR,function(evt){_model.playlist=new jwplayer.html5.playlist({playlist:[]});_loadComplete(false)});loader.load(playlistfile)}function _loadComplete(){if(_model.config.shuffle){_model.item=_getShuffleItem()}else{if(_model.config.item>=_model.playlist.length){_model.config.item=_model.playlist.length-1}else{if(_model.config.item<0){_model.config.item=0}}_model.item=_model.config.item}_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:_model.playlist});_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_ITEM,{index:_model.item});if(_model.playlist[_model.item].file||_model.playlist[_model.item].levels[0].file){_model.setActiveMediaProvider(_model.playlist[_model.item])}}_model.loadPlaylist=function(arg){var input;if(typeof arg=="string"){if(arg.indexOf("[")==0||arg.indexOf("{")=="0"){try{input=eval(arg)}catch(err){input=arg}}else{input=arg}}else{input=arg}var config;switch(jwplayer.utils.typeOf(input)){case"object":config=input;break;case"array":config={playlist:input};break;default:_loadExternal(input);return;break}_model.playlist=new jwplayer.html5.playlist(config);if(jwplayer.utils.extension(_model.playlist[0].file)=="xml"){_loadExternal(_model.playlist[0].file)}else{_loadComplete()}};function _getShuffleItem(){var result=null;if(_model.playlist.length>1){while(!jwplayer.utils.exists(result)){result=Math.floor(Math.random()*_model.playlist.length);if(result==_model.item){result=null}}}else{result=0}return result}function forward(evt){if(evt.type==jwplayer.api.events.JWPLAYER_MEDIA_LOADED){_container=_media.getDisplayElement()}_eventDispatcher.sendEvent(evt.type,evt)}var _mediaProviders={};_model.setActiveMediaProvider=function(playlistItem){if(playlistItem.provider=="audio"){playlistItem.provider="sound"}var provider=playlistItem.provider;var current=_media?_media.getDisplayElement():null;if(provider=="sound"||provider=="http"||provider==""){provider="video"}if(!jwplayer.utils.exists(_mediaProviders[provider])){switch(provider){case"video":_media=new jwplayer.html5.mediavideo(_model,current?current:_container);break;case"youtube":_media=new jwplayer.html5.mediayoutube(_model,current?current:_container);break}if(!jwplayer.utils.exists(_media)){return false}_media.addGlobalListener(forward);_mediaProviders[provider]=_media}else{if(_media!=_mediaProviders[provider]){if(_media){_media.stop()}_media=_mediaProviders[provider]}}if(_model.config.chromeless){_media.load(playlistItem,false)}return true};_model.getMedia=function(){return _media};_model.seek=function(pos){_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_MEDIA_SEEK,{position:_model.position,offset:pos});return _media.seek(pos)};_model.setupPlugins=function(){if(!jwplayer.utils.exists(_model.plugins)||!jwplayer.utils.exists(_model.plugins.order)||_model.plugins.order.length==0){jwplayer.utils.log("No plugins to set up");return _model}for(var i=0;i<_model.plugins.order.length;i++){try{var pluginName=_model.plugins.order[i];if(jwplayer.utils.exists(jwplayer.html5[pluginName])){if(pluginName=="playlist"){_model.plugins.object[pluginName]=new jwplayer.html5.playlistcomponent(_api,_model.plugins.config[pluginName])}else{_model.plugins.object[pluginName]=new jwplayer.html5[pluginName](_api,_model.plugins.config[pluginName])}}else{_model.plugins.order.splice(plugin,plugin+1)}if(typeof _model.plugins.object[pluginName].addGlobalListener=="function"){_model.plugins.object[pluginName].addGlobalListener(forward)}}catch(err){jwplayer.utils.log("Could not setup "+pluginName)}}};return _model}})(jwplayer);(function(a){a.html5.playlist=function(b){var d=[];if(b.playlist&&b.playlist instanceof Array&&b.playlist.length>0){for(var c in b.playlist){if(!isNaN(parseInt(c))){d.push(new a.html5.playlistitem(b.playlist[c]))}}}else{d.push(new a.html5.playlistitem(b))}return d}})(jwplayer);(function(a){var c={size:180,position:a.html5.view.positions.NONE,itemheight:60,thumbs:true,fontcolor:"#000000",overcolor:"",activecolor:"",backgroundcolor:"#f8f8f8",font:"_sans",fontsize:"",fontstyle:"",fontweight:""};var b={_sans:"Arial, Helvetica, sans-serif",_serif:"Times, Times New Roman, serif",_typewriter:"Courier New, Courier, monospace"};_utils=a.utils;_css=_utils.css;_hide=function(d){_css(d,{display:"none"})};_show=function(d){_css(d,{display:"block"})};a.html5.playlistcomponent=function(r,B){var w=r;var e=a.utils.extend({},c,w.skin.getComponentSettings("playlist"),B);if(e.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[e.position]=="undefined"){return}var x;var l;var C;var d;var g;var f;var k=-1;var h={background:undefined,item:undefined,itemOver:undefined,itemImage:undefined,itemActive:undefined};this.getDisplayElement=function(){return x};this.resize=function(F,D){l=F;C=D;if(w.jwGetFullscreen()){_hide(x)}else{var E={display:"block",width:l,height:C};_css(x,E)}};this.show=function(){_show(x)};this.hide=function(){_hide(x)};function j(){x=document.createElement("div");x.id=w.id+"_jwplayer_playlistcomponent";switch(e.position){case a.html5.view.positions.RIGHT:case a.html5.view.positions.LEFT:x.style.width=e.size+"px";break;case a.html5.view.positions.TOP:case a.html5.view.positions.BOTTOM:x.style.height=e.size+"px";break}A();if(h.item){e.itemheight=h.item.height}x.style.backgroundColor="#C6C6C6";w.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,s);w.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,u);w.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,m)}function p(){var D=document.createElement("ul");_css(D,{width:x.style.width,minWidth:x.style.width,height:x.style.height,backgroundColor:e.backgroundcolor,backgroundImage:h.background?"url("+h.background.src+")":"",color:e.fontcolor,listStyle:"none",margin:0,padding:0,fontFamily:b[e.font]?b[e.font]:b._sans,fontSize:(e.fontsize?e.fontsize:11)+"px",fontStyle:e.fontstyle,fontWeight:e.fontweight,overflowY:"auto"});return D}function y(D){return function(){var E=f.getElementsByClassName("item")[D];var F=e.fontcolor;var G=h.item?"url("+h.item.src+")":"";if(D==w.jwGetPlaylistIndex()){if(e.activecolor!==""){F=e.activecolor}if(h.itemActive){G="url("+h.itemActive.src+")"}}_css(E,{color:e.overcolor!==""?e.overcolor:F,backgroundImage:h.itemOver?"url("+h.itemOver.src+")":G})}}function o(D){return function(){var E=f.getElementsByClassName("item")[D];var F=e.fontcolor;var G=h.item?"url("+h.item.src+")":"";if(D==w.jwGetPlaylistIndex()){if(e.activecolor!==""){F=e.activecolor}if(h.itemActive){G="url("+h.itemActive.src+")"}}_css(E,{color:F,backgroundImage:G})}}function q(I){var P=d[I];var O=document.createElement("li");O.className="item";_css(O,{height:e.itemheight,display:"block",cursor:"pointer",backgroundImage:h.item?"url("+h.item.src+")":"",backgroundSize:"100% "+e.itemheight+"px"});O.onmouseover=y(I);O.onmouseout=o(I);var J=document.createElement("div");var F=new Image();var K=0;var L=0;var M=0;if(v()&&(P.image||P["playlist.image"]||h.itemImage)){F.className="image";if(h.itemImage){K=(e.itemheight-h.itemImage.height)/2;L=h.itemImage.width;M=h.itemImage.height}else{L=e.itemheight*4/3;M=e.itemheight}_css(J,{height:M,width:L,"float":"left",styleFloat:"left",cssFloat:"left",margin:"0 5px 0 0",background:"black",overflow:"hidden",margin:K+"px",position:"relative"});_css(F,{position:"relative"});J.appendChild(F);F.onload=function(){a.utils.stretch(a.utils.stretching.FILL,F,L,M,this.naturalWidth,this.naturalHeight)};if(P["playlist.image"]){F.src=P["playlist.image"]}else{if(P.image){F.src=P.image}else{if(h.itemImage){F.src=h.itemImage.src}}}O.appendChild(J)}var E=l-L-K*2;if(C<e.itemheight*d.length){E-=15}var D=document.createElement("div");_css(D,{position:"relative",height:"100%",overflow:"hidden"});var G=document.createElement("span");if(P.duration>0){G.className="duration";_css(G,{fontSize:(e.fontsize?e.fontsize:11)+"px",fontWeight:(e.fontweight?e.fontweight:"bold"),width:"40px",height:e.fontsize?e.fontsize+10:20,lineHeight:24,"float":"right",styleFloat:"right",cssFloat:"right"});G.innerHTML=_utils.timeFormat(P.duration);D.appendChild(G)}var N=document.createElement("span");N.className="title";_css(N,{padding:"5px 5px 0 "+(K?0:"5px"),height:e.fontsize?e.fontsize+10:20,lineHeight:e.fontsize?e.fontsize+10:20,overflow:"hidden","float":"left",styleFloat:"left",cssFloat:"left",width:((P.duration>0)?E-50:E)-10+"px",fontSize:(e.fontsize?e.fontsize:13)+"px",fontWeight:(e.fontweight?e.fontweight:"bold")});N.innerHTML=P?P.title:"";D.appendChild(N);if(P.description){var H=document.createElement("span");H.className="description";_css(H,{display:"block","float":"left",styleFloat:"left",cssFloat:"left",margin:0,paddingLeft:N.style.paddingLeft,paddingRight:N.style.paddingRight,lineHeight:(e.fontsize?e.fontsize+4:15)+"px",overflow:"hidden",position:"relative"});H.innerHTML=P.description;D.appendChild(H)}O.appendChild(D);return O}function s(E){x.innerHTML="";d=w.jwGetPlaylist();if(!d){return}items=[];f=p();for(var F=0;F<d.length;F++){var D=q(F);D.onclick=z(F);f.appendChild(D);items.push(D)}k=w.jwGetPlaylistIndex();o(k)();x.appendChild(f);if(_utils.isIOS()&&window.iScroll){f.style.height=e.itemheight*d.length+"px";var G=new iScroll(x.id)}}function z(D){return function(){w.jwPlaylistItem(D);w.jwPlay(true)}}function n(){f.scrollTop=w.jwGetPlaylistIndex()*e.itemheight}function v(){return e.thumbs.toString().toLowerCase()=="true"}function u(D){if(k>=0){o(k)();k=D.index}o(D.index)();n()}function m(){if(e.position==a.html5.view.positions.OVER){switch(w.jwGetState()){case a.api.events.state.IDLE:_show(x);break;default:_hide(x);break}}}function A(){for(var D in h){h[D]=t(D)}}function t(D){return w.skin.getSkinElement("playlist",D)}j();return this}})(jwplayer);(function(b){b.html5.playlistitem=function(d){var e={author:"",date:"",description:"",image:"",link:"",mediaid:"",tags:"",title:"",provider:"",file:"",streamer:"",duration:-1,start:0,currentLevel:-1,levels:[]};var c=b.utils.extend({},e,d);if(c.type){c.provider=c.type;delete c.type}if(c.levels.length===0){c.levels[0]=new b.html5.playlistitemlevel(c)}if(!c.provider){c.provider=a(c.levels[0])}else{c.provider=c.provider.toLowerCase()}return c};function a(e){if(b.utils.isYouTube(e.file)){return"youtube"}else{var f=b.utils.extension(e.file);var c;if(f&&b.utils.extensionmap[f]){c=b.utils.extensionmap[f].html5}else{if(e.type){c=e.type}}if(c){var d=c.split("/")[0];if(d=="audio"){return"sound"}else{if(d=="video"){return d}}}}return""}})(jwplayer);(function(a){a.html5.playlistitemlevel=function(b){var d={file:"",streamer:"",bitrate:0,width:0};for(var c in d){if(a.utils.exists(b[c])){d[c]=b[c]}}return d}})(jwplayer);(function(a){a.html5.playlistloader=function(){var c=new a.html5.eventdispatcher();a.utils.extend(this,c);this.load=function(e){a.utils.ajax(e,d,b)};function d(g){var f=[];try{var f=a.utils.parsers.rssparser.parse(g.responseXML.firstChild);c.sendEvent(a.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:new a.html5.playlist({playlist:f})})}catch(h){b("Could not parse the playlist")}}function b(e){c.sendEvent(a.api.events.JWPLAYER_ERROR,{error:e?e:"could not load playlist for whatever reason.  too bad"})}}})(jwplayer);(function(a){a.html5.skin=function(){var b={};var c=false;this.load=function(d,e){new a.html5.skinloader(d,function(f){c=true;b=f;e()},function(){new a.html5.skinloader("",function(f){c=true;b=f;e()})})};this.getSkinElement=function(d,e){if(c){try{return b[d].elements[e]}catch(f){a.utils.log("No such skin component / element: ",[d,e])}}return null};this.getComponentSettings=function(d){if(c){return b[d].settings}return null};this.getComponentLayout=function(d){if(c){return b[d].layout}return null}}})(jwplayer);(function(a){a.html5.skinloader=function(f,p,k){var o={};var c=p;var l=k;var e=true;var j;var n=f;var s=false;function m(){if(typeof n!="string"||n===""){d(a.html5.defaultSkin().xml)}else{a.utils.ajax(a.utils.getAbsolutePath(n),function(t){try{if(a.utils.exists(t.responseXML)){d(t.responseXML);return}}catch(u){h()}d(a.html5.defaultSkin().xml)},function(t){d(a.html5.defaultSkin().xml)})}}function d(y){var E=y.getElementsByTagName("component");if(E.length===0){return}for(var H=0;H<E.length;H++){var C=E[H].getAttribute("name");var B={settings:{},elements:{},layout:{}};o[C]=B;var G=E[H].getElementsByTagName("elements")[0].getElementsByTagName("element");for(var F=0;F<G.length;F++){b(G[F],C)}var z=E[H].getElementsByTagName("settings")[0];if(z&&z.childNodes.length>0){var K=z.getElementsByTagName("setting");for(var P=0;P<K.length;P++){var Q=K[P].getAttribute("name");var I=K[P].getAttribute("value");var x=/color$/.test(Q)?"color":null;o[C].settings[Q]=a.utils.typechecker(I,x)}}var L=E[H].getElementsByTagName("layout")[0];if(L&&L.childNodes.length>0){var M=L.getElementsByTagName("group");for(var w=0;w<M.length;w++){var A=M[w];o[C].layout[A.getAttribute("position")]={elements:[]};for(var O=0;O<A.attributes.length;O++){var D=A.attributes[O];o[C].layout[A.getAttribute("position")][D.name]=D.value}var N=A.getElementsByTagName("*");for(var v=0;v<N.length;v++){var t=N[v];o[C].layout[A.getAttribute("position")].elements.push({type:t.tagName});for(var u=0;u<t.attributes.length;u++){var J=t.attributes[u];o[C].layout[A.getAttribute("position")].elements[v][J.name]=J.value}if(!a.utils.exists(o[C].layout[A.getAttribute("position")].elements[v].name)){o[C].layout[A.getAttribute("position")].elements[v].name=t.tagName}}}}e=false;r()}}function r(){clearInterval(j);if(!s){j=setInterval(function(){q()},100)}}function b(y,x){var w=new Image();var t=y.getAttribute("name");var v=y.getAttribute("src");var A;if(v.indexOf("data:image/png;base64,")===0){A=v}else{var u=a.utils.getAbsolutePath(n);var z=u.substr(0,u.lastIndexOf("/"));A=[z,x,v].join("/")}o[x].elements[t]={height:0,width:0,src:"",ready:false,image:w};w.onload=function(B){g(w,t,x)};w.onerror=function(B){s=true;r();l()};w.src=A}function h(){for(var u in o){var w=o[u];for(var t in w.elements){var x=w.elements[t];var v=x.image;v.onload=null;v.onerror=null;delete x.image;delete w.elements[t]}delete o[u]}}function q(){for(var t in o){if(t!="properties"){for(var u in o[t].elements){if(!o[t].elements[u].ready){return}}}}if(e===false){clearInterval(j);c(o)}}function g(t,v,u){if(o[u]&&o[u].elements[v]){o[u].elements[v].height=t.height;o[u].elements[v].width=t.width;o[u].elements[v].src=t.src;o[u].elements[v].ready=true;r()}else{a.utils.log("Loaded an image for a missing element: "+u+"."+v)}}m()}})(jwplayer);(function(a){a.html5.api=function(c,n){var m={};var f=document.createElement("div");c.parentNode.replaceChild(f,c);f.id=c.id;m.version=a.version;m.id=f.id;var l=new a.html5.model(m,f,n);var j=new a.html5.view(m,f,l);var k=new a.html5.controller(m,f,l,j);m.skin=new a.html5.skin();m.jwPlay=function(o){if(typeof o=="undefined"){e()}else{if(o.toString().toLowerCase()=="true"){k.play()}else{k.pause()}}};m.jwPause=function(o){if(typeof o=="undefined"){e()}else{if(o.toString().toLowerCase()=="true"){k.pause()}else{k.play()}}};function e(){if(l.state==a.api.events.state.PLAYING||l.state==a.api.events.state.BUFFERING){k.pause()}else{k.play()}}m.jwStop=k.stop;m.jwSeek=k.seek;m.jwPlaylistItem=k.item;m.jwPlaylistNext=k.next;m.jwPlaylistPrev=k.prev;m.jwResize=k.resize;m.jwLoad=k.load;function h(o){return function(){return l[o]}}function d(o,q,p){return function(){var r=l.plugins.object[o];if(r&&r[q]&&typeof r[q]=="function"){r[q].apply(r,p)}}}m.jwGetItem=h("item");m.jwGetPosition=h("position");m.jwGetDuration=h("duration");m.jwGetBuffer=h("buffer");m.jwGetWidth=h("width");m.jwGetHeight=h("height");m.jwGetFullscreen=h("fullscreen");m.jwSetFullscreen=k.setFullscreen;m.jwGetVolume=h("volume");m.jwSetVolume=k.setVolume;m.jwGetMute=h("mute");m.jwSetMute=k.setMute;m.jwGetStretching=h("stretching");m.jwGetState=h("state");m.jwGetVersion=function(){return m.version};m.jwGetPlaylist=function(){return l.playlist};m.jwGetPlaylistIndex=m.jwGetItem;m.jwAddEventListener=k.addEventListener;m.jwRemoveEventListener=k.removeEventListener;m.jwSendEvent=k.sendEvent;m.jwDockSetButton=function(r,o,p,q){if(l.plugins.object.dock&&l.plugins.object.dock.setButton){l.plugins.object.dock.setButton(r,o,p,q)}};m.jwControlbarShow=d("controlbar","show");m.jwControlbarHide=d("controlbar","hide");m.jwDockShow=d("dock","show");m.jwDockHide=d("dock","hide");m.jwDisplayShow=d("display","show");m.jwDisplayHide=d("display","hide");m.jwGetLevel=function(){};m.jwGetBandwidth=function(){};m.jwGetLockState=function(){};m.jwLock=function(){};m.jwUnlock=function(){};function b(){if(l.config.playlistfile){l.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.loadPlaylist(l.config.playlistfile)}else{if(typeof l.config.playlist=="string"){l.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.loadPlaylist(l.config.playlist)}else{l.loadPlaylist(l.config);setTimeout(g,25)}}}function g(o){l.removeEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.setupPlugins();j.setup();var o={id:m.id,version:m.version};k.playerReady(o)}if(l.config.chromeless&&!a.utils.isIPad()){b()}else{m.skin.load(l.config.skin,b)}return m}})(jwplayer)};// JSON
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');}}}());

if (!Date.now) {
	Date.now = function() {
		return new Date().getTime();
	};
}





window._previousTinyDom = window.tinydom;

var tinydom = (function() {
	var self = {
			baseAnimationInterval : 20,
			allowCssTransitions : true,
			easingMethods : {
				'ease' : function(f) {
					return (Math.sin(f*Math.PI - Math.PI/2) + 1) / 2;
				},
				'ease-in-out' : function(f) {

					return (Math.sin(f*Math.PI - Math.PI/2) + 1) / 2;
				},
				'ease-in-out-2' : function(f) {
					return this['ease-in-out'](this['ease-in-out'](f));
				},
				'ease-in-out-3' : function(f) {
					return this['ease-in-out'](this['ease-in-out'](this['ease-in-out'](f)));
				}
			}
		},
		initialized = false,
		vendorCssPrefix,
		vendorCssPrefixJS,
		objConstructor = self.constructor,		// Not sure what Palm was thinking when they changed the default Object constructor...
		textContentProperty,
		getSupportedTextContentProperty,
		priv = {
			animationTimes : {
				fast	: 150,
				medium	: 450,
				slow	: 1000
			},
			animationTimeScale : 1,
			registeredEventCount : 0,
			support : {
				filters : false,

				webkitMultitouch : !!("createTouch" in document)
			},
			regex : {
				css3AutoPrefix : /([\s\;\/\*])(box\-shadow|text\-shadow|border\-radius)\:([^\;]*)(\;|$)/gim,
				css3VendorPrefix : /\b\-(moz|webkit|ms|o|vendor)\-/gim,
				templateFieldToken : /([^\\]?)\{([a-z0-9A-Z\$_\.]+)(\|[^\}]*?)?\}/gm,
				parseObjectNameFromString : /^\[object ([^\s]+)\]$/gim,
				autoDetectHTMLContent : /(<[a-z]|&[a-z#0-9]{1,10};)/gim,
				whitespaceCharacters : /\s/,
				getNumericCSSValue : /[^0-9\.\-]/gm,
				getCSSValueUnits : /([a-z]+|%)$/,
				getNonIntegerCharsSigned : /[^0-9\.\-]/gm,
				getUpperCaseAlphaChars : /[A-Z]/gm
			}
		};
	
	
	if (navigator.userAgent.match(/\b(iOS|Android|WebOS|iPhone|iPod|iPad)\b/gim)) {
		self.allowCssTransitions = false;		// not on mobile, just doesn't work well enough yet.
		self.baseAnimationInterval = 50;
		priv.animationTimeScale = 1.5;
	}
	
	
	if (navigator.userAgent.match(/\b(webkit|applewebkit|chrome|chromium|khtml)\b/gim)) {
		vendorCssPrefix = '-webkit';
		vendorCssPrefixJS = 'Webkit';
	}
	else if (navigator.userAgent.match(/\bopera\b/gim)) {
		vendorCssPrefix = '-o';
		vendorCssPrefixJS = 'O';
	}
	else if (navigator.userAgent.match(/\bgecko\b/gim)) {
		vendorCssPrefix = '-moz';
		vendorCssPrefixJS = 'Moz';
	}

	else if (navigator.userAgent.match(/\bmsie\s*?(9|[1-9][0-9]+)\b/gim)) {
		vendorCssPrefix = '-ms';
		vendorCssPrefixJS = 'Ms';
	}
	else if (navigator.userAgent.match(/\bmsie\s*?[4-8]\b/gim)) {
		priv.support.filters = true;
	}

	getSupportedTextContentProperty = function() {
		var d = document.body;
		textContentProperty = (d.textContent!==undefined && "textContent") || (d.innerText!==undefined && "innerText") || "innerHTML";
		getSupportedTextContentProperty = null;
		return textContentProperty;
	};
	
	
	
	self.extend = function(base) {
		var i, j, ext;
		base = base || {};
		for (i=1; i<arguments.length; i++) {
				ext = arguments[i];
				if (ext) {
						for (j in ext) {
								if (ext.hasOwnProperty(j)) {
										base[j] = ext[j];
								}
						}
				}
		}
		return base;
	};
	
	
	
	self.mixin = function(base) {
		var i, j, ext;
		base = base || {};
		for (i=1; i<arguments.length; i++) {
				ext = arguments[i];
				if (ext) {
						for (j in ext) {
								if (ext.hasOwnProperty(j) && !base.hasOwnProperty(j)) {
										base[j] = ext[j];
								}
						}
				}
		}
		return base;
	};
	
	
	
	self.strip = function(obj, andProto) {
		for (var i in obj) {
			if (andProto===true || obj.hasOwnProperty(i)) {
				obj[i] = null;			// faster than delete.
			}
		}
	};
	
	
	
	self.delve = function(obj, path, discardFirst, allowIncompleteMatch) {
		var i = 0;
		path = path.split('.');
		if (discardFirst===true) {
			path.splice(0, 1);
		}
		while (i<path.length && obj && obj.hasOwnProperty(path[i])) {
			obj = obj[path[i]];
			i += 1;
		}
		if (i>=path.length || (allowIncompleteMatch===true && i>0)) {
			return obj;
		}
	};
	
	
	self.flattenObj = function(obj, prefix, depth, flat) {
		var i, p;
		prefix = prefix || '';
		depth = depth || 0;
		flat = flat || {};
		for (i in obj) {
			if (obj.hasOwnProperty(i)) {
				p = prefix ? (prefix+'_'+i) : i;
				if (self.isScalar(obj[i])) {
					flat[p] = obj[i];
				}
				else {
					self.flattenObj(obj[i], p, depth+1, flat);
				}
			}
		}
		if (!depth) {
			return flat;
		}
	};
	
	
	
	
	
	
	self.template = function(text, fields, allowI18n) {
		var templated,
			i18n;
		if (allowI18n!==false && self.i18n) {
			i18n = self.i18n;
		}
		templated = (text+'').replace(priv.regex.templateFieldToken, function(str, pre, id, filters) {
			var val;
			if (pre!=='\\' && id) {
				val = self.delve(fields, id);
				if (val) {
					if (i18n) {
						val = i18n(val) || val;
					}
					if (filters && filters.substring(0,1)==='|') {
						val = self.text.filter(val, filters.substring(1));
					}
					str = pre + val;
				}
				else {
					str = pre;
				}
			}
			else {
				str = pre;
			}
			return str;
		});
		return templated;
	};
	
	
	
	self.inherits = function(base, superClass) {
		function F(){}
		F.prototype = superClass.prototype;
		var proto = base.prototype;
		base.prototype = new F();
		tinydom.extend(base.prototype, proto);
		base.prototype.constructor = base;
		base.prototype.__super = superClass;
	};
	
	
	
	
	
	self.typeOf = function(what) {
		if (what===undefined) {
			return 'undefined';
		}
		else if (what===null) {
			return 'null';
		}
		else if (what) {
			if (what.constructor===objConstructor) {
				return 'object';
			}
			else if (Object.prototype.toString.call(what)==="[object Array]") {
				return 'array';
			}
		}

		return Object.prototype.toString.call(what).replace(priv.regex.parseObjectNameFromString,'$1').toLowerCase();
	};
	
	
	
	self.isScalar = function(what) {
		var type = self.typeOf(what);
		if (type==='undefined' || type==='null' || type==='number' || type==='string' || type==='boolean') {
			return true;
		}
		return false;
	};
	
	
	
	if (!Array.prototype.indexOf || ([self]).indexOf(self)!==0) {
		try {
			Array.prototype.indexOf = function(what) {
				for (var x=0; x<this.length; x++) {
					if (this[x]===what) {
						return x;
					}
				}
				return -1;
			};
		}catch(arrayIndexErr){}
	}
	
	
	
	self.toArray = function(obj) {
		
		var arr=[], x=0, p;
		while (true) {
			if (obj.hasOwnProperty && obj.hasOwnProperty(x)) {
				arr.push(obj[x]);
			}
			else if (obj.hasOwnProperty && obj.hasOwnProperty(x+'')) {
				arr.push(obj[x+'']);
			}
			else {
				break;
			}
			x += 1;
		}
		return arr;
	};
	
	
	
	self.isArray = function(what) {
		return self.typeOf(what)==='array';
	};
	
	
	
	self.hasOwnProperty = function(obj, prop) {
		return Object.prototype.hasOwnProperty.call(obj, prop);
	};
	
	
	
	self.forEach = self.foreach = function(obj, iterator) {
		var i, r;
		if (self.isArray(obj)) {
			for (i=0; i<obj.length; i++) {
				r = iterator(obj[i], i);
				if (r===false) {
					break;
				}
			}
		}
		else {
			for (i in obj) {
				if (obj.hasOwnProperty(i)) {
					r = iterator(obj[i], i);
					if (r===false) {
						break;
					}
				}
			}
		}
		return obj;
	};
	
	
	
	self.createElement = function(options, parent) {
		var el, x, i, childFrag, processProp, insertedBefore;
		options = options || {};
		el = document.createElement(options.type || "div");
		parent = parent || options.parent;
		if (options.insertBefore && options.insertBefore.constructor===self.NodeSelection) {
			options.insertBefore = options.insertBefore._nodes[0];
		}
		if (!parent && options.insertBefore) {
			parent = options.insertBefore.parentNode;
		}
		
		for (x in options) {


			if (self.hasOwnProperty(options, x)) {
				if ((x+"").substring(0,2).toLowerCase()==="on") {
					self.addEvent(el, x.substring(2), options[x]);
				}
				else if (x==="css" || x==="cssText") {
					if (vendorCssPrefix) {
						options[x] = options[x].replace(priv.regex.css3AutoPrefix, '$1'+vendorCssPrefix+'-$2:$3; $2:$3;');
						options[x] = options[x].replace(priv.regex.css3VendorPrefix, '-'+vendorCssPrefix+'-');
						el.style.cssText = options[x];
					}
					else {
						el.style.cssText = options[x];
					}
				}
				else if (x==="attributes") {
					for (i in options[x]) {
						if (self.hasOwnProperty(options[x], i)) {
							el.setAttribute(i, options[x][i]);
						}
					}
				}
				else if (x!=='parent' && x!=='children' && x!=='insertBefore') {
					if (priv.support.filters) {
						try {
							el[x] = options[x];
						}catch(err){}
					}
					else {
						el[x] = options[x];
					}
				}
			}
		}
		if (parent) {
			if (options.insertBefore) {
				try {
					parent.insertBefore(el, options.insertBefore);
					insertedBefore = true;
				}catch(err) {
					insertedBefore = false;
				}
			}
			if (!insertedBefore) {
				parent.appendChild(el);
			}
		}
		if (options.children && self.isArray(options.children)) {







				childFrag = document.createDocumentFragment();
				for (x=0; x<options.children.length; x++) {
					self.createElement(options.children[x], childFrag);
				}
				el.appendChild(childFrag);

		}
		return el;
	};
	
	
	self.NodeSelection = function NodeSelection(nodes) {
		var x;
		this._results = [];
		this._nodes = [];
		this._animations = [];
		if (nodes) {
			if (self.isArray(nodes)) {
				for (x=0; x<nodes.length; x++) {
					if (nodes[x]) {
						if (nodes[x].constructor===NodeSelection && nodes[x]._nodes) {
							this._nodes.push(nodes[x]._nodes[0]);
						}
						else {
							this._nodes.push(nodes[x]);
						}
					}
				}
			}
			else {
				this._nodes.push(nodes);
			}
		}
	};
	self.extend(self.NodeSelection.prototype, {
		_results	: [],
		_nodes		: [],
		_animations	: [],
		getResult	: function(reverseIndex) {
			reverseIndex = Math.round(reverseIndex) || 0;
			return this._results[this._results.length - reverseIndex - 1];
		},
		pushResult : function(result) {
			this._results.push(result);
			return this;
		},
		each : function(action) {
			return this._each(action, true);
		},
		_each : function(action, asSelection, inReverse) {
			var nodes = this._nodes.slice(0,this._nodes.length),
				x, y, node;
			for (x=0; x<nodes.length; x++) {
				y = x;
				if (inReverse===true) {
					y = nodes.length-y-1;
				}
				node = nodes[y];
				if (asSelection===true) {
					node = new self.NodeSelection(node);
				}
				action.call(this, node, y);
			}
			return this;
		},
		wait : function(millis, callback) {
			var self = this;
			if (callback) {
				setTimeout(function() {
					callback.apply(self);
					self = callback = null;
				}, Math.abs(millis));
			}
			return this;
		},
		nodeName : function() {
			var node = this._nodes[0],
				nodeName = node && node.nodeName && node.nodeName.toLowerCase();
			if (node===window) {
				return '#window';
			}
			else if (nodeName) {
				return nodeName;
			}
			return null;
		},
		uuid : function() {
			return this._nodes[0] && priv.nodeToId(this._nodes[0]) || null;
		},
		html : function(content, asText) {
			if (arguments.length===0) {
				return this._nodes[0] && this._nodes[0].innerHTML || '';
			}
			content = content + "";
			if (content.match(priv.regex.autoDetectHTMLContent) && asText!==true) {

				this._each(function(el) {
					el.innerHTML = content;
				});
			}
			else {

				this._each(function(el) {
					el[textContentProperty || getSupportedTextContentProperty()] = content;
				});
			}
			return this;
		},
		css : function(css, options) {
			var type,
				selection = this;
			options = options || {};
			type = self.typeOf(options.tween);
			if ((type==='string' && options.tween!=='none') || (type==='number' && options.tween>0)) {
				var tween = (options.tween + '').replace(priv.regex.whitespaceCharacters,'').split(','),
					x,
					cb,
					total = 0,
					completed = 0;
				cb = function(node) {
					completed += 1;
					if (completed>=total) {
						cb = null;
						if (options.callback) {
							options.callback(node);
						}
						selection = node = null;
					}
				};
				for (x in css) {
					if (css.hasOwnProperty(x)) {
						total += 1;
						this.animateCss(x, css[x], tween[0], tween[1], cb);
					}
				}
			}
			else {
				this._each(function(el) {
					self.applyCss(el, css);
				});
				
				if (options.callback) {
					setTimeout(function(){
						options.callback(selection);
						selection = null;
					}, 1);
				}
				else {
					selection = null;
				}
			}
			return this;
		},
		show : function() {
			this.css({
				display		: '',
				visibility	: 'visible'
			});

			this._each(function(node) {
				if (node.style.display==='none' || self.nodeStyle(node, 'display')==='none') {
					node.style.display = 'block';
				}
			});
			return this;
		},
		
		hide : function(andIgnore) {
			
			return this.css(
				andIgnore===false ? {visibility:'hidden'} : {display:'none'}
			);
		},
		
		fadeIn : function(tween, callback) {
			var originalOpacity = parseFloat(this.getStyle('opacity') || '0') || 0,
				targetOpacity = 1;
			if (this.getStyle('display')==='none' || this.getStyle('visibility')==='hidden') {
				if (this.getStyle('opacity') && originalOpacity>0 && originalOpacity<1) {
					targetOpacity = originalOpacity;
				}
				originalOpacity = 0;
				this.css({
					opacity : 0
				});
			}

			if (self.typeOf(tween)==='function') {
				callback = tween;
				tween = arguments[1];
			}
			if (originalOpacity>=1 || tween==0 || tween===false) {
				this.css({
					opacity : targetOpacity
				}).show();
				setTimeout(function() {
					if (callback) {
						callback();
					}
					callback = null;
				}, 0);
				return this;
			}
			this.css({
				opacity : targetOpacity
			}, {tween:tween || 'medium', callback:function(selection) {
				if (callback) {
					callback(selection);
				}
				tween = callback = null;
			}}).show();
			return this;
		},
		
		fadeOut : function(tween, callback, andIgnore) {
			var originalOpacity = parseFloat(this.getStyle('opacity') || '1') || 1;
			if (self.typeOf(tween)==='function') {
				callback = tween;
				tween = arguments[1];
			}
			if (self.typeOf(callback)==='boolean') {
				andIgnore = callback;
				callback = null;
				if (self.typeOf(arguments[2])==='function') {
					callback = arguments[2];
				}
			}
			if (originalOpacity<=0 || this.getStyle('display')==='none' || this.getStyle('visibility')==='hidden' || tween===0 || tween===false) {
				this.css({
					opacity : 0
				}).hide(andIgnore);
				setTimeout(function() {
					if (callback) {
						callback();
					}
					callback = null;
				}, 0);
				return this;
			}
			this.css({
				opacity : 0
			}, {tween:tween || 'medium', callback:function(selection) {
				selection.hide(andIgnore).css({
					opacity : originalOpacity
				});
				if (callback) {
					callback(selection);
				}
				tween = callback = null;
			}});
			return this;
		},
		
		animateCSS : (function() {
			var manual, cssTransition, supportsCssTransition, checkCssTransitionSupport;
			
			manual = function(cssProp, targetValue, duration, easing, callback) {
				var startValues = [],

					perNodeProperties = [],
					numericTargetValue, units, s;
				
				cssProp = cssProp.toLowerCase();
				
				if (targetValue!=='auto') {
					numericTargetValue = parseFloat((targetValue + '').replace(priv.regex.getNumericCSSValue,'')) || 0;
					s = self.typeOf(targetValue)==='string' && targetValue.match(priv.regex.getCSSValueUnits);
					units = (s && s[0]) || 'px';
					if (cssProp==='opacity') {
						units = '';
					}
				}
				else {
					units = cssProp==='opacity' ? '' : 'px';
				}
				
				this._each(function(node, i) {
					var ts, tss, testCssObj={}, iprop, vis;
					
					startValues[i] = parseFloat((self.nodeStyle(node, cssProp) + '').replace(priv.regex.getNonIntegerCharsSigned,'')) || 0;
					
					if (targetValue==='auto') {
						vis = node.style.visibility || '';

						testCssObj[cssProp] = 'auto';
						testCssObj.visibility = 'hidden';
						self.applyCss(node, testCssObj);
						ts = self.nodeStyle(node, cssProp);
						if (ts==='auto' || ts.indexOf('px')<ts.length-3) {
							iprop = cssProp.substring(0,1).toUpperCase() + cssProp.substring(1).toLowerCase();
							ts = node['offset'+iprop] + 'px';
						}
						tss = self.typeOf(ts)==='string' && ts.match(priv.regex.getCSSValueUnits);
						perNodeProperties[i] = {
							_actualTarget : 'auto',
							numericTargetValue : parseFloat((ts + '').replace(priv.regex.getNumericCSSValue,'')) || 0,
							units : cssProp==='opacity' ? '' : (tss && tss[0] || 'px')
						};
						setTimeout(function() {
							node.style.visibility = vis;
							node = null;
						}, 51);
						testCssObj = ts = tss = null;
					}
					else {
						perNodeProperties[i] = {
							numericTargetValue : numericTargetValue,
							units : units
						};
					}
				});

				
				return this.animate(function(fraction, anim) {
					this._each(function(node, i) {
						var cssObj = {},
							value = (fraction * (perNodeProperties[i].numericTargetValue-startValues[i]) + startValues[i]),
							floatVal,
							units = perNodeProperties[i].units;
						if (units==='px') {
							value = Math.round(value);
						}
						else {
							floatVal = parseFloat(value);
							if (floatVal%1===0) {
								value = Math.round(floatVal);
							}
							else {
								value = floatVal.toFixed(2);
							}
						}
						cssObj[cssProp] = value + units;

						self.applyCss(node, cssObj);
					});
				}, duration, easing, function(sel) {
					sel._each(function(node, i) {
						var cssObj = {};
						if (perNodeProperties[i]._actualTarget) {
							cssObj[cssProp] = perNodeProperties[i]._actualTarget;
							self.applyCss(node, cssObj);
						}
					});
					callback.apply(sel, arguments);
				});
			};
			
			cssTransition = function(cssProp, targetValue, duration, easing, callback) {
				var anim = this._createAnimationObj(function(){}, duration, easing, callback),
					me = this,
					transition = {},
					css = {};

				
				cssProp = (cssProp+'').replace(priv.regex.getUpperCaseAlphaChars,'-$1').toLowerCase();
				if (self.typeOf(targetValue)==='number' && (cssProp+'').toLowerCase()!=='opacity') {
					targetValue = targetValue + 'px';
				}

				
				transition[cssProp] = {
					duration : anim.duration,
					timingFunction : anim.easing
				};
				
				css[cssProp] = targetValue;

				
				setTimeout(function() {
					me._each(function(node) {
						self.updateCssTransitions(node, transition);
						self.applyCss(node, css);
						priv.incrementAnimationCount(node);
					});
					anim._cb = function() {
						if (anim) {

							
							
							var nullTransition = {};
							nullTransition[cssProp] = null;
							me._each(function(node) {
								self.updateCssTransitions(node, nullTransition);
								priv.decrementAnimationCount(node);
							});
							
							if (anim.callback) {
								anim.callback(me);

								
							}
							for (var x in anim) {
								if (anim.hasOwnProperty(x)) {
									try{ delete anim[x]; }catch(err){}
								}
							}
						}
						anim = css = callback = me = null;
					};
					setTimeout(anim._cb, (parseInt(anim.duration,10) || 0)+20);
				}, 10);
			};
			
			checkCssTransitionSupport = function() {
				supportsCssTransition = document.body.style[vendorCssPrefixJS+'Transition']!==undefined || document.body.style.transition!==undefined;
				return supportsCssTransition;
			};
			
			return function(css) {
				var iosCompat=false, x;
				
				if (self.typeOf(supportsCssTransition)!=='boolean') {
					checkCssTransitionSupport();
				}
				if ((self.allowCssTransitions!==false || iosCompat===true) && supportsCssTransition) {
					cssTransition.apply(this, arguments);
				}
				else {
					manual.apply(this, arguments);
				}
				return this;
			};
		}()),
		animate : function(animator, duration, easing, callback) {
			if (animator) {
				var nodeSelection = this,
					anim = this._createAnimationObj.apply(this, arguments),
					frame;
				
				this._each(function(node) {
					priv.incrementAnimationCount(node);
				});
				
				frame = function() {
					anim.frameTime = Date.now();
					anim.position = anim.frameTime - anim.start;
					anim.fraction = anim.position / anim.duration;
					if (anim.position>=anim.duration) {
						anim.fraction = 1;
						anim.position = anim.duration;
					}
					else if (anim.easingMethod) {
						anim.fraction = anim.easingMethod.call(self.easingMethods, anim.fraction, anim);
					}

					anim.animator.call(nodeSelection, anim.fraction, anim);
					
					if (anim.fraction===1) {
						for (var x=nodeSelection._animations.length; x--; ) {
							if (nodeSelection._animations[x]===anim) {
								nodeSelection._animations.splice(x, 1);
								break;
							}
						}
						if (anim.callback) {
							setTimeout(function() {
								nodeSelection._each(function(node) {
									priv.decrementAnimationCount(node);
								});
								anim.callback.call(nodeSelection, nodeSelection, anim);
								nodeSelection = anim = null;
							}, 10);
						}
					}
					else {
						anim.timer = setTimeout(frame, self.baseAnimationInterval || 10);
					}
				};
				
				setTimeout(frame, self.baseAnimationInterval || 10);
				
				this._animations.push(anim);
			}
			return this;
		},
		_createAnimationObj : function(animator, duration, easing, callback) {
			var anim = {
				animator	: animator,
				duration	: duration,
				easing		: self.typeOf(easing)==='string' ? easing : 'ease',
				callback	: callback,
				start		: Date.now(),
				frameTime	: null
			};
			
			if (self.typeOf(anim.duration)==='string') {
				switch (anim.duration.toLowerCase()) {
					case 'long':
					case 'slow':
						anim.duration = priv.animationTimes.slow;		// 1000;
						break;
					case 'short':
					case 'fast':
						anim.duration = priv.animationTimes.fast;		// 150;
						break;
					default:
						anim.duration = parseInt(anim.duration) || priv.animationTimes.medium;		// 450;
				}
			}
			else {
				anim.duration = Math.round(anim.duration) || priv.animationTimes.medium;
			}
			
			if (priv.animationTimeScale) {
				anim.duration *= priv.animationTimeScale;
			}
			
			if (anim.easing && self.easingMethods.hasOwnProperty(anim.easing)) {
				anim.easingMethod = self.easingMethods[anim.easing];
			}
			else {
				anim.easing = null;
			}
			return anim;
		},
		classify : function(className) {
			var classes = [],
				method = arguments[0]==='{*^de^*}' ? 'removeClass' : 'addClass',
				x, y;
			for (x=0; x<arguments.length; x++) {
				if (self.isArray(arguments[x])) {
					for (y=0; y<arguments[x].length; y++) {
						classes.push(arguments[x][y]);
					}
				}
				else {
					classes.push(arguments[x]);
				}
			}
			this._each(function(el) {
				self[method](el, classes);
			});
			return this;
		},
		declassify : function(className) {
			var args = ['{*^de^*}'].concat(Array.prototype.slice.call(arguments, 0));
			return this.classify.apply(this, args);
		},
		hasClass : function(className, ifAny) {
			var result = ifAny!==true;
			this._each(function(node) {
				var exists = (' '+node.className+' ').indexOf(' '+className+' ')>-1;
				if (ifAny===true) {
					if (exists) {
						result = true;
					}
				}
				else if (!exists) {
					result = false;
				}
			});
			return result;
		},
		setOpacity : function(opacity) {
			this._each(function(el) {
				self.setOpacity(el, opacity);
			});
			return this;
		},
		sumOf : function(method) {
			var total = 0,
				args = Array.prototype.slice.call(arguments, 1);
			if (this.constructor.prototype.hasOwnProperty(method)) {
				this._each(function(node) {
					node = new self.NodeSelection(node);
					total += node[method].apply(node, args);
				});
			}
			return total;
		},
		height : function(height, options) {
			var units,
				node,
				matches,
				offsetHeight = 0;
			if (self.typeOf(height)==='object' && !options) {
				options = height;
				height = null;
			}
			options = options || {};
			if (height || height===0) {
				height = height + '';
				if (height==='auto') {
					units = '';
				}
				else {
					matches = (/^([\-0-9\.]+)(.*?)$/).exec(height);
					height = Math.round(matches && matches[1] || height) || 0;
					units = matches && matches[2] || 'px';
				}
				this.css({
					height : height + units
				});
				return this;
			}
			this._each(function(node) {
				offsetHeight += parseInt(node.offsetHeight, 10) || 0;
				if (options.border===true) {
					offsetHeight += parseInt( (self.nodeStyle(node, 'border-top-width')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
					offsetHeight += parseInt( (self.nodeStyle(node, 'border-bottom-width')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
				}
				if (options.margin===true) {
					offsetHeight += parseInt( (self.nodeStyle(node, 'margin-top')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
					offsetHeight += parseInt( (self.nodeStyle(node, 'margin-bottom')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
				}
				if (options.padding===false) {
					offsetHeight -= parseInt( (self.nodeStyle(node, 'padding-top')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
					offsetHeight -= parseInt( (self.nodeStyle(node, 'padding-bottom')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
				}
			});
			
			return offsetHeight;
		},
		width : function(width, options) {
			var units,
				node,
				matches,
				offsetWidth = 0;
			if (self.typeOf(width)==='object' && !options) {
				options = width;
				width = null;
			}
			options = options || {};
			if (width || width===0) {
				width = width + '';
				if (width==='auto') {
					units = '';
				}
				else {
					matches = (/^([\-0-9\.]+)(.*?)$/).exec(width);
					width = matches && matches[1] || width;
					units = matches && matches[2] || 'px';
				}
				this.css({
					width : width + units
				});
				return this;
			}
			this._each(function(node) {
				offsetWidth += parseInt(node.offsetWidth, 10) || 0;
				if (options.border===true) {
					offsetWidth += parseInt( (self.nodeStyle(node, 'border-left-width')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
					offsetWidth += parseInt( (self.nodeStyle(node, 'border-right-width')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
				}
				if (options.margin===true) {
					offsetWidth += parseInt( (self.nodeStyle(node, 'margin-left')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
					offsetWidth += parseInt( (self.nodeStyle(node, 'margin-right')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
				}
				if (options.padding===false) {
					offsetWidth -= parseInt( (self.nodeStyle(node, 'padding-left')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
					offsetWidth -= parseInt( (self.nodeStyle(node, 'padding-right')+'').replace(priv.regex.getNonIntegerCharsSigned,'') ,10) || 0;
				}
			});
			
			return offsetWidth;
		},
		x : function(absolute, mark) {
			var node = this._nodes[0],
				pos = null,
				posProp;
			if (node) {
				pos = node.offsetLeft;
				if (absolute===true) {
					while((node=node.parentNode) && node!==document) {
						pos += parseFloat(node.offsetLeft) || 0;
					}
					
				}
			}
			return pos;
		},
		y : function(absolute) {
			var node = this._nodes[0],
				pos = null;
			if (node) {
				pos = node.offsetTop;
				if (absolute===true) {
					while((node=node.parentNode) && node!==document) {
						pos += parseFloat(node.offsetTop) || 0;
					}
				}
			}
			return pos;
		},
		position : function(x, y, tween, units) {
			var css;
			units = units || 'px';
			if (arguments.length<1 || (arguments.length===1 && arguments[0]===true)) {
				return {
					x : this.x(arguments[0]===true),
					y : this.y(arguments[0]===true)
				};
			}
			else {
				css = {};
				if (tinydom.typeOf(x)==='number') {
					css.left = x + units;
				}
				else if (tinydom.typeOf(x)==='string') {
					css.left = x;
				}
				if (tinydom.typeOf(y)==='number') {
					css.top = y + units;
				}
				else if (tinydom.typeOf(y)==='string') {
					css.top = y;
				}
				this.css(css, tween);
				return this;
			}
		},
		scrollLeft : function(value) {
			if (value || value===0) {
				if (self.typeOf(value)!=='number') {
					value = Math.round((value+'').replace(priv.regex.getNonIntegerCharsSigned,''));
				}
				this._each(function(node) {
					node.scrollLeft = value;
				});
			}
			else {
				return this._nodes && this._nodes[0] && this._nodes[0].scrollLeft || 0;
			}
		},
		scrollTop : function(value) {
			if (value || value===0) {
				if (self.typeOf(value)!=='number') {
					value = Math.round((value+'').replace(priv.regex.getNonIntegerCharsSigned,''));
				}
				this._each(function(node) {
					node.scrollTop = value;
				});
			}
			else {
				return this._nodes && this._nodes[0] && this._nodes[0].scrollTop || 0;
			}
		},
		focus : function() {
			this._each(function(node) {
				if (node.focus) {
					node.focus();
				}
			});
			return this;
		},
		blur : function() {
			this._each(function(node) {
				if (node.blur) {
					node.blur();
				}
			});
			return this;
		},
		selectAll : function() {
			this._each(function(node) {
				if (node.SelectAll) {
					node.SelectAll();
				}
				if (node.select) {
					node.select();
				}
				if (node.selectionStart && node.hasOwnProperty('value')) {
					node.selectionStart = 0;
					node.selectionEnd = node.value.length;
				}
			});
		},
		getStyle : function(prop, returnValue) {
			var props = [];
			this._each(function(node) {
				props.push( self.nodeStyle(node, prop) || null );
			});
			if (returnValue===false) {
				this.pushResult(props);
				return this;
			}
			return props.length<=1 ? props[0] : props;
		},
		value : function(newValue, options) {
			options = options || {};
			if (newValue!==null && newValue!==undefined && arguments.length>0) {

				this._each(function(node) {
					var name = (node.nodeName+'').toLowerCase(),
						type = (node.getAttribute('type') || '').toLowerCase();
					if (name==='input' && (type==='checkbox' || type==='radio')) {
						
						node.checked = !!newValue;

					}

						node.value = newValue;

					
					if (options.fireChange!==false) {
						self.fireEvent({
							type : 'change',
							target : node,
							value : newValue
						});
					}
				});
				
				return this;
			}
			else {

				var values = [];
				this._each(function(node) {
					var name = (node.nodeName+'').toLowerCase(),
						type = (node.getAttribute('type') || '').toLowerCase(),
						value;
					if (name==='input' && (type==='checkbox' || type==='radio')) {

						values.push(!!node.checked);
					}
					else if (name==='select') {
						value = (node.multiselect || node.multiSelect) ? [] : null;
						self.el(node).query('option')._each(function(option) {
							if (option.selected || option.checked) {
								if (self.isArray(value)) {
									value.push(option.value);		// BUG FIX NOTE: innerHTML should not be used in place of the value!!.
								}
								else {
									value = option.value;			// || option.innerHTML
								}
							}
						});
						values.push(value);
					}
					else {
						values.push(node.value);
					}
				});
				return values.length<2 ? (values[0] || null) : values;
			}
		},
		attr : function(key, value, returnValue) {
			if (arguments.length>1) {
				return this._each(function(node) {
					try {
						node.setAttribute(key, value);
						if (node.removeAttribute && (value===null || value===undefined)) {
							node.removeAttribute(key);
						}
					} catch(err) {}
				});
			}
			else {
				var attrs = [];
				this._each(function(node) {
					var a = node.getAttribute(key);
					if (typeof(a)!=='string') {
						a = null;
					}
					attrs.push( a );
				});
				if (returnValue===false) {
					this.pushResult(attrs);
					return this;
				}
				return attrs.length<=1 ? attrs[0] : attrs;
			}
		},
		prop : function(key, value, returnValue) {
			if (arguments.length>1) {
				return this._each(function(node) {
					node[key] = value;
					if (value===undefined) {
						try{ delete node[key]; }catch(err){}
					}
				});
			}
			else {
				var props = [];
				this._each(function(node) {
					props.push( node[key] || null );
				});
				if (returnValue===false) {
					this.pushResult(props);
					return this;
				}
				return props.length<=1 ? props[0] : props;
			}
		},
		enable : function() {
			this.attr('disabled', null);
			this.declassify('_tinydom_disabled');
			return this;
		},
		disable : function() {
			this.attr('disabled', 'disabled');
			this.classify('_tinydom_disabled');
			return this;
		},
		enabled : function(newValue) {
			if (newValue===true || newValue===false) {
				this[newValue?'enable':'disable']();
				return this;
			}
			else {
				return this.attr('disabled')!=='disabled' && this.prop('disabled')!==true && !this.hasClass('_tinydom_disabled');
			}
		},
		addEvent : function(eventType, handler, useCapture) {
			this._each(function(el) {
				self.addEvent(el, eventType, handler, useCapture);
			});
			return this;
		},
		removeEvent : function(eventType, handler, useCapture) {
			this._each(function(el) {
				self.removeEvent(el, eventType, handler, useCapture);
			});
			return this;
		},
		fireEvent : function(type, e) {
			this._each(function(node) {
				self.fireEvent(self.extend({}, e || {}, {
					type : type,
					target : node
				}));
			});
			return this;
		},
		_removeAllEvents : function(deep) {
			var children;
			this._each(function(node) {
				priv.wrappedEventListener.destroyObjHandlers(node, true);
			});
			children = this.children();
			if (deep===true && children.count()>0) {
				children._removeAllEvents(true);
			}
			children = deep = null;
			return this;
		},
		appendChild : function(child) {
			if (child && this._nodes.length>0) {
				if (child.constructor===this.constructor) {
					var parent = this._nodes[0];
					child._each(function(node) {
						parent.appendChild(node);
					});
				}
				else {
					this._nodes[0].appendChild(child);
				}
			}
			return this;
		},
		insertBefore : function(child, before) {
			if (child && this._nodes.length>0) {
				if (before && before.constructor===this.constructor) {
					before = before._nodes[0];
				}
				if (!before || before.parentNode!==this._nodes[0]) {
					return this.appendChild(child);
				}
				if (child.constructor===this.constructor) {
					var parent = this._nodes[0];
					child._each(function(node) {
						parent.insertBefore(node, before);
					}, null, true);
				}
				else {
					this._nodes[0].insertBefore(child, before);
				}
			}
			return this;
		},
		insertInto : function(what) {
			var frag;
			if (what && this.count()>0) {
				if (what.constructor===this.constructor) {
					what = what._nodes[0];
				}
				if (this.count()===1) {
					what.appendChild(this._nodes[0]);
				}
				else {


					frag = document.createDocumentFragment();
					this._each(function(node) {
						frag.appendChild(node);
					}, null, true);							// reverse
					if (priv.support.filters!==true) {
						what.appendChild(frag);
					}
				}
			}
			return this;
		},
		remove : function() {
			this.fireEvent('remove');
			this._each(function(node) {
				if (node.parentNode) {
					node.parentNode.removeChild(node);
				}
			});
			return this;
		},
		destroy : function() {
			this.remove();
			this.fireEvent('destroy');
			
			this._removeAllEvents(true);
			this._nodes.splice(0, this._nodes.length);
			return this;
		},
		query : function(search, options) {
			var results = [];
			if (this._nodes.length>0) {
				this._each(function(node) {
					var r = self.getElement(search, tinydom.extend({}, options || {}, {
						within : node
					}));
					if (self.isArray(r) && r.length>0) {
						results = results.concat(r);
					}
				});
			}
			return new self.NodeSelection(results);
		},
		clone : function(deep, newParent) {
			var sel = [];
			if (newParent===true) {
				newParent = this.parent();
			}
			this._each(function(node) {
				sel.push( node.cloneNode(deep!==false) );
			});
			sel = new self.NodeSelection(sel);
			if (newParent) {
				newParent.appendChild(sel);
			}
			sel._each(priv.removeNodeUID);
			if (deep!==false) {
				sel.query('*')._each(priv.removeNodeUID);
			}
			return sel;
		},
		count : function() {
			return this._nodes.length;
		},
		exists : function() {
			return this.count()>0;
		},
		next : function() {
			var sib = this._nodes[0] && this._nodes[0].nextSibling;
			while (sib && sib.nodeType===3) {
				sib = sib.nextSibling;
			}
			return new self.NodeSelection(sib && [sib] || null);
		},
		prev : function() {
			var sib = this._nodes[0] && this._nodes[0].previousSibling;
			while (sib && sib.nodeType===3) {
				sib = sib.previousSibling;
			}
			return new self.NodeSelection(sib && [sib] || null);
		},
		previous : function(){ return this.prev.apply(this,arguments); },
		firstChild : function() {
			return this.children().first();
		},
		lastChild : function() {
			return this.children().last();
		},
		nthChild : function(n) {
			return this.children().index(n);
		},
		first : function(n) {
			return new self.NodeSelection( this._nodes.slice(0, n || 1) );
		},
		last : function(n) {
			return new self.NodeSelection( this._nodes.slice(this._nodes.length-(n || 1)) );
		},
		index : function(i, n) {
			return new self.NodeSelection(self.typeOf(i)==='number' && this._nodes.slice(i, i + (n || 1)) || null);
		},
		siblings : function() {
			var newSelection = new self.NodeSelection();
			this._each(function(node) {
				var n = node;
				while ((n=n.previousSibling)) {
					if (n.nodeName!=='#text' && n.nodeName!=='#comment' && n.nodeType!==3) {
						newSelection._nodes.push(n);
					}
				}
				n = node;
				while ((n=n.nextSibling)) {
					if (n.nodeName!=='#text' && n.nodeName!=='#comment' && n.nodeType!==3) {
						newSelection._nodes.push(n);
					}
				}
			});
			return newSelection;
		},
		parent : function() {
			var nodes=[], parent;
			this._each(function(node) {
				parent = node.parentNode;
				if (parent && nodes.indexOf(parent)<0) {
					nodes.push(parent);
				}
			});

			return new self.NodeSelection(nodes);
		},
		children : function() {
			var children = [], 
				x, y;
			if (this._nodes.length>0) {
				for (x=0; x<this._nodes.length; x++) {
					if (this._nodes[x].childNodes) {
						for (y=0; y<this._nodes[x].childNodes.length; y++) {
							if (this._nodes[x].childNodes[y].nodeType!==3 && this._nodes[x].childNodes[y].nodeName!=='#text' && this._nodes[x].childNodes[y].nodeName!=='#comment') {
								children.push(this._nodes[x].childNodes[y]);
							}
						}
					}
					else {

					}
				}
			}
			return new self.NodeSelection(children);
		},
		submit : function() {

			this._each(function(node) {
				var evt = self.fireEvent({
					type : 'submit',
					target : node
				});
				if (evt.rval!==false && evt.returnValue!==false && evt.preventDefault!==true) {
					if (node.submit) {
						node.submit();
					}
				}
			});
		},
		
		selection : function(start, end) {
			var el = this._nodes[0],
				value, sel, before, endMax, range;
			if (start && typeof(start)!=='number' && start.start) {
				end = start.end;
				start = start.start;
			}
			if (typeof(start)==='number') {
				if (start<0) {
					start = 0;
				}
				endMax = el.value.length;
				if (end>endMax) {
					end = endMax;
				}
				if (start>end) {
					start = end;
				}
				else if (end<start) {
					end = start;
				}
				
				if(window.getSelection) {
					el.selectionStart = start;
					el.selectionEnd = end;
				}
				else if (el.selectionEnd || el.selectionEnd===0) {
					el.selectionStart = start;
					el.selectionEnd = end;
				}
				else if (el.createTextRange) {
					range = el.createTextRange();
					range.collapse(true);
					range.moveStart('character', start);
					range.moveEnd('character', end);
					range.select();
				}
			}
			else {
				if (window.getSelection) {					// Stanadards
					value = typeof(el.value)==='string' ? el.value : el.innerHTML;
					sel = window.getSelection();
					return {
						start	: el.selectionStart+0,
						end		: el.selectionEnd+0,
						text	: value.substring(sel.start, sel.end)
					};
				}
				else if (document.selection) {				// IE
					sel = document.selection.createRange();
					before = document.body.createTextRange();
					before.moveToElementText(el);
					before.setEndPoint("EndToStart", sel);
					return {
						start	: before.text.length,
						end		: before.text.length + sel.text.length,
						text	: sel.text
					};
				}
				else {
					self.log("Selection retrieval is not supported in this browser.");
					return {
						start	: 0,
						end		: 0,
						text	: ''
					};
				}
			}
			return this;
		},
		template : function(templateFields) {
			var getFilters;
			templateFields = templateFields || {};
			
			getFilters = function(value, htmlEntities) {
				var filters = value.split('|'),
					i;
				value = filters.splice(0, 1)[0];

					for (i=filters.length; i--; ) {
						if (filters[i]==='htmlEntities') {
							filters.splice(i, 1);
						}
					}


				return filters;
			};

			
			this.query('[data-tpl-id]').each(function(node) {
				var nodeName = node.nodeName(),
					tplField = node.attr('data-tpl-id'),
					tplValue = tplField,						//tinydom.delve(templateFields, tplField);
					tplFilters;
				
				tplFilters = getFilters(tplField);
				tplField = tplField.split('|')[0];
				
				tplValue = tinydom.delve(templateFields, tplField);

				
				if (tplValue!==null && tplValue!==undefined) {
					if (typeof(tplValue)==='date' || tplValue.constructor===Date) {
						tplValue = tplValue.toLocaleString();
					}
					switch (nodeName) {
						case 'select':
						case 'input':
						case 'textarea':

							node.value(tplValue);
							break;
						
						case 'img':
						case 'video':
						case 'audio':
						case 'iframe':

							tplFilters.splice(0, 0, 'htmlEntities');
							tplValue = self.text.filter(tplValue, tplFilters.join('|'));
							node.attr('src', tplValue);
							break;
						
						default:
							tplFilters.splice(0, 0, 'htmlEntities');
							tplValue = self.text.filter(tplValue, tplFilters.join('|'));
							node.html(tplValue);
							break;
					}
				}
			});
			templateFields = null;
			return this;
		}
	});
	self.NodeSelection.prototype.on = self.NodeSelection.prototype.addEvent;
	self.NodeSelection.prototype.animateCss = self.NodeSelection.prototype.animateCSS;

	priv.incrementAnimationCount = function(node) {
		node.setAttribute('data-tinydom-animation-count', (priv.getAnimationCount(node) + 1) + '');
		self.addClass(node, '_tinydom_animating');
	};
	priv.decrementAnimationCount = function(node) {
		var current = Math.max(0, priv.getAnimationCount(node));
		if (current>1) {
			node.setAttribute('data-tinydom-animation-count', (current - 1) + '');
		}
		else {
			node.setAttribute('data-tinydom-animation-count', '');
			if (node.removeAttribute) {
				node.removeAttribute('data-tinydom-animation-count');
			}
			self.removeClass(node, '_tinydom_animating');
		}
	};
	priv.getAnimationCount = function(node) {
		return parseInt(node.getAttribute('data-tinydom-animation-count'), 10) || 0;
	};
	
	
	
	priv.unload = function() {

		var old, x;


		
		priv.wrappedEventListener.reset();




		
		self.getElement.clearCache();
		
		priv._nodeToIdList = {};










		setTimeout(function() {
			window.tinydom = priv = objConstructor = getSupportedTextContentProperty = null;
		}, 10);

	};

	
	
	
	
	
	self.el = function(query, log) {
		var results, type;
		if (query) {
			type = self.typeOf(query);
			if (type==='array') {
				results = [];
				for (var x=0; x<query.length; x++) {
					Array.prototype.splice.apply(results, [0,0].concat(self.el(query[x])._nodes) );
				}
			}
			if (query.constructor===self.NodeSelection) {
				log===true && console.log('query is already a NodeSelection', query.constructor+'', query.constructor.name);
				return query;
			}
			else if ((type==='string' && query.charAt(0)==='<') || (type==='object' && !query.nodeName && query!==window)) {
				log===true && console.log('query is an HTML fragment', query, type);
				results = self.createElement.apply(self, arguments);
			}
			else if (type==='string') {
				log===true && console.log('query is a CSS selector', query, type);
				results = self.getElement(query, arguments[1]);
			}
			else if (query.nodeName || query===window) {
				log===true && console.log('query is an HTML element', query, type);
				results = query;
			}
		}
		return new self.NodeSelection(results);
	};
	
	
	
	
	self.node = function(uniqueID) {
		return new self.NodeSelection(priv.idToNode(uniqueID));
	};
	
	
	
	
	self.getElement = (function() {
		var getElement,
			resetRegex,
			cache = {},
			cacheEnabled = false,
			nodeNameReg = /^((?:[a-z][a-z0-9\_\-]*)|\*)?/gi,
			removePaddingReg = /^\s*(.*?)\s*$/gm,
			removeCommaPaddingReg = /\s*?\,\s*?/gm,
			enableSelectorStats = false,
			selectors;
		
		
		selectors = [
			
			{
				title : 'ID selector {#id}',

				regex : /^#[_a-zA-Z0-9-]*/gm,
				filter : function(matches, results, config) {

					return [document.getElementById(matches[0].substring(1))];
				}
			},
			
			
			{
				title : 'Class selector {.className}',
				regex : /^\.([^#.:\[<>\{+\|\s]+)/gim,
				filter : function(matches, results, config) {
					var i, className,
						klass = ' '+matches[1]+' ';
					for (i=results.length; i--; ) {
						className = results[i] && results[i].className;
						if (!className || (' ' + className + ' ').indexOf(klass)===-1) {
							results.splice(i, 1);
						}
					}
					
					
				}
			},
			
			
			{
				title : 'Attribute selector {[name=value] & variants}',
				regex : /^\[([^\^\$\~=]+)(?:([\^\$\~=]+)([^\]]*))?\]/g,
				filter : function(rawMatches, results, config) {
					var i, matches, isMatch, attrValue, pos;
					if (rawMatches && rawMatches[1]) {
						matches = {
							attribute : rawMatches[1]
						};
						if (rawMatches[2] && rawMatches[3]) {
							matches.type = rawMatches[2];
							matches.attrValue = rawMatches[3] || '';
						}
						for (i=results.length; i--; ) {
							isMatch = false;
							attrValue = results[i].getAttribute(matches.attribute);
							if (matches.attribute==='checked') {
								if (matches.attrValue==='true' || matches.attrValue==='false') {
									attrValue = results[i].checked?'true':'false';
								}
								else {
									attrValue = results[i].checked?'checked':null;
								}
							}
							if (matches.attribute==='selected') {
								if (matches.attrValue==='true' || matches.attrValue==='false') {
									attrValue = results[i].selected?'true':'false';
								}
								else {
									attrValue = results[i].selected?'selected':null;
								}
							}
							matches.attrPresent = self.typeOf(attrValue)==='string';
							matches.attrSet = attrValue && attrValue.length>0;
							if (matches.attrValue) {
								pos = matches.attrPresent ? attrValue.indexOf(matches.attrValue) : -1;
							}
							switch (matches.type || '') {
								case '=':
									isMatch = attrValue===matches.attrValue;
									break;
								case '^=':
									isMatch = pos===0;
									break;
								case '$=':
									isMatch = matches.attrSet && attrValue.substring(attrValue.length-matches.attrValue.length)===matches.attrValue;
									break;
								case '~=':
									isMatch = pos>-1;
									break;
								default:
									isMatch = !matches.attrValue && matches.attrPresent;
							}

							if (!isMatch) {
								results.splice(i, 1);
							}
						}
					}
				}
			},
			
			
			{
				title : 'Descendant selector {>}',
				regex : /^\s*\>\s*((?:[a-z][a-z0-9\:\_\-]*)|\*)?/gi,
				filter : function(matches, results, config) {
					var originalResults = [].concat(results),
						nodeName = (matches[1] || '*').toLowerCase(),
						x, i, children, childN;
					results.splice(0, results.length);

					if (!config.isFiltered && config.first) {

						self.log('Descendant selector called on an unfiltered result set.  Operating on descendants of the document.');
					}
					if (!config.isFiltered || config.first) {
						originalResults = [config.searchBaseNode];
					}
					for (x=0; x<originalResults.length; x++) {
						children = originalResults[x].childNodes;
						for (i=0; i<children.length; i++) {
							childN = (children[i].nodeName + '').toLowerCase();
							if (childN===nodeName || (nodeName==='*' && childN!=='#text' && childN!=='#comment' && children[i].nodeType!==3)) {
								results.push(children[i]);
							}
						}
					}
				}
			},
			
			
			{
				title : 'nth-child aliases, like :first-child',
				regex : /^\:(first|last|only)\-(child|of\-type)/gm,
				filter : function(matches, results, config) {
					var map = {
							'first-child'	: ':nth-child(0n+1)',
							'first-of-type'	: ':nth-of-type(0n+1)',
							'last-child'	: ':nth-last-child(0n+1)',
							'last-of-type'	: ':nth-last-of-type(0n+1)'

						},
						i, selector, mappedSelector, submatches;
					for (i=selectors.length; i--; ) {
						if (selectors[i].isNthChildSelector===true) {
							selector = selectors[i];
							break;
						}
					}
					
					if (map.hasOwnProperty(matches[1]+'-'+matches[2]) && selector) {
						mappedSelector = map[matches[1]+'-'+matches[2]];
						selector.regex.lastIndex = 0;
						submatches = selector.regex.exec(mappedSelector);
						return selector.filter(submatches, results, config);
					}
					else {
						tinydom.log('Unknown nth-child alias "'+matches[1]+'-'+matches[2]+'"');
					}
				}
			},
			
			
			{
				isNthChildSelector : true,
				title : 'nth-child selector {:nth-child(n+2) & variants}',
				regex : /^\:(nth(?:\-last)?(?:\-of\-type|\-child))\((?:(\-?[0-9]*n(?:[+-][0-9]+)?)|([0-9]+)|([a-z]+))\)/gm,
				filter : function(matches, results, config) {
					var originalResults,
						x, i, d, p, t,
						type,
						child, childIndex,

						a, b, n,
						ofType = matches[1].indexOf('-of-type')!==-1,
						named = {
							odd : [2,1],
							even : [2]
						};



					
					originalResults = results.splice(0, results.length);
					
					if (matches[1].indexOf('-last')!==-1) {
						originalResults.reverse();
					}
					
					if (matches[2]) {		// explicit an+b
						p = matches[2].split('n');
						if (p[0].replace('-','').length===0) {
							p[0] = p[0] + '1';
						}
						a = Math.round(p[0].replace('+','')) || 0;
						b = Math.round(p[1].replace('+','')) || 0;
					}
					else if (matches[3]) {	// (implied 1n) + b
						a = 0;
						b = Math.round(matches[3]) || 0;
					}
					else if (matches[4]) {	// named sets: odd, even
						p = matches[4].toLowerCase();
						if (named.hasOwnProperty(p)) {
							a = named[p][0] || 0;
							b = named[p][1] || 0;
						}
						else {
							tinydom.log('Unknown named nth-child expression "'+r[4]+'"');
						}
					}
					
					if (a+b<=0) {
						return;
					}
					if (a===b) {
						b = 0;
					}

					
					for (x=0; x<originalResults.length; x++) {
						children = (originalResults[x].parentNode || {}).childNodes;
						type = (originalResults[x].nodeName+'').toLowerCase();
						isMatch = false;
						if (children) {
							childIndex = 0;
							for (i=0; i<children.length; i++) {
								child = children[i];
								t = ofType ? (child.nodeName+'').toLowerCase()===type : ((child.nodeName+'').substring(0,1)!=='#' || child.nodeType===1 || child.nodeType===9);
								if (t) {
									childIndex += 1;
									if (child===originalResults[x]) {

										if (a>0) {
											isMatch = (childIndex%a - b)===0;
										}
										else {
											isMatch = childIndex === b;
										}
										if (isMatch) {
											break;
										}
									}
								}
							}
						}
						if (isMatch) {
							results.push(originalResults[x]);
						}
					}

				}
			},
			
			
			{
				title : 'within_internal selector { }',
				regex : /^\s+((?:[a-z][a-z0-9\:\_\-]*)|\*)?/gi,
				filter : function(matches, results, config) {
					var originalResults = [].concat(results),
						nodeName = matches[1] || '*',
						x;

					results.splice(0, results.length);
					for (x=0; x<originalResults.length; x++) {
						Array.prototype.splice.apply(results, [results.length-1,0].concat(self.toArray(originalResults[x].getElementsByTagName(nodeName))));
					}
				}
			}
		];
		
		
		
		resetRegex = function(regex) {
			regex.lastIndex = 0;
		};
		
		
		
		getElement = function(search, options) {
			var baseNode = document && document.documentElement || document,
				currentResults,
				nodes,
				nodeName,
				originalSearch = search,
				handlerConfig,
				filterResponse,
				searchParsed,
				isMatch,
				matches,
				hasMatch,
				constrainedToNode,
				parseIterations = 0,
				doLogging = false,
				time = Date.now(),
				perSelectorSearchTime,
				perSelectorFilterTime,
				i, x;

			search = (search + '').replace(removePaddingReg, '$1');
			options = tinydom.extend({}, options || {});
			if (options.logging===true) {
				doLogging = true;
			}

			if (cacheEnabled && options.useCache===true && cache[search]) {
				return cache[search];
			}

			if (options.within) {
				baseNode = options.within;
			}

			if (search.indexOf(',')>-1) {
				search = search.split(',');

				nodes = [];
				for (x=search.length; x--; ) {
					search[x] = search[x].replace(removePaddingReg,'$1');
					if (search[x].length>0) {

						matches = getElement(search[x], tinydom.extend({}, options, {
							logging : false,
							internalLogging : doLogging,
							internal : true
						}));

						if (matches) {
							for (i=0; i<matches.length; i++) {
								if (nodes.indexOf(matches[i])===-1) {
									nodes.push(matches[i]);
								}
							}

						}
					}
				}
				if (doLogging) {
					self.log('query=',originalSearch, ', result=',node);
				}

				time = Date.now() - time;
				if (time>100) {
					self.log('Slow Selector Warning: "'+originalSearch+'" took ' + time + 'ms to complete.');
				}
				return nodes;
			}
			
			
			
			
			
			nodeName = search.match(nodeNameReg);
			nodeName = ((nodeName && nodeName[0]) || "").toLowerCase();
			search = search.substring(nodeName.length);



			
			searchParsed = search;
			if (searchParsed.match(/^#[^\s\[\]\(\)\:\*\.\,<>#]+$/gim)) {

				currentResults = [document.getElementById(searchParsed.substring(1))];
				searchParsed = '';
			}
			else if (search.substring(0,1)==='#') {
				currentResults = [];
			}
			else if ((!nodeName || nodeName==='*') && document.all && !window.opera && (baseNode===document || baseNode===document.documentElement)) {
				currentResults = self.toArray(document.all);
				constrainedToNode = false;
			}
			else {
				currentResults = self.toArray(baseNode.getElementsByTagName(nodeName || '*'));
				constrainedToNode = true;
			}

			handlerConfig = {
				searchBaseNode : baseNode,
				negated : false,
				first : true,
				isFiltered : constrainedToNode || !!(nodeName && nodeName!=='*')
			};

			while (searchParsed.length>0) {
				parseIterations += 1;
				hasMatch = false;
				for (i=0; i<selectors.length; i++) {
					if (enableSelectorStats===true) {
						perSelectorSearchTime = Date.now();
					}

					resetRegex(selectors[i].regex);
					matches = selectors[i].regex.exec(searchParsed);
					
					if (enableSelectorStats===true) {
						perSelectorSearchTime = Date.now() - perSelectorSearchTime;
					}
					
					if (matches) {

						hasMatch = true;
						if (doLogging) {
							self.log((selectors[i].title || selectors[i].regex) + ' ==>> matched:"'+ searchParsed.substring(0,matches[0].length) + '" ==>> remaining:"'+ searchParsed.substring(matches[0].length) + '" ||debug>> (submatches:'+ matches.slice(1).join(',') + ')');
						}
						
						if (enableSelectorStats===true) {
							perSelectorFilterTime = Date.now();
						}

						filterResponse = selectors[i].filter(matches, currentResults, handlerConfig);
						if (filterResponse && self.isArray(filterResponse)) {
							currentResults = filterResponse;
						}
						
						if (enableSelectorStats===true) {
							perSelectorFilterTime = Date.now() - perSelectorFilterTime;
						}

						searchParsed = searchParsed.substring(matches[0].length);

						handlerConfig.first = false;

						handlerConfig.isFiltered = true;
					}

					if (enableSelectorStats===true) {
						selectors[i].matchTimes.push(perSelectorSearchTime);
						if (hasMatch) {
							selectors[i].filterTimes.push(perSelectorFilterTime);
						}
					}

					if (searchParsed.length===0) {
						break;
					}
				}

				if (!hasMatch) {
					throw(new Error('tinydom.getElement() :: Unknown CSS selector near: ' + searchParsed.substring(0,20), 'tinydom.js', 1775));
					break;
				}
			}
			
			
			if (options.includeInvisibles!==true) {
				for (i=currentResults.length; i--; ) {
					if (currentResults[i] && (currentResults[i].nodeName+'').charAt(0)==='#') {
						currentResults.splice(i, 1);
					}
				}
			}
			
			
			if (doLogging) {
				self.log('query=',originalSearch, ', result=',currentResults);
			}

			if (cacheEnabled && options.cache===true) {
				cache[search] = currentResults;
			}
			
			if (options.internal!==true && doLogging===true) {
				time = Date.now() - time;
				if (time>10) {
					self.log('Slow Selector Warning: "'+originalSearch+'" took ' + time + 'ms to complete. '+parseIterations+' parse iterations.');
				}
			}

			return currentResults;
		};
		
		getElement.enableCache = function(enabled) {
			cacheEnabled = enabled!==false;
			if (!cacheEnabled) {
				cache = {};
			}
		};
		getElement.disableCache = function() {
			cacheEnabled = false;
			cache = {};
		};
		getElement.clearCache = function() {
			cache = {};
		};
		
		getElement._normalizeSelectorFilter = function(selectorFilter) {
			if (arguments.length===2) {
				selectorFilter = {
					regex : arguments[0],
					filter : arguments[1]
				};
			}
			if (selectorFilter && selectorFilter.regex && selectorFilter.filter) {
				return selectorFilter;
			}
			return false;
		};
		
		
		getElement.addSelectorFilter = function(selectorFilter) {
			selectorFilter = getElement._normalizeSelectorFilter.apply(getElement, arguments);
			if (selectorFilter) {
				selectors.push(selectorFilter);
				return true;
			}
			return false;
		};
		
		
		getElement.removeSelectorFilter = function(selectorFilter) {
			var x, p, isMatch;
			selectorFilter = getElement._normalizeSelectorFilter.apply(getElement, arguments);
			if (selectorFilter) {
				for (x=selectors.length; x--; ) {
					isMatch = true;
					for (p in selectors[x]) {
						if (selectors[x].hasOwnProperty(p) && selectors[x][p]!==selectorFilter[p]) {
							isMatch = false;
							break;
						}
					}
					if (isMatch) {
						selectors.splice(x, 1);
						break;
					}
				}
			}
			return isMatch===true;
		};
		
		if (enableSelectorStats===true) {
			(function() {
				for (var i=0; i<selectors.length; i++) {
					selectors[i].matchTimes = [];
					selectors[i].filterTimes = [];
				}
			}());
			getElement.selectorStats = function() {
				var stats = {
						title : "--- Selector Statistics: ---",
						selectors : []
					},
					stat, i, sel, j, time, totalTime;
				for (i=0; i<selectors.length; i++) {
					sel = selectors[i];
					stat = {};
					stat.title = sel.title;
					totalTime = 0;
					if (sel.matchTimes.length>0) {
						time = 0;
						for (j=0; j<sel.matchTimes.length; j++) {
							time += sel.matchTimes[j];
						}
						totalTime += time;
						stat.matching = Math.round(time/sel.matchTimes.length) + "ms";
					}
					if (sel.filterTimes.length>0) {
						time = 0;
						for (j=0; j<sel.filterTimes.length; j++) {
							time += sel.filterTimes[j];
						}
						totalTime += time;
						stat.filtering = Math.round(time/sel.filterTimes.length) + "ms";
					}
					stat.own_time = totalTime + "ms";
					stat.calls = sel.matchTimes.length;
					stats.selectors.push(stat);
				}
				return stats;
			};
		}
		else {
			getElement.selectorStats = function() {
				return "disabled";
			};
		}
		
		return getElement;
	}());
	
	
	
	
	
	
	window.wrappedEventListener = priv.wrappedEventListener = {
		list : [],
		none : {},
		summary : function() {
			for (var x=0; x<this.list.length; x++) {
				tinydom.log( priv.idToNode(this.list[x].target), '.on', this.list[x].type, ' -> ', (this.list[x].handler.displayName || this.list[x].handler.name) );
			}
		},
		reset : function(removeEvents) {
			var i, evt;
			if (removeEvents===true) {
				for (i=this.list.length; i--; ) {
					evt = this.list[i];

					this.list[i] = this.none;

					self.removeEvent(priv.idToNode(evt.target), evt.type, evt.wrappedHandler);
					this.unsetRefs(evt);
					window.killCount = (window.killCount || 0) + 1;
				}
			}
			this.list.splice(0, this.list.length);
		},
		destroyObjHandlers : function(obj) {
			var i, evt,
				objId = priv.nodeToId(obj);
			for (i=this.list.length; i--; ) {
				evt = this.list[i];
				if (evt.target===objId) {

					this.unsetRefs(evt);
					this.list.splice(i, 1);
					self.removeEvent(obj, evt.type, evt.wrappedHandler);
					window.killCount = (window.killCount || 0) + 1;
				}
			}
		},
		get : function(type, handler, obj, andDestroy) {
			var i, evt;
			obj = priv.nodeToId(obj);
			for (i=this.list.length; i--; ) {
				evt = this.list[i];
				if (evt.target===obj && evt.handler===handler && evt.type===type) {
					handler = evt.wrappedHandler;
					if (andDestroy===true) {
						this.list.splice(i, 1);

						window.killCount = (window.killCount || 0) + 1;
						this.unsetRefs(evt);
					}
					break;
				}
			}

			return handler;
		},
		
		
		unsetRefs : function(item) {
			item.wrappedHandler.type = null;
			item.wrappedHandler.handler = null;
			item.wrappedHandler.target = null;
		},
		
		
		internalFireEvent : function(event) {
			var target = priv.nodeToId(event.target),
				type = event.type.replace(/^on/gm,''),
				i, item, returnValue;
			for (i=this.list.length; i--; ) {
				item = this.list[i];

				if (item.target===target && item.type===type) {

					returnValue = item.handler.call(event.target, event);
					if (returnValue===false) {
						break;
					}
				}
			}
		},
		
		
		create : function(type, handler, obj) {
			var evt = {
				type	: type,
				target	: priv.nodeToId(obj),
				handler	: handler,
				wrappedHandler : function(e) {
					var handler = arguments.callee.handler,
						type = (arguments.callee.type || e.type).toLowerCase().replace(/^on/,''),
						originalTarget = this!==window ? this : (priv && priv.idToNode(arguments.callee.target)),
						event, i,
						d = {
							isInSelf : false,


							doPreventDefault : false,
							doCancelBubble : false,
							doStopPropagation : false,
							e : e || window.event,
							ret : null,
							end : function() {
								d.end = null;
								e = event = d = handler = type = originalTarget = null;

								return this.ret;
							}
						};
					if (!priv || !priv.idToNode) {
						self.log("target:<"+e.target.nodeName+' class="'+e.target.className+'" id="'+e.target.id+'"' + "> , type:"+type+"/"+e.type);
					}
					e = d.e;

					event = {
						which	: e.which,
						type	: type,
						target	: e.target || e.srcElement || originalTarget || document.body,
						relatedTarget : e.relatedTarget || (type==='mouseout' ? e.toElement : e.fromElement),
						preventDefault : function(){ d.doPreventDefault=true; },
						cancelBubble : function(){ d.doCancelBubble=true; },
						stopPropagation : function(){ d.doStopPropagation=true; },
						returnValue : true,
						originalEvent : e,
						timeStamp : e.timeStamp || Date.now()
					};


					for (i in e) {
						if (!event.hasOwnProperty(i) && typeof(e[i])!=='function' && i!==i.toUpperCase()) {
							event[i] = e[i];
						}
					}
					
					if (!event.target) {
						tinydom.log('Event target doesn\'t exist for type "'+event.type+'": ',event.target,', srcElement=',e.srcElement);
					}
					
					if (e.type==='touchend' && priv._lastTouchPos) {
						event.pageX = priv._lastTouchPos.pageX;
						event.pageY = priv._lastTouchPos.pageY;
					}
					else if (e.touches && e.touches[0]) {
						event.pageX = e.touches[0].pageX;
						event.pageY = e.touches[0].pageY;
						priv._lastTouchPos = {
							pageX : event.pageX,
							pageY : event.pageY
						};
					}
					else if (e.pageX || e.pageX===0 || e.clientX || e.clientX===0) {
						event.pageX = e.pageX || (e.clientX+document.body.offsetLeft);
						event.pageY = e.pageY || (e.clientY+document.body.offsetTop);
					}
					if (type.indexOf('key')>-1 || e.keyCode || e.charCode) {
						event.keyCode = e.keyCode || e.which;
						event.charCode = e.keyCode || e.charCode || e.which;			// this should never be used
						event.which = e.which;
					}
					if (type.indexOf('mouse')>-1 || type.indexOf('click')>-1 || (e.button!==null && e.button!==undefined)) {
						event.button = e.button || e.which;
					}

					if (event.target && event.target.nodeType===3 && originalTarget.nodeType!==3) {
						event.target = event.target.parentNode;
					}

					d.searchNode = event.relatedTarget || event.target;
					do {
						if (d.searchNode===originalTarget) {
							d.isInSelf = true;
							break;
						}
					} while(d.searchNode && (d.searchNode=d.searchNode.parentNode) && d.searchNode!==document);


					if ((type!=='mouseover' && type!=='mouseout') || !d.isInSelf) {
						if (typeof(handler)==='function' && handler.call) {
							d.handlerResponse = handler.call(originalTarget, event);
						}
						else {


						}
						
						event.returnValue = d.handlerResponse!==false && event.returnValue!==false;
						if (d.doPreventDefault) {
							event.returnValue = false;
							if (e.preventDefault) {

								e.preventDefault();
							}
						}
						if (d.doCancelBubble || d.doStopPropagation || event.cancelBubble===true) {
							if (e.stopPropagation) {

								e.stopPropagation();
							}
							if (self.typeOf(e.cancelBubble)==='function') {

								e.cancelBubble();
							}
							else {
								try {
									e.cancelBubble = true;
								}catch(err){}
							}
						}
						d.ret = event.returnValue;
					}
					else {
						d.ret = true;
					}
					return d.end();
				}
			};
			evt.wrappedHandler.displayName = 'wrappedEventHandler_'+type;
			evt.wrappedHandler.handler = handler;
			evt.wrappedHandler.type = type;
			evt.wrappedHandler.target = evt.target;		// an ID, not the node itself
			this.list.push(evt);

			obj = type = handler = evt = null;
			return this.list[this.list.length-1].wrappedHandler;
		}
		
		
		
	};
	
	
	
	
	
	
	
	self.eventTypeMap = {};
	if (priv.support.webkitMultitouch) {
		self.extend(self.eventTypeMap, {
			'mousedown'	: 'touchstart',
			'mousemove'	: 'touchmove',
			'mouseup'	: 'touchend'
		});
	}
	
	self.addEvent = function(obj, type, fn, useCapture) {
		var x, origType;
		if (obj) {
			if (self.typeOf(type)==='string' && type.indexOf(',')>-1) {
				type = type.replace(/\s/gm,'').split(',');
			}
			if (self.isArray(type)) {
				for (x=0; x<type.length; x++) {
					self.addEvent(obj, type[x], fn);
				}
				return true;
			}
			origType = type = (type+'').toLowerCase().replace(/^\s*(on)?(.*?)\s*$/gim,'$2');
			
			if (self.eventTypeMap.hasOwnProperty(type)) {
				type = self.eventTypeMap[type];
			}
			
			fn = priv.wrappedEventListener.create(origType, fn, obj);
			if (obj.attachEvent) {
				obj['e'+type+fn] = fn;
				obj[type+fn] = function () {obj['e'+type+fn]( window.event );};
				obj.attachEvent( 'on'+type, obj[type+fn] );
			}
			else if (obj.addEventListener) {
				obj.addEventListener( type, fn, useCapture===true );
				window._eventCount = (window._eventCount || 0) + 1;
			}
		}
	};
	
	self.removeEvent = function(obj, type, fn, useCapture) {
		var x, origType;
		if (obj) {
			if (self.typeOf(type)==='string' && type.indexOf(',')>-1) {
				type = type.replace(/\s/gm,'').split(',');
			}
			if (self.isArray(type)) {
				for (x=0; x<type.length; x++) {
					self.removeEvent(obj, type[x], fn, useCapture);
				}
				return true;
			}
			origType = type = (type+'').toLowerCase().replace(/^\s*(on)?(.*?)\s*$/gim,'$2');
			
			if (self.eventTypeMap.hasOwnProperty(type)) {
				type = self.eventTypeMap[type];
			}
			
			fn = priv.wrappedEventListener.get(origType, fn, obj, true);		// , useCapture===true ?
			if (obj.detachEvent) {
				try {
					obj.detachEvent( 'on'+type, obj[type+fn] );
				} catch(err) {
					self.log('Event removal failed with an error: ', 'on'+type, self.typeOf(obj[type+fn]));
				}
				obj[type+fn] = null;
			}
			else if (obj.removeEventListener) {
				try {
					obj.removeEventListener( type, fn, useCapture===true );
					window._eventCount = (window._eventCount || 0) - 1;
				}catch(err) {



				}
			}
		}
	};
	
	self.cancelEvent = function(e) {
		e = e || window.event;
		if (e) {
			if (e.preventDefault) {
				e.preventDefault();
			}
			if (e.stopPropagation) {
				e.stopPropagation();
			}
			try {
				e.cancelBubble = true;
			} catch(err) {}
			e.returnValue = false;
		}
		return false;
	};
	
	
	
	
	
	self.fireEvent = function (options) {
		var evt, rval, p, preventDefault, initError;
		options = options || {};
		if (document.createEventObject) {       // IE
			options = self.extend({}, options);
			options.type = 'on'+options.type.toLowerCase().replace(/^on/,'');

			
			try {
				evt = document.createEventObject();
			}catch(err) {
				initError = true;
			}
			if (!initError) {
				for (p in options) {
					if (options.hasOwnProperty(p)) {
						try {
							evt[p] = options[p];
						}catch(err){}
					}
				}
				try {
					rval = options.target.fireEvent(options.type, evt);
					preventDefault = evt.preventDefault===true;
				} catch(err) {
					initError = true;
				}
			}
			if (initError) {

				if (priv.wrappedEventListener.internalFireEvent) {
					priv.wrappedEventListener.internalFireEvent(options);
				}
			}
			
		}
		else {                                  // Everything else
			evt = document.createEvent("HTMLEvents");
			evt.initEvent(options.type.toLowerCase().replace(/^on/,''), true, true);
			for (p in options) {
				if (options.hasOwnProperty(p)) {
					try {
						evt[p] = options[p];
					} catch(err) {}
				}
			}

			rval = !options.target.dispatchEvent(evt);
			preventDefault = evt.preventDefault===true;
		}
		
		return {
			evt             : evt,
			preventDefault  : preventDefault,
			rval            : rval
		};
	};
	
	
	
	
	
	
	priv._nodeToIdIndex = 0;
	priv._nodeToIdList = {};
	window._nodeToIdList = priv._nodeToIdList;
	priv.nodeToId = function(el) {
		var search, id;
		if (el===window) {
			return '_td_autoid_window';
		}
		else if (el===document) {
			return '_td_autoid_document';
		}
		else if (el===document.body) {
			return '_td_autoid_documentbody';
		}
		search = (/\s_td_autoid_([0-9]+)\s/gm).exec(' ' + el.className + ' ');
		if (search && search[1]) {
			id = search[1];
		}
		else {
			priv._nodeToIdIndex += 1;
			id = priv._nodeToIdIndex + '';
			self.addClass(el, '_td_autoid_'+id);
		}
		priv.ensureNodeIdListing(el, id);
		return id;
	};
	
	priv.idToNode = function(id) {
		var search,
			listed = priv._nodeToIdList[id+''],
			node;
		if (id==='_td_autoid_window') {
			return window;
		}
		else if (id==='_td_autoid_document') {
			return document;
		}
		else if (id==='_td_autoid_documentbody') {
			return document.body;
		}
		if (listed) {


			node = self.getElement(listed);
			if (!(/\s_td_autoid_[0-9]+\s/gm).exec(' ' + node.className + ' ')) {
				node = null;
			}
		}
		if (!node) {

			search = self.getElement('._td_autoid_'+id);
			node = search && search[0];
			if (node) {
				priv.ensureNodeIdListing(node, id);
			}
		}
		return node || false;
	};
	
	priv.ensureNodeIdListing = function(node, id) {
		var idAttr;
		if (node.getAttribute) {
			idAttr = node.getAttribute('id');
			if (!idAttr) {
				idAttr = '_td_autoid_'+id;
				node.setAttribute('id', idAttr);
			}
			priv._nodeToIdList[id] = '#'+idAttr;

		}
	};
	
	priv.removeNodeUID = function(node) {
		var id = node.getAttribute('id');
		if (id && id.match(/^_td_autoid_[0-9]+$/g)) {
			if (node.removeAttribute) {
				node.removeAttribute('id');
			}
			else {
				node.setAttribute('id', '');
			}
		}
		if (node.className) {
			node.className = node.className.replace(/(^|\b)_td_autoid_[0-9]+(\b|$)/gim,'');
		}
	};
	
	
	
	
	
	
	
	self.setOpacity = function(el, opac) {
		if (opac<=1 && opac>0) {
			opac = opac * 100;
		}
		opac = Math.round(opac);
		if (opac<100) {
			el.style.opacity = parseFloat(opac/100).toFixed(2);
			el.style.filter = "alpha(opacity=" + opac + ")";
		}
		else {
			el.style.opacity = null;
			el.style.filter = null;
		}
	};
	
	self.applyMsFilter = function(el, type, value) {
		var i,
			props = {},
			vtype = self.typeOf(value),
			propsStr,
			existingProps = [],
			currentFilterStr = self.nodeStyle(el, 'filter') || el.style.filter || '';
		if (vtype==='string') {
			value = (value+'').replace(/\,\s*?/gim,',').split(',');
			for (i=0; i<value.length; i++) {
				props[ value[i].substring(0,value[i].indexOf('=')) ] = value[i].substring(value[i].indexOf('=')+1);
			}
		}
		else if(vtype==='object') {
			props = value;
		}
		props.enabled = props.enabled!==false;
		if (!el.filters[type]) {
			propsStr = '';
			for (i in props) {
				if (props.hasOwnProperty(i) && !(i==='enabled' && props[i]===true)) {
					existingProps.push(i);
					if (self.typeOf(props[i])==='number') {
						props[i] = Math.round(props[i]);
					}
					propsStr += (propsStr.length>0?', ':'') + i + '=' + props[i];
				}
			}
			if (existingProps.length===0 || (existingProps.length===1 && existingProps[0]==='enabled')) {
				el.style.filter = currentFilterStr;

			}
			else {
				el.style.filter = currentFilterStr + ' '+type+'('+propsStr+')';

			}
		}
		else {
			for (i in props) {
				if (props.hasOwnProperty(i)) {
					if (self.typeOf(props[i])==='number') {
						props[i] = Math.round(props[i]);
					}
					el.filters[type][i] = props[i];
				}
			}
		}
	};
	
	
	
	
	
	self.applyCss = function(el, properties) {
		var x, cx, d, p, ieOpac;
		properties = properties || {};
		for (x in properties) {
			if (properties.hasOwnProperty(x)) {
				try {
					cx = self.getStyleAsCSS(x);

						cx = cx.replace(/^\-(moz|webkit|ms|o|vendor)\-/gim, vendorCssPrefix+'-');

					cx = self.getStyleAsProperty(cx);
					if (cx==='opacity' && priv.support.filters) {
						ieOpac = Math.round( parseFloat(properties[x])*100 );
						if (ieOpac<100) {

							self.applyMsFilter(el, 'alpha', {
								enabled : true,
								opacity : ieOpac
							});
						}
						else {

							self.applyMsFilter(el, 'alpha', {
								enabled : false
							});
						}

					}
					else if (cx==='--box-shadow' && priv.support.filters) {
						d = properties[x].match(/\b(\#[0-9af]{3}[0-9af]{3}?|rgba?\([0-9\,\s]+\))\b/gim);
						d = d && d[0] || '';
						p = (' '+properties[x]+' ').replace(d,'').replace(/\s+/m,' ').split(' ').slice(1,4);
						self.applyMsFilter(el, 'glow', {
							Color : d,
							Strength : Math.round(p[3].replace(/[^0-9\-\.]/gim,''))
						});
					}
					else {
						el.style[cx] = properties[x];
						if (cx==="boxShadow" || cx==="textShadow" || cx==="borderRadius") {
							if (vendorCssPrefixJS) {
								el.style[vendorCssPrefixJS + cx] = properties[x];
							}
						}
					}
				}catch(err){}
			}
		}
	};
	
	self.getStyleAsProperty = function(style) {
		return self.typeOf(style)==='string' && style.replace(/\-[a-z0-9]/gim, function(a){return a.charAt(1).toUpperCase();}) || null;
	};
	
	self.getStyleAsCSS = function(style) {
		return self.typeOf(style)==='string' && style.replace(/\-*[A-Z]/gm, '-$0').toLowerCase() || null;
	};
	
	
	
	self.getCssTransitions = function(el) {
		var transitions = {},
			current = {
				properties			: '-vendor-transition-property',
				durations			: '-vendor-transition-duration',
				timingFunctions		: '-vendor-transition-timing-function'
			},
			p, x, durationStr, duration;
		for (p in current) {
			if (current.hasOwnProperty(p)) {
				current[p] = (self.nodeStyle(el, current[p]) || '').replace(/\s/,'').split(',');
			}
		}
		for (x=0; x<current.properties.length; x++) {
			if (current.properties[x] && current.properties[x]!=='null' && !(current.properties[x]==='all' && current.durations[x].match(/^[0\.ms]*$/))) {
				durationStr = current.durations[x] || current.durations[current.durations.length-1];
				duration = parseFloat(durationStr.replace(/[^\-0-9\.]/gim,'')) || 0;
				if (!durationStr.match(/ms$/i)) {
					duration *= 1000;
				}
				transitions[self.getStyleAsProperty(current.properties[x])] = {
					duration : duration,
					timingFunction : current.timingFunctions[x] || current.timingFunctions[current.timingFunctions.length-1] || 'ease'
				};
			}
		}
		
		return transitions;
	};
	
	self.setCssTransitions = function(el, transitions) {
		var css = {
				'-vendor-transition-property'			: [],
				'-vendor-transition-duration'			: [],
				'-vendor-transition-timing-function'	: []
			},
			p;
		
		for (p in transitions) {
			if (transitions.hasOwnProperty(p) && transitions[p]) {
				css['-vendor-transition-property'].push(p.toLowerCase());

				css['-vendor-transition-duration'].push((transitions[p].duration/1000).toFixed(3) + 's');
				css['-vendor-transition-timing-function'].push(transitions[p].timingFunction || 'ease');
			}
		}
		
		for (p in css) {
			if (css.hasOwnProperty(p)) {
				css[p] = css[p].join(', ');
			}
		}
		
		self.applyCss(el, css);
	};
	
	self.updateCssTransitions = function(el, transitionsToUpdate) {
		var transitions, p;
		if (transitionsToUpdate) {
			transitions = self.getCssTransitions(el);
			for (p in transitionsToUpdate) {
				if (transitionsToUpdate.hasOwnProperty(p)) {
					if (transitionsToUpdate[p]) {
						transitions[p] = transitionsToUpdate[p];
					}
					else {
						delete transitions[p];
					}
				}
			}
			self.setCssTransitions(el, transitions);
		}
	};
	
	
	self.addClass = function(el, classes) {
		var prev, i;
		if (classes) {
			if (!self.isArray(classes)) {
				classes = [classes];
			}
			prev = el.className || '';
			if (prev.length>0) {
				prev = ' ' + prev + ' ';
				for (i=0; i<classes.length; i++) {
					while (prev.indexOf(' '+classes[i]+' ')>-1) {
						prev = prev.replace(' ' + classes[i] + ' ', ' ');
					}
				}
				prev = prev.substring(1);
			}


			el.className = (prev + classes.join(' ')).replace(/\s+/gim,' ');
		}
	};
	
	self.removeClass = function(el, classes) {
		var prev, i;
		if (classes) {
			if (!self.isArray(classes)) {
				classes = [classes];
			}
			prev = el.className || '';
			if (prev.length>0) {
				prev = ' ' + prev + ' ';
				for (i=0; i<classes.length; i++) {
					while (prev.indexOf(' '+classes[i]+' ')>-1) {
						prev = prev.replace(' ' + classes[i] + ' ', ' ');
					}
				}
				prev = prev.substring(1);
			}
			el.className = prev.replace(/\s+/gim,' ');
		}
	};
	
	self.nodeStyle = function(node, property) {
		var dashed = (property+'').replace(/[A-Z]/g, '-$0').toLowerCase(),
			camelized,
			filter,
			s,
			style;
		
		dashed = dashed.replace(/^\-(moz|webkit|ms|o|vendor)\-/gim, vendorCssPrefix+'-');
		camelized = dashed.replace(/\-[a-z]/gim, function (s) {return s.substring(1).toUpperCase();});
		
		
		if (dashed==='opacity' && priv.support.filters) {

			return node.filters.alpha && node.filters.alpha.enabled!==false && Math.round(node.filters.alpha.opacity)/100;
		}
		
		if (node.style && node.style[camelized]) {
			style = node.style[camelized] || '';
		}
	
		else if (node.currentStyle && node.currentStyle[camelized]) {
			style = node.currentStyle[camelized] || node.currentStyle[dashed] || '';
		}
	
		else if (document.defaultView && document.defaultView.getComputedStyle) {
			s = document.defaultView.getComputedStyle(node, null);
			style = s && (s.getPropertyValue(dashed) || s.getPropertyValue(camelized)) || '';
		}
	
		else if (window.getComputedStyle) {
			s = window.getComputedStyle(node, null);
			style = s && (s.getPropertyValue(dashed) || s.getPropertyValue(camelized)) || '';
		}
		
		
		
		
		
		return style;
	};
	
	
	self.htmlEntities = function(str, stripTags) {
		var filters = ['htmlEntities'];
		if (stripTags===true) {
			filters.push('stripTags');
		}
		return self.text.filter(str, filters);
	};
	
	
	
	self.log = function() {
		var i,j,args;
		if (window.console && window.console.log) {
			try {
				window.console.log.apply(window.console, arguments);
			}catch(err){
				args = [];
				i = 'args[0]';
				for (j=1; j<arguments.length; j++) {
					args.push(arguments[j]);
					i += ',args['+j+']';
				}
				eval('window.console.log('+i+')');
			}
		}
	};
	
	
	
	self.addNodeSelectionPlugin = function(name, func) {
		if (!self.NodeSelection.prototype.hasOwnProperty(name)) {
			self.NodeSelection.prototype[name] = func;
		}
	};
	
	
	
	self.init = function() {
		if (!initialized) {
			initialized = true;


			
			self.fireEvent({
				target : document.body,
				type : "tinydomready",
				tinydom : self
			});
		}
	};
	self.addEvent(document, "DOMContentLoaded", self.init);
	self.addEvent(window, "load", self.init);
	self.addEvent(window, "unload", priv.unload);

	(function() {
		if (window._previousTinyDom) {
			for (var x in window._previousTinyDom) {
				if (window._previousTinyDom.hasOwnProperty(x)) {
					self[x] = window._previousTinyDom[x];
				}
			}
			window._previousTinyDom = null;
			try{ delete window._previousTinyDom; }catch(err){}		// cannot delete globals in IE
		}
	}());


	
	return self;
}());
window.tinydom = window.tinydom || {};

(function() {
	var util = {
		
		text : (function() {
			var base = function(){
					return base.filter.apply(this,arguments);
				},
				regexes = {
					htmlEntities : /[<>]/gim,
					ucWords : /(^|\s)[a-z]/gim,
					ucFirst : /^[a-z]/gim,
					nl2br : /\r?\n/g,
					numbersOnly : /[^0-9.-]/gim,
					linkify : /\b(http\:\/\/|https\:\/\/|www\.)[^\s\:\)\(\[\]\{\}\>"']+/gim,
					stripTags : /<\/?[a-z][a-z0-9]*(\s[^>]+)?\s*>/gim,
					trim : /^\s*?(.*?)\s*?$/gim
				};
			
			base.filter = function(str, filters) {
				var x, filter, ind, args, i;
				if (tinydom.typeOf(filters)!=='array') {
					filters = ((filters||'') + '').split('|');
				}
				if (arguments.length>2) {
					for (x=2; x<arguments.length; x++) {
						if (tinydom.typeOf(arguments[x])==='array') {
							filters = filters.concat(arguments[x]);
						}
						else {
							filters.push(arguments[x]);
						}
					}
				}
				for (x=0; x<filters.length; x++) {
					filter = filters[x];
					args = [str];
					ind = filter.indexOf(':');
					if (ind>-1) {
						filter = filter.substring(0, ind);
						args = args.concat(filters[x].substring(ind+1).split(','));
					}
					for (i in base) {
						if ((i+'').toLowerCase()===filter.toLowerCase()) {
							str = base[i].apply(base, args);
							break;
						}
					}
				}
				return str;
			};
			
			base.htmlEntities = function(str) {
				var map = {
					'<' : '&lt;',
					'>' : '&gt;'
				};
				return (str+'').replace(regexes.htmlEntities, function(s) {
					return map[s];
				});
			};
			
			base.ucWords = function(str) {
				return (str+'').toLowerCase().replace(regexes.ucWords, function(s) {
					return s.toUpperCase();
				});
			};
			
			base.ucFirst = function(str) {
				return (str+'').toLowerCase().replace(regexes.ucFirst, function(s) {
					return s.toUpperCase();
				});
			};
			
			base.nl2br = function(str) {
				return (str+'').replace(regexes.nl2br, '<br />');
			};
			
			base.numbersOnly = function(str) {
				return (str+'').replace(regexes.numbersOnly, '');
			};
			
			base.linkify = function(str, newWin) {
				str = (str+'').replace(regexes.linkify, function(s, b) {
					var attributes = '';
					if (s.substring(0,4).toLowerCase()==='www.') {
						s = 'http://' + s;
					}
					if (newWin!==false && newWin!=='false') {
						attributes += ' target="' + ((newWin!==false && newWin!=='false') ? '_blank' : newWin) + '"';
					}
					return '<a href="' + base.htmlEntities(s) + '"' + attributes + '>' + base.htmlEntities(s) + '</a>';
				});
				return str;
			};
			
			base.stripTags = function(str) {
				return (str+'').replace(regexes.stripTags, '');
			};
			
			
			base.truncate = function(str, maxLen, byWord, indicatorChars) {
				var trimmed = false,
					origStr = str+'';
				str = origStr;
				maxLen = parseInt(maxLen,10) || 80;
				byWord = byWord===true || byWord==='true' || byWord==='byWord';
				indicatorChars = indicatorChars || '...';
				if (str.length>maxLen) {
					if (byWord) {
						str = str.substring(0, maxLen);
						if (!origStr.charAt(maxLen).match(/\s/)) {
							str = str.replace(/\s[^\s]*$/,'');
						}
					}
					else {
						str = str.substring(0, maxLen-indicatorChars.length);
					}
					trimmed = true;
				}
				if (trimmed) {
					str += indicatorChars;
				}
				return str;
			};
			
			
			base.trim = function(str) {
				var ws,i;
				str = str.replace(/^\s\s*/, '');
				ws = /\s/;
				i = str.length;
				while (ws.test(str.charAt(--i)));
				return str.slice(0, i + 1);

			};
			
			return base;
		}()),
		
		url : {
			parse : function(url, config) {
				var parts, i, index, parsed, key, value;
				config = tinydom.extend({
					delimiter		: '&',
					startDelimiter	: '?',
					assignment		: '='
				}, config);
				parts = (/^(?:([a-z]+\:)\/\/([^\/]+)\/)?(?:([^\?\#]*))?(?:\?([^\#]*))?(?:\#(.*))?$/gim).exec(url);
				parsed = {
					href		: url,
					protocol	: parts[1],
					hostname	: parts[2],
					host		: parts[2],
					pathname	: parts[3],
					search		: parts[4] ? ('?'+parts[4]) : '',
					querystring	: parts[4],
					hash		: parts[5] ? ('#'+parts[5]) : '',
					hashValue	: parts[5]
				};
				if (parsed.querystring) {
					parts = parsed.querystring.split(config.delimiter);
					parsed.querystringParsed = {};
					for (i=0; i<parts.length; i++) {
						index = parts[i].indexOf(config.assignment);
						value = parts[i].substring(index+1) || '';
						if (value.match(/^\-?[0-9]$/gim)) {
							value = Math.round(value);
						}
						else if (value.match(/^\-?[0-9](\.[0-9])?$/gim)) {
							value = parseFloat(value);
						}
						else if (value.match(/^(true|false)$/gim)) {
							value = value.toLowerCase()==='true';
						}
						else if (value==='null') {
							value = null;
						}
						key = parts[i].substring(0,index);
						if (key.match(/\[\]$/)) {
							key = key.substring(0, key.length-2);
							if (!parsed.querystringParsed.hasOwnProperty(key)) {
								parsed.querystringParsed[key] = [];
							}
							else if (!tinydom.isArray(parsed.querystringParsed[key])) {
								parsed.querystringParsed[key] = [parsed[key]];
							}
							parsed.querystringParsed[key].push(value);
						}
						else {
							parsed.querystringParsed[key] = value;
						}
					}
				}
				return parsed;
			}
		},
		
		parameterize : function(obj, customConfig) {
			var t = "",
				key, value, x, type,
				config = this.extend({
					delimiter		: '&',
					startDelimiter	: '?',
					assignment		: '=',
					typeHandlers	: null
				}, customConfig);
			
			for (key in obj) {
				if (obj.hasOwnProperty(key)) {
					value = obj[key];
					type = this.typeOf(value);
					if (config.typeHandlers && config.typeHandlers.hasOwnProperty(type)) {
						t += config.delimiter + encodeURIComponent(key) + "[]=" + encodeURIComponent(config.typeHandlers[type](value));
					}
					else if (type==='array' && config.disableArrayParams!==true) {
						for (x=0; x<value.length; x++) {
							t += config.delimiter + encodeURIComponent(key) + "[]=" + encodeURIComponent(value[x]);
						}
					}
					else {
						switch (type) {
							case 'boolean':
								value = value ? 'true' : 'false';
								break;
							case 'null':
							case 'undefined':
								value = '';
								break;
							case 'object':
								if (config.useJsonForObjects!==false) {

									value = this.json(value);
								}
								else {

									value = this.parameterize(value);
								}
								break;
						}
						t += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(value);
					}
				}
			}
			if (t.substring(0, config.delimiter.length)===config.delimiter) {
				t = config.startDelimiter + t.substring(config.delimiter.length);
			}
			return t;

		},
		
		cookies : (function(){
			var cache = {};
			
			return {
				
				set : function (key, value, days, domain, path, secure) {
					var expires = '',
						cookie = '',
						date;
					path = typeof(path)==='string' ? path : '';
					if (days) {
						date = new Date();
						date.setTime(date.getTime() + days*24*60*60*1000);
						expires = "; expires="+date.toGMTString();
					}
					if(cache.hasOwnProperty(key) && cache[key].expires) {
						expires = "; expires="+cache[key].expires.toGMTString();
					}
					cookie = key + "=" + encodeURIComponent(value) + expires + "; path=/"+path.replace(/^\//,'');
					if (typeof(domain)==='string' && domain.length>0) {
						cookie += '; domain=' + domain.replace(/[\;\,]/,'');
					}
					if (secure===true) {
						cookie += '; secure';
					}

					document.cookie = cookie;
					cache[key] = {
						value : value,
						expires : date
					};
				},
				
				get : function (key, useCached) {
					if(cache.hasOwnProperty(key) && useCached!==true) {
						return cache[key].value;
					}
					var c, i, ca = document.cookie.split(';');
					for (i=0; i<ca.length; i++) {
						c = ca[i].replace(/^\s+/gim,'');
						if (c.indexOf(key+"=")===0) {
							return decodeURIComponent(c.substring(key.length+1,c.length));
						}
					}
					return null;
				},
				
				remove	: function (key) {
					this.set(key, "", -1);
					delete cache[key];
				},
				
				purge	: function () {
					for (var x in cache) {
						if(cache.hasOwnProperty(x)) {
							this.remove(x);
							delete cache[x];
						}
					}
				},
				
				read : function() {
					return this.get.apply(this,arguments);
				},
				
				write : function() {
					return this.set.apply(this,arguments);
				}
			};
		}()),
		
		json : (function() {
			
			var json = function(what) {
				if (tinydom.typeOf(what)==="string") {
					return json.parse(what);
				}
				return json.stringify(what);
			};
			
			json.stringify = json.serialize = function(what) {
				var result;
				try {
					result = JSON.stringify(what);
				}catch(err) {
					tinydom.log("tinydom.json:: Stringify failed: " + err + " | " + what);
				}
				return result;
			};
			
			json.parse = json.unserialize = function(what) {
				var result;
				if (typeof(what)==='string' && what.length>0) {
					try {
						result = JSON.parse(what);
					}catch(err) {
						tinydom.log("tinydom.json:: Parse failed: " + err + " | " + what);
					}
				}
				return result;
			};
			
			return json;
		}()),
		
		xml : {
			parse : function(xmlString) {
				var xmlDoc;
				if (window.DOMParser) {
					xmlDoc = new window.DOMParser().parseFromString(xmlString, "text/xml");
				}
				else {

					xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
					xmlDoc.async = "false";
					xmlDoc.loadXML(xmlString);
				}
				return xmlDoc;
			}
		}
		
	};

	for (var x in util) {
		if (util.hasOwnProperty(x)) {
			tinydom[x] = util[x];
		}
	}
	util = null;
}());window.tinydom = window.tinydom || {};


tinydom.EventEmitter = function EventEmitter(){
	this._eventRegistry = [];
};


tinydom.EventEmitter.prototype.addEventListener = function(type, handler) {
	var t, i;
	type = (type + '').toLowerCase().replace(/\s+/gim,'');
	if (type.indexOf(',')>-1) {
		t = type.split(',');
		for (i=0; i<t.length; i++) {
			this.addEventListener(t[i],handler);
		}
		return this;
	}
	type = type.replace(/^on/,'');
	this._eventRegistry.push({
		type : type,
		handler : handler
	});
	return this;
};
tinydom.EventEmitter.prototype.addListener = tinydom.EventEmitter.prototype.addEventListener;
tinydom.EventEmitter.prototype.on = tinydom.EventEmitter.prototype.addEventListener;



tinydom.EventEmitter.prototype.removeEventListener = function(type, handler) {
	var x, r, t, i;
	type = (type + '').toLowerCase().replace(/\s+/gim,'');
	if (type.indexOf(',')>-1) {
		t = type.split(',');
		for (i=0; i<t.length; i++) {
			this.removeEventListener(t[i],handler);
		}
		return this;
	}
	type = type.replace(/^on/,'');
	for (x=this._eventRegistry.length; x--; ) {
		r = this._eventRegistry[x];
		if (r.type===type && r.handler===handler) {
			this._eventRegistry.splice(x, 1);
			break;
		}
	}
	return this;
};
tinydom.EventEmitter.prototype.removeListener = tinydom.EventEmitter.prototype.removeEventListener;



tinydom.EventEmitter.prototype._fireEvent = function(type, args) {
	var x, r, errors=[], rval, returns=[];
	type = (type+'').toLowerCase().replace(/^on/,'');
	if (!tinydom.isArray(args)) {
		args = [args];
	}
	for (x=this._eventRegistry.length; x--; ) {
		r = this._eventRegistry[x];
		if (r.type===type) {
			if (returns.length===0) {
				returns.falsy = returns.falsey = returns.truthy = true;
			}
			rval = r.handler.apply(this, args);
			returns.push(rval);
			if (rval===true) {
				returns.falsy = returns.falsey = false;
			}
			else if (rval===false) {
				returns.truthy = false;
			}








			if (rval===false) {
				break;
			}
		}
	}





	errors = null;
	return returns;
};

window.tinydom = window.tinydom || {};


tinydom.date = {
	
	now : (
		Date.now ? function() {
			return Date.now();
		} : function() {
			return +new Date();
		}
	),
	
	create : function(str) {
		var date;
		if (str) {
			str = (str+'').replace(/^([0-9]{4})\-([0-9]{2})\-([0-9]{2})T([0-9]{2})\:([0-9]{2})\:([0-9]{2})\.[0-9]{3}Z$/, '$1/$2/$3 $4:$5:$6');
			date = new Date(str);
		}
		else {
			date = new Date();
		}
		return date;
	},
	
	
	parse : function(str, format) {
		format = format || "%d/%m/%Y";
		function setHours(hours, pm) {
			if (pm===false || pm===true) {
				temp.pm = pm===true;
			}
			if (hours || hours===0) {
				temp.hours = hours;
			}
			hours = temp.hours;
			if (temp.hours<12 && temp.pm) {
				hours -= 12;
			}
			var i = rdate.getDate();
			if (temp.hours===12 && temp.pm===false) {
				if (rdate.getHours()!==0 || pm===!!pm) {
					rdate.setHours(0);

				}
			}
			else {
				rdate.setHours(hours);
				rdate.setDate(i);
			}
		}
		var rdate = new Date(0),
			temp = {},
			weekdays = ['mo','tu','we','th','fr','sa','su'],
			replacers = {
				H : [/^[0-9]{1,2}/g, function(e){e=Math.round(e);setHours(e);}],
				I : [/^[0-9]{1,2}/g, function(e){e=Math.round(e);setHours(e);}],
				p : [/^[AP]M/gi, function(e){setHours(null, e.toLowerCase()==="pm");}],
				M : [/^[0-9]{1,2}/g, function(e){rdate.setMinutes(Math.round(e));}],
				a : [/^(Mon|Tue(s?)|Wed|Thu|Fri|Sat|Sun)/i, function(){}],									// dummy
				A : [/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)/i, function(){}],			// dummy


				d : [/^[0-9]{1,2}/g, function(e){temp.date=Math.round(e);rdate.setDate(temp.date);}],
				m : [/^[0-9]{1,2}/g, function(e){temp.month=Math.round(e)-1;rdate.setMonth(temp.month);}],
				B : [new RegExp('^('+this.months.join("|")+')','gi'), function(e){temp.month=date._getMonthIndex(e);rdate.setMonth(temp.month);}],
				b : [/^(Jan|Feb|Mar|Apr|May|Jun(e?)|Jul(y?)|Aug|Sep(t?)|Oct|Nov|Dec)/gi, function(e){temp.month=date._getMonthIndex(e);rdate.setMonth(temp.month);}],
				y : [/^[0-9]{2}/g, function(e){e=Math.round(e)+1900;if(e<1950){e+=100;}rdate.setFullYear(e);}],		// wrap 2-digit dates at 1950/2050
				Y : [/^[0-9]{4}/g, function(e){rdate.setFullYear(Math.round(e));}]
			},
			index, rep, r;
		replacers.l = replacers.I;
		replacers.e = replacers.d;
		replacers.P = replacers.p;
		replacers.h = replacers.b;
		
		for (index=0; index<format.length; index++) {
			if (format.charAt(index)==="%") {
				rep = null;
				for (r in replacers) {
					if (replacers.hasOwnProperty(r) && format.substring(index+1, index+1+r.length)===r) {
						rep = replacers[r];
						str = str.replace(rep[0], function(e){rep[1](e);return '';});
						index += rep.length-1;		// advance past the used symbol in format str
						break;
					}
				}
				if (!rep) {

					index += 1;
				}
			}
			else {
				if (str.charAt(0)===format.charAt(index)) {
					str = str.substring(1);
				}
			}
		}
		
		if (temp.month || temp.month===0) {
			rdate.setMonth(temp.month);
		}
		
		return rdate;
	},
	unformat : function(){return this.parse.apply(this,arguments);},
	
	
	format : function(date, format) {
		format = format || "%d/%m/%Y";
		
		if (!date || date.constructor!==Date || !date.toDateString) {
			return false;
		}
		
		var dateStr = date.toDateString();
		if (!dateStr || dateStr.toLowerCase()==="invalid date") {
			return false;
		}


		
		var dateParts = dateStr.split(" "),
			hours = date.getHours(),
			hv = ((hours+11)%12)+1,
			m = date.getMonth()+1,
			replacers = {
				H : hours,						// 24 hour time
				I : (hv<10?"0":"") + hv,		// 12 hour time, leading 0
				l : hv,							// 12 hour time
				p : hours>11?"PM":"AM",
				P : hours>11?"pm":"am",
				M : (date.getMinutes()<10?"0":"") + date.getMinutes(),
				S : (date.getSeconds()<10?"0":"") + date.getSeconds(),		// seconds
				a : dateParts[0],
				A : this.weekdays[date.getDay()],
				d : dateParts[2],
				e : Math.round(dateParts[2]),
				m : (m<10?"0":"") + m,
				B : this.months[Math.round(dateParts[1])],
				b : dateParts[1],
				h : dateParts[1],
				y : dateParts[3].substring(2),
				Y : dateParts[3]
			};
		
		return format.replace(/%[HIlpPMSaAdemBbhyY]/gm, function(s) {
			var v = replacers[s.charAt(1)];
			return (v || v===0 || v===false) ? v : s;
		});
	},
	
	
	_getMonthIndex : function(m){
		m = m.substring(0,3).toLowerCase();
		for (var x=0; x<this.months.length; x++) {
			if (this.months[x].substring(0,3).toLowerCase()===m) {
				return x;
			}
		}
		return -1;
	},
	
	
	weekdays : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
	
	months : ["January","February","March","April","May","June","July","August","September","October","November","December"]
};window.tinydom = window.tinydom || {};

tinydom.net = {
	get : function(url, callback, options) {
		return this.request(tinydom.extend({
			url : url,
			type : "GET",
			callback : callback
		}, options || {}));
	},
	post : function(url, post, callback, options) {
		return this.request(tinydom.extend({
			url : url,
			type : "POST",
			post : post,
			callback : callback
		}, options || {}));
	},
	multiLoad : function(resources, callback) {
		if (!resources) {
			return false;
		}
		var cur = -1,
			max = resources.length,
			loaded,
			loadNext;
		
		loaded = function(result, data) {
			if (result && data) {
				var res = resources[cur],
					returnData;
				if (res.callback) {
					returnData = res.callback(data);
				}
				else if (res.process) {
					returnData = res.process(data);
				}
				if (returnData===undefined) {
					returnData = data;
				}
				if (callback) {
					callback(true, returnData, data);
				}

				loaded = loadNext = resources = null;
			}
			else {
				loadNext();
			}
		};
		
		loadNext = function() {
			cur += 1;
			var res = resources[cur];
			if (res) {
				http.get(res.url || res.file || res, loaded);
			}
			else {
				if (cur<max) {
					loadNext();
				}
				else {
					callback(false, null, null, "No resources were available.");
				}
			}
		};
		
		loadNext();
		
		return true;
	},
	request : function(options) {
		var opt, h, self;
		if (!options.url) {
			return false;
		}
		self = this;
		options = options || {};
		opt = {
			url			: options.url,
			type		: options.type || (options.post ? "POST" : "GET"),
			callback	: options.callback || function(){},
			post		: options.post,
			headers		: options.headers
		};
		if (options.contentTypeOverride) {
			opt.contentTypeOverride = options.contentTypeOverride;
			delete options.contentTypeOverride;
		}

		this.createXHR(opt.url, function(xhrCarrier) {
			opt.request = xhrCarrier.xhr;
			opt._xdrFrame = xhrCarrier.frame;
			xhrCarrier = null;
			
			if (opt.post && tinydom.typeOf(opt.post)==='object') {
				opt.post = tinydom.parameterize(opt.post);
				if (opt.post.substring(0,1)==='?') {
					opt.post = opt.post.substring(1);
				}
			}
			opt.request.onreadystatechange = function() {
				var contentType, data, i;

				if (opt.request._orig) {
					opt.request.readyState = opt.request._orig.readyState;
					opt.request.status = opt.request._orig.status;
					opt.request.responseText = opt.request._orig.responseText;
					opt.request.responseXML = opt.request._orig.responseXML;
				}
				
				if (opt.request.readyState===4) {


					if (opt._xdrFrame) {
						setTimeout(function() {
							
							self._freeIframes.push(opt._xdrFrame);
							self = null;
						}, 100);
					}
					
					opt.status = opt.request.status;
					if (opt.contentTypeOverride) {
						contentType = opt.contentTypeOverride.toLowerCase();
					}
					else {
						try {
							contentType = (opt.request.getResponseHeader("Content-Type")).toLowerCase();
						} catch(err) {}
						contentType = contentType || "";
					}
					opt.responseText = opt.request.responseText;
					
					if (contentType.match(/\/(json|javascript)$/gm) || contentType==="json") {
						opt.responseType = "json";
						data = opt.responseJSON = null;
						try {
							data = opt.responseJSON = JSON.parse(opt.request.responseText.replace(/^[^\[\{]*(.*)[^\[\{]*$/g,'$1'));
						}catch(jsonParseError){
							opt.jsonParseError = true;
						}
					}
					else if (contentType==="application/xml" || contentType==="xml") {
						opt.responseType = "xml";
						data = opt.responseXML = opt.request.responseXML;
					}
					else {
						opt.responseType = "text";
						data = opt.responseText;
					}
					
					if (opt.callback) {
						opt.callback(opt.request.status<300, data);
					}
				}
			};
			opt.request.open(opt.type, opt.url, opt.async!==false);
			opt.request.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
			if (opt.headers) {
				for (h in opt.headers) {
					if (opt.headers.hasOwnProperty(h)) {
						try {
							opt.request.setRequestHeader(h, opt.headers[h]);
						} catch(err) {}
					}
				}
			}
			opt.request.send(opt.post || null);
		});
		return opt;
	},
	
	_freeIframes : [],
	_xhrIndex : 0,
	createXHR : function(url, callback) {
		var isCrossDomain = false,
			self = this,
			domain, frame, xhr, _loadHandler, timer;
		this._xhrIndex += 1;
		if (url) {
			domain = (/^[a-z]{3,9}\:\/\/([^\/\?#]+)/gim).exec(url);
			domain = domain && domain[1];
			if (domain && domain!==location.hostname) {
				isCrossDomain = true;
				document.domain = location.hostname.match(/[^.]+\.[^.]+$/gim)[0];
				frame = this._freeIframes.length>0 && this._freeIframes.splice(0,1)[0];
				if (frame) {

					callback(self._createXHRObj(frame.contentWindow, frame));
				}
				else {

					frame = document.createElement('iframe');
					frame.style.cssText = "position:absolute; left:0; top:-1000px; width:1px; height:1px; border:none; overflow:hidden;";
					_loadHandler = function() {
						var win, body;
						try {
							win = frame.contentWindow;
							body = win && win.document && win.document.domain===document.domain && win.document.body;
						}catch(err){
							body = null;
						}
						if (body && body.innerHTML) {
							clearInterval(timer);
							frame.onload = frame.onerror = null;
							callback(self._createXHRObj(win, frame));
							self = callback = xhr = frame = domain = _loadHandler = timer = null;
						}
					};
					frame.onload = frame.onerror = _loadHandler;
					frame.setAttribute('src', location.protocol+'//'+domain+'/xd_receiver.html');
					document.body.appendChild(frame);
					timer = setInterval(_loadHandler, 50);
				}
			}
		}

		if (!isCrossDomain) {
			xhr = this._createXHRObj();
			callback(xhr);
			return xhr;
		}
	},
	_createXHRObj : function(win, frame) {
		var xmlHttp;
		win = win || window;
		
		try {
			xmlHttp = new win.XMLHttpRequest();
		} catch(err) {
			try {
				xmlHttp = new win.ActiveXObject("Msxml2.XMLHTTP");
			} catch(err2) {
				xmlHttp = new win.ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		
		return {
			xhr : xmlHttp,
			frame : frame
		};
	},
	
	jsonp : (function() {
		var jsonp = function() {
				return jsonp.get.apply(jsonp, arguments);
			},
			reqIndex = 0;
		
		
		jsonp.get = function(url, options, callback) {
			var script, requestObj, callbackId, tmp;
			
			if (tinydom.typeOf(options)==='function') {
				if (callback && util.typeOf(callback)==='object') {
					tmp = callback;
				}
				callback = options;
				if (tmp) {
					options = tmp;
				}
			}
			options = options || {};
			if (options.callback && !callback) {
				callback = options.callback;
			}
			if (!options.timeout) {
				options.timeout = 10;
			}
			
			if (!url && !options.url) {
				return false;
			}
			reqIndex += 1;
			
			options.callback = callbackId = "tinydom_net_jsonp_"+reqIndex;
			(function(jsonp, reqIndex) {
				window[options.callback] = function(data) {

					if (callback) {
						callback(data);
						callback = null;
					}

					if (requestObj) {
						requestObj.stop();
						requestObj = null;
					}
				};
			}());

			
			if (!url) {
				url = options.url;
			}
			if (url.indexOf('{!callback}')>-1) {
				url = url.replace('{!callback}', callbackId);
			}
			else {
				url += (url.indexOf('?')<0?'?':'&') + encodeURIComponent(options.callbackParam || 'callback') + '=' + encodeURIComponent(callbackId);
			}
			
			if (!this._head) {
				tmp = document.getElementsByTagName('head');
				this._head = tmp && tmp[0];
			}
			
			script = tinydom.el({
				type : 'script',
				attributes : {
					src		: url,
					async	: 'async',
					type	: 'text/javascript'
				},

				parent : this._head || document.body
			});
			
			requestObj = {
				id : callbackId,
				stop : function() {
					if (requestObj._timer) {
						clearTimeout(requestObj._timer);
					}
					window[callbackId] = null;
					try {
						delete window[callbackId];
					}catch(err){}
					callback = null;
					script.attr('src', 'about:blank').remove();
					callbackId = requestObj = script = null;
				}
			};
			
			if (options.timeout && options.timeout>0) {
				requestObj._timer = setTimeout(function() {
					if (callback) {
						callback({
							_requestTimedOut : true,
							_jsonpTimedout : true,
							success : false,
							result : false
						});
					}
					if (requestObj) {
						requestObj.stop();
					}
				}, Math.round(options.timeout*1000));
			}
			
			url = options = tmp = null;
			
			return requestObj;
		};
		
		return jsonp;
	}())
};
window.tinydom = window.tinydom || {};



tinydom.NativeAPI = function(api) {
	var self = (this.constructor===arguments.callee ? this : api) || {},		
		priv = {},
		globalParameters = {},
		authParameters = {},
		getQueryStringFromObj,
		shallowObjectCopy,
		isArray,
		objConstructor = ({}).constructor,
		createApiMethod,
		NativeAPIMethod,
		MessageStringWithData,
		createNativeAPIResponse,
		emptyFunc = function(){},
		log;
	
	log = function(text) {
		if (window.console && window.console.log) {
			window.console.log(text);
		}
	};
	
	
	getQueryStringFromObj = function (obj) {
		var querystring = "",
			x, i;
		for (x in obj) {
			if (obj[x]!==null && obj[x]!==undefined && obj[x].constructor!==Function && obj[x].constructor!==objConstructor && obj[x].constructor!==Array) {
				querystring += "&" + encodeURIComponent(x) + "=" + encodeURIComponent(obj[x]);
			}
			else if (obj[x] && isArray(obj[x])) {
				for (i=0; i<obj[x]; i++) {
					querystring += "&" + encodeURIComponent(x) + "[]=" + encodeURIComponent(obj[x]);
				}
			}
		}
		return querystring;
	};
	
	shallowObjectCopy = function(base, args) {
		var i, p, obj;
		for (i=1; i<arguments.length; i++) {
			obj = arguments[i];
			for (p in obj) {
				if (obj.hasOwnProperty(p)) {
					base[p] = obj[p];
				}
			}
		}
		return base;
	};
	
	isArray = function(what) {
		return Object.prototype.toString.apply(what)==="[object Array]";
	};
	
	NativeAPIMethod = function NativeAPIMethod(){};
	
	self.MessageStringWithData = MessageStringWithData = function MessageStringWithData(data, message){
		this.message = message || '';
		shallowObjectCopy(this, data);
	};
	MessageStringWithData.prototype.toString = MessageStringWithData.prototype.toSource = function(){
		return this.message;
	};
	
	createNativeAPIResponse = function(data, originalResponse) {
		var response;
		if (tinydom.isArray(data.data) && data.data.length===0) {
			data.data = {};
		}
		
		function NativeAPIResponse(){}
		shallowObjectCopy(NativeAPIResponse.prototype, {
			getData : function() {
				return tinydom.extend({}, this);
			},
			getResponse : function() {
				return this.constructor.prototype._originalResponse;
			},
			_originalResponse : originalResponse
		});
		
		response = new NativeAPIResponse();
		shallowObjectCopy(response, data);
		return (function() {
			data = response = originalResponse = NativeAPIResponse = null;
			return arguments[0];
		}(response));
	}
	
	self.setGlobalParameter = function (key, value) {
		if (value===undefined || arguments.length<2) {
			delete globalParameters[key];
		}
		else {
			globalParameters[key] = value;
		}
	};
	
	self.setAuthParameter = function (key, value) {
		if (value===undefined || arguments.length<2) {
			delete authParameters[key];
		}
		else {
			authParameters[key] = value;
		}
	};
	
	
	
	
	priv.validateParameters = function(options, method) {
		var requiredParams, name, p, pType, errorType, inputField, error,
			response = {
				errors : [],
				message : ''
			},
			baseErrorMessage = {
				nativeApiError : true,
				clientSideError : true
			};
		
		if (method.parameters) {
			requiredParams = {};
			for (name in method.parameters) {
				if (method.parameters.hasOwnProperty(name)) {
					p = method.parameters[name];
					pType = tinydom.typeOf(p);

					if (pType==='function' && p.name) {
						pType = 'string';
						p = p.name.toLowerCase();
					}
					else if (pType==='regexp' || p.constructor===RegExp) {
						pType = 'string';
						p = '/' + p.source + '/' + (p.global?'g':'') + (p.ignoreCase?'i':'') + (p.multiline?'m':'');
					}

					if (pType==='string') {
						if (p.substring(0,1)==='/') {
							p = (/^\/(.*?)\/([gim]*?)$/gim).exec(p);
							requiredParams[name] = {
								validate : 'regex',
								against : new RegExp(p[1] || '', p[2] || '')
							};
						}
						else {
							requiredParams[name] = {
								validate : 'type',
								against : p.toLowerCase()
							};
						}
					}
				}
			}
		}

		if (requiredParams) {
			for (name in requiredParams) {
				if (requiredParams.hasOwnProperty(name)) {
					pType = requiredParams[name].validate;
					p = requiredParams[name].against;
					inputField = options[name];
					error = null;
					if (!options.hasOwnProperty(name) || inputField===null || inputField===undefined || inputField==='') {
						error = {
							field : name,
							type : 'RequiredError',
							message : name + ' is required'
						}
					}
					else if (pType==='regex' && !(p.lastIndex=0) && !p.test(inputField+'')) {
						error = {
							field : name,
							type : 'ValidationError',
							message : name + ' is invalid'
						};
					}
					else if (pType==='type' && p!==tinydom.typeOf(inputField)) {
						error = {
							field : name,
							type : 'TypeError',
							message : name + ' is invalid'
						};
					}
					if (error) {
						error.missingParameter = error.field;
						response.message += (response.message.length>0?', ':'') + error.message + ' ('+error.type+')';
						response.errors.push(tinydom.extend(error, baseErrorMessage));
					}












				}
			}
		}

		
		response.failed = response.errors.length>0;
		return response;
	};
	
	
	
	createApiMethod = function(subject, action, method) {
		self[subject][action] = function (options) {
			var validationResponse = priv.validateParameters(options=options||{}, method),
				callback, req, type, querystring, x, i,
				funcs, postData, requestParameters,
				isLongPolling = method.longPolling===true || (method.allowLongPolling===true && options.longPolling===true),
				optionsHasLongPollingProperty = options.hasOwnProperty('longPolling'),
				optionsLongPollingProperty = options.longPolling;


			if (validationResponse.failed) {
				log("api."+subject+"."+action+": Errors: " + validationResponse.message, 9);

				options.callback(false, validationResponse.errors[0], validationResponse.errors);
				return false;
			}

			callback = function callback(json, extraData) {
				var success = json && (json[api.statusProperty || 'success']===true || json[api.statusProperty || 'success']===1),			// The response.success property MUST be Boolean TRUE or Integer 1  <---
					data = json.data || json || null,
					message = json.errorMessage || json.message || null,
					sval = json[api.statusProperty || 'success'],
					optionsLongPollingRef,
					enhancedMessage;

				extraData = extraData || {};
				extraData.apiMethod = method.endpoint;
				
				if (method.verifyResult) {
					success = method.verifyResult(json);
				}
				else if ((sval!==true && sval!==false && sval!==0 && sval!==1) || (json.constructor!==objConstructor && !isArray(json))) {
					success = (json.constructor===objConstructor || isArray(json)) ? true : false;
					data = json;
					message = null;
				}

				if (isLongPolling) {

					if (success && json.timedout===true) {

						optionsLongPollingRef = options;
						
						setTimeout(function() {
							self[subject][action](optionsLongPollingRef);
							callback = optionsLongPollingRef = success = json = data = message = sval = null;
						}, 1);

						return true;
					}
				}

				data = createNativeAPIResponse(data, json, extraData);
				enhancedMessage = new MessageStringWithData(json, message);
				
				if (extraData.parseError===true) {
					success = false;
					data = data.message || data;
					if (api.onParseError) {
						api.onParseError(json, extraData);
					}
				}
				
				(method.onbeforecomplete || method.onBeforeComplete || method.precallback || emptyFunc)(success, success===true?data:enhancedMessage, json);
				if (success===true) {
					(options.onsuccess || method.onsuccess || emptyFunc).call(api.endpoints[subject][action], data, json);
				}
				else {
					(options.onerror || method.onerror || emptyFunc).call(api.endpoints[subject][action], message, data, json);
				}
				(options.oncomplete || options.callback || emptyFunc).call(api.endpoints[subject][action], success,success===true?data:enhancedMessage, json);
				(method.oncomplete || method.onComplete || method.callback || emptyFunc)(success, success===true?data:enhancedMessage, json);
				if (api.onRequestCompleted) {
					api.onRequestCompleted(subject+'.'+action, data, success, requestParameters, options);
				}
				callback = req = type = querystring = x = i = funcs = postData = requestParameters = isLongPolling = optionsHasLongPollingProperty = optionsLongPollingProperty = enhancedMessage = null;
				options = p = null;
			};//-callback

			type = method.type && method.type.toLowerCase() || "";
			querystring = method.endpoint;
			if (method.formatSuffix) {
				querystring += method.formatSuffix;
			}
			else if (api.formatSuffix) {
				querystring += api.formatSuffix;
			}
			if (!querystring.match(/^(http|https|ftp)\:/)) {
				querystring = api.root + querystring;
			}
			
			if (isLongPolling) {
				options.longPolling = null;
				try{ delete options.longPolling; }catch(err){}
				options.timeout = options.timeout || method.longPollingTimeout || self.longPollingTimeout || 60;
			}

			switch (type) {
				case "xdr":
					log("Cross-domain requests are not yet supported.", 7);
					break;
				
				case "post":
					funcs = {};
					for (i in options) {
						if (options.hasOwnProperty(i) && Object.prototype.toString.apply(options[i])==="[object Function]") {
							funcs[i] = options[i];
							options[i] = null;
							try{ delete options[i]; }catch(err2){}
						}
					}
					requestParameters = postData = shallowObjectCopy(
						{},
						globalParameters,
						method.auth===true ? authParameters : {},
						method.defaultParameters || {},
						options
					);
					for (i in funcs) {
						if (funcs.hasOwnProperty(i)) {
							options[i] = funcs[i];
						}
					}
					funcs = null;

					tinydom.net.request({
						url : querystring,
						type : "POST",
						post : postData,
						callback : function(success, response) {
							if (success && response) {
								callback(response);
							}
							else {
								if (this.jsonParseError===true) {
									callback({status:false, message:"Unable to parse server response", rawdata:this.responseText}, {parseError:true, clientsideErrorDetection:true});
								}
								else {
									callback({status:false, message:"Connection error "+this.status}, {clientsideErrorDetection:true});
								}
							}
						},
						contentTypeOverride : 'application/json'
					});
					break;
				
				case "jsonp":

					requestParameters = shallowObjectCopy(
						{},
						globalParameters,
						method.auth===true ? authParameters : {},
						method.defaultParameters || {},
						options
					);
					querystring += getQueryStringFromObj(requestParameters);

					if (querystring.indexOf("?")===-1 || querystring.indexOf("?")>querystring.indexOf("&")) {
						querystring = querystring.replace("&","?");
					}


					req = tinydom.net.jsonp(querystring, callback);
					break;
				
				case "get":
				default:

					requestParameters = shallowObjectCopy(
						{},
						globalParameters,
						method.auth===true ? authParameters : {},
						method.defaultParameters || {},
						options
					);
					querystring += getQueryStringFromObj(requestParameters);

					if (querystring.indexOf("?")===-1 || querystring.indexOf("?")>querystring.indexOf("&")) {
						querystring = querystring.replace("&","?");
					}

					tinydom.net.request({
						url : querystring,
						type : "GET",
						callback : function(success, response) {
							if (success && response) {
								callback(response);
							}
							else {
								if (this.jsonParseError===true) {
									callback({status:false, message:"Unable to parse server response", rawdata:this.responseText}, {parseError:true, clientsideErrorDetection:true});
								}
								else {
									callback({status:false, message:"Connection error "+this.status}, {clientsideErrorDetection:true});
								}
							}
						},
						contentTypeOverride : 'application/json'
					});
					break;
			}
			
			if (optionsHasLongPollingProperty) {
				options.longPolling = optionsLongPollingProperty;
			}
			
			return req;
		};
	};
	
	
	if (self.constructor===({}).constructor) {
		self = (function(obj) {
			function NativeAPI(){}
			for (var i in obj) {
				if (obj.hasOwnProperty(i)) {
					NativeAPI.prototype[i] = obj[i];
				}
			}
			return new NativeAPI();
		}(self));
	}
	
	
	var subject, action;
	for (subject in api.endpoints) {
		if (api.endpoints.hasOwnProperty(subject)) {
			self[subject] = new NativeAPIMethod();
			for (action in api.endpoints[subject]) {
				if (api.endpoints[subject].hasOwnProperty(action)) {
					createApiMethod(subject, action, api.endpoints[subject][action]);
				}
			}
		}
	}
	
	if (self.globalParameters) {
		for (var o in self.globalParameters) {
			if (self.globalParameters.hasOwnProperty(o)) {
				self.setGlobalParameter(o, self.globalParameters[o]);
			}
		}
	}
	
	if (this.constructor!==arguments.callee) {
		return self;
	}
};
tinydom.StateManager = function(adaptor, options) {
	var x;
	if (tinydom.typeOf(adaptor)==='object' && !options) {
		options = adaptor;
		adaptor = options.adaptor;
	}
	options = options || {};
	
	this.initialized = false;
	this.objects = {};
	this.states = {};
	
	if (!adaptor || !this.adaptors[adaptor]) {
		adaptor = this.defaultAdaptor;
	}
	this.adaptor = tinydom.extend({}, this.adaptors.none, this.adaptors[adaptor], {
		stateManager : this
	});
	if (this.adaptor.init) {
		this.adaptor.init(tinydom.extend({}, options.adaptorOptions || {}, {
			adaptor : adaptor
		}), this);
	}
	
	if (options.state) {
		this.adaptor.setState(options.state);
		this.restoreFromState(options.state);
	}
	
	if (options.objects) {
		for (x in options.objects) {
			this.addObject(x, options.objects[x]);
		}
	}
};
tinydom.extend(tinydom.StateManager.prototype, {
	
	
	saveQueueDelay : 50,
	
	
	adaptors : {
		session : {
			getState : function(callback){
				callback(this.state);
			},
			setState : function(state, callback){
				this.state = state;
				callback(true);
			},
			state : {}
		},
		base : {
			getState : function(cb) {
				throw(new Error("StateManager:: getState method not defined for the specified adaptor."));
				cb({});
			},
			setState : function(s,cb) {
				throw(new Error("StateManager:: setState method not defined for the specified adaptor."));
				cb(true);
			}
		}
	},
	
	objects : {},
	states : {},
	initialized : false,
	
	init : function(options) {
		if (this.initialized===true) {
			return this;
		}
		options = options || {};
		if (options.state) {
			this.adaptor.setState(options.state);
			this.restoreFromState(options.state);
		}
		if (options.objects) {
			for (x in options.objects) {
				this.addObject(x, options.objects[x]);
			}
		}
		this.initialized = true;
		if (options.restore!==false) {
			this.restore();
		}
		
		this.startPolling();
		
		return this;
	},
	
	destroy : function() {
		this.stopPolling();
		
		this.adaptor.stateManager = null;
		this.adaptor = this.states = this.objects = null;
		this.initialized = false;
	},
	
	emptyFunc : function(){},
	
	startPolling : function() {
		if (this.adaptor && this.adaptor.startPolling) {
			this.adaptor.startPolling();
		}
	},
	
	stopPolling : function() {
		if (this.adaptor && this.adaptor.stopPolling) {
			this.adaptor.stopPolling();
		}
	},
	
	addObject : function(id, obj, callback) {
		var stateManager;
		if (this.objects.hasOwnProperty(id)) {
			throw(new Error("Cannot add duplicate object ID '"+id+"' to state list."));
			if (callback) {
				callback(false);
			}
		}
		else {
			stateManager = this;
			this.objects[id] = obj;
			this.states[id] = {};
			
			obj.updateState = function(stateUpdates, callback, now) {
				stateManager.setObjState(id, tinydom.extend(
					{},
					stateManager.getObjState(id),
					stateUpdates
				), callback || stateManager.emptyFunc, now);
			};
			
			obj.setState = function(state, callback, now) {
				stateManager.setObjState(id, state, callback || stateManager.emptyFunc, now);
			};
			
			obj.getState = function() {
				return stateManager.getObjState(id);
			};
			
			obj.destroyStateManagerConnections = function() {
				this.updateState = this.setState = this.getState = this.destroyStateManagerConnections = stateManager.emptyFunc;
				stateManager = null;
				
			};
			
			obj = null;

			if (this.initialized===true) {
				this.restoreOne(id, function() {

				});
			}
		}
		return this;
	},
	addObj : function(){ return this.addObject.apply(this,arguments); },
	
	removeObject : function(id, callback) {
		if (this.objects.hasOwnProperty(id)) {
			if (this.objects[id].destroyStateManagerConnections) {
				this.objects[id].destroyStateManagerConnections();
			}
			this.objects[id] = null;
			this.states[id] = null;
			try {
				delete this.objects[id];
				delete this.states[id];
			}catch(err){}
			this.save(callback);
		}
	},
	removeObj : function(){ return this.removeObject.apply(this,arguments); },
	
	restoreFromState : function(state, callback, andSave) {
		var self=this, cb, id, total=0, count=0;
		if (callback) {
			cb = function() {

				count += 1;
				if (count>=total) {
					if (andSave!==false) {
						self.save(function(state) {
							if (callback) {
								callback(true);
							}
							self = callback = null;
						});
					}
					else {
						if (callback) {
							callback(true);
						}
						self = callback = null;
					}
				}
			};
		}
		else {
			cb = function(){};
		}
		if (tinydom.typeOf(state)==='string') {
			state = tinydom.json(state);
		}

			for (id in this.objects) {
				if ( this.objects[id].restoreState) {
					total += 1;

					this.objects[id].restoreState(state[id]);
					cb();
				}
			}

		if (total===0) {
			if (callback) {
				callback(false);
			}
			self = callback = null;
		}
		return this;
	},

	disableSave : function() {

		this._saveDisabled = true;
	},
	enableSave : function() {


		this._saveDisabled = false;
	},
	
	
	restoreOne : function(id, callback) {
		var self = this;
		this.adaptor.getState(function(state) {
			if ( self.objects[id] && self.objects[id].restoreState) {
				self.objects[id].restoreState(state[id]);
			}
			self = null;
			if (callback) {
				callback();
			}
		});
	},
	
	restore : function(callback) {

		var self = this;
		this._restoring = true;

		this.adaptor.getState(function(state) {

			var newCurrentState = state && tinydom.json(state);

			if (newCurrentState && newCurrentState!==self.currentState) {
				self.currentState = newCurrentState;
				self.restoreFromState(state, function() {
					self._restoring = false;
					if (callback) {
						callback();
					}
					self = null;
				}, false);
			}
			else {
				self.save(function() {
					self._restoring = false;
					self = null;
					if (callback) {
						callback(false);
					}
					callback = null;
				});
			}
		});
		return this;
	},
	
	save : function(callback, now) {
		var self = this;
		if (this.initialized===true  && !this._saveDisabled) {
			if (now===true) {
				if (this.currentSaveTimer) {
					clearTimeout(this.currentSaveTimer);
					delete this.currentSaveTimer;
				}

				this.getStateObj(function(state) {
					var newCurrentState = tinydom.json(state);
					if (newCurrentState!==self.currentState) {
						self.currentState = newCurrentState;
						self.adaptor.setState(state, function(success) {
							self = null;
							if (callback && tinydom.typeOf(callback)==='function') {
								callback(!!success);
							}
							callback = null;
						});
					}
					else if (callback && tinydom.typeOf(callback)==='function') {
						callback();
						callback = null;
					}
				});
			}
			else if (!this.currentSaveTimer) {
				this.currentSaveTimer = setTimeout(function() {
					self.save(callback, true);
					delete self.currentSaveTimer;
					self = callback = null;
				}, this.saveQueueDelay);
			}
		}
		return this;
	},
	
	setObjState : function(id, state, callback, now) {

		this.states[id] = state;
		this.save(callback, now);
	},
	
	getObjState : function(id, state) {
		this.states[id] = state;
	},
	
	getStateObj : function(callback) {
		if (callback) {
			callback(this.states);
		}
		return this;
	},
	
	emptyFunc : function(){}
	
	
	
	
});



tinydom.StateManager.prototype.adaptors.url = {
	init : function(options) {
		var self = this,
			_doPoll = this._doPoll,
			_doPollTimed = this._doPollTimed;
		this._doPoll = function() {
			return _doPoll.apply(self,arguments);
		};
		this._doPollTimed = function() {
			return _doPollTimed.apply(self,arguments);
		};
		
		this.usePreceedingSlash = options.usePreceedingSlash!==false;
		this.urlMapping = options.urlMapping;
		this.urlHistory = [];
		if (options.html5UrlPrefix) {
			this.html5UrlPrefix = options.html5UrlPrefix;
		}
		if (options.beforeParse) {
			this.beforeParse = options.beforeParse;
		}
		if (options.beforeCommit) {
			this.beforeCommit = options.beforeCommit;
		}
	},
	
	getPrefix : function() {
		if (this.html5UrlPrefix) {
			if (typeof(this.html5UrlPrefix)==='function') {
				return this.html5UrlPrefix();
			}
			else {
				return this.html5UrlPrefix;
			}
		}
		return '';
	},
	
	
	pollInterval : 30,
	
	
	urlHistory : [],
	
	
	startPolling : function() {
		if (!this.polling) {

			this.polling = true;
			this.getCurrentUrl(true);
			this.pollingTimer = setTimeout(this._doPollTimed, this.getPollInterval());
			tinydom.addEvent(window, 'hashchange,pushstate,popstate', this._doPoll);
		}
	},
	
	
	stopPolling : function() {

		clearTimeout(this.pollingTimer);
		tinydom.removeEvent(window, 'hashchange,pushstate,popstate', this._doPoll);
		this.polling = false;
	},
	
	getPollInterval : function() {
		return this.stateManager && (this.stateManager.pollInterval || this.stateManager.adaptorPollInterval) || this.pollInterval;
	},
	
	
	_doPoll : function() {
		var self = this,		// arguments.callee._self || 
			currentUrl = self.currentUrl || null,
			url = self.getCurrentUrl(true) || null;
		if (url!==currentUrl) {

			var startTime = new Date().getTime();
			self.stateManager.disableSave();
			self.stateManager.restore(function() {
				self.stateManager.enableSave();
				self = currentUrl = url = null;
				
			});
		}
	},
	_doPollTimed : function() {
		this._doPoll.apply(this,arguments);
		if (this.pollingTimer) {
			clearTimeout(this.pollingTimer);
		}
		if (this.polling) {
			this.pollingTimer = setTimeout(this._doPollTimed, this.getPollInterval());
		}
	},
	
	normalizeUrl : function(url) {
		return (this.usePreceedingSlash?'/':'') + url.replace(/^[#!\/]+/gm,'').replace(/#.+$/gm,'');
	},
	
	
	getCurrentUrl : function(andSave) {
		var url = location.href + '',
			crunchbangIndex = url.indexOf('#!'),
			index = url.indexOf(location.host+'/');
		if (crunchbangIndex>-1) {
			url = url.substring(crunchbangIndex+2);
			if (window.history.replaceState) {
				window.history.replaceState(null, null, url);
			}
		}
		else if (index>-1) {

			url = url.substring(index+location.host.length+1);
		}
		else {
			url = null;
		}
		
		if (url) {
			url = this.normalizeUrl(url);
		}




		
		
		if (andSave===true) {
			if (url!==this.currentUrl && this.urlHistory[this.urlHistory.length-1]!==url) {
				this.urlHistory.push(url);
			}
			this.currentUrl = url;
		}
		return url || false;
	},
	
	setCurrentUrl : function(url, replace) {
		var currentUrl = this.getCurrentUrl(false),
			crunchedUrl,
			stateObj,
			isCurrentHistoryEntry;
		
		url = this.normalizeUrl(url);
		crunchedUrl = '#!' + url;
		isCurrentHistoryEntry = this.urlHistory.length>0 && this.urlHistory[this.urlHistory.length-1]===url;


		if (url!==currentUrl && !isCurrentHistoryEntry) {

			
			if (window.history.pushState ) {

				if (url.substring(0,1)!=='/') {
					url = '/' + url;
				}
				url = this.getPrefix() + url;
				if (this.beforeCommit) {
					url = this.beforeCommit(url) || url;
				}


				if (replace===true && window.history.replaceState) {
					window.history.replaceState(null, null, url);
				}
				else {
					window.history.pushState(null, null, url);
				}
			}
			else {


				if (window.location.href!==crunchedUrl) {
					if (replace===true && window.location.replace) {
						window.location.replace(crunchedUrl);
					}
					else {
						window.location.href = crunchedUrl;
					}
				}
			}

			this.getCurrentUrl(true);
		}
	},
	
	
	setState : function(state, callback) {
		var url = location.href + '',
			index = url.indexOf('#!'),
			stateUrl,
			currentUrl = this.getCurrentUrl(false);
		
		stateUrl = this.stringify(state);
		
		this.setCurrentUrl(stateUrl);

		
		callback(true);
	},
	
	
	getState : function(callback) {
		var url = this.getCurrentUrl(true),
			state;
		if (url) {
			state = this.parse(url);
			callback(state);
		}
		else {
			callback(false);
		}

	},
	
	
	parse : function(str) {
		var obj = {},
			a, prefix, parts, x, y, index, key, value, encodedValue, levelKey, level, mappedUrl, mappedUrlIndex,
			isArrayKey, autoConvertValue;
		
		isArrayKey = function(key) {
			return !!key.match(/^\-?[0-9]+$/);

		};
		
		
		autoConvertValue = function(value) {
			if (value==='undefined') {
				value = undefined;
			}
			else if (value==='null') {
				value = null;
			}
			else if (value.match(/^\-?[0-9]+$/)) {			// int
				value = parseInt(value,10);
			}
			else if (value.match(/^\-?[0-9\.]+$/)) {		// float
				value = parseFloat(value);
			}
			else if (value.match(/^(true|false)$/i)) {		// boolean
				value = value.toLowerCase()==='true';
			}
			else if (value.match(/^\[[a-z0-9%_\-]+(,[a-z0-9%_\-]+)*\]$/)) {
				value = value.substring(1, value.length-1).split(',');
				for (var x=0; x<value.length; x++) {
					value[x] = autoConvertValue(value[x]);
				}
			}
			return value;
		};
		
		if (this.beforeParse) {
			a = this.beforeParse(str);
			if (a || a==='') {
				str = a;
			}
		}
		
		prefix = this.getPrefix();

		if (prefix && str.substring(0,prefix.length)===prefix) {
			str = str.substring(prefix.length);
		}
		if (this.usePreceedingSlash!==false && str.charAt(0)==='/') {
			str = str.substring(1);
		}



		mappedUrlIndex = str.indexOf('?');
		if (mappedUrlIndex===-1 && str.indexOf('=')===-1) {

			mappedUrlIndex = str.length;
		}
		if (this.urlMapping && mappedUrlIndex>0) {
			mappedUrl = str.substring(0, mappedUrlIndex);
			str = encodeURIComponent(this.urlMapping) + '=' + encodeURIComponent(mappedUrl) + '&' + str.substring(mappedUrlIndex+1);
		}
		if (str.substring(0,1)==='?') {
			str = str.substring(1);
		}
		
		parts = str.split('&');
		for (x=0; x<parts.length; x++) {
			index = parts[x].indexOf('=');
			key = decodeURIComponent(parts[x].substring(0, index));
			encodedValue = decodeURIComponent(parts[x].substring(index+1));
			value = decodeURIComponent(encodedValue);

			if (key.match(/\[\]$/g)) {
				key = key.substring(0, key.length-2);
				value = value.split(',');
				for (y=0; y<value.length; y++) {
					value[y] = decodeURIComponent(value[y]);
				}
			}
			else {

				value = autoConvertValue(value);
			}

			key = key.split('.');
			level = obj;
			for (y=0; y<key.length; y++) {
				levelKey = key[y];
				if (isArrayKey(levelKey)) {

					levelKey = parseInt(levelKey.replace(/[^0-9]/,''),10);
				}
				
				if (y<key.length-1) {

					if (!level[levelKey]) {

						if (isArrayKey(key[y+1])) {
							level[levelKey] = [];
						}
						else {
							level[levelKey] = {};
						}
					}

					level = level[levelKey];
				}
				else {

					level[levelKey] = value;
				}
			}


		}

		
		return obj;
	},
	
	
	stringify : function(obj) {
		var str = '',
			p,
			serialize,
			mappedUrl = '',
			urlMapping = this.urlMapping;
		
		serialize = function(obj, id) {
			var p, isSimpleArray;
			switch (tinydom.typeOf(obj)) {

				case 'object':
					for (p in obj) {
						if (obj.hasOwnProperty(p)) {
							serialize(obj[p], (id?(id+'.'):'') + p);
						}
					}
					break;

				case 'array':
					isSimpleArray = true;
					for (p=0; p<obj.length; p++) {
						t = tinydom.typeOf(obj[p]);
						if (t!=='string' && t!=='number' && t!=='boolean') {
							isSimpleArray = false;
						}
					}
					if (isSimpleArray) {
						str += '&' + encodeURIComponent(id) + '[]=';
						for (p=0; p<obj.length; p++) {
							str += (p>0?',':'') + encodeURIComponent(obj[p]);
						}

					}
					else {
						for (p=0; p<obj.length; p++) {
							serialize(obj[p], (id?(id+'.'):'') + p);

						}
					}
					break;

				case 'null':
				case 'undefined':
				case 'function':
					break;
				default:
					if (urlMapping && id===urlMapping) {
						mappedUrl = obj;
					}
					else {
						str += '&' + encodeURIComponent(id) + '=' + encodeURIComponent(obj);
					}

			}
		};
		
		
		
		serialize(obj);
		serialize = obj = null;
		if (str.substring(0,1)==='&') {
			str = '?' + str.substring(1);
		}

		if (this.usePreceedingSlash!==false && mappedUrl.charAt(0)!=='/') {
			mappedUrl = '/' + mappedUrl;
		}
		
		return mappedUrl + str;
	}
};




tinydom.StateManager.prototype.adaptors.urlbasic = {
	setState : function(state, callback) {
		var url = location.href + '',
			index = url.indexOf('#!');

		if (index>-1) {
			url = url.substring(0, index);
		}
		url += '#!' + this.serializeState(state);
		location.href = url;
		callback(true);
	},
	
	getState : function(callback) {
		var url = location.href + '',
			index = url.indexOf('#!'),
			state;
		if (index>-1) {
			url = url.substring(index+2);
			state = tinydom.json.parse(url);
			callback(state);
		}
		else {
			callback(false);
		}

	},
	
	serializeState : function(state) {
		return tinydom.json.stringify(state);
	}
};




tinydom.StateManager.prototype.adaptors.cookies = {
	init : function(options) {
		options = options || {};
		this.dbName = options.dbName || 'state';
	},
	
	setState : function(state, callback) {
		tinydom.cookies.set(this.dbName, tinydom.json.stringify(state));
		callback(true);
	},
	
	getState : function(callback) {
		var state = tinydom.cookies.get(this.dbName);
		state = tinydom.json.parse(state);
		callback(state);
	},
	
	serializeState : function(state) {
		return tinydom.json.stringify(state);
	}
};


tinydom.ControllerManager = function(options) {
	tinydom.EventEmitter.call(this);
	
	this.controllerOptions = tinydom.extend({}, this.controllerOptions);
	this._messageListeners = [];
	this._controllers = [];
	this._current = null;
	
	if (options) {
		if (options.instanceId) {
			this.instanceId = options.instanceId;
		}
		if (options.controllerOptions) {
			tinydom.extend(this.controllerOptions, options.controllerOptions);
		}
		if (tinydom.typeOf(options.singular)==='boolean') {
			this.singular = options.singular;
		}
		if (tinydom.typeOf(options.allowLoadDefault)==='boolean') {
			this.allowLoadDefault = options.allowLoadDefault;
		}
	}
};

tinydom.extend(tinydom.ControllerManager.prototype, {
	
	controllerOptions : {},
	
	restoreState : function(state) {
		if (this.initialized!==true) {
			this._initState = state;
		}
		else {
			if (state && state.current) {
				this.load(state.current);
			}
			else {
				this.loadDefault();
			}
		}
	},
	
	doStateUpdate : function(state) {
		if (this.updateState) {
			this.updateState(state);
		}
	},
	
	init : function(options) {
		var autoRestore = true;

		if (this.initialized!==true) {
			this.initialized = true;
			if (options) {
				if (options.controllerOptions) {
					tinydom.extend(this.controllerOptions, options.controllerOptions);
				}
				if (tinydom.typeOf(options.singular)==='boolean') {
					this.singular = options.singular;
				}
				if (tinydom.typeOf(options.allowLoadDefault)==='boolean') {
					this.allowLoadDefault = options.allowLoadDefault;
				}
				if (options.autoRestoreOnInit===false) {
					autoRestore = false;
				}
			}
			if (this._initState && autoRestore) {
				this.restoreState(this._initState);
			}
			this._initState = null;
			try {
				delete this._initState;
			}catch(err){}
			if (this.allowLoadDefault!==false && !this.current()) {
				this.loadDefault();
			}
		}
	},
	
	destroy : function() {
		var current, x;

		try {
			current = this.current();
			if (current) {
				if (current.unload) {
					current.unload();
				}
			}
			for (x=this._controllers.length; x--; ) {
				if (this._controllers[x].destroy) {
					this._controllers[x].destroy();
				}
			}
		}catch(err){}
		this.controllerOptions = {};
		this._controllers = [];
		this._messageListeners = [];
		this._current = null;
	},
	
	register : function(name, controller) {
		controller = controller || {};
		if (tinydom.typeOf(name)==='string') {
			controller.name = name;
		}
		else {
			controller = name;
		}
		this._controllers.push(controller);
		this._fireEvent('add', [this.getIdFromName(controller.name)]);
	},
	load : function(name, options) {
		var sandboxController, previousController, params, newController, eventResponse, response, loadResponse;
		
		name = (name+'').toLowerCase();
		previousController = this.singular===true && this.current();
		
		if (previousController && previousController.name.toLowerCase()===name) {
			if (previousController.handleRepeatLoad) {
				previousController.handleRepeatLoad(options || {});
			}
			return true;
		}



		
		sandboxController = this._createControllerSandbox(name);
		params = tinydom.extend({
				previousController : previousController
			}, 
			this.controllerOptions || {}, 
			options || {},
			sandboxController.sandbox
		);
		newController = name && this.get(name);
		
		if (newController) {



			tinydom.extend(newController, sandboxController.sandbox);
			if (this.singular===true) {
				this._unloadCurrent();
			}
			
			response = newController;
			if (newController.load) {
				eventResponse = this._fireEvent('beforeload', [newController.name]);

				if (eventResponse===false || (eventResponse.falsey && !eventResponse.truthy)) {
					return false;
				}
				loadResponse = newController.load(params);
				if (loadResponse!==null && loadResponse!==undefined) {
					response = loadResponse;
				}
			}

			if (loadResponse===false) {
				eventResponse = this._fireEvent('loadcancel', [newController.name]);
				if (eventResponse===false || (eventResponse.falsey && !eventResponse.truthy)) {
					return false;
				}
				if (this.singular===true && params.previousController) {
					this.load(params.previousController.name, options);
				}
				else {
					this.loadDefault(options);
				}
			}
			else {
				this._current = this.getIdFromName(name);
				this._fireEvent('load', [name]);
				this._fireEvent('change', [name]);
				this.doStateUpdate({
					current : name
				});
			}
			return response;
		}
		return false;
	},
	loadDefault : function(options) {
		for (var x=this._controllers.length; x--; ) {
			if (this._controllers[x].isDefault===true) {
				return this.load(this._controllers[x].name, options);
			}
		}
		return false;
	},
	
	loadPrevious : function(options) {
		if (this._previousController) {
			this.load(this._previousController, options);
		}
	},
	none : function() {
		this._unloadCurrent();
	},
	_unloadCurrent : function() {
		var current = this.current(),
			time;
		if (current && current.unload) {
			this._fireEvent('beforeunload', [current.name]);

			current.unload();




			this._fireEvent('unload', [current.name]);
			this._current = null;
		}
	},
	get : function(name, returnIndex) {
		name = (name+'').toLowerCase();
		for (var x=this._controllers.length; x--; ) {
			if (this._controllers[x].name.toLowerCase()===name) {
				return returnIndex===true ? x : this._controllers[x];
			}
		}
		return false;
	},
	postMessage : function(type, msgObj) {
		var current = this.current();
		if (current && current.onmessage) {


			current.onmessage(type, msgObj);
			return true;
		}
		return false;
	},
	onMessage : function(type, handler, controller) {
		var obj = {
			type : (type+'').toLowerCase().replace(/^on/gim,''),
			handler : handler
		};
		if (controller) {
			if (tinydom.typeOf(controller)==='string') {
				obj.controller = controller.toLowerCase();
			}
			else if (controller.hasOwnProperty('name')) {
				obj.controller = (controller.name + '').toLowerCase();
			}
		}
		this._messageListeners.push(obj);
	},
	
	getList : function(properties) {
		var map = [],
			i, j, ob;
		properties = (properties || []);
		for (i=0; i<this._controllers.length; i++) {
			ob = {
				name : this._controllers[i].name
			};
			for (j=0; j<properties.length; j++) {
				ob[properties[j]] = this._controllers[i][properties[j]];
			}
			map.push(ob);
		}
		return map;
	},
	getIdFromName : function(name) {
		return this.get(name, true);
	},
	getNameFromId : function(id) {
		var controller = tinydom.typeOf(id)==='number' && this._controllers[id];
		return controller && controller.name || false;
	},
	current : function() {
		return tinydom.typeOf(this._current)==='number' && this._controllers[this._current] || false;
	},
	
	
	_createControllerSandbox : function(name) {
		var controllerManager = this,
			sandbox,
			sandboxController,
			muted = false,
			throwListenerControllerError;
		
		name = (name + '').toLowerCase();
		
		
		throwListenerControllerError = function(listener, error) {
			var customError = new Error(
				'Listener error encountered in ControllerManager#sandbox.postMessage() :: ' + error.message,
				error.fileName,
				error.lineNumber
			);
			setTimeout(function() {
				throw(customError);
				error = customError = listener = null;
			}, 10);
		};
		
		
		sandbox = {
			controllerManager : controllerManager,
			manager : controllerManager,
			postMessage : function(type, msgObj) {
				var listener, x;
				msgObj = tinydom.extend({}, msgObj, {
					controller	: name,
					type		: (type + '').replace(/^on/gim,'')
				});
				if (!muted) {
					controllerManager._fireEvent('message', msgObj);
					controllerManager._fireEvent(msgObj.type, msgObj);
					for (var x=0; x<controllerManager._messageListeners.length; x++) {
						listener = controllerManager._messageListeners[x];
						if (!listener.controller || listener.controller===name.toLowerCase()) {
							try {
								listener.handler(msgObj);
							} catch(err) {
								throwListnerError(listener, err);
							}
						}
					}
				}
			}
		};
		
		
		sandboxController = {
			setName : function(newName) {
				name = (newName + '').toLowerCase();
			},
			mute : function() {
				muted = true;
			},
			unmute : function() {
				muted = false;
			},
			destroy : function() {
				for (var x in this.sandbox) {
					if (this.sandbox.hasOwnProperty(x)) {
						this.sandbox[x] = null;
					}
				}
				delete this.sandbox;
				controllerManager = null;
			},
			sandbox : sandbox
		};
		
		
		setTimeout(function() {
			sandboxController = sandbox = null;
		}, 1);
		
		return sandboxController;
	},
	_postMessageFromController : function(type, msgObj) {
	},
	
	_controllers : [],
	_messageListeners : [],
	_current : null
});


tinydom.inherits(tinydom.ControllerManager, tinydom.EventEmitter);

















window.tinydom = window.tinydom || {};


tinydom.LocalStorage = function LocalStorage(id, callback, options){
	var self = this;
	options = options || {};
	
	this.id = id;
	this.adapter = null;
	this.data = {};
	
	if (options.adapter) {
		this.setAdapter(options.adapter);
	}
	if (!this.adapter && options.useBest!==false) {
		this.useBestAdapter();
	}
	if (this.adapter && options.restore!==false) {
		this.restore(function() {
			if (callback) {
				callback(self);
			}
			self = options = null;
		});
	}
	else if (callback) {
		callback(self);
		self = null;
	}
};



tinydom.LocalStorage.prototype.commitDelay = 100;


tinydom.LocalStorage.prototype.data = {};



tinydom.LocalStorage.prototype.setAdapter = function(type) {
	var list = this.constructor.adapters,
		lcType = (type+'').toLowerCase(),
		found = false,
		i;
	for (i in list) {
		if (list.hasOwnProperty(i) && (i+'').toLowerCase()===lcType) {
			if (list[i].test(this)===true) {
				found = true;
				this.adapterName = type;
				this.adapter = list[i];
				break;
			}
		}
	}
	if (!found) {
		tinydom.log('tinydom.LocalStorage :: Could not find "'+type+'" adapter.');
		return false;
	}
	return true;
};


tinydom.LocalStorage.prototype.getAdapter = function() {
	return this.adapterName;
};


tinydom.LocalStorage.prototype.useBestAdapter = function() {
	var list = this.constructor.adapters,
		best, bestName, i;
	for (i in list) {
		if (list.hasOwnProperty(i) && list[i].test(this)===true) {
			if (!best || (Math.round(best.rating) || 0)<(Math.round(list[i].rating) || 0)) {
				best = list[i];
				bestName = i;
			}
		}
	}
	if (best) {
		this.adapterName = bestName;
		this.adapter = best;
	}
	else {
		setTimeout(function() {
			throw('tinydom.LocalStorage :: Could not find the best adapter.');
		}, 1);
		return false;
	}
	return true;
};


tinydom.LocalStorage.prototype.getNamespace = function(ns) {
	var self = this;
	ns = ns + '';
	if (ns.substring(0,1)==='.') {
		ns = ns.substring(1);
	}
	if (ns.substring(ns.length-1)==='.') {
		ns = ns.substring(0, ns.length-1);
	}
	return tinydom.extend(new tinydom.LocalStorage.NamespacedLocalStorage(), {
		getAdapter : function() {
			return self.getAdapter();
		},
		
		getNamespace : this.getNamespace,
		getValue : function(key) {
			return self.getValue(ns+'.'+key);
		},
		setValue : function(key, value) {
			self.setValue(ns+'.'+key, value);
			return this;
		},
		removeKey : function(key) {
			self.removeKey(ns+'.'+key);
			return this;
		},
		purge : function() {
			self.removeKey(ns);
			return this;
		},
		getData : function() {
			return self.getValue(ns);
		},
		restore : function(callback) {
			var proxiedCallback,
				proxiedContext = this;
			if (callback) {
				proxiedCallback = function() {
					callback(proxiedContext);
					proxiedContext = proxiedCallback = callback = null;
				};
			}
			self.restore(proxiedCallback);
			return this;
		},
		commit : function(callback) {
			var proxiedCallback,
				proxiedContext = this;
			if (callback) {
				proxiedCallback = function() {
					callback(proxiedContext);
					proxiedContext = proxiedCallback = callback = null;
				};
			}
			self.commit(proxiedCallback);
			return this;
		}
	});
};


tinydom.LocalStorage.prototype.getData = function() {
	return this.data;
};


tinydom.LocalStorage.prototype.getValue = function(key) {



	var value = tinydom.delve(this.data, key);

	return value;
};


tinydom.LocalStorage.prototype.setValue = function(key, value) {
	var node = this.data,
		keyParts = key.split('.'),
		i;

	for (i=0; i<keyParts.length-1; i++) {
		if (!node.hasOwnProperty(keyParts[i])) {
			node[keyParts[i]] = {};
		}
		node = node[keyParts[i]];
	}
	if (value===undefined || value===null) {
		node[keyParts[keyParts.length-1]] = null;
		delete node[keyParts[keyParts.length-1]];
	}
	else {
		node[keyParts[keyParts.length-1]] = value;
	}
	this.queueCommit();
	return this;
};


tinydom.LocalStorage.prototype.removeKey = function(key) {
	this.setValue(key, undefined);
	return this;
};


tinydom.LocalStorage.prototype.purge = function() {
	this.data = {};
	this.queueCommit();
	return this;
};


tinydom.LocalStorage.prototype.restore = function(callback) {
	var self = this,
		data, asyncData;
	data = this._adapterCall('load', function(r) {
		self.data = asyncData = r || {};
		if (callback) {
			callback(self);
		}
		self = null;
	});
	if (data && !asyncData) {
		this.data = data;
		if (callback) {
			callback(this);
		}
	}
	data = asyncData = null;
	return this;
};


tinydom.LocalStorage.prototype.commit = function(callback) {
	var self = this;
	if (this._commitTimer) {
		clearTimeout(this._commitTimer);
		this._commitTimer = null;
	}
	this._adapterCall('save', this.data, function() {
		if (callback) {
			callback(self);
		}
		self = null;
	});
	return this;
};


tinydom.LocalStorage.prototype.queueCommit = function() {
	var self = this;
	if (!this._commitTimer) {
		this._commitTimer = setTimeout(function() {
			self.commit();
			self = null;
		}, this.commitDelay);
	}
};


tinydom.LocalStorage.prototype._adapterCall = function(func, args) {
	if (this.adapter && this.adapter[func]) {
		return this.adapter[func].apply(this.adapter, [this].concat(tinydom.toArray(arguments).slice(1)));
	}
};








tinydom.LocalStorage.NamespacedLocalStorage = function(){};


tinydom.LocalStorage.adapters = {};


tinydom.LocalStorage.addAdapter = function(name, adapter) {
	if (!adapter.save) {
		throw('tinydom.LocalStorage :: Adapter "'+name+'" attempted to register, but does not provide a save() method.');
	}
	else  if (!adapter.load) {
		throw('tinydom.LocalStorage :: Adapter "'+name+'" attempted to register, but does not provide a load() method.');
	}
	else {
		this.adapters[name] = adapter;
	}
};








tinydom.LocalStorage.addAdapter('LocalStorage', {
	
	
	defaultName : 'db',
	
	
	rating : 60,
	
	
	test : function(storage) {
		var available = !!('localStorage' in window),
			prev,
			val = tinydom.json({a:'a',b:4/3,c:true,d:null});
		if (available) {
			try {
				prev = localStorage.__test;
				localStorage.__test = val;
				if (localStorage.__test!==val) {
					available = false;
				}
				localStorage.__test = prev;
				if (prev===undefined) {
					delete localStorage.__test;
				}
			} catch(err) {
				available = false;
			}
		}
		return available;
	},
	
	
	load : function(storage, callback) {
		var key = this._getKey(storage),
			data;
		if (localStorage.hasOwnProperty(key)) {
			data = tinydom.json.parse(localStorage[key]);
		}
		if (callback) {
			callback(data);
		}
		return data;
	},
	
	
	save : function(storage, data, callback) {
		var key = this._getKey(storage);
		if (data===undefined) {
			delete localStorage[key];
		}
		else {
			localStorage[key] = tinydom.json.stringify(data);
		}
		if (callback) {
			callback(true);
		}
		return true;
	},
	
	
	_getKey : function(storage) {
		return (storage.id || this.defaultName || '') + '';
	}
	
});tinydom.LocalStorage.addAdapter('cookie', {
	
	
	defaultName : 'db',
	
	
	rating : 0,
	
	
	test : function(storage) {
		if (tinydom.cookies && tinydom.cookies.get && ('cookie' in document)) {
			return true;
		}
		return false;
	},
	
	
	load : function(storage, callback) {
		var jsonStr = tinydom.cookies.get(storage.id || this.defaultName),
			obj;
		if (jsonStr) {
			obj = tinydom.json(jsonStr);
		}
		if (callback) {
			callback(obj);
		}
		return obj;
	},
	
	
	save : function(storage, data, callback) {
		tinydom.cookies.set(
			storage.id || this.defaultName,
			tinydom.json(data)
		);
		if (callback) {
			callback(true);
		}
	}
	
});tinydom.FormHandler = function(form, options) {
	options = options || {};
	if (arguments.length===1 && typeof(form)==='object' && form.constructor!==tinydom.NodeSelection) {
		options = form;
		form = options.form;
	}
	
	tinydom.EventEmitter.call(this);
	
	this._customTypes = [].concat(this._customTypes);
	if (form) {
		this.setForm(form);
	}
	if (options.enhance===true) {
		this.enhance();
	}
	if (options.data) {
		this.setData(options.data);
	}
	if (options.onsubmit && typeof(options.onsubmit)==='function') {
		this.on('submit', options.onsubmit);
		this._constructorSubmitHandler = options.onsubmit;
	}
	if (options.submitButton && options.submitButton.on) {
		options.submitButton.on('click', this._defaultSubmitButtonHandler);
		this._constructorSubmitButton = options.submitButton;
	}
};

tinydom.extend(tinydom.FormHandler.prototype, {
	
	errorMessageSelector : '.errorMessage, .generalForm_errorMessage',
	
	setForm : function(form) {
		var self = this;
		this.form = tinydom.el(form);
		
		if (!this.action) {
			this.action = this.form.attr('action');
		}
		if (!this.method) {
			this.method = this.form.attr('method');
		}

		tinydom.el({
			type : 'input',
			attributes : {
				type : 'submit'
			},
			css : 'position:absolute; left:0; top:-999em; width:1px; height:1px; font-size:1px; visibility:hidden;'
		}, this.form);
		
		
		this.form.on('submit', function(e) {
			self.submit();
			return tinydom.cancelEvent(e);
		});
		
		this._kill = function() {
			self = null;
		};
		
		return this;
	},
	
	enhance : function() {
		var self = this,
			fields = this._getFields();
		if (fields) {
			fields.each(function(input) {
				var customType = self._getCustomType(input);
				if (customType && customType.enhance) {
					customType.enhance(input);
				}
			});
		}
		self = fields = null;
		return this;
	},
	
	disable : function() {
		this.disabled = true;
		this._getFields().disable();
		return this;
	},
	
	enable : function() {
		this.disabled = false;
		this._getFields().enable();
		return this;
	},
	
	destroy : function() {
		var self = this,
			fields = this._getFields();
		if (fields) {
			fields.each(function(input) {
				var customType = self._getCustomType(input);
				if (customType && customType.destroy) {
					customType.destroy(input);
				}
			});
		}
		if (this._constructorSubmitHandler) {
			this.removeEventListener('submit', this._constructorSubmitHandler);
		}
		if (this._constructorSubmitButton) {
			this._constructorSubmitButton.removeEvent(this._defaultSubmitButtonHandler);
		}
		self = fields = null;
		return this;
	},
	
	clear : function() {
		this.setData({}, true);
		this.clearErrors();
		return this;
	},
	reset : function(){ return this.clear.apply(this,arguments); },
	
	submit : function() {
		var data, eventResponse;
		if (this.disabled===true) {
			tinydom.log('Notice: Not submitting disabled form.');
			return this;
		}
		this.clearErrors(false);
		data = this.getData();
		this._hasErrors = false;
		if (data) {
			eventResponse = this._fireEvent('submit', [data]);
		}
		else {
			eventResponse = this._fireEvent('submitfailed', [data]);
		}
		if (!this._hasErrors && (!eventResponse || eventResponse.falsy!==true)) {
			this.clearErrors();
		}
		return this;
	},
	
	clearErrors : function(clearMessage) {
		this._getFields().each(function(node) {
			node.parent().declassify('error');
		});
		if (clearMessage!==false) {
			this._hasErrors = false;
			this.form.query(this.errorMessageSelector).first().css({
				height : 0,
				opacity : 0
			}, {tween:'fast', callback:function(sel) {
				sel.hide();
			}});
		}
	},
	
	showFieldErrors : function(fields) {
		var self = this;
		
		this._hasErrors = true;

		
		tinydom.forEach(fields, function(value, key) {
			var message;
			self.form.query('[name='+key+']').focus().parent().classify('error');
			if (value.indexOf(' ')===-1) {
				value = tinydom.i18n(value.toUpperCase());
			}
			message = self.form.query(self.errorMessageSelector).first();
			message.html('<div class="formHandlerErrorMessage">'+value+'</div>');
			message.css({
				height : Math.round(message.prop('offsetHeight')) || 0,
				opacity : 0
			}).show().css({
				height : message.children().first().height()+'px',
				opacity : 1
			}, {tween:'medium'});
			return false;
		});
		
		self = null;
	},
	
	getData : function() {
		var data = null,
			self = this,
			fields = this._getFields();
		if (fields) {
			data = {};
			fields.each(function(input) {
				var name = input.attr('name');
				if (name) {
					data[name] = self._getInputValue(input);
				}
			});
		}
		self = fields = null;
		return data;
	},
	
	setData : function(data, includeMissing) {
		var touched = [],
			self = this,
			fields = this._getFields();
		if (data && fields) {
			fields.each(function(input) {
				var name = input.attr('name');
				if (data.hasOwnProperty(name)) {
					touched.push(name);
					self._setInputValue(input, data[name]);
				}
				else if (includeMissing===true) {
					self._setInputValue(input, null);
				}
			});
		}
		self = fields = null;
		return this;
	},
	
	
	addCustomType : function(typeDefinition) {
		var self = this,
			fields = this._getFields();

		this._customTypes.push(typeDefinition);

		if (fields && typeDefinition.enhance) {
			fields.each(function(input) {
				var customType = self._getCustomType(input);
				if (customType===typeDefinition) {
					customType.enhance(input);
				}
			});
		}
		
		self = fields = null;
		return this;
	},
	
	
	
	_getFields : function() {
		var fields = null;
		if (this.form) {
			fields = this.form.query('input,textarea,select');

		}
		return fields;
	},
	
	
	_setInputValue : function(el, value) {
		var customType = this._getCustomType(el);
		if (value===undefined || value===null) {
			value = '';
		}
		if (customType && customType.setValue) {
			customType.setValue(el, value);
		}
		else {
			el.value(value);
		}
		return this;
	},
	
	
	_getInputValue : function(el) {
		var customType = this._getCustomType(el);
		if (customType && customType.getValue) {
			return customType.getValue(el);
		}
		else {
			return el.value();
		}
	},
	
	
	_getCustomType : function(el) {
		var x, type, nodeName, customType;
		if (el.attr('customtype')) {
			type = (el.attr('customtype')+'').toLowerCase()
		}
		else if (el.attr('type')) {
			type = (el.attr('type')+'').toLowerCase()
		}
		nodeName = (el.prop('nodeName')+'').toLowerCase();
		for (x=0; x<this._customTypes.length; x++) {
			customType = this._customTypes[x];

			if ( (customType.types && this._arrayIndexNC(customType.types,type)>-1) 
				|| (customType.type && (customType.type+'').toLowerCase()===type)
				|| (customType.nodeNames && this._arrayIndexNC(customType.nodeNames,nodeName)>-1)
				|| (customType.nodeName && (customType.nodeName+'').toLowerCase()===nodeName) ) {
				return customType;
			}
		}
		return false;
	},
	
	
	_arrayIndexNC : function(arr, val) {
		val = (val + '').toLowerCase()
		for (var x=0; x<arr.length; x++) {
			if ((arr[x]+'').toLowerCase()===val) {
				return x;
			}
		}
		return -1;
	},
	
	
	_defaultSubmitButtonHandler : function(e) {
		var node = tinydom.el(this);
		do {
			if (node.nodeName()==='form') {
				node.submit();
				break;
			}
		} while((node=node.parent()).exists() && node.nodeName()!=='body')
		return tinydom.cancelEvent(e);
	},
	
	
	_customTypes : []
	
});


tinydom.inherits(tinydom.FormHandler, tinydom.EventEmitter);






tinydom.FormHandler.addCustomType = function(typeDefinition) {
	this.prototype._customTypes.push(typeDefinition);
};
(function(){  this.tinydom = this.tinydom || {}; }());


tinydom.Notifier = function(options) {
	var self = this;
	
	tinydom.EventEmitter.call(this);
	this._data = {
		counter : 0,
		list : {}
	};
	
	this._notificationClickHandler = function(e) {
		self._performAction(tinydom.el(this).attr('data-notification-id'), 'notificationclick', e);
		return tinydom.cancelEvent(e);
	};
	
	options = options || {};
	if (options.parent) {
		this._createBase(options.parent);
	}
};

tinydom.extend(tinydom.Notifier.prototype, {
	show : function(config) {
		var notify;
		if (config) {
			this._data.counter += 1;
			notify = {
				id : this._data.counter + '',
				timeout : config.timeout || this.timeout
			};
			this._data.list[notify.id] = notify;
			
			notify.base = this._build(notify.id, config);
			this._show(notify.id);
			
			if (notify.timeout) {
				this._resetTimeout(notify.id);
			}
			return notify;
		}
		return false;
	},
	
	_createBase : function(parent) {
		if (this.notifications_base) {
			this.notifications_base.remove();
			this.notifications_base.appendTo(parent);
		}
		else {
			this.notifications_base = tinydom.el({
				className : 'notifications_base'
			}, parent);
		}
	},
	
	_build : function(id, options) {
		var base, iconSrc;
		base = tinydom.el({
			className : "notification",
			css : 'height:0; opacity:0;',
			attributes : {
				'data-notification-id' : id
			},
			children : [
				{ className:'notification_top' },
				{
					className : 'notification_inner',
					children : [
						{ className:'notification_inner_top' },
						{
							className : 'notification_closeButton',
							children : [
								{ className:'label', innerHTML:this.closeButtonLabel || '&times;' }
							]
						},
						{
							className : 'notification_message',
							children : [
								{ className:'label', innerHTML:options.message || options.text }
							]
						},
						{ className:'notification_inner_bottom' }
					]
				},
				{ className:'notification_bottom' }
			],
			onclick : this._notificationClickHandler
		}, this.notifications_base);

		iconSrc = options.icon || options.image;
		if (iconSrc!==false && this.defaultIcon) {
			iconSrc = this.defaultIcon;
		}
		if (iconSrc) {
			tinydom.el({
				type : 'img',
				className : 'notification_message',
				attributes : {
					src : options.icon || options.image || this.defaultIcon
				}
			}, base.query('.notification_inner'));
		}
		
		if (options.userDismiss===false) {
			base.query('.notification_closeButton').hide(true);
		}
		
		return base;
	},
	
	_show : function(id) {
		var notify = this.get(id);
		if (notify) {
			notify.base.css({
				opacity : 0
			}).css({
				opacity : 1,
				height : notify.base.children().height()
			}, {tween:this.showTween || 'medium'});
		}
	},
	
	_hide : function(id) {
		var notify = this.get(id);
		if (notify) {
			notify.base.css({
				opacity : 0,
				height : 0
			}, {tween:this.hideTween || 'medium', callback:function() {
				notify.base.remove();
				notify = null;
			}});
		}
	},
	
	_resetTimeout : function(id) {
		var notify = this.get(id),
			self = this;
		if (notify) {
			if (notify._hideTimer) {
				clearTimeout(notify._hideTimer);
			}
			if (notify.timeout) {
				notify._hideTimer = setTimeout(function() {
					self._hide(id);
					self = id = null;
				}, notify.timeout*1000);
			}
			notify = null;
		}
	},
	
	
	get : function(id) {
		return id && this._data.list.hasOwnProperty(id+'') && this._data.list[id+''] || false;
	},
	
	_performAction : function(id, action, args) {
		var notify = this.get(id),
			ret;
		if (!tinydom.isArray(args)) {
			args = [args];
		}
		if (action && notify) {
			args = [id].concat(args);
			ret = this._fireEvent(action, args);
			if (ret!==false) {
				switch (action.toLowerCase()) {
					case 'notificationclick':
					case 'notificationclicked':
						this._hide(id);
						break;
				}
			}
		}
	},
	
	timeout : 15,
	
	_data : {
		counter : 0,
		list : {}
	}
});


tinydom.inherits(tinydom.Notifier, tinydom.EventEmitter);


window.tinydom = window.tinydom || {};


window.timber = tinydom.timber = {
	log : function() {
		this._message('Log', tinydom.toArray(arguments));
	},
	error : function() {
		this._message('Error', tinydom.toArray(arguments));
	},
	warn : function() {
		this._message('Warning', tinydom.toArray(arguments));
	},
	_message : function(type, args) {
		var message = type + " from " + location.hostname + " UI",
			message_type = type.toLowerCase(),
			obj = {
				log : args,
				env : {
					url : location.href,
					title : document.title,
					cookies : document.cookie,
					time : new Date()+'',
					timestamp : Date.now()
				}
			};
		if (args.length>1 && typeof(args[0])==='string') {
			message = obj.log.splice(0,1)[0];
		}
		tinydom.net.jsonp(location.protocol+'//timber.'+location.hostname.match(/([^\.]+\.[^\.]+)$/gm)[0]+'/api/logger/add' + tinydom.parameterize({
			message	: message,
			message_type : message_type,
			data	: tinydom.json(obj),
			app_id	: location.hostname
		}));
	}
};(function(){  this.tinydom = this.tinydom || {}; }());

tinydom.facebook = new tinydom.EventEmitter();

tinydom.extend(tinydom.facebook, {
	
	loginOptions : {

	},
	
	init : function(options, callback) {
		options = options || {};
		
		if (options.loginOptions) {
			tinydom.extend(this.loginOptions, options.loginOptions);
			options.loginOptions = null;
		}
		
		options = tinydom.extend({
			appId	: '',
			status	: false,
			cookie	: true,
			xfbml	: false,
			oauth: true,
			channelUrl: "http://socialseek.com/xd_facebook_receiver.html"
		}, options);
		
		console.log("FB OPT:", options);
	
		FB.init(options);
		
		if (callback) {
			setTimeout(callback, 10);
		}

	},
	
	
	query : function(query, callback) {
		tinydom.net.jsonp(location.protocol+'//api.facebook.com/method/fql.query?format=json&query='+encodeURIComponent(query), function(response) {
			if (response && tinydom.isArray(response)) {
				if (callback) {
					callback(response);
				}
			}
			else {
				if (callback) {
					callback(false);
				}
			}
		});
	},
	
	
	getLikeCount : function(url, callback) {
		url = url.replace(/(\\|")/gim,'\\$1');
		this.query('SELECT total_count,like_count FROM link_stat WHERE url="'+url+'"', function(result) {
			var ret = false;
			if (result && (result.hasOwnProperty('total_count') || result.hasOwnProperty('like_count'))) {
				ret = result.total_count || result.like_count;
			}
			if (callback) {
				callback(ret);
			}
		});
	},
	
	
	share : function(options, callback) {
		var self = this,
			hasRun = false;
		options = tinydom.extend({
			name : document.title,
			href	: location.href
		}, options || {});
		
		this.ensureLogin(function(isLoggedIn) {
			if (isLoggedIn) {
				var overlay, internalCallback;
				
				if (hasRun) {
					return true;
				}
				hasRun = true;
				
				overlay = tinydom.el({
					className : 'shim facebookBoxShim',
					onclick : function() {
						internalCallback(false, true);
					}
				}, document.body);
				
				
				internalCallback  = function(response, isCustomClose) {
					if (response && response.post_id) {
						self._log('Post '+response.post_id+' published.');
						self._fireEvent('postsuccess');
						if (callback) {
							callback(true, response.post_id);
						}
					}
					else {
						self._fireEvent('postfail');
						if (callback) {
							callback(false, 'Post was not published');
						}
					}
					if (isCustomClose && FB.Dialog._active) {
						FB.Dialog.remove(FB.Dialog._active);
					}
					
					overlay.fadeOut('medium', function(node) {
						overlay.destroy();
						overlay = null;
					}, true);
					
					self = options = internalCallback = callback = null;
				};
				
				overlay.fadeIn('medium', function() {
					FB.ui({
						method : 'stream.publish',

						name : options.name || options.title,
						message : options.message,	// || options.description || options.name,
						description : options.description || options.title || options.name,
						link : options.href,
						picture : options.picture || options.img || options.image || options.thumb

					}, internalCallback);
				});
			}
			else {
				if (callback) {
					callback(false, 'The user refused to log in.');
				}
				self = options = callback = null;
			}
		});
	},
	
	share_old : function(options, callback) {
		var self = this,
			hasRun = false;
		options = tinydom.extend({
			name : document.title,
			href	: location.href
		}, options || {});
		
		this.ensureLogin(function(isLoggedIn) {
			if (isLoggedIn) {
				var overlay, internalCallback, interval, lastOffsetTop, lastOffsetLeft;
				
				if (hasRun) {
					return true;
				}
				hasRun = true;
				
				overlay = tinydom.el({
					className : 'facebookBoxOverlay',
					children : [
						{
							className : 'facebookBoxOverlayBg',
							onclick : function() {
								internalCallback(false, true);
							}
						},
						{ className:'facebookBoxWrap', children:[
							{ className:'facebookBoxHolder', css:'visibility:hidden;' },
							{ className:'loadingIndicator', innerHTML:'Loading', css:'position:absolute;left:0;top:50%;width:100%;margin:-0.6em 0 0;font-size:130%;color:#999;text-align:center;' }
						]}
					]
				}, document.body);
				
				
				internalCallback  = function(response, isCustomClose) {
					if (response && response.post_id) {
						self._log('Post '+response.post_id+' published.');
						self._fireEvent('postsuccess');
						if (callback) {
							callback(true, response.post_id);
						}
					}
					else {
						self._fireEvent('postfail');
						if (callback) {
							callback(false, 'Post was not published');
						}
					}
					
					if (interval) {
						clearInterval(interval);
					}
					
					overlay.query('.facebookBoxHolder').hide(true);
					
					
					
					if (isCustomClose && FB.Dialog._active) {
						FB.Dialog.remove(FB.Dialog._active);
					}
					
					overlay.query('.facebookBoxWrap').declassify('customPosition').css({
						top : '50%',
						left : '50%'
					}).css({
						left : '-50%'
					}, {tween:'medium', callback:function(node) {
						overlay.query('.facebookBoxOverlayBg').fadeOut('medium', function(node) {
							overlay.destroy();
							overlay = null;
						}, true);
					}});
					
					self = fbDialog = options = internalCallback = callback = null;
				};
				
				
				
				interval = setInterval(function() {
					var d = FB.Dialog._active,
						offsetTop, offsetLeft;
					if (!overlay) {
						clearInterval(interval);
						return false;
					}
					if (d) {
						offsetTop = Math.round(d.offsetTop) || 0;
						offsetLeft = Math.round(d.offsetLeft) || 0;
						if (offsetTop!==lastOffsetTop || offsetLeft!==lastOffsetLeft) {
							lastOffsetTop = offsetTop;
							lastOffsetLeft = offsetLeft;
							overlay.query('.facebookBoxWrap').classify('customPosition').css({
								top : offsetTop + 'px',
								left : offsetLeft + 'px'
							});
							d.style.background = 'none';
						}
					}
				}, 50);
				
				
				
				overlay.query('.facebookBoxOverlayBg').fadeIn('medium', function(node) {
					overlay.query('.facebookBoxWrap').css({
						left : '50%'
					}, {tween:'medium', callback:function(node) {
						FB.ui({
							method : 'stream.publish',
							attachment : options
						}, internalCallback);


					}});
				});
			}
			else {
				if (callback) {
					callback(false, 'The user refused to log in.');
				}
				self = options = callback = null;
			}
		});
	},
	
	ensureLogin : function(callback) {
		var self = this;
		
		FB.getLoginStatus(function(response) {
			if (response && response.authResponse) {
				callback(true);
			}
			else {
				console.log(self.loginOptions);
				FB.login(function(response) {
					if (response && response.authResponse) {
						callback(true);
					}
					else {
						callback(false);
					}
				}, self.loginOptions);
			}
			self = null;
		});
	},
	
	_log : function(t) {
		if (window.console && window.console.log) {
			console.log('tinydom.facebook.log:: ', t);
		}
	}
	
	
});
(function(){  this.tinydom = this.tinydom || {}; }());

tinydom.twitter = new tinydom.EventEmitter();

tinydom.extend(tinydom.twitter, {
	
	counter : 0,
	
	init : function(options, callback) {
		var self = this;
		this._initOptions = tinydom.extend({
		}, options || {});
		
		if (options.callbackURL){
			twttr.anywhere.config({callbackURL : options.callbackURL});
		}
		
		
		twttr.anywhere(function(T) {
			T.bind('authComplete', function(e, user, bridge_code) {
				self._log(['twttr::authComplete', e, user, oauth_token]);
				self._fireEvent('authComplete', [e, user, bridge_code]);
			});
			
			if (callback) {
				callback();
			}
		});
	},
	
	share : function(options, callback) {
		var overlay,
			boxid;
		
		this.counter += 1;
		
		boxid = 'twttr_tweetbox_holder_'+this.counter;
		
		options = tinydom.extend({
			name : document.title,
			href	: location.href,
		}, options || {});
		options.defaultContent = options.text || options.status || options.update || options.message;
		if (!options.defaultContent) {
			options.defaultContent = tinydom.text.filter((options.name || ''),'truncate:'+(140-options.href.length-1)+',byWord') + ' ' + options.href
		}
		
		overlay = tinydom.el({
			className : 'tweetBoxOverlay',
			children : [
				{
					className : 'tweetBoxOverlayBg',
					onclick : function() {
						options.onTweet(false);
					}
				},
				{ className:'tweetBoxWrap', css:'visibility:hidden;', children:[
					{ className:'closeButton', onclick:function() {
						options.onTweet(false);
					} },
					{ className:'tweetBoxHolder', attributes:{id:boxid}, css:'display:none; position:relative; z-index:10; overflow:hidden;' },
					{ className:'loadingIndicator', innerHTML:'Connecting to Twitter...', css:'position:absolute;left:0;top:50%;width:100%;margin:-0.6em 0 0;font-size:150%;color:#999;text-align:center;z-index:5;' }
				]}
			]
		}, document.body);
		
		options.onTweet = function() {
			overlay.query('.tweetBoxHolder').hide(true);
			overlay.query('.tweetBoxWrap').fadeOut('medium', function(node) {
				overlay.query('.tweetBoxOverlayBg').fadeOut('medium', function(node) {
					overlay.destroy();
					overlay = options = null;
				}, true);
			}, true);
		};
		
		overlay.query('.tweetBoxOverlayBg').fadeIn('medium', function(node) {
			overlay.query('.tweetBoxWrap').fadeIn('medium', function(node) {
				overlay.query('.tweetBoxWrap').query('.tweetBoxHolder').show();
			});
		});
		
		
		
		
		
		
		
		function loadTweetBox() {
			twttr.anywhere(function() {
				twttr.anywhere(function(T) {
					frame = overlay.query('.tweetBoxHolder iframe');
					if (!frame.exists() || frame.height()<10) {

						T(overlay.query('.tweetBoxHolder')._nodes[0]).tweetBox(options);
					}
				});
			});
		}
		loadTweetBox();
		setTimeout(loadTweetBox, 1500);
	},
	
	
	
	_log : function(t) {
		if (window.console && window.console.log) {
			console.log('tinydom.twitter.log:: ', t);
		}
	}
});



tinydom.FormHandler.addCustomType({
	
	id : 'file',
	
	types : ['file','image'],
	
	objs : [],
	counter : 0,
	
	enhance : function(input) {
		var ui;
		this.counter += 1;
		input.attr('data-customInputType_file-origType', input.attr('type'))
		     .attr('data-customType','file')
		     .attr('type','url')
		     .attr('data-customInputType_file-id', this.counter+'-'+new Date().getTime());
		
		ui = tinydom.el({
			className : 'customInputType_file',
			css : 'overflow:hidden; display:inline-block; *display:table-cell;',
			children : [
				{
					type : 'iframe',
					attributes : {
						frameborder : '0'
					},
					css : 'position:absolute; left:0; top:0; width:100%; height:100%; z-index:10; opacity:0.01; cursor:pointer;'
				},
				{
					type : 'button',
					innerHTML : input.attr('data-label') || 'Upload...'
				}
			]
		});
		input.parent().insertBefore(ui, input.next());
		
		this.createObj(input, ui);
	},
	
	createObj : function(input, ui) {
		var obj = {
			input : input,
			ui : ui,
			resetFrame : function() {
				var win, doc, html, params, i, ind;
				
				this.stopLoading();
				
				win = this.ui.query('iframe').prop('contentWindow');
				doc = win.document;
				
				html = '<html><head><style type="text/css">html,body,form,input{position:absolute;margin:0;padding:0;right:0;top:0;width:100%;height:100%;display:block;overflow:hidden;cursor:pointer;}input{font-size:100px;}</style></head>';
				html += '<body><form id="form" action="'+this.input.attr('data-upload-action')+'" method="POST" enctype="multipart/form-data">';
				params = this.input.attr('data-upload-params');
				if (params) {
					params = params.split('&');
					for (i=0; i<params.length; i++) {
						ind = params[i].indexOf('=');
						if (ind>0) {
							html += '<input name="' + tinydom.text.filter(params[i].substring(0,ind),'htmlEntities')
								 + '" value="' + tinydom.text.filter(params[i].substring(ind+1),'htmlEntities')
								 + '" type="hidden" style="top:-999px;" />';
						}
					}
				}
				if (this.receiverUrl) {
					html += '<input type="hidden" name="'+tinydom.text.filter(this.input.attr('data-upload-receiver-param') || 'receiver','htmlEntities')+'" value="'+tinydom.text.filter(this.receiverUrl,'htmlEntities')+'" />';
				}
				html += '<input type="file" name="'+(this.input.attr('data-upload-name') || this.input.attr('name') || 'file')+'" onchange="document.forms[0].submit();if(window._doSubmit){window._doSubmit();}" /><input type="submit" style="top:-999px;" value="Upload" /></form></body></html>';
				
				doc.open();
				doc.write(html);
				doc.close();
				
				html = params = null;
				
				this.form = doc.forms[0];
				this.form.onsubmit = this.formSubmitHandler;
				win._doSubmit = this.formSubmitHandler;
			},
			init : function() {
				var self = this;
				
				this.receiverUrl = this.input.attr('data-xdr-receiver') || (location.protocol + '//' + location.host + '/');
				this.receiverParam = this.input.attr('data-upload-receiver-param') || null;
				
				this.formSubmitHandler = function() {
					self.form.submit = null;
					self.initialLoadingUrl = self.ui.query('iframe').prop('contentWindow').location.href;
					self.startLoading();
				};
				
				this.loadingTimerCallback = function() {
					var frame = self.ui.query('iframe'),
						win = frame.prop('contentWindow'),
						str, search;
					if (win && win.document && win.document.body && win.document.body.innerHTML && win.document.body.innerHTML.length>0 && win.document.body.innerHTML.match(/^\{.+\}/gim)) {
						self.uploadCallback(win.document.body.innerHTML);
					}


					else if (win && win.location && win.location.href && win.location.href.indexOf(self.receiverUrl)===0 && decodeURIComponent(win.location.href).match(/\{.+\}/gim)) {
						str = decodeURIComponent(win.location.href);
						search = str.match(/\{.+\}/gim);


						if (search && search[0]) {
							str = search[0];
						}
						else {
							str = str.substring(self.receiverUrl.length).replace(/^[?&#]+/gim,'');
						}
						self.uploadCallback(str);
					}
				};
				
				this._kill = function() {
					self = null;
				};
				
				this.resetFrame();
				
				obj = null;
				return this;
			},
			destroy : function() {
				this.clearLoadingTimer();
				
				this._kill();
				
				if (this.form) {

					this.form.onsubmit = null;
					delete this.form;
				}
				delete this.formSubmitHandler;
				delete this.loadingTimerCallback;
				
				this.input.attr('type', this.input.attr('data-customInputType_file-origType'));
				this.input.attr('data-customInputType_file-origType', null);
				this.input.attr('data-customInputType_file-id', null);
				this.ui.remove();
				
				this.ui = this.input = obj = null;
			},
			uploadCallback : function(data) {
				var prop = this.input.attr('data-response-prop') || 'url',
					url = '';
				if (tinydom.typeOf(data)==='string') {
					try {
						data = tinydom.json.parse(data) || data;
					}catch(err){}

				}
				if (data && data.hasOwnProperty(prop)) {
					url = data[prop] + '';
				}
				else {
					url = data && data.url || (data+'');
				}

				this.stopLoading();
				this.resetFrame();
				this.input.value(url);
			},
			startLoading : function() {

				if (this.loading!==true) {
					this.loading = true;
					this.clearLoadingTimer();
					this.loadingTimer = setInterval(this.loadingTimerCallback, 100);
					this.ui.query('.customInputType_file_loadingIndicator').fadeIn();
				}
			},
			stopLoading : function() {

				this.clearLoadingTimer();
				if (this.loading===true) {
					this.loading = false;
					this.ui.query('.customInputType_file_loadingIndicator').fadeOut(null, null, true);
				}
			},
			clearLoadingTimer : function() {
				if (this.loadingTimer) {
					clearInterval(this.loadingTimer);
					this.loadingTimer = null;
				}
			}
		};
		
		input = ui = null;
		
		return obj.init();
	},
	
	
	setValue : function(input, value) {
		var obj = this.getObjForInput(input);
		input.attr('value', value || '');
		if (obj) {
			obj.resetFrame();
		}
	},
	
	getValue : function(input) {
		return input.attr('value');
	},
	
	destroy : function(input) {
		var obj = this.getObjForInput(input);
		if (obj) {
			obj.destroy();
		}
	},
	unenhance : function(input) { this.destroy(input); },
	
	getObjForInput : function(input) {
		var id = input.attr('data-customInputType_file-id'),
			x;
		for (x=this.objs.length; x--; ) {
			if (this.objs[x].input.attr('data-customInputType_file-id')===id) {
				return this.objs[x];
			}
		}
		return false;
	}
	
});tinydom.FormHandler.addCustomType({
	
	id : 'color',
	
	types : ['color'],
	
	objs : [],
	
	color : (function() {
		var d, digit, dbl, hexDigit;
		d = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
		digit = function(x) {
			return d.indexOf((x+"").toUpperCase());
		};
		dbl = function(x) {
			return digit(x.charAt(0))*16 + digit(x.charAt(1));
		};
		hexDigit = function(x) {
			return d[Math.floor(x/16)] + d[Math.floor(x%16)];
		};
		
		return function(){
			var obj = {
				r : 0,
				g : 0,
				b : 0,
				darken	: function(fraction) {
					this.r -= Math.round(this.r * fraction);
					this.g -= Math.round(this.g * fraction);
					this.b -= Math.round(this.b * fraction);
					return this;
				},
				lighten	: function(fraction) {
					this.r += Math.round(this.r * fraction);
					this.g += Math.round(this.g * fraction);
					this.b += Math.round(this.b * fraction);
					return this;
				},
				hex	: function() {
					return this.toHex.apply(this,arguments);
				},
				toHex	: function() {
					return hexDigit(this.r)+hexDigit(this.g)+hexDigit(this.b);
				},
				toRGB	: function() {
					return {
						r : Math.round(this.r),
						g : Math.round(this.g),
						b : Math.round(this.b)
					};
				},
				toHSV : function() {

					return this._getInternalHSVL('hsv');
				},
				toHSL : function() {
					return this._getInternalHSVL('hsl');
				},
				_getInternalHSVL : function(type) {
					var r = {
							h : 0,
							s : 0
						},
						max = Math.max(this.r, this.g, this.b),
						min = Math.min(this.r, this.g, this.b),
						chroma = max-min,
						aHue;

					
					type = (type || 'hsv').toLowerCase();
					
					if (chroma===0) {
						aHue = 0;			// technically undefined, 0 is universally accepted.
					}
					else if (this.r===max) {
						aHue = ((this.g-this.b)/chroma)%6;
						if (aHue<0) {
							aHue += 6;
						}
					}
					else if (this.g===max) {
						aHue = (this.b-this.r)/chroma + 2;
					}
					else if (this.b===max) {
						aHue = (this.r-this.g)/chroma + 4;
					}
					
					r.h = 60 * aHue;
					
					if (type==='hsv') {
						r.v = Math.round(max) || 0;
						r.s = Math.round(chroma / max * 100) || 0;
					}
					else {
						r.l = (max-min)/2;
						r.s = Math.round(chroma / (1-Math.abs(2*r.l-1)) * 100) || 0;
						r.l = Math.round(r.l);

					}
					
					return r;
				},
				fromRGB : function(rgb) {
					var p = (rgb+'').replace(/[^0-9\,]/gim,'').split(',');
					this.r = parseInt(p[0],10);
					this.g = parseInt(p[1],10);
					this.b = parseInt(p[2],10);
					return this;
				},
				fromHex : function(hex) {
					hex = (hex+'').replace(/[^0-9a-f]/mgi,'');
					if (hex.length===3) {
						hex = hex[0]+hex[0] + hex[1]+hex[1] + hex[2]+hex[2];
					}
					this.r = dbl(hex.substring(0,2));
					this.g = dbl(hex.substring(2,4));
					this.b = dbl(hex.substring(4,6));
					return this;
				},
				fromHSV : function(hue, sat, val) {
					var aHue = hue / 60,							// hue
						chroma = val * sat / 100,					// chroma
						x = chroma * (1 - Math.abs(aHue%2-1)),		// intermediate
						m = val - chroma;							// lightness adjustment

					this._applyChromaKey(m, aHue, chroma, x);

					return this;
				},
				fromHSL : function(hue, sat, lit) {
					var aHue = hue / 60,							// hue
						chroma = (1-Math.abs(2*lit/100-1)) * sat,		// chroma
						x = chroma * (1 - Math.abs(aHue%2-1)),		// intermediate
						m = lit - chroma/2;							// lightness adjustment
					this._applyChromaKey(m, aHue, chroma, x);
					return this;
				},
				_applyChromaKey : function(m, hue, chroma, x) {
					this.r = this.g = this.b = m;

					if (hue<1) {
						this.r += chroma;
						this.g += x;
					}
					else if (hue<2) {
						this.r += x;
						this.g += chroma;
					}
					else if (hue<3) {
						this.g += chroma;
						this.b += x;
					}
					else if (hue<4) {
						this.g += x;
						this.b += chroma;
					}
					else if (hue<5) {
						this.r += x;
						this.b += chroma;
					}
					else if (hue<6) {
						this.r += chroma;
						this.b += x;
					}
				},
				parse : function() {
					var a, type;
					if(arguments.length===3) {
						this.fromRGB(Array.prototype.join.call(arguments,','));
					}
					else if(arguments.length===1) {
						if ((arguments[0]+'').indexOf(',')>-1) {
							a = arguments[0].replace('(',',').replace(/[^0-9a-z\.\-\,]+/gim,'').toLowerCase().split(',');
							type = 'rgb';
							if (a.length>3) {
								type = a.splice(0,1)[0];
							}
							for (var x=0; x<a.length; x++) {
								a[x] = parseFloat(a[x]);
							}
							switch (type) {
								case 'hsv':
									this.fromHSV.apply(this,a);
									break;
								default:
									this.fromRGB(arguments[0]);
							}
						}
						else {
							this.fromHex(arguments[0]);
						}
					}
					return this;
				},
				init : function() {
					obj = null;
					delete this.init;
					return this;
				}
			};
			
			obj.parse.apply(obj, arguments);
			
			return obj.init();
		};
	}()),
	
	
	colorPickerHueSatMousedown : function(e, self) {
		var me = this,
			body = tinydom.el(document.body),
			shim,
			update, move, up;
		
		self = tinydom.el(self);
		
		shim = tinydom.el({
			className : 'shim',
			css : 'z-index:999;'
		}, document.body);
		
		update = function(e, tween) {
			var x = Math.round(e.pageX - self.x(true)),
				y = Math.round(e.pageY - self.y(true)),
				height = self.height(),
				width = self.width(),
				hsv = me.currentColor.toHSV();
			x = Math.min(Math.max(x, 0), width);
			y = Math.min(Math.max(y, 0), height);
			self.query('.colorPicker_huesat_fg').position(x, y );
			hsv.s = Math.round((height-y)/height*100);
			hsv.h = Math.round(x/width*362);
			if (hsv.h>=360) {
				hsv.h = 0;
			}
			if (hsv.v===0) {
				hsv.v = 1;
			}
			var color = me.color().fromHSV(hsv.h, hsv.s, hsv.v);








			me.setPickerValue(color, true);

		};
		
		move = function(e) {
			update(e);
			return tinydom.cancelEvent(e);
		};
		body.on('mousemove', move);
		
		up = function(e) {
			update(e);
			body.removeEvent('mousemove', move);
			body.removeEvent('mouseup', up);
			shim.destroy();
			me = self = body = shim = up = move = update = null;
			return tinydom.cancelEvent(e);
		};
		body.on('mouseup', up);
		
		update(e, true);
		e = null;
	},
	
	colorPickerValueMousedown : function(e, self) {
		var me = this,
			body = tinydom.el(document.body),
			shim,
			update, move, up;
		
		self = tinydom.el(self);
		
		shim = tinydom.el({
			className : 'shim',
			css : 'z-index:999;'
		}, document.body);
		
		update = function(e, tween) {
			var y = Math.round(e.pageY - self.y(true)) - self.query('.colorPicker_value_fg').height()/4,
				height = self.height(),
				hsv = me.currentColor.toHSV();
			y = Math.min(Math.max(y, 0), height);
			
			hsv.v = Math.round((height-y)/height*255);
			hsv.v = Math.max(0, Math.min(255,hsv.v));
			var color = me.color().fromHSV(hsv.h, hsv.s, hsv.v),
				c = color.toRGB();
			me.setPickerValue(color, true);



		};
		
		move = function(e) {
			update(e);
			return tinydom.cancelEvent(e);
		};
		body.on('mousemove', move);
		
		up = function(e) {
			update(e);
			body.removeEvent('mousemove', move);
			body.removeEvent('mouseup', up);
			shim.destroy();
			me = self = body = shim = up = move = update = null;
			return tinydom.cancelEvent(e);
		};
		body.on('mouseup', up);
		
		update(e, true);
		e = null;
	},
	
	createPicker : function() {
		var self = this;
		this.picker = tinydom.el({
			className : 'colorPicker',
			children : [
				{ className:'colorPicker_huesat', children:[
					{ className:'colorPicker_huesat_bg' },
					{ className:'colorPicker_huesat_fg', innerHTML:'+' }
				], onmousedown:function(e) {
					return self.colorPickerHueSatMousedown(e, this);
				}},
				{ className:'colorPicker_value', children:[
					{ className:'colorPicker_value_bg' },
					{ className:'colorPicker_value_fg', innerHTML:decodeURIComponent('%E2%97%80') }
				], onmousedown:function(e) {
					return self.colorPickerValueMousedown(e, this);
				}},
				{ className:'colorPicker_bgPreview' },
				{ className:'colorPicker_fgPreview', innerHTML:'Example.' }
			],
			onfocus : tinydom.cancelEvent,
			onmousedown : tinydom.cancelEvent,
			ontouchstart : tinydom.cancelEvent
		}, document.body);
		
		this.picker.hidden = true;
	},
	
	openPicker : function(input) {
		if (this.closePickerTimer) {
			clearTimeout(this.closePickerTimer);
			this.closePickerTimer = null;
		}
		if (!this.picker) {
			this.createPicker();
		}
		this.picker.fadeIn('fast').position(
			input.x(true),
			input.y(true) - this.picker.height(),
			this.picker.hidden ? null : {tween:'fast'}
		);
		this.picker.currentInput = input;
		this.picker.hidden = false;
		this.currentColor = null;
		var color = this.color();
		if (input.attr('data-color-hsv')) {
			color.parse('hsv(' + input.attr('data-color-hsv') + ')');
		}
		else {
			color.parse(input.value());
		}
		this.setPickerValue(color);
	},
	
	closePicker : function() {
		var self = this;
		this.picker.currentInput = null;
		this.currentColor = null;
		if (this.closePickerTimer) {
			return true;
		}
		this.closePickerTimer = setTimeout(function() {
			if (self.picker) {
				self.picker.fadeOut('fast', function(){
					if (self.picker) {
						self.picker.hidden = true;
					}
					self = null;
				}, false);
			}
		}, 20);
	},
	
	
	
	setPickerValue : function(color, fromUser) {
		if (this.picker && color) {
			var hex = '#' + color.toHex(),
				hsv = color.toHSV(),
				bg,
				valuePicker = this.picker.query('.colorPicker_value_fg'),
				hueSatPicker = this.picker.query('.colorPicker_huesat_fg');

			if (hsv.v<100) {
				bg = '0 1px 3px rgba(255,255,255,'+((hsv.v)/200+0.5)+')';
			}
			else {
				bg = '0 -1px 3px rgba(0,0,0,'+((255-hsv.v)/200+0.25)+')';
			}

			valuePicker.position(null, (1-hsv.v/255)*valuePicker.parent().height());

			hueSatPicker.position(
				hsv.h/360 * hueSatPicker.parent().width(),
				(1-hsv.s/100) * hueSatPicker.parent().height()
			);

			this.picker.query('.colorPicker_fgPreview').css({
				color : hex,
				'text-shadow' : bg

			});

			this.picker.query('.colorPicker_bgPreview').css({
				'background-color' : hex
			});
			
			if (this.picker.currentInput) {
				this.picker.currentInput.value(hex).attr('data-color-hsv', hsv.h+','+hsv.s+','+hsv.v);

			}
		}
		this.currentColor = color;
	},
	
	enhance : function(input) {
		var self = this,
			obj;
		
		obj = {
			input : input,
			color : this.color(),
			init : function() {
				obj.input.on('focus', obj.openPicker);
				obj.input.on('blur', obj.closePicker);
				obj.input.on('keyup,paste,mouseup', obj.update);
				obj.update();
				obj.input.value('#'+obj.color.hex());
			},
			update : function() {
				var value = (obj.input.value() || '').replace(/[^0-9a-f,]/mgi,'');
				if (value.length===3 || value.length===6) {
					obj.color.parse(value);

					self.setPickerValue(obj.color);
				}
			},
			destroy : function() {
				obj.input.removeEvent('focus', obj.openPicker);
				obj.input.removeEvent('blur', obj.closePicker);
				obj.input.removeEvent('keyup,paste,mouseup', obj.update);
				for (var x=self.objs.length; x--; ) {
					if (self.objs[x]===obj) {
						self.objs.splice(x, 1);
						break;
					}
				}
				self = obj = null;
			},
			openPicker : function() {
				self.openPicker(obj.input);



			},
			closePicker : function() {
				self.closePicker();
			}
		};
		
		this.objs.push(obj);
		
		obj.init();
		
		input = null;
	},
	
	setValue : function(input, value) {
		var obj = this.getObjForInput(input);
		input.value(value || input.attr('data-default-color') || '#000000');
		if (obj) {
			obj.update();
		}
	},
	
	getValue : function(input) {
		return input.value();
	},
	
	destroy : function(input) {
		var obj = this.getObjForInput(input);
		if (obj) {
			obj.destroy();
		}
	},
	unenhance : function(input) { this.destroy(input); },
	
	
	getObjForInput : function(input) {
		for (var x=this.objs.length; x--; ) {
			if (this.objs[x].input===input) {
				return this.objs[x];
			}
		}
		return false;
	}
	
});tinydom.FormHandler.addCustomType({
	
	id : 'tags',
	
	types : ['tags'],
	
	objs : [],
	
	createUI : function(obj) {
		obj.ui = tinydom.el({
			className : 'tagsInput',
			attributes : {
				'data-input' : obj.input.uuid()
			},
			children : [
				{ className:'tagsInput_inner', children:[
					{ className:'tagsInput_taglist' },
					{
						className : 'tagsInput_inputwrap',
						children : [
							{
								type : 'input',
								className : 'tagsInput_input',
								attributes : {
									type : 'text'
								},
								onkeydown : obj.handlers.keydown,
								onclick : obj.handlers.inputClick,
								onfocus : obj.handlers.inputFocus,
								onblur : obj.handlers.inputBlur
							}
						]
					}
				]},
			],
			onmousedown : obj.handlers.grabFocus,
			ononmouseup : obj.handlers.grabFocus,
			onfocus : obj.handlers.grabFocus,
			insertBefore : obj.input.next(),
			parent : obj.input.parent()
		});
	},
	
	addTag : function(obj, tag) {
		tinydom.el({
			className : 'tagsInput_tag',
			attributes : {
				'data-tag' : tag
			},
			children : [
				{
					type : 'span',
					className : 'tagsInput_tag_label',
					innerHTML : tag ? tinydom.htmlEntities(tag) : '&nbsp;'
				},
				{
					type  : 'span',
					className : 'tagsInput_tag_removeBtn',
					innerHTML : '&times;',
					onmousedown : obj.handlers.removeClick
				}
			],
			onmousedown : obj.handlers.tagClick,
			oncontextmenu : tinydom.cancelEvent,
			onselectstart : tinydom.cancelEvent
		}, obj.ui.query('.tagsInput_taglist'));
	},
	
	removeTag : function(obj, tag) {
		obj.ui.query('.tagsInput_tag[data-tag]').each(function(node) {
			if (node.attr('data-tag')===tag) {
				node.destroy();
				return false;
			}
		});
	},
	
	update : function(obj) {
		var value = (obj.input.value() || '').replace(/(\s+\,\s+|\s+\,|\,\s+)/gim,','),
			tags = value ? value.split(',') : [],
			cur = obj.currentTags || [],
			added = [],
			removed = [],
			i;
		for (i=0; i<tags.length; i++) {
			if (cur.indexOf(tags[i])===-1) {
				this.addTag(obj, tags[i], {
					fireChange : false
				});
			}
		}
		for (i=0; i<cur.length; i++) {
			if (tags.indexOf(cur[i])===-1) {
				this.removeTag(obj, cur[i], {
					fireChange : false
				});
			}
		}
		obj.currentTags = tags;
	},
	
	enhance : function(input) {
		var self = this,
			obj;
		
		this.destroy(input);
		
		obj = {
			input : input,
			init : function() {
				self.createUI(obj);
				
				
				obj.input.css({ display:'none' });
				
				obj.update();
				
				obj.input.on('change', obj.handlers.inputChanged);
			},
			update : function() {
				self.update(obj);
			},
			destroy : function() {
				console.log('destroying tag editor');
				for (var x=self.objs.length; x--; ) {
					if (self.objs[x]===obj) {
						self.objs.splice(x, 1);
						break;
					}
				}
				obj.input.removeEvent('change', obj.handlers.inputChanged);
				obj.ui.destroy();
				obj.ui = obj.input = null;
				self = obj = null;
			},
			filterEmpties : function(arr) {
				for (var x=arr.length; x--; ) {
					if (!arr[x]) {
						arr.splice(x, 1);
					}
				}
			},
			add : function(tag, visualFeedback) {
				var tags = (obj.input.value() || '').replace(/(\s+\,\s+|\s+\,|\,\s+)/gim,',').split(','),
					i;
				i = tags.indexOf(tag);
				if (i!==-1) {
					if (visualFeedback===true) {
						obj.ui.query('[data-tag]').each(function(node) {
							if (node.attr('data-tag')===tag) {
								obj.tagExists(node);
								return false;
							}
						});
					}
					return false;
				}
				tags.push(tag);
				obj.filterEmpties(tags);
				obj.input.value(tags.join(','));
				return true;
			},
			remove : function(tag) {
				var tags = (obj.input.value() || '').replace(/(\s+\,\s+|\s+\,|\,\s+)/gim,',').split(','),
					i;
				i = tags.indexOf(tag);
				if (i===-1) {
					return false;
				}
				tags.splice(i, 1);
				obj.filterEmpties(tags);
				obj.input.value(tags.join(','));
				return true;
			},
			tagExists : function(node) {
				node.classify('tagInput_existsblink').wait(200, function() {
					this.declassify('tagInput_existsblink').wait(200, function() {
						this.classify('tagInput_existsblink').wait(200, function() {
							this.declassify('tagInput_existsblink');
						});
					});
				});
				node = null;
			},
			getSelected : function() {
				return obj.ui.query('.tagsInput_tag.selected');
			},
			handlers : {
				inputChanged : function(e) {
					obj.update();
				},
				keydown : function(e) {
					var me = tinydom.el(this),
						key = e.keyCode || e.which,
						value = tinydom.text.trim(me.value() || ''),
						sel = me.selection(),
						selected = obj.getSelected();
					selected.declassify('selected');
					if (key===13 || key===188 || key===9) {			// return or comma
						if (obj.add(value,true)!==false) {
							me.value('');
						}
						if (value.length>0 || key===188) {
							return tinydom.cancelEvent(e);
						}
					}
					else if (key===27) {					// escape
						me.value('').blur();
						return tinydom.cancelEvent(e);
					}
					else if (key===8 || key===46) {			// backspace or del (backspace is <delete> on mac)
						if (selected.exists()) {
							obj.remove(selected.attr('data-tag'));
							me.value('').focus();
							return tinydom.cancelEvent(e);
						}
						else {
							if (key===8 && (sel.start===sel.end && sel.start===0)) {
								selected = obj.ui.query('.tagsInput_tag').last();
								if (selected.exists()) {
									obj.remove(selected.attr('data-tag'));
								}
							}
						}
					}
					else if (key===37) {					// left

						if (!value || (sel.start===sel.end && sel.start===0)) {
							if (selected.exists()) {
								if (selected.previous().exists()) {
									selected.previous().classify('selected');
								}
								else {
									selected.classify('selected');
								}
							}
							else {
								selected = obj.ui.query('.tagsInput_tag').last();
								if (selected.exists()) {
									selected.classify('selected');
								}
							}
							return tinydom.cancelEvent(e);
						}
					}
					else if (key===39) {					// right
						if (selected.exists() && (!value || (sel.start===sel.end && sel.start===0))) {
							if (selected.next().exists()) {
								selected.next().classify('selected');
							}
							return tinydom.cancelEvent(e);
						}
					}
				},
				tagClick : function(e) {
					obj.handlers.grabFocus();
					obj.ui.query('.tagsInput_tag.selected').declassify('selected');
					tinydom.el(this).classify('selected');
					return tinydom.cancelEvent(e);
				},
				removeClick : function(e) {
					obj.remove(tinydom.el(this).parent().attr('data-tag'));
					return tinydom.cancelEvent(e);
				},
				grabFocus : function(e) {
					obj.ui.query('input.tagsInput_input').focus();

				},
				inputClick : function(e) {
					obj.handlers.inputBlur.call(e);
				},
				inputFocus : function(e) {
					obj.handlers.inputBlur.call(e);
				},
				inputBlur : function(e) {
					var value = tinydom.el(this).value();
					obj.getSelected().declassify('selected');
					obj.add(value,true);
					tinydom.el(this).value('');
				}
			}
		};
		
		this.objs.push(obj);
		
		obj.init();
		
		input = null;
	},
	
	setValue : function(input, value) {
		var obj = this.getObjForInput(input);
		input.value(value || '');
		if (obj) {
			obj.update();
		}
	},
	
	getValue : function(input) {
		return input.value();
	},
	
	destroy : function(input) {
		var obj = this.getObjForInput(input);
		if (obj) {
			obj.destroy();
		}
	},
	unenhance : function(input) { this.destroy(input); },
	
	
	getObjForInput : function(input) {
		for (var x=this.objs.length; x--; ) {
			if (this.objs[x].input._nodes[0]===input._nodes[0]) {
				return this.objs[x];
			}
		}
		return false;
	}
	
});
(function(window, undefined){
  var document = window.document;

(function(){var initializing=false, fnTest=/xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; this.JRClass = function(){}; JRClass.extend = function(prop) { var _super = this.prototype; initializing = true; var prototype = new this(); initializing = false; for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } function JRClass() { if ( !initializing && this.init ) this.init.apply(this, arguments); } JRClass.prototype = prototype; JRClass.constructor = JRClass; JRClass.extend = arguments.callee; return JRClass;};})();

var VideoJS = JRClass.extend({


  init: function(element, setOptions){

    if (typeof element == 'string') {
      this.video = document.getElementById(element);
    } else {
      this.video = element;
    }


    this.video.player = this;
    this.values = {}; // Cache video values.
    this.elements = {}; // Store refs to controls elements.

    this.options = {
      autoplay: false,
      preload: true,
      useBuiltInControls: false, // Use the browser's controls (iPhone)
      controlsBelow: false, // Display control bar below video vs. in front of
      controlsAtStart: false, // Make controls visible when page loads
      controlsHiding: true, // Hide controls when not over the video
      defaultVolume: 0.85, // Will be overridden by localStorage volume if available
      playerFallbackOrder: ["html5", "flash", "links"], // Players and order to use them
      flashPlayer: "htmlObject",
      flashPlayerVersion: false // Required flash version for fallback
    };

    if (typeof VideoJS.options == "object") { _V_.merge(this.options, VideoJS.options); }

    if (typeof setOptions == "object") { _V_.merge(this.options, setOptions); }

    if (this.getPreloadAttribute() !== undefined) { this.options.preload = this.getPreloadAttribute(); }
    if (this.getAutoplayAttribute() !== undefined) { this.options.autoplay = this.getAutoplayAttribute(); }

    this.box = this.video.parentNode;
    this.linksFallback = this.getLinksFallback();
    this.hideLinksFallback(); // Will be shown again if "links" player is used




    this.each(this.options.playerFallbackOrder, function(playerType){
      if (this[playerType+"Supported"]()) { // Check if player type is supported
        this[playerType+"Init"](); // Initialize player type
        return true; // Stop looping though players
      }
    });

    this.activateElement(this, "player");
    this.activateElement(this.box, "box");
  },
  
  behaviors: {},
  newBehavior: function(name, activate, functions){
    this.behaviors[name] = activate;
    this.extend(functions);
  },
  activateElement: function(element, behavior){

    if (typeof element == "string") { element = document.getElementById(element); }
    this.behaviors[behavior].call(this, element);
  },
  
  errors: [], // Array to track errors
  warnings: [],
  warning: function(warning){
    this.warnings.push(warning);
    this.log(warning);
  },
  
  history: [],
  log: function(event){
    if (!event) { return; }
    if (typeof event == "string") { event = { type: event }; }
    if (event.type) { this.history.push(event.type); }
    if (this.history.length >= 50) { this.history.shift(); }
    try { console.log(event.type); } catch(e) { try { opera.postError(event.type); } catch(e){} }
  },
  
  setLocalStorage: function(key, value){
    if (!localStorage) { return; }
    try {
      localStorage[key] = value;
    } catch(e) {
      if (e.code == 22 || e.code == 1014) { // Webkit == 22 / Firefox == 1014
        this.warning(VideoJS.warnings.localStorageFull);
      }
    }
  },
  
  getPreloadAttribute: function(){
    if (typeof this.video.hasAttribute == "function" && this.video.hasAttribute("preload")) {
      var preload = this.video.getAttribute("preload");

      if (preload === "" || preload === "true") { return "auto"; }
      if (preload === "false") { return "none"; }
      return preload;
    }
  },
  getAutoplayAttribute: function(){
    if (typeof this.video.hasAttribute == "function" && this.video.hasAttribute("autoplay")) {
      var autoplay = this.video.getAttribute("autoplay");
      if (autoplay === "false") { return false; }
      return true;
    }
  },

  bufferedPercent: function(){ return (this.duration()) ? this.buffered()[1] / this.duration() : 0; },


  each: function(arr, fn){
    if (!arr || arr.length === 0) { return; }
    for (var i=0,j=arr.length; i<j; i++) {
      if (fn.call(this, arr[i], i)) { break; }
    }
  },
  extend: function(obj){
    for (var attrname in obj) {
      if (obj.hasOwnProperty(attrname)) { this[attrname]=obj[attrname]; }
    }
  }
});
VideoJS.player = VideoJS.prototype;

// Player Types
////////////////////////////////////////////////////////////////////////////////


VideoJS.player.extend({
  flashSupported: function(){
    if (!this.flashElement) { this.flashElement = this.getFlashElement(); }

    if (this.flashElement && this.flashPlayerVersionSupported()) {
      return true;
    } else {
      return false;
    }
  },
  flashInit: function(){
    this.replaceWithFlash();
    this.element = this.flashElement;
    this.video.src = ""; // Stop video from downloading if HTML5 is still supported
    var flashPlayerType = VideoJS.flashPlayers[this.options.flashPlayer];
    this.extend(VideoJS.flashPlayers[this.options.flashPlayer].api);
    (flashPlayerType.init.context(this))();
  },

  getFlashElement: function(){
    var children = this.video.children;
    for (var i=0,j=children.length; i<j; i++) {
      if (children[i].className == "vjs-flash-fallback") {
        return children[i];
      }
    }
  },

  replaceWithFlash: function(){

    if (this.flashElement) {
      this.box.insertBefore(this.flashElement, this.video);
      this.video.style.display = "none"; // Removing it was breaking later players
    }
  },

  flashPlayerVersionSupported: function(){
    var playerVersion = (this.options.flashPlayerVersion) ? this.options.flashPlayerVersion : VideoJS.flashPlayers[this.options.flashPlayer].flashPlayerVersion;
    return VideoJS.getFlashVersion() >= playerVersion;
  }
});
VideoJS.flashPlayers = {};
VideoJS.flashPlayers.htmlObject = {
  flashPlayerVersion: 9,
  init: function() { return true; },
  api: { // No video API available with HTML Object embed method
    width: function(width){
      if (width !== undefined) {
        this.element.width = width;
        this.box.style.width = width+"px";
        this.triggerResizeListeners();
        return this;
      }
      return this.element.width;
    },
    height: function(height){
      if (height !== undefined) {
        this.element.height = height;
        this.box.style.height = height+"px";
        this.triggerResizeListeners();
        return this;
      }
      return this.element.height;
    }
  }
};



VideoJS.player.extend({
  linksSupported: function(){ return true; },
  linksInit: function(){
    this.showLinksFallback();
    this.element = this.video;
  },

  getLinksFallback: function(){ return this.box.getElementsByTagName("P")[0]; },

  hideLinksFallback: function(){
    if (this.linksFallback) { this.linksFallback.style.display = "none"; }
  },

  showLinksFallback: function(){
    if (this.linksFallback) { this.linksFallback.style.display = "block"; }
  }
});

// Class Methods
// Functions that don't apply to individual videos.
////////////////////////////////////////////////////////////////////////////////

VideoJS.merge = function(obj1, obj2, safe){
  for (var attrname in obj2){
    if (obj2.hasOwnProperty(attrname) && (!safe || !obj1.hasOwnProperty(attrname))) { obj1[attrname]=obj2[attrname]; }
  }
  return obj1;
};
VideoJS.extend = function(obj){ this.merge(this, obj, true); };

VideoJS.extend({

  setupAllWhenReady: function(options){

    VideoJS.options = options;
    VideoJS.DOMReady(VideoJS.setup);
  },

  DOMReady: function(fn){
    VideoJS.addToDOMReady(fn);
  },





  setup: function(videos, options){
    var returnSingular = false,
    playerList = [],
    videoElement;

    if (!videos || videos == "All") {
      videos = VideoJS.getVideoJSTags();

    } else if (typeof videos != 'object' || videos.nodeType == 1) {
      videos = [videos];
      returnSingular = true;
    }

    for (var i=0; i<videos.length; i++) {
      if (typeof videos[i] == 'string') {
        videoElement = document.getElementById(videos[i]);
      } else { // assume DOM object
        videoElement = videos[i];
      }
      playerList.push(new VideoJS(videoElement, options));
    }

    return (returnSingular) ? playerList[0] : playerList;
  },

  getVideoJSTags: function() {
    var videoTags = document.getElementsByTagName("video"),
    videoJSTags = [], videoTag;

    for (var i=0,j=videoTags.length; i<j; i++) {
      videoTag = videoTags[i];
      if (videoTag.className.indexOf("video-js") != -1) {
        videoJSTags.push(videoTag);
      }
    }
    return videoJSTags;
  },

  browserSupportsVideo: function() {
    if (typeof VideoJS.videoSupport != "undefined") { return VideoJS.videoSupport; }
    VideoJS.videoSupport = !!document.createElement('video').canPlayType;
    return VideoJS.videoSupport;
  },

  getFlashVersion: function(){

    if (typeof VideoJS.flashVersion != "undefined") { return VideoJS.flashVersion; }
    var version = 0, desc;
    if (typeof navigator.plugins != "undefined" && typeof navigator.plugins["Shockwave Flash"] == "object") {
      desc = navigator.plugins["Shockwave Flash"].description;
      if (desc && !(typeof navigator.mimeTypes != "undefined" && navigator.mimeTypes["application/x-shockwave-flash"] && !navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)) {
        version = parseInt(desc.match(/^.*\s+([^\s]+)\.[^\s]+\s+[^\s]+$/)[1], 10);
      }
    } else if (typeof window.ActiveXObject != "undefined") {
      try {
        var testObject = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
        if (testObject) {
          version = parseInt(testObject.GetVariable("$version").match(/^[^\s]+\s(\d+)/)[1], 10);
        }
      }
      catch(e) {}
    }
    VideoJS.flashVersion = version;
    return VideoJS.flashVersion;
  },

  isIE: function(){ return !+"\v1"; },
  isIPad: function(){ return navigator.userAgent.match(/iPad/i) !== null; },
  isIPhone: function(){ return navigator.userAgent.match(/iPhone/i) !== null; },
  isIOS: function(){ return VideoJS.isIPhone() || VideoJS.isIPad(); },
  iOSVersion: function() {
    var match = navigator.userAgent.match(/OS (\d+)_/i);
    if (match && match[1]) { return match[1]; }
  },
  isAndroid: function(){ return navigator.userAgent.match(/Android/i) !== null; },
  androidVersion: function() {
    var match = navigator.userAgent.match(/Android (\d+)\./i);
    if (match && match[1]) { return match[1]; }
  },

  warnings: {

    videoNotReady: "Video is not ready yet (try playing the video first).",

    localStorageFull: "Local Storage is Full"
  }
});

if(VideoJS.isIE()) { document.createElement("video"); }

window.VideoJS = window._V_ = VideoJS;


VideoJS.player.extend({
  html5Supported: function(){
    if (VideoJS.browserSupportsVideo() && this.canPlaySource()) {
      return true;
    } else {
      return false;
    }
  },
  html5Init: function(){
    this.element = this.video;

    this.fixPreloading(); // Support old browsers that used autobuffer
    this.supportProgressEvents(); // Support browsers that don't use 'buffered'

    this.volume((localStorage && localStorage.volume) || this.options.defaultVolume);

    if (VideoJS.isIOS()) {
      this.options.useBuiltInControls = true;
      this.iOSInterface();
    } else if (VideoJS.isAndroid()) {
      this.options.useBuiltInControls = true;
      this.androidInterface();
    }

    if (!this.options.useBuiltInControls) {
      this.video.controls = false;

      if (this.options.controlsBelow) { _V_.addClass(this.box, "vjs-controls-below"); }

      this.activateElement(this.video, "playToggle");

      this.buildStylesCheckDiv(); // Used to check if style are loaded
      this.buildAndActivatePoster();
      this.buildBigPlayButton();
      this.buildAndActivateSpinner();
      this.buildAndActivateControlBar();
      this.loadInterface(); // Show everything once styles are loaded
      this.getSubtitles();
    }
  },
  
  canPlaySource: function(){

    if (this.canPlaySourceResult) { return this.canPlaySourceResult; }

    var children = this.video.children;
    for (var i=0,j=children.length; i<j; i++) {
      if (children[i].tagName.toUpperCase() == "SOURCE") {
        var canPlay = this.video.canPlayType(children[i].type) || this.canPlayExt(children[i].src);
        if (canPlay == "probably" || canPlay == "maybe") {
          this.firstPlayableSource = children[i];
          this.canPlaySourceResult = true;
          return true;
        }
      }
    }
    this.canPlaySourceResult = false;
    return false;
  },

  canPlayExt: function(src){
    if (!src) { return ""; }
    var match = src.match(/\.([^\.]+)$/);
    if (match && match[1]) {
      var ext = match[1].toLowerCase();

      if (VideoJS.isAndroid()) {
        if (ext == "mp4" || ext == "m4v") { return "maybe"; }

      } else if (VideoJS.isIOS()) {
        if (ext == "m3u8") { return "maybe"; }
      }
    }
    return "";
  },


  forceTheSource: function(){
    this.video.src = this.firstPlayableSource.src; // From canPlaySource()
    this.video.load();
  },

  fixPreloading: function(){
    if (typeof this.video.hasAttribute == "function" && this.video.hasAttribute("preload") && this.video.preload != "none") {
      this.video.autobuffer = true; // Was a boolean
    } else {
      this.video.autobuffer = false;
      this.video.preload = "none";
    }
  },


  supportProgressEvents: function(e){
    _V_.addListener(this.video, 'progress', this.playerOnVideoProgress.context(this));
  },
  playerOnVideoProgress: function(event){
    this.setBufferedFromProgress(event);
  },
  setBufferedFromProgress: function(event){ // HTML5 Only
    if(event.total > 0) {
      var newBufferEnd = (event.loaded / event.total) * this.duration();
      if (newBufferEnd > this.values.bufferEnd) { this.values.bufferEnd = newBufferEnd; }
    }
  },

  iOSInterface: function(){
    if(VideoJS.iOSVersion() < 4) { this.forceTheSource(); } // Fix loading issues
    if(VideoJS.isIPad()) { // iPad could work with controlsBelow
      this.buildAndActivateSpinner(); // Spinner still works well on iPad, since iPad doesn't have one
    }
  },


  androidInterface: function(){
    this.forceTheSource(); // Fix loading issues
    _V_.addListener(this.video, "click", function(){ this.play(); }); // Required to play
    this.buildBigPlayButton(); // But don't activate the normal way. Pause doesn't work right on android.
    _V_.addListener(this.bigPlayButton, "click", function(){ this.play(); }.context(this));
    this.positionBox();
    this.showBigPlayButtons();
  },
  
  loadInterface: function(){
    if(!this.stylesHaveLoaded()) {

      if (!this.positionRetries) { this.positionRetries = 1; }
      if (this.positionRetries++ < 100) {
        setTimeout(this.loadInterface.context(this),10);
        return;
      }
    }
    this.hideStylesCheckDiv();
    this.showPoster();
    if (this.video.paused !== false) { this.showBigPlayButtons(); }
    if (this.options.controlsAtStart) { this.showControlBars(); }
    this.positionAll();
  },
  
  buildAndActivateControlBar: function(){

    this.controls = _V_.createElement("div", { className: "vjs-controls" });

    this.box.appendChild(this.controls);
    this.activateElement(this.controls, "controlBar");
    this.activateElement(this.controls, "mouseOverVideoReporter");

    this.playControl = _V_.createElement("div", { className: "vjs-play-control", innerHTML: "<span></span>" });
    this.controls.appendChild(this.playControl);
    this.activateElement(this.playControl, "playToggle");

    this.progressControl = _V_.createElement("div", { className: "vjs-progress-control" });
    this.controls.appendChild(this.progressControl);

    this.progressHolder = _V_.createElement("div", { className: "vjs-progress-holder" });
    this.progressControl.appendChild(this.progressHolder);
    this.activateElement(this.progressHolder, "currentTimeScrubber");

    this.loadProgressBar = _V_.createElement("div", { className: "vjs-load-progress" });
    this.progressHolder.appendChild(this.loadProgressBar);
    this.activateElement(this.loadProgressBar, "loadProgressBar");

    this.playProgressBar = _V_.createElement("div", { className: "vjs-play-progress" });
    this.progressHolder.appendChild(this.playProgressBar);
    this.activateElement(this.playProgressBar, "playProgressBar");

    this.timeControl = _V_.createElement("div", { className: "vjs-time-control" });
    this.controls.appendChild(this.timeControl);

    this.currentTimeDisplay = _V_.createElement("span", { className: "vjs-current-time-display", innerHTML: "00:00" });
    this.timeControl.appendChild(this.currentTimeDisplay);
    this.activateElement(this.currentTimeDisplay, "currentTimeDisplay");

    this.timeSeparator = _V_.createElement("span", { innerHTML: " / " });
    this.timeControl.appendChild(this.timeSeparator);

    this.durationDisplay = _V_.createElement("span", { className: "vjs-duration-display", innerHTML: "00:00" });
    this.timeControl.appendChild(this.durationDisplay);
    this.activateElement(this.durationDisplay, "durationDisplay");

    this.volumeControl = _V_.createElement("div", {
      className: "vjs-volume-control",
      innerHTML: "<div><span></span><span></span><span></span><span></span><span></span><span></span></div>"
    });
    this.controls.appendChild(this.volumeControl);
    this.activateElement(this.volumeControl, "volumeScrubber");

    this.volumeDisplay = this.volumeControl.children[0];
    this.activateElement(this.volumeDisplay, "volumeDisplay");

    this.fullscreenControl = _V_.createElement("div", {
      className: "vjs-fullscreen-control",
      innerHTML: "<div><span></span><span></span><span></span><span></span></div>"
    });
    this.controls.appendChild(this.fullscreenControl);
    this.activateElement(this.fullscreenControl, "fullscreenToggle");
  },
  
  buildAndActivatePoster: function(){
    this.updatePosterSource();
    if (this.video.poster) {
      this.poster = document.createElement("img");

      this.box.appendChild(this.poster);

      this.poster.src = this.video.poster;

      this.poster.className = "vjs-poster";
      this.activateElement(this.poster, "poster");
    } else {
      this.poster = false;
    }
  },
  
  buildBigPlayButton: function(){
    
    this.bigPlayButton = _V_.createElement("div", {
      className: "vjs-big-play-button",
      innerHTML: "<span></span>"
    });
    this.box.appendChild(this.bigPlayButton);
    this.activateElement(this.bigPlayButton, "bigPlayButton");
  },
  
  buildAndActivateSpinner: function(){
    this.spinner = _V_.createElement("div", {
      className: "vjs-spinner",
      innerHTML: "<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>"
    });
    this.box.appendChild(this.spinner);
    this.activateElement(this.spinner, "spinner");
  },



  buildStylesCheckDiv: function(){
    this.stylesCheckDiv = _V_.createElement("div", { className: "vjs-styles-check" });
    this.stylesCheckDiv.style.position = "absolute";
    this.box.appendChild(this.stylesCheckDiv);
  },
  hideStylesCheckDiv: function(){ this.stylesCheckDiv.style.display = "none"; },
  stylesHaveLoaded: function(){
    if (this.stylesCheckDiv.offsetHeight != 5) {
       return false;
    } else {
      return true;
    }
  },
  
  positionAll: function(){
    this.positionBox();
    this.positionControlBars();
    this.positionPoster();
  },
  positionBox: function(){

    if (this.videoIsFullScreen) {
      this.box.style.width = "";
      this.element.style.height="";
      if (this.options.controlsBelow) {
        this.box.style.height = "";
        this.element.style.height = (this.box.offsetHeight - this.controls.offsetHeight) + "px";
      }
    } else {
      this.box.style.width = this.width() + "px";
      this.element.style.height=this.height()+"px";
      if (this.options.controlsBelow) {
        this.element.style.height = "";

      }
    }
  },
  
  getSubtitles: function(){
    var tracks = this.video.getElementsByTagName("TRACK");
    for (var i=0,j=tracks.length; i<j; i++) {
      if (tracks[i].getAttribute("kind") == "subtitles" && tracks[i].getAttribute("src")) {
        this.subtitlesSource = tracks[i].getAttribute("src");
        this.loadSubtitles();
        this.buildSubtitles();
      }
    }
  },
  loadSubtitles: function() { _V_.get(this.subtitlesSource, this.parseSubtitles.context(this)); },
  parseSubtitles: function(subText) {
    var lines = subText.split("\n"),
        line = "",
        subtitle, time, text;
    this.subtitles = [];
    this.currentSubtitle = false;
    this.lastSubtitleIndex = 0;

    for (var i=0; i<lines.length; i++) {
      line = _V_.trim(lines[i]); // Trim whitespace and linebreaks
      if (line) { // Loop until a line with content

        subtitle = {
          id: line, // Subtitle Number
          index: this.subtitles.length // Position in Array
        };

        line = _V_.trim(lines[++i]);
        time = line.split(" --> ");
        subtitle.start = this.parseSubtitleTime(time[0]);
        subtitle.end = this.parseSubtitleTime(time[1]);

        text = [];
        for (var j=i; j<lines.length; j++) { // Loop until a blank line or end of lines
          line = _V_.trim(lines[++i]);
          if (!line) { break; }
          text.push(line);
        }
        subtitle.text = text.join('<br/>');

        this.subtitles.push(subtitle);
      }
    }
  },

  parseSubtitleTime: function(timeText) {
    var parts = timeText.split(':'),
        time = 0;

    time += parseFloat(parts[0])*60*60;

    time += parseFloat(parts[1])*60;

    var seconds = parts[2].split(/\.|,/); // Either . or ,
    time += parseFloat(seconds[0]);

    ms = parseFloat(seconds[1]);
    if (ms) { time += ms/1000; }
    return time;
  },

  buildSubtitles: function(){
    
    this.subtitlesDisplay = _V_.createElement("div", { className: 'vjs-subtitles' });
    this.box.appendChild(this.subtitlesDisplay);
    this.activateElement(this.subtitlesDisplay, "subtitlesDisplay");
  },

  
  addVideoListener: function(type, fn){ _V_.addListener(this.video, type, fn.rEvtContext(this)); },

  play: function(){
    this.video.play();
    return this;
  },
  onPlay: function(fn){ this.addVideoListener("play", fn); return this; },

  pause: function(){
    this.video.pause();
    return this;
  },
  onPause: function(fn){ this.addVideoListener("pause", fn); return this; },
  paused: function() { return this.video.paused; },

  currentTime: function(seconds){
    if (seconds !== undefined) {
      try { this.video.currentTime = seconds; }
      catch(e) { this.warning(VideoJS.warnings.videoNotReady); }
      this.values.currentTime = seconds;
      return this;
    }
    return this.video.currentTime;
  },
  onCurrentTimeUpdate: function(fn){
    this.currentTimeListeners.push(fn);
  },

  duration: function(){
    return this.video.duration;
  },

  buffered: function(){

    if (this.values.bufferStart === undefined) {
      this.values.bufferStart = 0;
      this.values.bufferEnd = 0;
    }
    if (this.video.buffered && this.video.buffered.length > 0) {
      var newEnd = this.video.buffered.end(0);
      if (newEnd > this.values.bufferEnd) { this.values.bufferEnd = newEnd; }
    }
    return [this.values.bufferStart, this.values.bufferEnd];
  },

  volume: function(percentAsDecimal){
    if (percentAsDecimal !== undefined) {

      this.values.volume = Math.max(0, Math.min(1, parseFloat(percentAsDecimal)));
      this.video.volume = this.values.volume;
      this.setLocalStorage("volume", this.values.volume);
      return this;
    }
    if (this.values.volume) { return this.values.volume; }
    return this.video.volume;
  },
  onVolumeChange: function(fn){ _V_.addListener(this.video, 'volumechange', fn.rEvtContext(this)); },

  width: function(width){
    if (width !== undefined) {
      this.video.width = width; // Not using style so it can be overridden on fullscreen.
      this.box.style.width = width+"px";
      this.triggerResizeListeners();
      return this;
    }
    return this.video.offsetWidth;
  },
  height: function(height){
    if (height !== undefined) {
      this.video.height = height;
      this.box.style.height = height+"px";
      this.triggerResizeListeners();
      return this;
    }
    return this.video.offsetHeight;
  },

  supportsFullScreen: function(){
    if(typeof this.video.webkitEnterFullScreen == 'function') {

      if (!navigator.userAgent.match("Chrome") && !navigator.userAgent.match("Mac OS X 10.5")) {
        return true;
      }
    }
    return false;
  },

  html5EnterNativeFullScreen: function(){
    try {
      this.video.webkitEnterFullScreen();
    } catch (e) {
      if (e.code == 11) { this.warning(VideoJS.warnings.videoNotReady); }
    }
    return this;
  },


  enterFullScreen: function(){
    if (this.supportsFullScreen()) {
      this.html5EnterNativeFullScreen();
    } else {
      this.enterFullWindow();
    }
  },

  exitFullScreen: function(){
    if (this.supportsFullScreen()) {

    } else {
      this.exitFullWindow();
    }
  },

  enterFullWindow: function(){
    this.videoIsFullScreen = true;

    this.docOrigOverflow = document.documentElement.style.overflow;

    _V_.addListener(document, "keydown", this.fullscreenOnEscKey.rEvtContext(this));

    _V_.addListener(window, "resize", this.fullscreenOnWindowResize.rEvtContext(this));

    document.documentElement.style.overflow = 'hidden';

    _V_.addClass(this.box, "vjs-fullscreen");

    this.positionAll();
  },

  exitFullWindow: function(){
    this.videoIsFullScreen = false;
    document.removeEventListener("keydown", this.fullscreenOnEscKey, false);
    window.removeEventListener("resize", this.fullscreenOnWindowResize, false);

    document.documentElement.style.overflow = this.docOrigOverflow;

    _V_.removeClass(this.box, "vjs-fullscreen");

    this.positionAll();
  },

  onError: function(fn){ this.addVideoListener("error", fn); return this; },
  onEnded: function(fn){
    this.addVideoListener("ended", fn); return this;
  }
});

// Element Behaviors
// Tell elements how to act or react
////////////////////////////////////////////////////////////////////////////////


VideoJS.player.newBehavior("player", function(player){
    this.onError(this.playerOnVideoError);

    this.onPlay(this.playerOnVideoPlay);
    this.onPlay(this.trackCurrentTime);

    this.onPause(this.playerOnVideoPause);
    this.onPause(this.stopTrackingCurrentTime);

    this.onEnded(this.playerOnVideoEnded);


    this.trackBuffered();

    this.onBufferedUpdate(this.isBufferFull);
  },{
    playerOnVideoError: function(event){
      this.log(event);
      this.log(this.video.error);
    },
    playerOnVideoPlay: function(event){ this.hasPlayed = true; },
    playerOnVideoPause: function(event){},
    playerOnVideoEnded: function(event){
      this.currentTime(0);
      this.pause();
    },


    trackBuffered: function(){
      this.bufferedInterval = setInterval(this.triggerBufferedListeners.context(this), 500);
    },
    stopTrackingBuffered: function(){ clearInterval(this.bufferedInterval); },
    bufferedListeners: [],
    onBufferedUpdate: function(fn){
      this.bufferedListeners.push(fn);
    },
    triggerBufferedListeners: function(){
      this.isBufferFull();
      this.each(this.bufferedListeners, function(listener){
        (listener.context(this))();
      });
    },
    isBufferFull: function(){
      if (this.bufferedPercent() == 1) { this.stopTrackingBuffered(); }
    },

    
    trackCurrentTime: function(){
      if (this.currentTimeInterval) { clearInterval(this.currentTimeInterval); }
      this.currentTimeInterval = setInterval(this.triggerCurrentTimeListeners.context(this), 100); // 42 = 24 fps
      this.trackingCurrentTime = true;
    },

    stopTrackingCurrentTime: function(){
      clearInterval(this.currentTimeInterval);
      this.trackingCurrentTime = false;
    },
    currentTimeListeners: [],

    triggerCurrentTimeListeners: function(late, newTime){ // FF passes milliseconds late as the first argument
      this.each(this.currentTimeListeners, function(listener){
        (listener.context(this))(newTime || this.currentTime());
      });
    },

    
    resizeListeners: [],
    onResize: function(fn){
      this.resizeListeners.push(fn);
    },

    triggerResizeListeners: function(){
      this.each(this.resizeListeners, function(listener){
        (listener.context(this))();
      });
    }
  }
);

VideoJS.player.newBehavior("mouseOverVideoReporter", function(element){

    _V_.addListener(element, "mousemove", this.mouseOverVideoReporterOnMouseMove.context(this));

    _V_.addListener(element, "mouseout", this.mouseOverVideoReporterOnMouseOut.context(this));
  },{
    mouseOverVideoReporterOnMouseMove: function(){
      this.showControlBars();
      clearInterval(this.mouseMoveTimeout);
      this.mouseMoveTimeout = setTimeout(this.hideControlBars.context(this), 4000);
    },
    mouseOverVideoReporterOnMouseOut: function(event){

      var parent = event.relatedTarget;
      while (parent && parent !== this.box) {
        parent = parent.parentNode;
      }
      if (parent !== this.box) {
        this.hideControlBars();
      }
    }
  }
);

VideoJS.player.newBehavior("box", function(element){
    this.positionBox();
    _V_.addClass(element, "vjs-paused");
    this.activateElement(element, "mouseOverVideoReporter");
    this.onPlay(this.boxOnVideoPlay);
    this.onPause(this.boxOnVideoPause);
  },{
    boxOnVideoPlay: function(){
      _V_.removeClass(this.box, "vjs-paused");
      _V_.addClass(this.box, "vjs-playing");
    },
    boxOnVideoPause: function(){
      _V_.removeClass(this.box, "vjs-playing");
      _V_.addClass(this.box, "vjs-paused");
    }
  }
);

VideoJS.player.newBehavior("poster", function(element){
    this.activateElement(element, "mouseOverVideoReporter");
    this.activateElement(element, "playButton");
    this.onPlay(this.hidePoster);
    this.onEnded(this.showPoster);
    this.onResize(this.positionPoster);
  },{
    showPoster: function(){
      if (!this.poster) { return; }
      this.poster.style.display = "block";
      this.positionPoster();
    },
    positionPoster: function(){

      if (!this.poster || this.poster.style.display == 'none') { return; }
      this.poster.style.height = this.height() + "px"; // Need incase controlsBelow
      this.poster.style.width = this.width() + "px"; // Could probably do 100% of box
    },
    hidePoster: function(){
      if (!this.poster) { return; }
      this.poster.style.display = "none";
    },


    updatePosterSource: function(){
      if (!this.video.poster) {
        var images = this.video.getElementsByTagName("img");
        if (images.length > 0) { this.video.poster = images[0].src; }
      }
    }
  }
);

VideoJS.player.newBehavior("controlBar", function(element){
    if (!this.controlBars) {
      this.controlBars = [];
      this.onResize(this.positionControlBars);
    }
    this.controlBars.push(element);
    _V_.addListener(element, "mousemove", this.onControlBarsMouseMove.context(this));
    _V_.addListener(element, "mouseout", this.onControlBarsMouseOut.context(this));
  },{
    showControlBars: function(){
      if (!this.options.controlsAtStart && !this.hasPlayed) { return; }
      this.each(this.controlBars, function(bar){
        bar.style.display = "block";
      });
    },

    positionControlBars: function(){
      this.updatePlayProgressBars();
      this.updateLoadProgressBars();
    },
    hideControlBars: function(){
      if (this.options.controlsHiding && !this.mouseIsOverControls) {
        this.each(this.controlBars, function(bar){
          bar.style.display = "none";
        });
      }
    },

    onControlBarsMouseMove: function(){ this.mouseIsOverControls = true; },
    onControlBarsMouseOut: function(event){
      this.mouseIsOverControls = false;
    }
  }
);

VideoJS.player.newBehavior("playToggle", function(element){
    if (!this.elements.playToggles) {
      this.elements.playToggles = [];
      this.onPlay(this.playTogglesOnPlay);
      this.onPause(this.playTogglesOnPause);
    }
    this.elements.playToggles.push(element);
    _V_.addListener(element, "click", this.onPlayToggleClick.context(this));
  },{
    onPlayToggleClick: function(event){
      if (this.paused()) {
        this.play();
      } else {
        this.pause();
      }
    },
    playTogglesOnPlay: function(event){
      this.each(this.elements.playToggles, function(toggle){
        _V_.removeClass(toggle, "vjs-paused");
        _V_.addClass(toggle, "vjs-playing");
      });
    },
    playTogglesOnPause: function(event){
      this.each(this.elements.playToggles, function(toggle){
        _V_.removeClass(toggle, "vjs-playing");
        _V_.addClass(toggle, "vjs-paused");
      });
    }
  }
);
// Play
VideoJS.player.newBehavior("playButton", function(element){
    _V_.addListener(element, "click", this.onPlayButtonClick.context(this));
  },{
    onPlayButtonClick: function(event){ this.play(); }
  }
);
// Pause
VideoJS.player.newBehavior("pauseButton", function(element){
    _V_.addListener(element, "click", this.onPauseButtonClick.context(this));
  },{
    onPauseButtonClick: function(event){ this.pause(); }
  }
);

VideoJS.player.newBehavior("playProgressBar", function(element){
    if (!this.playProgressBars) {
      this.playProgressBars = [];
      this.onCurrentTimeUpdate(this.updatePlayProgressBars);
    }
    this.playProgressBars.push(element);
  },{

    updatePlayProgressBars: function(newTime){
      var progress = (newTime !== undefined) ? newTime / this.duration() : this.currentTime() / this.duration();
      if (isNaN(progress)) { progress = 0; }
      this.each(this.playProgressBars, function(bar){
        if (bar.style) { bar.style.width = _V_.round(progress * 100, 2) + "%"; }
      });
    }
  }
);

VideoJS.player.newBehavior("loadProgressBar", function(element){
    if (!this.loadProgressBars) { this.loadProgressBars = []; }
    this.loadProgressBars.push(element);
    this.onBufferedUpdate(this.updateLoadProgressBars);
  },{
    updateLoadProgressBars: function(){
      this.each(this.loadProgressBars, function(bar){
        if (bar.style) { bar.style.width = _V_.round(this.bufferedPercent() * 100, 2) + "%"; }
      });
    }
  }
);


VideoJS.player.newBehavior("currentTimeDisplay", function(element){
    if (!this.currentTimeDisplays) {
      this.currentTimeDisplays = [];
      this.onCurrentTimeUpdate(this.updateCurrentTimeDisplays);
    }
    this.currentTimeDisplays.push(element);
  },{

    updateCurrentTimeDisplays: function(newTime){
      if (!this.currentTimeDisplays) { return; }

      var time = (newTime) ? newTime : this.currentTime();
      this.each(this.currentTimeDisplays, function(dis){
        dis.innerHTML = _V_.formatTime(time);
      });
    }
  }
);


VideoJS.player.newBehavior("durationDisplay", function(element){
    if (!this.durationDisplays) {
      this.durationDisplays = [];
      this.onCurrentTimeUpdate(this.updateDurationDisplays);
    }
    this.durationDisplays.push(element);
  },{
    updateDurationDisplays: function(){
      if (!this.durationDisplays) { return; }
      this.each(this.durationDisplays, function(dis){
        if (this.duration()) { dis.innerHTML = _V_.formatTime(this.duration()); }
      });
    }
  }
);


VideoJS.player.newBehavior("currentTimeScrubber", function(element){
    _V_.addListener(element, "mousedown", this.onCurrentTimeScrubberMouseDown.rEvtContext(this));
  },{

    onCurrentTimeScrubberMouseDown: function(event, scrubber){
      event.preventDefault();
      this.currentScrubber = scrubber;

      this.stopTrackingCurrentTime(); // Allows for smooth scrubbing

      this.videoWasPlaying = !this.paused();
      this.pause();

      _V_.blockTextSelection();
      this.setCurrentTimeWithScrubber(event);
      _V_.addListener(document, "mousemove", this.onCurrentTimeScrubberMouseMove.rEvtContext(this));
      _V_.addListener(document, "mouseup", this.onCurrentTimeScrubberMouseUp.rEvtContext(this));
    },
    onCurrentTimeScrubberMouseMove: function(event){ // Removeable
      this.setCurrentTimeWithScrubber(event);
    },
    onCurrentTimeScrubberMouseUp: function(event){ // Removeable
      _V_.unblockTextSelection();
      document.removeEventListener("mousemove", this.onCurrentTimeScrubberMouseMove, false);
      document.removeEventListener("mouseup", this.onCurrentTimeScrubberMouseUp, false);
      if (this.videoWasPlaying) {
        this.play();
        this.trackCurrentTime();
      }
    },
    setCurrentTimeWithScrubber: function(event){
      var newProgress = _V_.getRelativePosition(event.pageX, this.currentScrubber);
      var newTime = newProgress * this.duration();
      this.triggerCurrentTimeListeners(0, newTime); // Allows for smooth scrubbing

      if (newTime == this.duration()) { newTime = newTime - 0.1; }
      this.currentTime(newTime);
    }
  }
);

VideoJS.player.newBehavior("volumeDisplay", function(element){
    if (!this.volumeDisplays) {
      this.volumeDisplays = [];
      this.onVolumeChange(this.updateVolumeDisplays);
    }
    this.volumeDisplays.push(element);
    this.updateVolumeDisplay(element); // Set the display to the initial volume
  },{


    updateVolumeDisplays: function(){
      if (!this.volumeDisplays) { return; }
      this.each(this.volumeDisplays, function(dis){
        this.updateVolumeDisplay(dis);
      });
    },
    updateVolumeDisplay: function(display){
      var volNum = Math.ceil(this.volume() * 6);
      this.each(display.children, function(child, num){
        if (num < volNum) {
          _V_.addClass(child, "vjs-volume-level-on");
        } else {
          _V_.removeClass(child, "vjs-volume-level-on");
        }
      });
    }
  }
);

VideoJS.player.newBehavior("volumeScrubber", function(element){
    _V_.addListener(element, "mousedown", this.onVolumeScrubberMouseDown.rEvtContext(this));
  },{

    onVolumeScrubberMouseDown: function(event, scrubber){

      _V_.blockTextSelection();
      this.currentScrubber = scrubber;
      this.setVolumeWithScrubber(event);
      _V_.addListener(document, "mousemove", this.onVolumeScrubberMouseMove.rEvtContext(this));
      _V_.addListener(document, "mouseup", this.onVolumeScrubberMouseUp.rEvtContext(this));
    },
    onVolumeScrubberMouseMove: function(event){
      this.setVolumeWithScrubber(event);
    },
    onVolumeScrubberMouseUp: function(event){
      this.setVolumeWithScrubber(event);
      _V_.unblockTextSelection();
      document.removeEventListener("mousemove", this.onVolumeScrubberMouseMove, false);
      document.removeEventListener("mouseup", this.onVolumeScrubberMouseUp, false);
    },
    setVolumeWithScrubber: function(event){
      var newVol = _V_.getRelativePosition(event.pageX, this.currentScrubber);
      this.volume(newVol);
    }
  }
);

VideoJS.player.newBehavior("fullscreenToggle", function(element){
    _V_.addListener(element, "click", this.onFullscreenToggleClick.context(this));
  },{

    onFullscreenToggleClick: function(event){
      if (!this.videoIsFullScreen) {
        this.enterFullScreen();
      } else {
        this.exitFullScreen();
      }
    },

    fullscreenOnWindowResize: function(event){ // Removeable
      this.positionControlBars();
    },

    fullscreenOnEscKey: function(event){ // Removeable
      if (event.keyCode == 27) {
        this.exitFullScreen();
      }
    }
  }
);

VideoJS.player.newBehavior("bigPlayButton", function(element){
    if (!this.elements.bigPlayButtons) {
      this.elements.bigPlayButtons = [];
      this.onPlay(this.bigPlayButtonsOnPlay);
      this.onEnded(this.bigPlayButtonsOnEnded);
    }
    this.elements.bigPlayButtons.push(element);
    this.activateElement(element, "playButton");
  },{
    bigPlayButtonsOnPlay: function(event){ this.hideBigPlayButtons(); },
    bigPlayButtonsOnEnded: function(event){ this.showBigPlayButtons(); },
    showBigPlayButtons: function(){
      this.each(this.elements.bigPlayButtons, function(element){
        element.style.display = "block";
      });
    },
    hideBigPlayButtons: function(){
      this.each(this.elements.bigPlayButtons, function(element){
        element.style.display = "none";
      });
    }
  }
);

VideoJS.player.newBehavior("spinner", function(element){
    if (!this.spinners) {
      this.spinners = [];
      _V_.addListener(this.video, "loadeddata", this.spinnersOnVideoLoadedData.context(this));
      _V_.addListener(this.video, "loadstart", this.spinnersOnVideoLoadStart.context(this));
      _V_.addListener(this.video, "seeking", this.spinnersOnVideoSeeking.context(this));
      _V_.addListener(this.video, "seeked", this.spinnersOnVideoSeeked.context(this));
      _V_.addListener(this.video, "canplay", this.spinnersOnVideoCanPlay.context(this));
      _V_.addListener(this.video, "canplaythrough", this.spinnersOnVideoCanPlayThrough.context(this));
      _V_.addListener(this.video, "waiting", this.spinnersOnVideoWaiting.context(this));
      _V_.addListener(this.video, "stalled", this.spinnersOnVideoStalled.context(this));
      _V_.addListener(this.video, "suspend", this.spinnersOnVideoSuspend.context(this));
      _V_.addListener(this.video, "playing", this.spinnersOnVideoPlaying.context(this));
      _V_.addListener(this.video, "timeupdate", this.spinnersOnVideoTimeUpdate.context(this));
    }
    this.spinners.push(element);
  },{
    showSpinners: function(){
      this.each(this.spinners, function(spinner){
        spinner.style.display = "block";
      });
      clearInterval(this.spinnerInterval);
      this.spinnerInterval = setInterval(this.rotateSpinners.context(this), 100);
    },
    hideSpinners: function(){
      this.each(this.spinners, function(spinner){
        spinner.style.display = "none";
      });
      clearInterval(this.spinnerInterval);
    },
    spinnersRotated: 0,
    rotateSpinners: function(){
      this.each(this.spinners, function(spinner){

        spinner.style.WebkitTransform = 'scale(0.5) rotate('+this.spinnersRotated+'deg)';
        spinner.style.MozTransform =    'scale(0.5) rotate('+this.spinnersRotated+'deg)';
      });
      if (this.spinnersRotated == 360) { this.spinnersRotated = 0; }
      this.spinnersRotated += 45;
    },
    spinnersOnVideoLoadedData: function(event){ this.hideSpinners(); },
    spinnersOnVideoLoadStart: function(event){ this.showSpinners(); },
    spinnersOnVideoSeeking: function(event){  },
    spinnersOnVideoSeeked: function(event){  },
    spinnersOnVideoCanPlay: function(event){  },
    spinnersOnVideoCanPlayThrough: function(event){ this.hideSpinners(); },
    spinnersOnVideoWaiting: function(event){


      this.showSpinners();
    },
    spinnersOnVideoStalled: function(event){},
    spinnersOnVideoSuspend: function(event){},
    spinnersOnVideoPlaying: function(event){ this.hideSpinners(); },
    spinnersOnVideoTimeUpdate: function(event){

      if(this.spinner.style.display == "block") { this.hideSpinners(); }
    }
  }
);

VideoJS.player.newBehavior("subtitlesDisplay", function(element){
    if (!this.subtitleDisplays) {
      this.subtitleDisplays = [];
      this.onCurrentTimeUpdate(this.subtitleDisplaysOnVideoTimeUpdate);
      this.onEnded(function() { this.lastSubtitleIndex = 0; }.context(this));
    }
    this.subtitleDisplays.push(element);
  },{
    subtitleDisplaysOnVideoTimeUpdate: function(time){

      if (this.subtitles) {

        if (!this.currentSubtitle || this.currentSubtitle.start >= time || this.currentSubtitle.end < time) {
          var newSubIndex = false,


              reverse = (this.subtitles[this.lastSubtitleIndex].start > time),

              i = this.lastSubtitleIndex - (reverse) ? 1 : 0;
          while (true) { // Loop until broken
            if (reverse) { // Looping in reverse

              if (i < 0 || this.subtitles[i].end < time) { break; }

              if (this.subtitles[i].start < time) {
                newSubIndex = i;
                break;
              }
              i--;
            } else { // Looping forward

              if (i >= this.subtitles.length || this.subtitles[i].start > time) { break; }

              if (this.subtitles[i].end > time) {
                newSubIndex = i;
                break;
              }
              i++;
            }
          }

          if (newSubIndex !== false) {
            this.currentSubtitle = this.subtitles[newSubIndex];
            this.lastSubtitleIndex = newSubIndex;
            this.updateSubtitleDisplays(this.currentSubtitle.text);
          } else if (this.currentSubtitle) {
            this.currentSubtitle = false;
            this.updateSubtitleDisplays("");
          }
        }
      }
    },
    updateSubtitleDisplays: function(val){
      this.each(this.subtitleDisplays, function(disp){
        disp.innerHTML = val;
      });
    }
  }
);

// Convenience Functions (mini library)
// Functions not specific to video or VideoJS and could probably be replaced with a library like jQuery
////////////////////////////////////////////////////////////////////////////////

VideoJS.extend({

  addClass: function(element, classToAdd){
    if ((" "+element.className+" ").indexOf(" "+classToAdd+" ") == -1) {
      element.className = element.className === "" ? classToAdd : element.className + " " + classToAdd;
    }
  },
  removeClass: function(element, classToRemove){
    if (element.className.indexOf(classToRemove) == -1) { return; }
    var classNames = element.className.split(/\s+/);
    classNames.splice(classNames.lastIndexOf(classToRemove),1);
    element.className = classNames.join(" ");
  },
  createElement: function(tagName, attributes){
    return this.merge(document.createElement(tagName), attributes);
  },

  blockTextSelection: function(){
    document.body.focus();
    document.onselectstart = function () { return false; };
  },

  unblockTextSelection: function(){ document.onselectstart = function () { return true; }; },

  formatTime: function(secs) {
    var seconds = Math.round(secs);
    var minutes = Math.floor(seconds / 60);
    minutes = (minutes >= 10) ? minutes : "0" + minutes;
    seconds = Math.floor(seconds % 60);
    seconds = (seconds >= 10) ? seconds : "0" + seconds;
    return minutes + ":" + seconds;
  },

  getRelativePosition: function(x, relativeElement){
    return Math.max(0, Math.min(1, (x - this.findPosX(relativeElement)) / relativeElement.offsetWidth));
  },

  findPosX: function(obj) {
    var curleft = obj.offsetLeft;
    while(obj = obj.offsetParent) {
      curleft += obj.offsetLeft;
    }
    return curleft;
  },
  getComputedStyleValue: function(element, style){
    return window.getComputedStyle(element, null).getPropertyValue(style);
  },

  round: function(num, dec) {
    if (!dec) { dec = 0; }
    return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
  },

  addListener: function(element, type, handler){
    if (element.addEventListener) {
      element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
      element.attachEvent("on"+type, handler);
    }
  },
  removeListener: function(element, type, handler){
    if (element.removeEventListener) {
      element.removeEventListener(type, handler, false);
    } else if (element.attachEvent) {
      element.detachEvent("on"+type, handler);
    }
  },

  get: function(url, onSuccess){
    if (typeof XMLHttpRequest == "undefined") {
      XMLHttpRequest = function () {
        try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
        try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (f) {}
        try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (g) {}

        throw new Error("This browser does not support XMLHttpRequest.");
      };
    }
    var request = new XMLHttpRequest();
    request.open("GET",url);
    request.onreadystatechange = function() {
      if (request.readyState == 4 && request.status == 200) {
        onSuccess(request.responseText);
      }
    }.context(this);
    request.send();
  },

  trim: function(string){ return string.toString().replace(/^\s+/, "").replace(/\s+$/, ""); },

  bindDOMReady: function(){
    if (document.readyState === "complete") {
      return VideoJS.onDOMReady();
    }
    if (document.addEventListener) {
      document.addEventListener("DOMContentLoaded", VideoJS.DOMContentLoaded, false);
      window.addEventListener("load", VideoJS.onDOMReady, false);
    } else if (document.attachEvent) {
      document.attachEvent("onreadystatechange", VideoJS.DOMContentLoaded);
      window.attachEvent("onload", VideoJS.onDOMReady);
    }
  },

  DOMContentLoaded: function(){
    if (document.addEventListener) {
      document.removeEventListener( "DOMContentLoaded", VideoJS.DOMContentLoaded, false);
      VideoJS.onDOMReady();
    } else if ( document.attachEvent ) {
      if ( document.readyState === "complete" ) {
        document.detachEvent("onreadystatechange", VideoJS.DOMContentLoaded);
        VideoJS.onDOMReady();
      }
    }
  },

  DOMReadyList: [],
  addToDOMReady: function(fn){
    if (VideoJS.DOMIsReady) {
      fn.call(document);
    } else {
      VideoJS.DOMReadyList.push(fn);
    }
  },

  DOMIsReady: false,
  onDOMReady: function(){
    if (VideoJS.DOMIsReady) { return; }
    if (!document.body) { return setTimeout(VideoJS.onDOMReady, 13); }
    VideoJS.DOMIsReady = true;
    if (VideoJS.DOMReadyList) {
      for (var i=0; i<VideoJS.DOMReadyList.length; i++) {
        VideoJS.DOMReadyList[i].call(document);
      }
      VideoJS.DOMReadyList = null;
    }
  }
});
VideoJS.bindDOMReady();

// when using in event listeners and timeouts
Function.prototype.context = function(obj){
  var method = this,
  temp = function(){
    return method.apply(obj, arguments);
  };
  return temp;
};

// But insteaad keep "this" intact, and passes the var as the second argument of the function
// Need for event listeners where you need to know what called the event
// Only use with event callbacks
Function.prototype.evtContext = function(obj){
  var method = this,
  temp = function(){
    var origContext = this;
    return method.call(obj, arguments[0], origContext);
  };
  return temp;
};

// Replaces the original function with a version that has context
// So it can be removed using the original function name.
// In order to work, a version of the function must already exist in the player/prototype
Function.prototype.rEvtContext = function(obj, funcParent){
  if (this.hasContext === true) { return this; }
  if (!funcParent) { funcParent = obj; }
  for (var attrname in funcParent) {
    if (funcParent[attrname] == this) {
      funcParent[attrname] = this.evtContext(obj);
      funcParent[attrname].hasContext = true;
      return funcParent[attrname];
    }
  }
  return this.evtContext(obj);
};

if (window.jQuery) {
  (function($) {
    $.fn.VideoJS = function(options) {
      this.each(function() {
        VideoJS.setup(this, options);
      });
      return this;
    };
    $.fn.player = function() {
      return this[0].player;
    };
  })(jQuery);
}

window.VideoJS = window._V_ = VideoJS;

})(window);

(function(){  this.tinydom = this.tinydom || {}; }());

tinydom.plusone = new tinydom.EventEmitter();
tinydom.extend(tinydom.plusone, {
	
	counter : 0,
	callbacks : {},
	
	init : function(options, callback) {
		this._initOptions = tinydom.extend({}, options || {});
		
		if (callback) {
			callback();
		}
	},
	
	render : function(options, callback) {
		this.counter += 1;

		options = tinydom.extend({

			href	: location.href,
			size	: 'standard'
		}, options || {});
		options.callback = 'tinydom.plusone.callbacks.cb'+this.counter;
		options.count = (options.count!==false && options.count!=="false" && options.showCount!==false) ? 'true' : 'false';
		
		console.log('+1 Options: ', options);
		
		if (options.customUrl) {
			options.href = options.customUrl;
		}
		else {
			options.href = options.href.replace(/^(.*?:\/\/[^\/]+)[#!\/]*/gim,'$1/#!/');
		}
		
		this.callbacks['cb'+this.counter] = function(opt) {

			tinydom.plusone._fireEvent('share', opt);

			if (callback) {
				callback(opt);
			}
		};

		if (!options.parent.attr('id')) {
			options.parent.attr('id', 'plusone_'+this.counter);
		}

		
		gapi.plusone.render(options.parent.attr('id'), options);
	},
	
	_log : function(t) {
		if (window.console && window.console.log) {
			console.log('tinydom.plusone.log:: ', t);
		}
	}
});


(function(){  this.tinydom = this.tinydom || {}; }());

tinydom.linkedin = new tinydom.EventEmitter();
tinydom.extend(tinydom.linkedin, {
	
	counter : 0,
	callbacks : {},
	
	init : function(options, callback) {
		this._initOptions = tinydom.extend({}, options || {});
		
		if (callback) {
			callback();
		}
	},
	
	share: function(options, callback){
		var overlay,
			boxid;
		
		this.counter += 1;
		
		boxid = 'linkedin_linkedbox_holder_'+this.counter;
		
		options = tinydom.extend({
			name : document.title,
			href	: location.href,
			site: "dev2.socialseek.com"
		}, options || {});

		var shareSource = 'http://www.linkedin.com/shareArticle?&url='+options.href+'&title='+options.name+'&summary='+options.description+'&source='+options.site;
		
		console.log('LinkedIn Options: ', options);

		
		app.components.load('ModalOverlay', {
			on: {
				ready : function(dialog){
					tinydom.el({
						className : 'linkedin_overlaycontent_base',
						children : [
							{
								css: "position: absolute; width: 40px; height: 40px;top: 0; right: 0; cursor: pointer; z-index: 600;",
								onclick: function(e){
									dialog.close();
									dialog = null;
									return tinydom.cancelEvent(e);
								}
							},
							{
								type: 'iframe',
								css : "display:block; width:100%; height:100%; border:none;",
								attributes: {
									src: shareSource
								}
							}
						]
					}, dialog.content);
					dialog.adjustSize(true, {
						height: 400,
						width: 500
					});
				}
			}
		});
		
	},
		
	_log : function(t) {
		if (window.console && window.console.log) {
			console.log('tinydom.linkedin.log:: ', t);
		}
	}
});


tinydom.addNodeSelectionPlugin('placeholder', (function(){
	var nativeSupport = false;	//!!('placeholder' in document.createElement('input'));
	return  function() {
		var placeholders = this;
		if (!nativeSupport && placeholders.attr('data-placeholder-active')!=='1') {
			placeholders.attr('data-placeholder-active', '1');
			placeholders.on('focus', function() {
				var me = tinydom.el(this);
				if (me.value()===me.attr('data-placeholder')) {
					me.declassify('placeHolderContent').value('', {fireChange:false});
				}
			});
			placeholders.on('blur,change', function() {
				var me = tinydom.el(this);
				setTimeout(function() {
					var val = me.value();
					if (!val || val.length<1) {
						me.classify('placeHolderContent').value(me.attr('data-placeholder'), {fireChange:false});
					}
					else {
						me.declassify('placeHolderContent');
					}
					me = null;
				}, 10);
			});
			placeholders.fireEvent('change');
		}
		return this;
	};
}()));window.tinydom = window.tinydom || {};
tinydom.ui = tinydom.ui || {};

(function(events, f, data) {
	
	data = {
		instanceid_counter : 0,
		instances : {}
	};
	
	f = {
		className : 'tabContainerBase',
		getBase : function(child) {
			var p = child;
			do {
				if (p.hasClass(f.className)) {
					return p;
				}
			} while((p=p.parent()).exists() && p.nodeName()!=='body')
			return false;
		},
		getDataFromBase : function(base) {
			var id = base.attr('data-tabs-instance');
			return f.getDataFromId(id);
		},
		getDataFromId : function(id) {
			var self = data.instances[id];
			if (id && self) {
				return self;
			}
			return null;
		}
	};
	
	events = {
		tabClick : function(e) {
			var me = tinydom.el(this),
				tabId = me.attr('data-tabid'),
				base = f.getBase(me),
				data = f.getDataFromBase(base),
				activePanel;
			me.siblings().declassify('active');
			me.classify('active');
			data.activeTab = tabId;
			base.query('>.tabPanelContainer>[data-tabid]').each(function(panel) {
				if (panel.attr('data-tabid')===tabId) {
					activePanel = panel.show();
				}
				else {
					panel.hide(true);
				}
			});

			if (data.tabState) {
				data.tabState.doStateUpdate();
			}
			return tinydom.cancelEvent(e);
		}
	};
	
	
	
	tinydom.ui.tabs = function(base, stateManager, options) {
		var self,
			id;
		options = options || {};
		if (!base || !base.each) {
			return null;
		}
		
		if (base.attr('data-tabs-instance')) {
			id = base.attr('data-tabs-instance');
		}
		else {
			data.instanceid_counter += 1;
			id = data.instanceid_counter+'';
		}
		self = data.instances[id] = {
			id : id
		};
		
		self.tabViewName = options.tabviewName || options.stateId || base.attr('data-tabview-name') || ('tab'+id);
		
		base.classify('tabContainerBase').attr('data-tabs-instance', id);
		
		base.query('>.tabContainer>.tab').on('click', events.tabClick);
		
		
		self.tabState = {
			id : self.id,
			doStateUpdate : function() {
				var self = f.getDataFromId(this.id),
					tab = self.activeTab;		//base.query('>.tabContainer>.tab.active').attr('data-tabid');
				if (this.setState) {
					this.setState(tab);
				}
			},
			restoreState : function(tab) {
				if (tab) {
					base.query('>.tabContainer>.tab[data-tabid='+tab+']').fireEvent('click');
				}
				else {
					base.query('>.tabContainer>.tab').first().fireEvent('click');
				}
			}
		};
		
		if (stateManager) {
			stateManager.removeObject(self.tabViewName);
			stateManager.addObject(self.tabViewName, self.tabState);
		}
		else {

			self.tabState.restoreState();
		}
		
		setTimeout(function() {
			options = stateManager = self = null;
		}, 1);
		
		return self.tabState;
	};
	
	
	tinydom.ui.tabs.remove = function(base, stateManager) {
		var self = f.getDataFromBase(base);

		if (self) {
			if (stateManager) {
				stateManager.removeObject(self.tabViewName);
			}
			data.instances[self.id] = null;
		}
	};
	
	
	
	tinydom.addNodeSelectionPlugin('tabs', function(stateManager, options) {
		tinydom.ui.tabs(this, stateManager, options);
	});
	
	
	tinydom.addNodeSelectionPlugin('removeTabs', function(stateManager) {
		tinydom.ui.tabs.remove(this, stateManager);
	});
	
}());

var Socialseek = (function() {
		
	var self = tinydom.extend(new tinydom.EventEmitter(), {
			version : '0.5.0',
			apiConnectors : {}
		}),
		
		
		config = ({

			'dev2.socialseek.com' : {
				apiRoot : '/',
				chatApiRoot : 'http://chatdev2.socialseek.com/'
			},

			'socialseek.com' : {
				apiRoot : '/',
				chatApiRoot : 'http://chat.socialseek.com/'			// CHANGE THIS
			}
		})[location.hostname.toLowerCase().replace(/^www\./gim,'')],
		
		
		defaultLocalFormatter = function(y,r,s){ return r[s+'-results']; };
	
	
	
	self.storage = new tinydom.LocalStorage('me_ssk');
	
	
	
	self.services = {
		
		
		
		twitter : {
			symbol	: 'T',
			title	: 'Twitter',
			localFormatter : defaultLocalFormatter,
			directFormatter : function(result, response) {

				var results = tinydom.isArray(response) ? response : (response && response.results),
					result, x, d, body;
				if (results) {
					for (x=results.length; x--; ) {
						result = results[x];
						body = result.text || result.body || '';
						if (app && app.hotTopics && app.hotTopics.isThisSpamAsync(body)) {

							results.splice(x, 1);
						}

						else if (body.match(/^RT\b/gm)) {

							results.splice(x, 1);
						}
						
						else {
							d = new Date(result.date || result.created_at);
							results[x] = {
								id			: result.id_str,
								username	: (result.user && result.user.name) || result.user || result.from_user,
								text		: body,
								thumb		: ((result.user && result.user.profile_image_url) || result.thumb || result.profile_image_url || '').replace(/_normal(\.[a-zA-Z0-9]+)$/gm,'_reasonably_small$1'),
								time		: d,
								time_formatted	: tinydom.date.format(d, '%l:%M %P')		// :%S
							};
						}
					}
				}
				return results;
			}
		},
		
		facebook : {
			symbol	: 'K',
			title	: 'Facebook',
			localFormatter : function(result, response, service) {
				var results = response[service+'-results'],
					x;
				if (result && results) {
					for (x=results.length; x--; ) {
						if (results[x].from==='Facebook') {		// omit system messages
							results.splice(x, 1);
						}
						else {
							if (!results[x].id) {
								results[x].id = results[x].from+''+results[x].updated_time
							}
							results[x].username = results[x].from;
							delete results[x].from;
							results[x].text = ((results[x].text || results[x].text) + '').replace(/<\/?[a-z][a-z0-9\:](\s.*?)?>/gim,'');
						}
					}
				}
				return results;
			},
			directFormatter : function(result, response, service) {
				var results, origResults, result, d, x;
				if (result && response.data) {
					origResults = response.data;
					results = [];
					for (x=0; x<origResults.length; x++) {
						result = origResults[x];
						d = new Date(result.updated_time || result.created_time);
						if (result.from.name!=='Facebook') {
							results.push({
								id				: result.id,
								username		: result.from.name,
								thumb			: result.picture,
								text			: (result.type==='video' ? result.name : result.message) || result.description || result.name || result.link || '',
								userid			: result.from.id,
								type			: result.type,
								time			: d,
								time_formatted	: tinydom.date.format(d, '%l:%M:%S%P'),
								url				: result.link
							});
						}
					}
				}
				return results;
			}
		},
		
		flickr : {
			symbol	: 'F',
			title	: 'Flickr',
			directSearchParam : 'text',
			directParameters : {
				per_page : 50,
				extras : 'description,owner_name,url_t,url_b,url_m,url_z'
			},
			localFormatter : defaultLocalFormatter,
			directFormatter : function(result, response) {
				var results = [],
					i, photo;
				if (response && response.photos && response.photos.photo) {
					for (i=0; i<response.photos.photo.length; i++) {
						photo = response.photos.photo[i];
						results.push({
							title : photo.title,
							text : photo.description._content,
							url : photo.url_b || photo.url_z || photo.url_m || photo.url_s || photo.url_t,	// large (1024), newMedium (640), oldMedium (500 or 240)
							thumb : photo.url_s || photo.url_t,												// small (75x75), falls back to thumb (100 bounded)
							username : photo.ownername
						});
					}
				}
				return results;
			}
		},
		
		youtube : {
			symbol	: 'Y',
			title	: 'YouTube',
			directFormatter : function(success, response) {
				var results = [],
					i, p, r, t;
				if (success && response && response.data && response.data.items) {
					for (i=0; i<response.data.items.length; i++) {
						p = response.data.items[i];
						t = tinydom.date.create(p.uploaded);

						r = {
							id : p.id,
							date : t.getTime(),
							time : t.getTime(),
							time_formatted : tinydom.date.format(t, '%h %d, %Y'),
							title : p.title,
							text : p.description,
							thumb : p.thumbnail.sqDefault || p.thumbnail.hqDefault,
							username : p.uploader
						};
						results.push(r);
					}
				}

				return results;
			}
		},
		
		buzz : {
			symbol	: 'Z',
			title	: 'Buzz'
		},
		
		
		
		events : {
			symbol	: 'E',
			title	: 'Events'
		},
		
		news_blogs : {
			title	: 'News & Blogs'
		}
		
		
		
	};
	
	
	self.serviceList = [
		'news_blogs', 'twitter', 'youtube',  'flickr', 'facebook', 'events'
	];
	
	
	self.api = {
		root : config.apiRoot,
		statusProperty : "success",
		onRequestCompleted : function(id, data, success, requestParameters, options) {
			self._fireEvent(id+'.complete', [data, success, requestParameters, options]);
			self._fireEvent('action', [id, data, success, requestParameters, options]);
		},


		endpoints : {
			
			
			chat : {
				login : {
					parameters : {
						userid : 'string'
					},
					endpoint : config.chatApiRoot + 'auth/login',
					auth : true
				},
				
				logout : {
					endpoint : config.chatApiRoot + 'auth/logout',
					auth : true
				},
				
				post : {
					parameters : {
						body	: 'string'
					},
					optionalParameters : {
						'attachment-title'	: 'string',
						'attachment-url'	: 'string',
						'site-id'			: 'string',
						'site-keywords'		: 'string'
					},
					endpoint : config.chatApiRoot + 'a/message/new',
					auth : true
				},
				
				updates : {
					optionalParameters : {
						'site-id'			: 'string',
						'site-keywords'		: 'string'
					},
					endpoint : config.chatApiRoot + 'a/message/updates',
					auth : false
				},
				
				history : {
					optionalParameters : {
						'site-id'			: 'string',
						'site-keywords'		: 'string'
					},
					endpoint : config.chatApiRoot + 'a/history',
					auth : false
				}
			},
			
			
			proxied : {
				all : {
					parameters : {
						q	: String
					},
					endpoint : "api.php?method=Request&tpl=false",
					type : "GET"
				}
			},
			
			
			twitter : {
				user_timeline : {
					parameters : {
						screen_name : String
					},
					endpoint : 'http://api.twitter.com/1/statuses/user_timeline.json',
					type : 'jsonp'
				}
			},
			
			
			youtube : {
				user_timeline : {
					parameters : {
						screen_name : String
					},
					endpoint : 'http://api.twitter.com/1/statuses/user_timeline.json',
					type : 'jsonp'
				}
			},
			
			
			
			engage : {
				search : {
					parameters : {
						q : String
					},
					endpoint : "api.php?method=Engage&operation=search",
					type : 'POST'
				},
				post : {
					auth : true,
					parameters : {
						q : String,
						message : String
					},
					endpoint : "api.php?method=Engage&operation=post",
					type : 'POST'
				}
			},
			
			direct : {
				engage : {
					parameters : {
						q : String
					},
					endpoint : "api.php?method=Engage&operation=search",
					type : 'POST'
				},
				
				twitter : {
					parameters : {
						q	: String
					},
					optionalParameters : {
						rpp			: Number,			
						page		: Number,			
						since_id	: Number,			
						until		: String,			
						geocode		: String,			
						result_type	: String			
					},
					endpoint : "http://search.twitter.com/search.json?rpp=50",
					type : "jsonp"
				},
				
				facebook : {
					parameters : {
						q	: String
					},
					
					endpoint : "http://graph.facebook.com/search?type=post",
					type : "jsonp"
				},
				
				buzz : {
					parameters : {
						q	: String
					},
					
					endpoint : "http://www.googleapis.com/buzz/v1/activities/search?alt=json",

					type : "jsonp"
				},
				
				blogs : {


					parameters : {
						q	: String
					},
					
					endpoint : "http://ajax.googleapis.com/ajax/services/search/blogs?v=1.0&rsz=8",		// &scoring=d (date), rsz=results per page
					type : "jsonp"
				},
				
				
				flickr : {

					parameters : {
						text	: String
					},
					optionalParameters : {
						per_page	: Number,		// Results per page, defaults to 100
						page		: Number,		// Page number, defaults to 1
						extras		: String		// CSV of options
					},
					endpoint : "http://www.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key=90760f7f0f5b533d185a68acba216c35&jsoncallback={!callback}",
					type : "jsonp"
				},
				
				youtube : {
					parameters : {

					},
					optionalParamters : {
						q : String,
						author : String
					},
					endpoint : "http://gdata.youtube.com/feeds/api/videos?v=2&alt=jsonc&max-results=50",
					type : "jsonp"
				},
				
				news : {
					
					parameters : {
						q	: String
					},
					
					endpoint : "http://ajax.googleapis.com/ajax/services/search/news?v=1.0&rsz=8",		// &scoring=d (date), rsz=results per page
					type : "jsonp"
				}
			},
			
			
			localAuth : {
				socialLogin : {
					parameters : {
						acct_type	: String
					},
					optionalParameters : {
						twttr_bridge_code : String,
						fb_session : String,
						twttr_session : String
					},
					endpoint : "api.php?method=Login",
					type : "POST",
					oncomplete : function(result, response) {
						if (result && response.session) {
							self.api.setAuthParameter('token', response.session.token);
						}
					}
				},
				login : {
					parameters : {
						username	: String,
						password	: String
					},
					endpoint : "api.php?method=Login",
					type : "POST",
					oncomplete : function(result, response) {
						if (result && response.session) {
							self.api.setAuthParameter('token', response.session.token);
						}
					}
				},
				register : {
					parameters : {
						email		: String,
						username	: String,
						password	: String
					},
					endpoint : "api.php?method=Register",
					type : "POST",
					precallback : function(result, response) {
						if (result && response.session) {
							self.api.setAuthParameter('token', response.session.token);
						}
					}
				},
				continueSession : {
					parameters : {
						token	: String
					},
					endpoint : "api.php?method=ContinueSession",
					type : "POST",
					precallback : function(result, response) {
						if (result && response.session) {
							self.api.setAuthParameter('token', response.session.token);
						}
					}
				},
				resetPassword : {
					parameters : {
						email	: String
					},
					endpoint : "api.php?method=ResetPassword",
					type : "POST"
				},
				logout : {
					endpoint : "api.php?method=Logout",
					type : "POST",
					precallback : function(result, response) {
						self.api.setAuthParameter('token', null);
					},
					auth : true
				}
			},
			
			subscription : {
				purchaseSessionTransfer : {
					auth : true,
					endpoint : 'api.php?method=Subscription&operation=purchaseSessionTransfer',
					type : 'POST'
				}
			},
			
			sites : {
				getCategories : {
					endpoint : "api.php?method=Sites&operation=getCategories",
					type : "GET"
				},
				getSitesByCategory : {
					optionalParameters : {
						category : String
					},
					endpoint : "api.php?method=Sites&operation=getSitesByCategory",
					type : "GET"
				},
				similar : {
					optionalParameters : {
						site_id : String,
						keywords : String
					},
					endpoint : "api.php?method=Sites&operation=similar",
					type : "POST"
				},
				autosuggest : {
					parameters : {

					},
					optionalParameters : {
						q : String,
						from_user : String
					},
					endpoint : "api.php?method=Sites&operation=autosuggestSites",
					type : "POST"
				},
				quicklist : {
					endpoint : "api.php?method=Sites&operation=quicklist",
					type : "POST",
					auth : true
				},
				add : {
					parameters : {
					},
					endpoint : "api.php?method=Sites&operation=add",
					type : "POST",
					auth : true
				},
				update : {
					parameters : {

					},
					endpoint : "api.php?method=Sites&operation=update",
					type : "POST",
					auth : true
				},
				adminUpdate : {
					parameters : {
						id : String
					},
					endpoint : "api.php?method=Sites&operation=adminUpdate",
					type : "POST",
					auth : true
				},
				remove : {
					parameters : {
						id : String
					},
					endpoint : "api.php?method=Sites&operation=remove",
					type : "POST",
					auth : true
				},
				get : {
					endpoint : "api.php?method=Sites&operation=get",
					type : "POST",
					auth : true
				},
				info : {
					parameters : {


					},
					endpoint : "api.php?method=Sites&operation=info",
					type : "POST"
				},
				stats : {
					parameters : {
						id : String
					},
					endpoint : 'api.php?method=Sites&operation=stats',
					type : 'POST',
					auth : true
				},
				checkUrl : {
					parameters : {
						url : String
					},
					endpoint : "api.php?method=Sites&operation=checkUrl",
					type : "POST",
					auth : true
				}
			},
			
			savedSeeks : {
				add : {
					parameters : {
						keywords : String
					},
					endpoint : "api.php?method=SavedSeeks&operation=add",
					type : "POST",
					auth : true
				},
				remove : {
					parameters : {
						id : String
					},
					endpoint : "api.php?method=SavedSeeks&operation=remove",
					type : "POST",
					auth : true
				},
				get : {
					endpoint : "api.php?method=SavedSeeks&operation=get",
					type : "POST",
					auth : true
				}
			},
			
			userPrefs : {
				save : {
					parameters : {


					},
					endpoint : "api.php?method=UserPrefs&operation=save",
					type : "POST",
					auth : true
				},
				get : {
					endpoint : "api.php?method=UserPrefs&operation=get",
					type : "POST",
					auth : true
				}
			},
			
			userSeeks : {
				add : {
					parameters : {
						keywords : String
					},
					endpoint : "api.php?method=UserSeeks&operation=add",
					type : "POST"
				},
				getTrends : {
					endpoint : "api.php?method=UserSeeks&operation=getTrends",
					type : "POST"
				}
			},
			
			shares: {
				add: {
					parameters: {
						url: String,
						type: String,
						site: String
					},
					endpoint: "api.php?method=AddShare",
					type: "POST"
				}
			},
			
			messages : {
				share : {
					endpoint : "api.php?method=Messages&operation=share",
					type : "POST"
				},
				shareWithAuth : {
					endpoint : "api.php?method=Messages&operation=share",
					type : "POST",
					auth : true
				},
				feedback : {
					endpoint : "api.php?method=Messages&operation=feedback",
					type : "POST"
				},
				feedbackWithAuth : {
					endpoint : "api.php?method=Messages&operation=feedback",
					type : "POST",
					auth : true
				},
				signup : {
					parameters : {





					},
					endpoint : "api.php?method=Messages&operation=signup",
					type : "POST"
				},
				signupWithAuth : {
					endpoint : "api.php?method=Messages&operation=signup",
					type : "POST",
					auth : true
				},
				contactme : {
					endpoint : "api.php?method=Messages&operation=contactme",
					type : "POST"
				},
				contactmeWithAuth : {
					endpoint : "api.php?method=Messages&operation=contactme",
					type : "POST",
					auth : true
				}
			},
			
			
			trends : {
				twitter : {
					endpoint : "http://api.twitter.com/1/trends/current.json",
					type : "jsonp"
				}
			},
			
			
			googleServices : {
				feedLoad : {
					parameters : {
						q : String
					},
					optionalParameters : {
						num : Number				// limit results. default=4, max=100
					},
					endpoint : 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0',
					type : 'jsonp'
				},
				
				translate : {
					parameters : {
						q : 'string',
						langpair : 'string'		// |en
					},
					endpoint : 'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0',
					type : 'jsonp'
				}
			}
		}
	};
	
	
	for (var svc in self.services) {
		if (self.services.hasOwnProperty(svc)) {
			self.api.endpoints.proxied[svc] = {
				parameters : {
					q : String
				},
				endpoint : self.services[svc].endpoint || ("api.php?method=Request&tpl=false&" + self.services[svc].symbol+"=1"),
				type : self.services[svc].type || "GET"
			};
		}
	}
	
	
	self.api = tinydom.NativeAPI(self.api);
	
	
	self.api.combined = {};
	
	self.api.combined.news_blogs = function(options) {
		var originalCallback = options.callback,
			compiledResults = [],
			servicesLeft = 2,
			callback;
		
		callback = function(service, result, response) {
			var x, r, r2, i, inserted, publisher, siteDomain, blogDomain;
			servicesLeft -= 1;
			if (result && response && response.responseData && response.responseData.results) {
				for (x=0; x<response.responseData.results.length; x++) {
					r = response.responseData.results[x];
					d = new Date(r.publishedDate);
					r2 = {
						type : service,
						thumb : r.image && r.image.tbUrl,
						time : d,
						time_formatted : tinydom.date.format(d, '%l:%M%P, %b %e %Y'),
						text : tinydom.text.filter(r.content || r.title, 'truncate:300'),

						title : r.titleNoFormatting,
						url : r.unescapedUrl || r.postUrl
					};
					if (!r2.thumb && self.config.defaultFeedImages && self.config.defaultFeedImages.newsBlogs) {
						r2.thumb = self.config.defaultFeedImages.newsBlogs;
						r2.hasDefaultThumb = true;
					}
					
					if (service==='news') {
						publisher = r.publisher;
						siteDomain = (/\:\/\/([^\/]+)/gim).exec(r.unescapedUrl);
						siteDomain = (siteDomain && siteDomain[1] || '').replace(/^www\./gi,'');
						r2.username = publisher;
						r2.profile_url = r.unescapedUrl;
					}
					else if (service==='blogs') {
						author = r.author;
						blogDomain = (/\:\/\/([^\/]+)/gim).exec(r.blogUrl);
						blogDomain = (blogDomain && blogDomain[1] || '').replace(/^www\./gi,'');
						r2.username = blogDomain || author;
						r2.profile_url = r.blogUrl;
						r.thumb = r.thumb || ('http://'+blogDomain+'/favicon.ico');
					}

					inserted = false;
					for (i=0; i<compiledResults.length; i++) {
						if (compiledResults[i].time.getTime()<r2.time.getTime()) {
							compiledResults.splice(i, 0, r2);
							inserted = true;
							break;
						}
					}
					if (!inserted) {
						compiledResults.push(r2);
					}
				}
			}
			if (servicesLeft<=0) {

				originalCallback(true, compiledResults);
			}
		};
		
		self.api.direct.news(tinydom.extend({}, options, {
			callback : function(result, response) {
				callback('news', result, response);
			}
		}));
		self.api.direct.blogs(tinydom.extend({}, options, {
			callback : function(result, response) {
				callback('blogs', result, response);
			}
		}));
	};
	
	
	self.getFeed = function(service, search, callback, options) {
		var source = self.api.proxied,
			sourceProp = "proxied",
			method,
			searchParam,
			params = {};
		options = options || {};
		
		if(search || options.parameters) {
			if (options.source) {
				if (this.api.hasOwnProperty(options.source.toLowerCase())) {
					sourceProp = options.source.toLowerCase();
					source = this.api[sourceProp];
				}
				else {
					throw(new Error("SocialSeek.getFeed() :: Unknown source (=arguments[0]) requested."));
				}
			}
			if (service && source.hasOwnProperty(service)) {
				method = source[service];
				tinydom.extend(params, options);
				delete params.source;

				searchParam = self.services[service] && self.services[service][sourceProp.toLowerCase()+'SearchParam'];
				params[searchParam || 'q'] = search;
				if (options.hasOwnProperty('parameters')) {
					tinydom.extend(
						params,
						self.services[service] && self.services[service][sourceProp.toLowerCase()+'Parameters'] || {},
						options.parameters
					);
				}
				params.callback = function(result, response) {
					var formatter = sourceProp.toLowerCase() + "Formatter",
						formatterResponse;
					if (self.services.hasOwnProperty(service)) {
						if (self.services[service].hasOwnProperty(formatter)) {
							formatterResponse = self.services[service][formatter](result, response, service);
							if (formatterResponse===true || formatterResponse===false) {
								result = formatterResponse;
							}
							else if (formatterResponse!==null && formatterResponse!==undefined) {
								response = formatterResponse;
							}
						}
					}
					callback(result, response);
				};

				method(params);
			}
			else {
				throw(new Error("SocialSeek.getFeed() :: Unknown service requested."));
			}
		}
		else {
			throw(new Error("SocialSeek.getFeed() :: 'search' (=arguments[1]) is required."));
		}
	};
	
	
	
	
	self.createUpdateServiceConnector = function(service, keywords, responseFormatter, additionalParams) {
		var serviceOptions = {},
			sIndex = service.indexOf('.');
		if (sIndex>-1) {
			serviceOptions.source = service.substring(sIndex+1);
			service = service.substring(0, sIndex);
		}
		keywords = keywords || '';
		additionalParams = additionalParams || {};
		serviceOptions.parameters = additionalParams;
		var connector = function(callback, options) {
			var feedContainer = this;
			options = options || {};
			if (!options.currentKeywords) {
				options.currentKeywords = keywords;
			}
			self.getFeed(service, options.currentKeywords, function(success, response) {
				if (success && response) {
					var formatterResponse;
					if (responseFormatter) {
						formatterResponse = responseFormatter(response, service, serviceOptions.source);
						if (formatterResponse && formatterResponse!==true) {
							response = formatterResponse;
						}
					}
					feedContainer.updateWithResults(response, callback, options);
				}
				feedContainer = null;
			}, serviceOptions);
		};
		
		connector.setKeywords = function(newKeywords) {
			keywords = newKeywords;
		};
		
		connector.getKeywords = function() {
			return keywords;
		};
		
		connector.setSource = function(newSource) {
			serviceOptions.source = newSource;
		};
		
		connector.setService = function(newService) {
			service = newService;
		};
		
		connector.setAdditionalParams = function(newAdditionalParams) {
			tinydom.extend(additionalParams, newAdditionalParams);
		};
		
		return connector;
	};
	
	
	return self;
}());

var SocialSeek = Socialseek;

Socialseek.config = (function(webroot) {
	
	webroot = location.protocol + '//' + location.host + '/';
	
	return {
		sites : {
			baseUrl : webroot
		},
		company : {
			name	: 'Sensidea',
			url		: 'http://www.sensidea.com/',
			twitterUrl : 'http://twitter.com/socialseek/',
			facebookUrl : 'http://www.facebook.com/pages/Socialseek/78229964774',
			termsUrl	: webroot + 'pages/terms.html',
			privacyUrl	: webroot + 'pages/privacy.html'
		},
		
		defaultFeedImages : {
			newsBlogs : '/app/img/news_blogs_default.png'
		},
		
		profanityBlacklist : ('fuck,shit,nigga,nigger,slut,skank,ho,whore,bullshit,sucks,suck').split(','),
		
		translation : {
			languages : {
				"af"	: "Afrikaans",
				"sq"	: "Albanian",
				"am"	: "Amharic",
				"ar"	: "Arabic",
				"hy"	: "Armenian",
				"az"	: "Azerbaijani",
				"eu"	: "Basque",
				"be"	: "Belarusian",
				"bn"	: "Bengali",
				"bh"	: "Bihari",
				"br"	: "Breton",
				"bg"	: "Bulgarian",
				"my"	: "Burmese",
				"ca"	: "Catalan",
				"chr"	: "Cherokee",
				"zh"	: "Chinese",
				"zh-CN"	: "Chinese Simplified",
				"zh-TW"	: "Chinese Traditional",
				"co"	: "Corsican",
				"hr"	: "Croatian",
				"cs"	: "Czech",
				"da"	: "Danish",
				"dv"	: "Dhivehi",
				"nl"	: "Dutch",
				"en"	: "English",
				"eo"	: "Esperanto",
				"et"	: "Estonian",
				"fo"	: "Faroese",
				"tl"	: "Filipino",
				"fi"	: "Finnish",
				"fr"	: "French",
				"fy"	: "Frisian",
				"gl"	: "Galician",
				"ka"	: "Georgian",
				"de"	: "German",
				"el"	: "Greek",
				"gu"	: "Gujarati",
				"ht"	: "Haitian Creole",
				"iw"	: "Hebrew",
				"hi"	: "Hindi",
				"hu"	: "Hungarian",
				"is"	: "Icelandic",
				"id"	: "Indonesian",
				"iu"	: "Inuktitut",
				"ga"	: "Irish",
				"it"	: "Italian",
				"ja"	: "Japanese",
				"jw"	: "Javanese",
				"kn"	: "Kannada",
				"kk"	: "Kazakh",
				"km"	: "Khmer",
				"ko"	: "Korean",
				"ku"	: "Kurdish",
				"ky"	: "Kyrgyz",
				"lo"	: "Lao",
				"la"	: "Latin",
				"lv"	: "Latvian",
				"lt"	: "Lithuanian",
				"lb"	: "Luxembourgish",
				"mk"	: "Macedonian",
				"ms"	: "Malay",
				"ml"	: "Malayalam",
				"mt"	: "Maltese",
				"mi"	: "Maori",
				"mr"	: "Marathi",
				"mn"	: "Mongolian",
				"ne"	: "Nepali",
				"no"	: "Norwegian",
				"oc"	: "Occitan",
				"or"	: "Oriya",
				"ps"	: "Pashto",
				"fa"	: "Persian",
				"pl"	: "Polish",
				"pt"	: "Portuguese",
				"pt-PT"	: "Portuguese Portugal",
				"pa"	: "Punjabi",
				"qu"	: "Quechua",
				"ro"	: "Romanian",
				"ru"	: "Russian",
				"sa"	: "Sanskrit",
				"gd"	: "Scots Gaelic",
				"sr"	: "Serbian",
				"sd"	: "Sindhi",
				"si"	: "Sinhalese",
				"sk"	: "Slovak",
				"sl"	: "Slovenian",
				"es"	: "Spanish",
				"su"	: "Sundanese",
				"sw"	: "Swahili",
				"sv"	: "Swedish",
				"syr"	: "Syriac",
				"tg"	: "Tajik",
				"ta"	: "Tamil",
				"tt"	: "Tatar",
				"te"	: "Telugu",
				"th"	: "Thai",
				"bo"	: "Tibetan",
				"to"	: "Tonga",
				"tr"	: "Turkish",
				"uk"	: "Ukrainian",
				"ur"	: "Urdu",
				"uz"	: "Uzbek",
				"ug"	: "Uighur",
				"vi"	: "Vietnamese",
				"cy"	: "Welsh",
				"yi"	: "Yiddish",
				"yo"	: "Yoruba"
			}
		}
	};
	
}());

Socialseek.URLShortener = {
	shorten : function(url, callback) {
		if (url.substring(0,14).toLowerCase()==='http://ssk.me/') {
			if (callback) {
				callback(url);
			}
			return true;
		}
		if (this.urlTemplate) {
			url = this.urlTemplate.replace(/\{url\}/gm, encodeURIComponent(url));
		}
		tinydom.net.jsonp('http://ssk.me/api/shorten' + tinydom.parameterize({
			url		: url,
			format	: 'json'
		}), function(response) {
			var url = response && response.result && response.url;
			if (callback) {
				callback(url || false);
			}
		});
	},
	
	expand : function(shortUrlOrId, callback) {
		var id = (shortUrlOrId+'').replace(/^.*?\/([^\/]+)\/?$/gim,'$1');
		tinydom.net.jsonp('http://ssk.me/api/expand' + tinydom.parameterize({
			id		: id,
			format	: 'json'
		}), function(response) {
			var url = response && response.result && response.url;
			if (callback) {
				callback(url || false);
			}
		});
	}
};

Socialseek.Categories = {
	list : function(callback) {
		var self;
		if (this._cache && this._cache.categoryList) {
			if (callback) {
				callback(this._cache.categoryList);
			}
		}
		else {
			self = this;
			Socialseek.api.sites.getCategories({
				callback : function(result, response) {
					var categories = result && response && response.categories;
					if (categories) {
						self._cache.categoryList = categories;
					}
					if (callback) {
						callback(categories || false);
					}
					callback = self = null;
				}
			});
		}
	},
	
	getSites : function(category, callback, options) {
		var self = this,
			categoryMushed;
		
		options = options || {};
		if (tinydom.typeOf(category)==='function') {
			callback = category;
			category = '';
		}
		else {
			category = category || '';
		}
		options.categoryMushed = categoryMushed = (category + '').replace(/\s/gim,'').toLowerCase();
		if (options.cached!==false && options.reload!==true) {
			if (this._cache.categorySites.hasOwnProperty(categoryMushed)) {
				if (callback) {
					callback(this._cache.categorySites[categoryMushed]);
				}
				return true;
			}
		}
		Socialseek.api.sites.getSitesByCategory({
			category : category,
			callback : function(result, response) {
				var sites = result && response && response.results;
				self._cache.categorySites[categoryMushed] = sites;
				if (callback) {
					callback(sites || false);
				}
				callback = category = null;
			}
		});
	},
	
	_cache : {
		categorySites : {}
	}
};var app = (function() {
	var app = new tinydom.EventEmitter(),
		priv = {},
		appState = {},
		data = {
			initialized : false,
			defaultSearchKeywords : 'social',
			allowKeywordRestore : true,
			saveKeywordState : true
		};
	
	app.model = SocialSeek;
	
	
	app.controllers = new tinydom.ControllerManager({
		instanceId : 'app.controllers',
		singular : true,
		allowLoadDefault : false,
		controllerOptions : {
			model : app.model
		}
	});
	
	
	app.feedContainerConfigs = new tinydom.ControllerManager({
		instanceId : 'app.feedContainerConfigs',
		controllerOptions : {
			model : app.model
		}
	});
	
	
	app.dialogConfigs = new tinydom.ControllerManager({
		instanceId : 'app.dialogConfigs'
	});

	
	
	app.components = new tinydom.ControllerManager({
		instanceId : 'app.components',
		controllerOptions : {
			model : app.model,
			app : app
		}
	});
	
	
	
	app.storage = app.model.storage.getNamespace('app');
	
	
	app.prefPanels = new tinydom.ControllerManager({
		instanceId : 'app.prefPanels',
		singular : true,
		loadDefault : false,
		controllerOptions : {
			model : app.model,
			app : app
		}
	});
	
	
	app.stateManager = new tinydom.StateManager({
		adaptor : 'url',
		objects : {
			'controller' : app.controllers
		},
		adaptorOptions : {
			usePreceedingSlash : !!history.pushState,
			html5UrlPrefix : '/app',
			beforeParse : function(str) {
				var prefix,
					ctrl,
					matches = (/^\/([^\/]+)(?:\/([^\/\?\#]*))?/gim).exec(str);
				if (!history.pushState) {
					return str;
				}
				prefix = matches[1];
				ctrl = matches[2] || 'main';

				if (prefix==='app' || ctrl!=='main') {
					data.currentSiteUrl = '';
					return str;
				}
				else {
					ctrl = 'main';
					data.currentSiteUrl = prefix;
					if (data.stateHasBeenRestored) {

					}
				}

				return '/app/' + ctrl + str.substring(prefix.length+ctrl.length+2);		//str.replace(/^\/[^\/]\//gim,'/app/');
			},
			beforeCommit : function(url) {
				var site = app.getSite(),
					urlPrefix = (site && site.url) || (data.currentSite && data.currentSite.url) || data.currentSiteUrl,
					ctrl = app.controllers.current(),
					prefix,
					controllerName,
					matches = (/^\/([^\/]+)(?:\/?([^\/\?\#]+))/gim).exec(url);
				if (!history.pushState) {
					return url;
				}
				prefix = matches[1];
				controllerName = matches[2] || 'main';
				if (controllerName!=='main' || (ctrl && ctrl.name!=='main') || !site || data.searchKeywords!==site.keywords) {
					urlPrefix = 'app';
				}
				url = url.replace(/^\/[^\/]+\//gim,'/'+urlPrefix+'/');

				return url;
			},
			
			urlMapping : 'controller.current'

		}
	});
	
	
	app.getUrlPrefix = function() {
		return data.urlPrefix || '';
	};
	
	
	app.init = function() {
		var site;
		if (data.initialized===true) {
			return false;
		}
		data.initialized = true;
		
		data.initialUrl = location.href+'';
		data.sites_baseurl = decodeURIComponent(((/[?&]sites_baseurl=([^&#]+)/gm).exec(data.initialUrl) || [])[1] || '') || false;

		
		tinydom.el('#createsite_message').on('click', function() {
			app.controllers.load('sites');
		});
		app.addEventListener('sitechange', priv.siteChanged);
		
		
		tinydom.el(document.body).classify('loaded');
		
;
		
		tinydom.el('#sidebar_right').css({right:'-200px',opacity:0}).show();

		tinydom.addEvent(window, "resize", app.onresize);
		
		
		app.on('siteChange', priv.siteChanged);
		
		
		site = priv.getSiteNameFromURL();

		if (!site || site==='app') {
			app._fireEvent('sitechange', []);
			app._fireEvent('sitechanged', []);
			app.finalize({
				initialView : 'home'
			});
		}
		else {
			data.urlPrefix = site;
			app.model.api.sites.info({
				url : site,
				callback : function(result, response) {
					if (result && response && response.site) {
						data.allowKeywordRestore = false;
						data.searchKeywords = response.site.keywords;

						if (data.sites_baseurl) {
							app.model.URLShortener.urlTemplate = data.sites_baseurl + '#ssk_url={url}';
							tinydom.log('Setting short URL template to: ', app.model.URLShortener.urlTemplate);
						}
						
						
						app.finalize({
							initialView : 'main',
							callback : function() {

								app.loadSite(response.site, true);
								response = result = null;
							}
						});



					}
					else {
						app._fireEvent('sitechange', []);
						app._fireEvent('sitechanged', []);
						app.finalize({
							initialView : 'home'
						});
					}
				}
			});
		}
	};
	
	
	
	
	priv.getSiteNameFromURL = function() {
		var site = (location.href + '').replace(/^[a-z0-9]+\:\/\/[^\/]+\/?/gim,'');
		site = site.match(/^[^\/#?&]+/gim);
		site = site && site[0];



		return site && site.length>2 ? site : false;
	};
	
	
	
	app.loadSite = function(site, forceReload) {
		var ready, params={};
		ready = function() {
			ready = null;
			app.setKeywords(site.keywords, true, false, true);
			app.switchToSite(site, true, forceReload===true);
			ready = site = params = null;
		};
		if (tinydom.typeOf(site)==='string') {
			if (site.substring(0,4)==='url:') {
				params.url = site.substring(4);
			}
			else {
				params.id = site;
			}
			params.callback = function(result, response) {
				site = result && response && response.site;
				if (site) {
					ready();
				}
				else {

					console.log('Could not load site.');
				}
			};
			app.model.api.sites.info(params);
		}
		else {
			ready();
		}
	};
	
	
	app.switchToSite = function(site, andFinalize, forceSiteReload) {
		var style, css, subtitle, i,
			prefixes = ['','-webkit-','-moz-','-o-'];
		
		if ( forceSiteReload!==true && ((site && site.url===data.currentSiteUrl) || (!site && !data.currentSiteUrl)) ) {
			return false;
		}
		data.currentSiteUrl = site && site.url;
		
		if (document.getElementById('site_style')) {
			document.getElementById('site_style').parentNode.removeChild(document.getElementById('site_style'));
		}
		
		if (site) {
			css  = "body #container { background-image:url('" + site.background + "'); ";
			css += "background-color:" + site.bgcolor + "; background-repeat:" + (site.bgrepeat?'repeat':'no-repeat') + "; }";
			
			css += "body #site_title { color:"+site.titlecolor+";";
			if (site.titleshadowcolor) {
				for (i=0; i<prefixes.length; i++) {
					css += ' ' + prefixes[i] + 'text-shadow: 0 1px 4px ' + site.titleshadowcolor + ';';
				}
			}
			css += " }";

			
			tinydom.el('#site_title').css({ opacity:0 });
			
			tinydom.el('#site_logo_wrap').query('img').destroy();
			if (site.logo) {
				tinydom.el({
					type : 'img',
					className : 'site_logo',
					css : 'visibility:hidden;',
					attributes : {
						src : site.logo
					},
					onclick : function() {

						app.controllers.load('main');
					},
					onload : function() {
						var self = tinydom.el(this);
						if (self.height()>self.parent().height()) {
							self.css({
								height : self.parent().height() + 'px',
								width : 'auto'
							});
						}
						if (self.width()>self.parent().width()) {
							self.css({
								width : self.parent().width() + 'px',
								height : 'auto'
							});
						}
						self.fadeIn('medium', function() {

							var title = tinydom.el('#site_title');
							if (site.title) {
								title.css({
									left : ((self.x()+self.parent().x())*2 + self.width()) + 'px',
									top : (title.parent().height()-title.height())/2 + 'px',
									opacity : 1
								}, {tween:'medium'});
							}
							site = self = null;
						});
					},
					onerror : function() {
						tinydom.el(this).destroy();
					}
				}, tinydom.el('#site_logo_wrap'));
			}
			else {
				setTimeout(function() {
					var title = tinydom.el('#site_title'),
						logoWrap = tinydom.el('#site_logo_wrap');
					title.css({
						left : (logoWrap.x()*2) + 'px',
						top : (title.parent().height()-title.height())/2 + 'px',
						opacity : 1
					}, {tween:'medium'});
				}, 25);
			}
			
			style = document.createElement("style");
			style.setAttribute("type", "text/css");
			style.setAttribute("id", "site_style");
			if (style.styleSheet) {
				style.styleSheet.cssText = css;
			}
			else {
				style.appendChild(document.createTextNode(css));
			}
			(document.getElementsByTagName("head")[0] || document.body).appendChild(style);
			
			document.title = site.title + " | SocialSeek";
			
			if (site.showtitle===false) {
				tinydom.el('#site_title').html('');
			}
			else {
				tinydom.el('#site_title').html(tinydom.text.filter(site.title,'htmlEntities')).fadeIn();
			}

			
			
			tinydom.el('#search_keywords').query('input').value(site.keywords + '');
			tinydom.el('#search_keywords').query('input').attr('data-lastvalue', site.keywords+'');

			data.searchKeywords = site.keywords + '';
			
			data.currentSite = site;
			
			subtitle = tinydom.el('#site_subtitle');
			
			if (site.subtitle) {
				if (subtitle.exists()) {
					subtitle.html(tinydom.text.filter(site.subtitle,'htmlEntities')).show();
				}
				else {
					subtitle = tinydom.el({
						type : 'h2',
						className : 'site_subtitle',
						attributes : {
							id : 'site_subtitle'
						},
						innerHTML : tinydom.text.filter(site.subtitle,'htmlEntities')
					}, tinydom.el('#searchbox').parent());
				}
			}
			else {

				subtitle.hide();
			}
			
		}
		else {
			var currentController = app.controllers.current(),
				cTitle = app.getKeywords() || currentController.name || '';
			if (currentController.getTitle && typeof(currentController.getTitle)==='function') {
				cTitle = currentController.getTitle();
			}
			else if (currentController.title) {
				cTitle = currentController.title;
			}
			document.title = cTitle + " | SocialSeek";
			
			tinydom.el('#site_logo_wrap').query('img').destroy();
			tinydom.el('#site_title').html('SocialSeek').hide();
			tinydom.el('#searchbox').show();
			subtitle = tinydom.el('#site_subtitle').hide();
			
			data.currentSite = null;
		}

		app._fireEvent('sitechange', [data.currentSite]);
		app._fireEvent('sitechanged', [data.currentSite]);
		if (data.stateHasBeenRestored===true) {
			priv.updateState();
		}
		
		
		if (andFinalize===true) {
			app.finalize();
			
			if (site) {

			}
		}
	};
	
	
	
	
	priv.setupSitesAutoSuggest = function() {
		var input = tinydom.el('#search_keywords').query('input'),
			menu,
			req,
			handler,
			delay,
			changed,
			updateResults,
			blurTimer,
			itemsToList,
			menuClosed,
			resultClick,
			mushingRegex = /[^a-z0-9]/gim,
			focussed = false,
			currentItems = '',
			defaultMouseEvent = {
				pageX : 0,
				pageY : 0
			};
		
		input.on('keydown', function(e) {
			var key = parseInt(e.keyCode || e.charCode, 10) || -1,
				prevent = true,
				selected = menu && menu.getSelectedItems().count()>0 && menu.getSelectedItems().first();

			switch (key) {
				case 38:		// up arrow
					if (selected) {

						if (selected.previous().exists()) {
							selected.declassify('hover').previous().classify('hover');
						}
					}
					else {

						menu.getItems().last().classify('hover');
					}
					break;
				
				case 40:		// down arrow
					if (selected) {


						if (selected.next().exists()) {
							selected.declassify('hover').next().classify('hover');
						}
					}
					else {


						menu.getItems().first().classify('hover');
					}
					break;
				
				case 13:		// enter
					if (selected) {
						data.disableInputSubmit = true;
						selected.fireEvent('mouseup',defaultMouseEvent);
						setTimeout(function() {
							data.disableInputSubmit = false;
						}, 10);
					}
					break;
				
				case 27:		// esc
					menu.hide();
					break;
				
				default:
					prevent = false;
			}
			if (prevent) {
				return tinydom.cancelEvent(e);
			}
		});
		
		input.on('keyup', function() {
			if (!delay) {
				clearTimeout(delay);

			}
			if (blurTimer) {
				clearTimeout(blurTimer);
			}
			delay = setTimeout(changed, 100);
		});
		
		input.on('focus', function() {
			focussed = true;
			if (blurTimer) {
				clearTimeout(blurTimer);
			}

		});
		
		input.on('blur', function() {
			focussed = false;
			if (blurTimer) {
				clearTimeout(blurTimer);
			}
			if (req && req.cancel) {
				req.cancel();
			}
			blurTimer = setTimeout(function() {
				if (menu) {
					menu.hide();
				}
			}, 150);
		});
		
		resultClick = function(e) {
			app.setKeywords(e.data.keywords);
			setTimeout(function() {
				menu = null;
				input.blur();
			}, 20);
			return true;
		};
		
		menuClosed = function() {
			menu = null;
			currentItems = '';
		};
		
		itemsToList = function(items) {
			var list = [],
				x;
			for (x=0; x<items.length; x++) {
				list.push(items[x].keywords+'|'+items[x].url);
			}
			return list.join(',');
		};
		
		changed = function() {
			var val = input.value() || '',
				mushed = val.replace(mushingRegex,'');
			if (mushed.length>=2) {
				req = app.model.api.sites.autosuggest({
					q : val,
					max_results : 10,
					callback : function(success, response) {
						updateResults(val, success && response && response.results);
					}
				});
			}
			else {
				updateResults(val);
			}
		};
		
		updateResults = function(keywords, results) {
			var items = [],
				x,
				itemLabelAlt,
				keywordsMushed = keywords.replace(mushingRegex,'');
			
			if (results) {
				for (x=0; x<results.length; x++) {
					if (results[x].title) {
						if (results[x].title.replace(mushingRegex,'').toLowerCase()===results[x].keywords.replace(mushingRegex,'').toLowerCase()) {
							itemLabelAlt = '<span class="menuListItemAltLabel"><span class="innerIcon"></span>&nbsp;</span>';
						}
						else {
							itemLabelAlt = '<span class="menuListItemAltLabel"><span class="innerIcon"></span>' + tinydom.text.filter(results[x].title,'truncate:30,byWord|htmlEntities') + '</span>';
						}
					}
					else {
						itemLabelAlt = '';
					}
					items.push({
						label : itemLabelAlt + (results[x].keywords + '').replace(/(["']|\sAND\s|\sOR\s|\,)/gim,''),
						className : 'sitesAutosuggestMenuItem',
						data : {
							keywords : results[x].keywords
						},
						action : resultClick
					});
				}
			}
			
			if (blurTimer) {
				clearTimeout(blurTimer);
			}
			if (items.length===0 || focussed===false) {
				if (menu) {

					menu.removeAllItems();
					currentItems = '';
					menu.hide();
				}
			}
			else if (!menu) {

				menu = app.menus.createMenu({
					fromElement : input,
					showAnimations : false,
					className : 'autosuggestMenu',
					items : items
				});
				menu.addEventListener('close', menuClosed);
				currentItems = itemsToList(items);
			}
			else {
				if (currentItems!==itemsToList(items)) {

					menu.removeAllItems();
					menu.addItems(items);
					currentItems = itemsToList(items);
				}
				menu.show();
			}
		};
	};
	
	
	
	
	
	app.finalize = function(finalizeOptions) {
		finalizeOptions = finalizeOptions || {};
		if (data.finalized===true) {
			return true;
		}
		data.finalized = true;
		
		tinydom.log('app.finalize');
		
		app.dialogManager = app.components.load("DialogManager", {
			parent : tinydom.el('#container'),
			configManager : app.dialogConfigs,
			showAnimations : false
		});
		
		app.menus = app.components.load("MenuManager", {
			parent : tinydom.el('#container'),
			fadeInDuration : 0,
			fadeOutDuration : 300		// in ms
		});
		
		app.videoPlayer = app.components.load("VideoPlayer");
		
		
		
		app.auth = app.components.load('Auth', {
			init : false
		});
		app.auth.on('change', priv.authChanged);
		
		
		
		app.profileBox = app.components.load('ProfileBox', {
			auth : app.auth
		});
		app.profileBox.addEventListener('openPreferences', function() {
			app.controllers.load('preferences');
			return false;
		});
		app.profileBox.addEventListener('openSites', function(id) {
			app.controllers.load('sites', id && {id:id});
			return false;
		});
		app.profileBox.addEventListener('openAdmin', function() {
			app.controllers.load('admin');
			return false;
		});
		app.profileBox.addEventListener('setTranslationLanguage', function(lang) {
			var controller = app.controllers.current();
			app.translationLanguage = lang;
			if (controller && controller.feedContainers) {
				controller.feedContainers.setTranslationLanguage(lang);
			}
		});
		
		
		
		app.subscription = app.components.load('Subscription');
		
		
		
		app.emailClient = app.components.load('EmailClient', {
			model : app.model,
			auth : app.auth
		});
		
		
		
		app.chat = app.components.load('Chat', {

		});
		
		
		
		app.notifications = app.components.load('Notifications', {
			model : app.model
		});

		
		app.savedSeeks = app.components.load('SavedSeeks', {
			auth : app.auth
		});
		app.savedSeeks.addEventListener('seek', function(keywords) {
			app.setKeywords(keywords);
		});
		app.savedSeeks.addEventListener('openSites', function(id) {
			app.controllers.load('sites', id && {id:id});
			return false;
		});
		app.savedSeeks.addEventListener('goSite', function(site) {
			var ready;
			ready = function() {
				ready = null;
				app.switchToSite(site, true, false);
				app.setKeywords(site.keywords, true, false, true);
			};
			if (tinydom.typeOf(site)==='string') {
				app.model.api.sites.info({
					id : site,
					callback : function(result, response) {
						site = result && response && response.site;
						if (site) {
							ready();
						}
						else {

							alert('Could not load site.');
						}
					}
				});
			}
			else {
				ready();
			}
		});
		
		
		app.hotTopics = app.components.load('HotTopics');
		app.hotTopics.addEventListener('seek', function(keywords) {
			app.setKeywords(keywords);
		});
		app.hotTopics.addEventListener('showAllCategories', function() {
			app.controllers.load('categories');
		});
		app.hotTopics.addEventListener('emailShare', function(obj) {
			app.emailClient.share(obj);
		});
		
		
		app.footer = app.components.load('Footer');
		app.footer.addEventListener('showCategoryExplorer', function(category) {
			app.controllers.load('categories', {
				name : category
			});
		});
		app.footer.addEventListener('action', function(action) {

			switch ((action+'').toLowerCase()) {
				case 'togglechat':
					app.chat.toggle();
					break;
				case 'feedback':
					app.emailClient.feedback();
					break;
				case 'reportabuse':
					app.emailClient.reportAbuse();
					break;
				case 'contact':
					app.emailClient.contactUs();
					break;
				case 'brands':
					app.emailClient.brandContact();
					break;
				case 'claimsite':
					app.emailClient.claimSite();
					break;
				
				default:
					if (app.controllers.get(action)) {
						app.controllers.load(action);
					}
					break;
			}
		});

		
		
		app.stateManager.init({
			restore : false,
			objects : {
				'q'			: appState,
				'dialog'	: app.dialogManager,
				'auth'		: app.auth
			}
		});
		
		
		app.feedContainerConfigs.init({
			controllerOptions : {
				dialogManager : app.dialogManager
			}
		});
		
		
		
		app.controllers.addEventListener('change', function() {
			priv.controllerChanged(this.current());
		});
		
		
		app.controllers.init({
			autoRestoreOnInit : false,
			allowLoadDefault : false,
			controllerOptions : {

				viewBase : tinydom.el('#content_inner'),
				app : app,
				searchKeywords : app.getKeywords()
			}
		});
		
		
		setTimeout(function() {
			app.stateManager.restore(function(restored) {
				
				data.stateHasBeenRestored = true;
				
				if (!app.controllers.current()) {
					if (data.searchKeywords) {
						app.controllers.loadDefault({
							searchKeywords : data.searchKeywords
						});
					}
					else {
						priv.hideSidebar();
						app.controllers.load(finalizeOptions.initialView || 'home');
					}
				}
				
				if (finalizeOptions && finalizeOptions.callback) {
					finalizeOptions.callback();
				}
			});

			app.auth.init();

			app.onresize();

			priv.setupSitesAutoSuggest();
		}, 50);
		
		app.onresize();
	};

	priv.controllerChanged = function(controller) {

		
		if (controller.name==='main') {
			data.saveKeywordState = true;
		}
		else {
			if (controller.name==='home') {
				app.switchToSite(null, false, true);
				data.saveKeywordState = false;
			}

			tinydom.el('#search_keywords').query('input').attr('data-lastvalue','').value('');
		}

		if (controller.allowSharing===false) {
			tinydom.el('#sharing_wrap').fadeOut('medium');
		}
		else {
			tinydom.el('#sharing_wrap').fadeIn('medium');
		}

		if (!app.auth.getInfo().loggedin || controller.allowSharing===false || controller.allowSaving===false) {
			tinydom.el('#button_save_search').disable();
		}
		else {
			tinydom.el('#button_save_search').enable();
		}

		if (controller.isDefault===true || controller.showCloseButton===false) {
			tinydom.el('#view_globalCloseButton').hide(true);
		}
		else {
			tinydom.el('#view_globalCloseButton').show();
		}

		if (controller.showSidebar===false) {
			priv.hideSidebar();
		}
		else {
			priv.showSidebar();
		}

		priv.updateState();
	};
	
	
	priv.siteChanged = function() {
		var controller = app.controllers.current(),
			site = app.getSite();

		if (!site && controller && controller.name==='main') {
			tinydom.el('#createsite_message').fadeIn('fast');
		}
		else {
			tinydom.el('#createsite_message').fadeOut('fast', null, true);
		}

		if (site) {
			tinydom.el('#footer_brands_link').show();
		}
		else {
			tinydom.el('#footer_brands_link').hide(true);
		}
		if ((site && site.adspot1)!==data.currentAdSpot) {
			data.currentAdSpot = site && site.adspot1;
			priv.reloadSidebarAd();
		}
	};
	
	
	
	
	priv.authChanged = function(loggedin) {
		var info = app.auth.getInfo(),
			subscription = loggedin && info.profile && info.profile.subscription && (info.profile.subscription.type || '').toLowerCase(),
			controller = app.controllers.current();

				priv.getSites(null, true);
		if (subscription==='plus') {





		}
		else {



			
		}
	};
	
	
	
	priv.ads = {
		show : function() {
			var bar = tinydom.el('#sidebar_right_rev').show();
			bar.css({
				height : bar.children().height(),
				opacity : 1
			}, {tween:'short', callback:function(){
				bar.css({height:'95%'});
				tinydom.el('#sidebar_right_top').show();
				app.onresize();
				bar = null;
			}});
		},
		hide : function() {
			var bar = tinydom.el('#sidebar_right_rev').show();
			bar.css({
				height : 0,
				opacity : 0
			}, {tween:'short', callback:function(){
				bar.hide(true);
				app.onresize();
				bar = null;
			}});
			tinydom.el('#sidebar_right_top').hide(true);
		}
	};
	
	
	
	
	priv.hideSidebar = function(options) {
		options = options || {};
		if (data.hasSwitchedSidebar!==true) {
			data.hasSwitchedSidebar = true;
			options.animate = false;
		}
		if (data.sidebarShowing!==false) {
			tinydom.el('#sidebar_right').css({
				right : '-220px',  //'-350px',
				opacity : 0
			}, options.animate!==false ? {tween:'medium'} : null);
			
			tinydom.el('#app').css({
				'margin-right' : '-20px'
			}, options.animate!==false ? {tween:'medium', callback:function(){
				setTimeout(app.onresize,100);
			}} : null );
			
			data.sidebarShowing = false;
			if (options.animate===false) {
				app.onresize();
			}
		}
	};
	
	
	priv.showSidebar = function(options) {
		options = options || {};
		if (priv.sidebarDisabled===true) {
			return true;
		}
		if (data.hasSwitchedSidebar!==true) {
			data.hasSwitchedSidebar = true;
			options.animate = false;
		}
		if (data.sidebarShowing!==true) {
			tinydom.el('#sidebar_right').css({
				right : '0',
				opacity : 1
			}, options.animate!==false ? {tween:'medium'} : null );
			
			tinydom.el('#app').css({
				'margin-right' : '180px'	// '300px'
			}, options.animate!==false ? {tween:'medium', callback:function(){
				setTimeout(app.onresize,100);
			}} : null );
			
			data.sidebarShowing = true;
			if (options.animate===false) {
				app.onresize();
			}
		}
	};
	
	
	
	app.reportAbuse = function() {
		app.emailClient.reportAbuse.apply(app.emailClient, arguments);
	};
	
	app.handleLink = function(el, service) {
		var url;
		if (el) {
			if (tinydom.typeOf(el)==='string') {
				url = el;
			}
			else if (el.getAttribute) {
				url = el.getAttribute('href');
			}
			if (url) {
				window.open(url);
			}
		}
		return false;
	};
	
	
	
	
	app.translation = tinydom.extend(new tinydom.EventEmitter(), {
		setLang : function(lang) {
			var list = app.model.config.translation.languages;
			lang = (lang+'').toLowerCase();
			if (!list.hasOwnProperty(lang)) {
				lang = null;
			}
			this.lang = lang;
			this._fireEvent('change', lang);
		},
		getLang : function() {
			return this.lang || null;
		}
	});
	
	
	
	app.getSeekMetaInfo = function() {
		if (data.currentSite) {
			return tinydom.extend({ isSite:true }, data.currentSite);
		}
		else {
			return {
				isSite : false,
				title : data.searchKeywords,
				keywords : data.searchKeywords,
				tags : []
			};
		}
	};
	
	
	app.getSite = function() {
		return data.currentSite || false;
	};
	
	app.getKeywords = function() {
		return data.searchKeywords;		// || data.defaultSearchKeywords;
	};
	
	app.setKeywords = function(keywords, updateField, detectSites, allowViewSwitch) {
		var input = tinydom.el('#search_keywords'),
			siteLoaderKeywords;
		
		if (!keywords || keywords.length<1) {
			return false;
		}
		
		if (updateField!==false) {
			input.query('input').attr('data-lastvalue',keywords).value(keywords+'');
		}
		
		data.searchKeywords = keywords;
		
		document.title = keywords + " | SocialSeek";
		
		if (app.controllers && app.controllers.controllerOptions) {
			app.controllers.controllerOptions.searchKeywords = keywords;
		}
		
		if (allowViewSwitch!==false) {
			app.controllers.load('main', {
				searchKeywords : keywords
			});
		}
		
		app.controllers.postMessage('searchsubmit', {
			value : keywords
		});
		app._fireEvent('searchsubmit', [keywords]);
		
		app._fireEvent('keywordchange', [keywords]);
		app._fireEvent('keywordschanged', [keywords]);

		
		if (detectSites===false) {
			priv.updateState();
		}
		else {
			
			siteLoaderKeywords = keywords;
			app.model.api.sites.info({
				keywords : keywords,
				callback : function(result, response) {
					if (app && app.getKeywords()===siteLoaderKeywords) {
						if (result && response && response.site) {
							app.switchToSite(response.site, false);
						}
						else {
							app.switchToSite(null, false, true);
						}
					}
				}
			});
		}
	};
	
	
	priv.reloadSidebarAd = function() {
		var frame,
			adCode = '<script>var google_ad_client="ca-pub-0664415180440322",google_ad_slot="2692088590",google_ad_width=160,google_ad_height=600;</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>',
			siteInfo = app.getSite(),
			isCustom = false;
		if (priv.reloadSidebarAd) {
			clearTimeout(priv.reloadSidebarAd);
		}
		if (siteInfo && siteInfo.adspot1 && (siteInfo.adspot1+'').length>1) {
			adCode = siteInfo.adspot1;
			isCustom = true;
		}
		if (data.sidebarShowing || isCustom===true) {
			frame = tinydom.el({
				type	: "iframe",
				css : 'opacity:0;',
				className : 'is_loading',
				attributes : {
					frameBorder : '0',
					allowTransparency : 'true',
					'data-loaded' : 'false'
				},
				onload : function() {
					var frame = tinydom.el(this);
					if (frame.attr('data-loaded')==='false') {
						frame.attr('data-loaded', 'true');
						frame.wait(500, function() {
							frame.fadeIn('slow', function() {
								if (data.currentAdFrame) {
									data.currentAdFrame.destroy();
								}
								data.currentAdFrame = frame;
								frame.declassify('is_loading');
								frame = null;
							});
						});
					}
				},
				parent : tinydom.el('#sidebar_right_rev')
			});
			win = frame.prop('contentWindow');
			win.document.open();
			win.document.write('<html><head><style type="text/css">html,body,img,object,embed{margin:0;padding:0;overflow:hidden;background:none;}body{background:#DDD;}</style></head><body>' + adCode + '</body></html>');
			win.document.close();
			win = frame = null;
		}
		setTimeout(priv.reloadSidebarAd, 120*1000);
	};
	
	
	priv.startAnalyticsLogger = function() {
		var getUrl, currentUrl;
		getUrl = function() {
			var url = location.href+'';
			if (url.indexOf('#!')) {
				url = url.substring(url.indexOf('#!')+2);
			}
			else {
				url = url.substring(url.indexOf('/',location.protocol.length+4));
			}
			if (url.substring(0,1)!=='/') {
				url = '/' + url;
			}
			return url;
		};

		setInterval(function gAnalyticsLogPoller() {
			var url = getUrl();
			if (url!==currentUrl) {
				if (window._gaq) {
					window._gaq.push(['_setAccount', 'UA-4660177-6']);
					window._gaq.push(['_trackPageview', url]);
				}
				currentUrl = url;
			}
		}, 1000);
	};
	
	priv.createEditHandler = function() {
		var url = "#!sites";
		if (history.pushState) {
			url = url.replace(/^(\/?app)?\/?#!/gim,'/app/');
			history.pushState(null,null,url);
		}
		else {
			location.href = url;
		}
	};
	
	priv.getSites = function(callback, forceReload) {
			var fireCallback = true;
			callback = callback || data.noFunc;
			if (data.sitesChecked===true && forceReload!==true) {
				fireCallback = false;
				callback(data.sites);
			}
			else {
				app.model.api.sites.quicklist({
					callback : function(result, response) {
						data.sitesChecked = true;
						data.sites = result && response && response.sites;
						if (fireCallback) {
							callback(data.sites);
						}
					}
				});
			}
		};
		
	priv.sitesListClickHandler = function(e){
			app.model.api.sites.info({
				url: e.data.url,
				callback: function(result, response){
					if (result && response && response.site) {
						app.loadSite(response.site,true);
					}
				}
			});
	};
	
	
	
	app.load = function() {
		if (data.appLoaded===true) {
			return false;
		}
		data.appLoaded = true;
		
		
		priv.startAnalyticsLogger();


		
		
		
		tinydom.el(document.body).on('click', function(e) {
			var target = tinydom.el(e.target),
				button = e.button || e.which,
				found, loaded, name;

			if (button!==2) {
				do {
					if (target.nodeName()==='a' && (target.attr('href')+'').match(/^(\/?|#\!)/m)) {
						found = true;
						break;
					}
				} while((target=target.parent()).exists() && target.nodeName()!=='body')
				if (found) {
					url = (target.attr('href') || '').replace(/^(\/?app)?\/?#!/gim,'');	//.replace(/^\/?#\!/m,'');
					if (url.match(/^(http\:\/\/|javascript(\:){1})/gim,'')) {		// superfluous regex to fool JSLint.
						return true;
					}

					if (target.attr('data-email-dialog')) {
						app.emailClient[target.attr('data-email-dialog')]();
						return tinydom.cancelEvent(e);
					}
					if (window.history.pushState ) {
						window.history.pushState({url:'/app/'+url}, '', '/app/'+url);
					}
					else {
						window.location.href = '#!' + url;
					}

					return tinydom.cancelEvent(e);
				}
			}
		});
		

		
		tinydom.el('.showUpgradeOptionsLink').attr('href',null).on('click', function(e) {
			var me = tinydom.el(this);
			app.subscription.showUpgradeOptions({
				type : me.attr('data-upgrade-type') || 'plus',
				site_id : me.attr('data-upgrade-site-id') || null
			});
			return tinydom.cancelEvent(e);
		});
		
		tinydom.el('.contactUsLink').attr('href',null).on('click', function(e) {
			app.emailClient.contactUs();
			return tinydom.cancelEvent(e);
		});
		
		
		
		
		tinydom.el('#site_title, #view_globalCloseButton, #site_logo_inner_default').on('click', function(e) {				// #site_logo_wrap
			if (app.getSite()) {
				app.controllers.load('main');
			}
			else {
				app.controllers.loadDefault();
			}
			return tinydom.cancelEvent(e);
		});
		
		
		
		tinydom.el('#search_keywords').query('input').on('change,keyup,paste,blur', function() {
			var lastValue = this.getAttribute('data-lastvalue') || '';
			if (this.value!==lastValue) {
				app.controllers.postMessage('searchchanging', {
					value : this.value,
					previous : lastValue
				});
				this.setAttribute('data-lastvalue', this.value);
			}
		});
		
		tinydom.el('#search_keywords').query('input').on('keydown', function(e) {
			e = e || window.event;
			var key = e.keyCode || e.which,
				me = this;
			if (key===13) {		// enter
				setTimeout(function() {
					console.log(me.value, data.disableInputSubmit);
					if (me.value && me.value.length>0 && data.disableInputSubmit!==true) {
						app.setKeywords(me.value);
						tinydom.el(me).blur();
					}
					me = e = null;
				}, 1);
				return tinydom.cancelEvent(e);
			}
		});
		
		tinydom.el('#search_submit').on('click', function(e) {
			var value = tinydom.el('#search_keywords').query('input').prop('value');
			if (value && value.length>0) {
				app.setKeywords(value);
			}
			return tinydom.cancelEvent(e);
		});
		
		tinydom.el('#search_keywords').query('input').on('focus', function() {
			tinydom.el(this).parent().classify('focussed');
		});
		tinydom.el('#search_keywords').query('input').on('blur', function() {
			tinydom.el(this).parent().declassify('focussed');
		});
		
		
		tinydom.el('#icon_button_explorer_site').on('click', function(e){
			var url = '#!categories';
			if (history.pushState) {
				url = url.replace(/^(\/?app)?\/?#!/gim,'/app/');
				history.pushState(null,null,url);
			}
			else {
				location.href = url;
			}
			return tinydom.cancelEvent(e);
		});
			
		tinydom.el('#icon_button_edit_site').on('click', function(e){
			priv.getSites(function(sites){
				var permissions = app.auth.getPermissions(),
					menuItems,siteItems;
					
				menuItems = [
					{
						label: "Create/Edit Sites..",
						action: priv.createEditHandler
					}
				];
				
				if (permissions.sites && permissions.sites.general && sites){
					siteItems = [
						{
							type: "grouptitle",
							label: "My Sites"
						}];
					
					for (i=0; i<Math.min(sites.length,10); i++) {
						siteItems.push({
							label : sites[i].title,
							data : {
								id : sites[i].id,
								url : sites[i].url,
								data: sites[i]
							},
							action : priv.sitesListClickHandler,
						});
					}
					menuItems = menuItems.concat(siteItems);
					
				}
				
				app.menus.createMenu({
					fromElement: tinydom.el('#icon_button_edit_site'),
					offsetY: 24,
					items: menuItems
				});
			});
		});
		
		
		
		
		
		
		tinydom.linkedin.init({
			api_key : "9cbr7wivx2uc"
		});
		
		tinydom.facebook.init({
			appId : '171379202905592',
			loginOptions : {
				scope : 'email',
			},
		});
		
		tinydom.twitter.init({
			callbackURL: location.protocol + '//' + document.domain + "/xd_twitter_receiver.html" 
		});
	};
	
	
	
	
	app.unload = function() {
		app.controllers.destroy();
		app.feedContainerConfigs.destroy();
		app.dialogConfigs.destroy();
		app.components.destroy();
		app.stateManager.destroy();
		window.app = app = appState = data = priv = SocialSeek = null;
	};
	
	
	
	priv.updateState = function() {
		var state = {},
			info = app.getSeekMetaInfo(),
			keywords = app.getKeywords();

		if (data.saveKeywordState===true ) {
			state = app.getKeywords() || {};
		}

		appState.setState(state);
	};
	appState.restoreState = function(state) {
		var allowViewSwitch;
		if (state) {
			if (typeof(state)==='string' && data.saveKeywordState===true && data.allowKeywordRestore!==false) {

				allowViewSwitch = !app.controllers.current() || app.controllers.current().name==='home';
				app.setKeywords(state, true, null, allowViewSwitch===true);
			}
		}
	};
	
	
	app.onresize = function() {
		var height = tinydom.el('#content').height() + tinydom.el('#bottombar').height() - Math.abs(tinydom.el('#content_inner')._nodes[0].offsetTop) - tinydom.el('#content_bottom_padding').height();
		
		tinydom.el('#content_inner').css({
			height : height + 'px'
		});
		
		app.chat.setHeight(tinydom.el('#app').height() - tinydom.el('#chatbase').y());
		
		app._fireEvent('resize', {
			height : height,
			width : tinydom.el('#content').width()
		});
		
		app.controllers.postMessage('appresized', {
			height : height
		});
	};
	
	return app;
}());


tinydom.addEvent(window, "tinydomready", function() {

});

tinydom.addEvent(window, "load", function() {
	setTimeout(function() {
		app.init();
		if (app.load) {
			app.load();
		}
	}, 50);
});

tinydom.addEvent(window, "unload", function() {
	if (window.app && app.unload) {
		app.unload();
	}
});



app.components.register('Auth', {
	
	load : function(options) {
		if (!this.self) {
			this.self = this.create(options);
		}
		else {
			this.self.reconfigure(options);
		}
		return this.self;
	},
	
	create : function(initOptions) {
		var exports = {},
			data = {
				loggedin : false,
				hasCheckedSession : false,
				initialView : null,
				defaultProfile : {
					loggedin : false,
					username : ''
				},
				profile : {}
			},
			ui = {},
			priv = {},
			model = initOptions.model,
			events = new tinydom.EventEmitter();
		
		
		exports.init = function(callback) {
			if (data.initialized===true) {
				return false;
			}
			data.initialized = true;


			priv.twitterLoginInit();
			
			
			ui.loginDialog = tinydom.el('#auth_logindialog');
			
			ui.loginDialog.query('.auth_loginform_registerlink').on('click', function(e) {
				setTimeout(function() {
					priv.showRegistration();
				}, 20);
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.loginDialog.query('.auth_loginform_forgotpass').on('click', function(e) {
				setTimeout(function() {
					priv.showForgotPass();
				}, 20);
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.loginDialog.query('.auth_loginform').on('submit', function() {
				if (!data.tempLoginDisableSubmitHandler) {
					priv.processLocalLoginForm();
				}
			});
			
			ui.loginDialog.query('.loginButton').on('click', function(e) {
				data.tempLoginDisableSubmitHandler = true;
				ui.loginDialog.query('.auth_loginform').submit();
				data.tempLoginDisableSubmitHandler = null;
				priv.processLocalLoginForm();
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.loginDialog.query('.cancelButton').on('click', function(e) {
				priv.cancelLogin();
				return tinydom.cancelEvent(e || window.event);
			});
			
			
			
			
			
			
			
			
			ui.forgotPassDialog = tinydom.el('#auth_forgotpassdialog');
			
			ui.forgotPassDialog.query('.resetpasswordButton').on('click', function(e) {
				priv.processForgotPassForm();
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.forgotPassDialog.query('.loginButton').on('click', function(e) {
				priv.showLogin();
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.forgotPassDialog.query('.cancelButton').on('click', function(e) {
				priv.cancelForgotPass(true);
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.forgotPassDialog.query('.resendPasswordButton').on('click', function(e) {
				priv.cancelForgotPass(true);
				setTimeout(function() {
					priv.showForgotPass();
				}, 20);
				return tinydom.cancelEvent(e || window.event);
			});
			
			
			
			
			
			ui.registerDialog = tinydom.el('#auth_registerdialog');
			
			ui.registerDialog.query('.auth_registerform_loginlink').on('click', function(e) {
				setTimeout(function() {
					priv.showLogin()
				}, 20);
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.registerDialog.query('.auth_registerform').on('submit', function() {
				if (!data.tempRegisterDisableSubmitHandler) {
					priv.processRegistrationForm();
				}
			});
			
			ui.registerDialog.query('.registerButton').on('click', function(e) {
				data.tempRegisterDisableSubmitHandler = true;
				ui.loginDialog.query('.auth_registerform').submit();
				data.tempRegisterDisableSubmitHandler = null;
				priv.processRegistrationForm();
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.registerDialog.query('.cancelButton').on('click', function(e) {
				priv.cancelRegistration();
				return tinydom.cancelEvent(e || window.event);
			});
			
			ui.registerDialog.query('#auth_register_email').on('change,keyup,keydown,blur', function() {
				var emailInput;
				if (ui.registerDialog.query('#auth_register_use_email').prop('checked')===true) {
					emailInput = ui.registerDialog.query('#auth_register_email'),
					ui.registerDialog.query('#auth_register_username').value(emailInput.value() || '');
				}
			});
			
			ui.registerDialog.query('#auth_register_use_email').on('click,change', function() {
				var self = tinydom.el(this),
					value = self.prop('checked')===true,
					emailInput = ui.registerDialog.query('#auth_register_email'),
					usernameInput = ui.registerDialog.query('#auth_register_username');
				if (value) {
					usernameInput.value(emailInput.value() || '').disable();
				}
				else {
					usernameInput.enable();
				}
			});
			
			ui.registerDialog.query('#auth_register_username').disable();
			ui.registerDialog.query('#auth_register_use_email').value(true);

			
			
			
			
			
			var storedToken = tinydom.cookies.get('ss_token');
			if (storedToken) {
				model.api.localAuth.continueSession({
					token : storedToken,
					callback : function(result, response) {
						var loggedin = false;

						data.hasCheckedSession = true;
						if (result && response && response.session) {
							loggedin = true;


							data.session = response.session;
							data.profile = data.session.profile || {};
							delete data.session.profile;
							priv.setLoginStatus(true);
						}
						if (callback) {
							callback(false);
						}
						events._fireEvent('sessionCheckin', [loggedin]);
					}
				});
			}
			else {
				data.hasCheckedSession = true;
				events._fireEvent('sessionCheckin', [false]);
			}
			
			if (data.initialView) {
				exports.loadView(data.initialView);
				data.initialView = null;
			}
		};

		
		exports.restoreState = function(state) {
			if (state) {
				if (state.confirmationCode) {
					data.confirmationCode = state.confirmationCode;
				}
				if (state.view) {
					exports.loadView(state.view);
				}
			}
		};
		
		
		exports.loadView = function(view) {
			if (view) {
				switch ((view+'').toLowerCase()) {
					case 'login':
						exports.login();
						break;
					case 'register':
						exports.register();
						break;
					case 'confirm':
						exports.confirmEmail();
						break;
				}
			}
		};
		
		
		
		
		
		
		exports.requireLogin = function(callback) {
			var checkin, doLogin;
			callback = callback || function(){};
			
			doLogin = function() {
				if (data.loggedin) {
					callback(true);
					callback = doLogin = null;
				}
				else {
					exports.login(function() {
						callback(data.loggedin);
						callback = doLogin = null;
					});
				}
			};
			
			if (data.hasCheckedSession===true) {
				doLogin();
			}
			else {
				checkin = function(loggedin) {
					doLogin();
					events.removeEventListener('sessionCheckin', checkin);
					checkin = null;
				};
				events.addEventListener('sessionCheckin', checkin);
			}
		};
		
		
		
		exports.getSession = function(callback) {
			var response = data.loggedin && data.session || false;
			if (callback) {
				callback(response);
			}
			return response;
		};
		
		
		exports.getProfile = function(callback) {
			var response = data.loggedin && data.profile || false;
			if (callback) {
				callback(response);
			}
			return response;
		};
		
		
		exports.getInfo = function() {
			return {
				loggedin : data.loggedin,
				profile : data.profile,
				session : data.session
			};
		};
		
		
		exports.getPermissions = function(callback) {
			var response = data.loggedin && data.profile && data.profile.permissions || false;
			if (callback) {
				callback(response);
			}
			return response;
		};
		
		
		
		exports.loginWithCredentials = function(username, password, callback) {
			model.api.localAuth.login({
				username : username,
				password : password,
				type : 'local',
				callback : function(result, response) {
					var errorMessage = (tinydom.typeOf(response)==='string' && response) || (response && response.message) || 'There was an error logging you in.';
					if (result && response && response.session) {
						setTimeout(function() {
							data.session = response.session;
							data.profile = data.session.profile || {};
							delete data.session.profile;
							priv.setLoginStatus(true);
							if (callback) {
								callback(true, null, response);
							}
						}, 100);
					}
					else {
						events._fireEvent('loginfailed', [response && response.message || null]);
						priv.setLoginStatus(false);
						if (callback) {
							callback(false, errorMessage, response);
						}
					}
				}
			});
		};
		
		
		exports.forgotPass = exports.recoverPassword = function(callback) {
			priv.showForgotPass(callback);
		};
		
		
		
		
		priv.setLoginStatus = function(newLoggedInStatus) {
			if (newLoggedInStatus) {
				data.loggedin = true;
				data.profile.loggedin = true;

				if (data.session.token) {
					tinydom.cookies.set('ss_token', data.session.token);
				}
				events._fireEvent('login', [true, data.profile, data.session]);
				events._fireEvent('change', [true, data.profile, data.session]);
			}
			else if (data.loggedin===true) {
				data.loggedin = false;
				data.previousSession = data.session;
				data.session = null;
				data.previousProfile = data.profile;
				data.profile = tinydom.extend({}, data.defaultProfile);

				tinydom.cookies.set('ss_token', null);
				events._fireEvent('logout', [false, data.profile]);
				events._fireEvent('change', [false, data.profile]);
			}
		};
		
		
		priv.processLocalLoginForm = function() {
			var inputs = ui.loginDialog.query('.auth_loginform').query('input'),
				params = {};
			inputs.each(function(node) {
				if (node.attr('name')) {
					params[node.attr('name')] = node.value();
				}
			});
			params.callback = function(result, response) {
				var errorMessage = (tinydom.typeOf(response)==='string' && response) || (response && response.message) || 'There was an error logging you in.',
					errorMessageHeight;
				if (result && response && response.session) {
					setTimeout(function() {
						data.session = response.session;
						data.profile = data.session.profile || {};
						delete data.session.profile;
						priv.setLoginStatus(true);
						priv.hideLogin();
						if (data.loginFormInlineCallback) {
							data.loginFormInlineCallback(true, data.session, data.profile);
							data.loginFormInlineCallback = null;
						}
					}, 100);
				}
				else {
					errorMessageHeight = ui.loginDialog.query('#auth_login_error_message').html(errorMessage).height();
					ui.loginDialog.query('.error_message').hide().fadeIn().css({
						height : errorMessageHeight+'px'
					}, {tween:'medium'});
					
					events._fireEvent('loginfailed', [response && response.message || null]);
					priv.setLoginStatus(false);
				}
			};
			model.api.localAuth.login(params);
		};
		
		
		priv.processForgotPassForm = function() {
			model.api.localAuth.resetPassword({
				email : ui.forgotPassDialog.query('#auth_forgotpass_email').value(),
				callback : function(result, response) {
					var errorMessage;
					if (result && response) {
						priv.showForgotPassExplainer();
					}
					else {
						errorMessage = (tinydom.typeOf(response)==='string' && response) || response.message || 'Unknown error.';
						errorMessageHeight = ui.forgotPassDialog.query('#auth_forgotpass_error_message').html(errorMessage).height();
						ui.forgotPassDialog.query('.error_message').hide().fadeIn().css({
							height : errorMessageHeight+'px'
						}, {tween:'medium'});
					}
				}
			});
		};
		
		
		priv.processRegistrationForm = function() {
			var inputs = ui.registerDialog.query('.auth_registerform').query('input'),
				params = {};
			inputs.each(function(node) {
				if (node.attr('name')) {
					params[node.attr('name')] = node.value();
				}
			});
			params.callback = function(result, response) {
				var event,
					errorMessage = ((tinydom.typeOf(response)==='string' && response) || (response && response.message) || 'There was an error registering.').replace(/^[a-z]/,function(s){return s.toUpperCase();}),
					errorMessageHeight;
				if (result && response && response.session) {
					data.loggedin = true;
					data.session = response.session;
					data.profile = data.session.profile || {};
					delete data.session.profile;
					priv.setLoginStatus(true);
					priv.hideRegistration();
					
					if (data.registerFormInlineCallback) {
						data.registerFormInlineCallback(true, data.session, data.profile);
						data.registerFormInlineCallback = null;
					}
					
					event = [true, data.profile, data.session];
					events._fireEvent('register', event);
					events._fireEvent('registered', event);
				}
				else {
					errorMessageHeight = ui.loginDialog.query('#auth_register_error_message').html(errorMessage).height();
					ui.registerDialog.query('.error_message').hide().fadeIn().css({
						height : errorMessageHeight+'px'
					}, {tween:'medium'});
					
					events._fireEvent('registerfailed', [response && response.message || null]);
					events._fireEvent('registrationfailed', [response && response.message || null]);
					priv.setLoginStatus(false);
					
				}
			};
			model.api.localAuth.register(params);
		};
		
		
		
		
		priv.showFacebookLogin = function(callback) {
			callback = callback || function(){};
			FB.login(function(response) {
				if (response.session) {
					data.facebookSession = response.session;
					model.api.localAuth.socialLogin({
						acct_type : 'facebook',
						fb_session : tinydom.json(data.facebookSession),
						callback : function(success, response) {

							if (success && response && response.session) {

								data.session = response.session;
								data.profile = response.session.profile || {};
								delete data.session.profile;
								priv.setLoginStatus(true);
							}
							callback(success, data.session, data.profile);
							callback = null;
						}
					});
				}
				else {
					callback(false);
					callback = null;
				}
			});
		};
		
		
		
		
		
		priv.twitterLoginInit = function() {
			tinydom.twitter.addEventListener('authComplete', function(e, user, bridge_code) {
				console.log('Auth component detected Twitter::authComplete');
				if (e && user && bridge_code) {
					model.api.localAuth.socialLogin({
						acct_type : 'twttr',
						twttr_session : tinydom.json(user),
						twttr_bridge_code : bridge_code,
						callback : function(success, response) {
							tinydom.log('Twitter Login Dispatch Callback :: ', success, response);
							if (success && response && response.session) {

								data.session = response.session;
								data.profile = response.session.profile || {};
								delete data.session.profile;
								priv.setLoginStatus(true);
							}
							callback(success, data.session, data.profile);
							callback = null;
						}
					});
				}
			});
		};
		
		priv.showTwitterLogin = function() {
			tinydom.twitter.requireLogin();
		};
		
		
		
		
		
		priv.showLogin = function(callback) {
			if (!data.initialized) {
				data.initialView = 'login';
				return true;
			}
			if (data.registerFormInlineCallback) {
				data.loginFormInlineCallback = data.registerFormInlineCallback;
				data.registerFormInlineCallback = null;
			}
			priv.hideForgotPass();
			priv.hideRegistration();
			exports.updateState({
				view : 'login'
			});
			data.loginFormInlineCallback = callback;
			ui.loginDialog.query('.error_message').height(0);
			ui.loginDialog.show();
			ui.loginDialog.query('#auth_login_username').focus();
			
		};
		
		priv.hideLogin = function() {
			exports.updateState({
				view : null
			});
			ui.loginDialog.hide(true);
		};
		
		priv.cancelLogin = function() {
			priv.hideLogin();
			if (data.loginFormInlineCallback) {
				data.loginFormInlineCallback(false);
			}
		};
		
		
		
		
		
		
		
		priv.showForgotPass = function(callback) {
			if (!data.initialized) {

				return true;
			}
			priv.hideLogin();
			priv.hideRegistration();
			exports.updateState({
				view : null
			});

			ui.forgotPassDialog.query('.error_message').height(0);
			ui.forgotPassDialog.declassify('forgotPassSubmitted');
			ui.forgotPassDialog.show();
			ui.forgotPassDialog.query('#auth_forgotpass_email').focus();
			
		};
		
		priv.cancelForgotPass = priv.hideForgotPass = function(fromInternal) {
			ui.forgotPassDialog.hide(true);
			if (fromInternal===true) {
				priv.showLogin();
			}
		};
		
		priv.showForgotPassExplainer = function() {
			ui.forgotPassDialog.classify('forgotPassSubmitted');
		};
		
		
		
		
		
		
		priv.showRegistration = function(callback) {
			if (!data.initialized) {
				data.initialView = 'register';
				return true;
			}
			if (data.loginFormInlineCallback) {
				data.registerFormInlineCallback = data.loginFormInlineCallback;
				data.loginFormInlineCallback = null;
			}
			priv.hideLogin();
			exports.updateState({
				view : 'register'
			});
			data.registerFormInlineCallback = callback;
			ui.registerDialog.query('.error_message').height(0);
			ui.registerDialog.show();
			ui.registerDialog.query('#auth_register_email').focus();
			
		};
		
		priv.hideRegistration = function() {
			exports.updateState({
				view : null
			});
			ui.registerDialog.hide(true);
		};
		
		priv.cancelRegistration = function() {
			priv.hideRegistration();
			if (data.registerFormInlineCallback) {
				data.registerFormInlineCallback(false);
			}
		};
		
		
		
		priv.logout = function(callback) {
			tinydom.cookies.remove('ss_token');

			
			priv.setLoginStatus(false);

			model.api.localAuth.logout({
				callback : function() {
					if (callback) {
						callback();
					}
				}
			});
		};
		
		
		
		exports.logout = function() {
			priv.logout();
		};
		
		
		exports.login = function(type, callback) {
			if (tinydom.typeOf(type)!=='string') {
				callback = type;
				type = null;
				if (tinydom.typeOf(arguments[1])==='string') {
					type = arguments[1];
				}
			}
			if (data.loggedin===true) {
				if (callback) {
					setTimeout(function() {
						callback(data.session);
					}, 1);
				}
			}
			else {
				type = (type+'').toLowerCase();

				if (type==='facebook' || type==='fb') {
					priv.showFacebookLogin(callback);
				}
				else if (type==='twitter') {
					priv.showTwitterLogin(callback);
				}
				else {
					priv.showLogin(callback);
				}
			}
		};
		
		
		exports.register = function(callback) {
			if (data.loggedin===true) {
				priv.logout(function() {
					priv.showRegistration(callback);
				});
			}
			else {
				priv.showRegistration(callback);
			}
		};
		
		
		exports.reconfigure = function(newOptions) {
			if (tinydom.typeOf(newOptions)==='object') {

			}
		};

		exports.on = exports.addEventListener = exports.addListener = function(type, handler) {
			events.addEventListener(type, handler);
		};
		exports.removeEventListener = exports.removeListener = function(type, handler) {
			events.removeEventListener(type, handler);
		};
		
		
		if (initOptions.init!==false) {
			exports.init();
		}
		
		return exports;
	}
});
app.components.register('Subscription', {
	
	config : {
		purchaseUrl	: 'https://secure.socialseek.com/?t={token}&type={plan}'

	},
	
	load : function(params) {
		if (params && params.model) {
			this.model = params.model;
			this.auth = params.app.auth;
		}
		return this;
	},
	
	destroy : function() {
		this.model = this.auth = null;
	},
	
	showUpgradeOptions : function(options, callback) {
		var self = this,
			ui,
			exports = {};
		
		if (options.type==='proPicker' || options.type==='propick') {
			options.type = 'proPicker';

		}
		
		if (options.type==='proPicker' || options.type==='pro') {
			ui = tinydom.el('#subscription_upgradedialog_type_pro');
		}
		else {
			ui = tinydom.el('#subscription_upgradedialog');
		}
		
		exports.getToken = function() {
			var session = self.app.auth.getSession();
			return session && session.token;
		};
		
		exports.signupForPlan = function(type) {
			self.auth.requireLogin(function(loggedin) {
				var token, url, session, token;
				if (loggedin) {
					session = self.auth.getSession();
					token = session && session.token;
					if (token) {
						url = tinydom.template(self.config.purchaseUrl, {
							plan : type,
							token : token
						}, false);
					}
				}
				if (url) {

					self.model.api.subscription.purchaseSessionTransfer({
						type : type,
						site_id : type==='pro' ? options.site_id : null,
						callback : function(success, response) {
							if (success) {
								location.href = url;
							}
							else {
								exports.close();
							}
						}
					});
				}
				else {
					exports.close();
				}
			});
		};
		
		exports.proBtnClick = function(e) {
			exports.signupForPlan('pro');
			return tinydom.cancelEvent(e);
		};
		
		exports.proPickerBtnClick = function(e) {

			exports.close();

		};
		
		exports.plusBtnClick = function(e) {
			exports.signupForPlan('plus');
			return tinydom.cancelEvent(e);
		};
		
		exports.close = function() {
			if (ui.player) {



				if (ui.player.stop) {
					ui.player.stop();
				}

			}
			ui.query('.subscriptionUpgrade_proBtn').removeEvent('click', exports.proBtnClick);
			ui.query('.subscriptionUpgrade_proPickerBtn').removeEvent('click', exports.proPickerBtnClick);
			ui.query('.subscriptionUpgrade_plusBtn').removeEvent('click', exports.plusBtnClick);
			ui.query('.closeButton, .emailClientOverlayBg').removeEvent('click', exports.close);
			ui.query('.emailClientWrap').fadeOut('fast', function(node) {
				ui.query('.emailClientOverlayBg').fadeOut('fast', function(node) {
					ui.hide(true)
					ui = null;
				}, true);
			}, true);

			exports = self = options = callback = null;
		};
		if (options.direct)
		{
			exports.signupForPlan(options.type);	
		}
		ui.query('.subscriptionUpgradeDialogOption').hide(true);
		
		ui.query('.subscriptionUpgrade_proBtn').on('click', exports.proBtnClick);
		ui.query('.subscriptionUpgrade_proPickerBtn').on('click', exports.proPickerBtnClick);
		ui.query('.subscriptionUpgrade_plusBtn').on('click', exports.plusBtnClick);
		ui.query('.closeButton, .emailClientOverlayBg').on('click', exports.close);
		
		ui.show();
		ui.query('.emailClientOverlayBg').fadeIn('medium', function(node) {
			ui.query('.emailClientWrap').fadeIn('medium', function(node) {
				var otherType;
				if (options.type) {


					ui.query('.subscriptionUpgradeDialog_'+options.type+'Option').show();
					
					if (options.type==='pro' || options.type==='proPicker') {
						
						ui.player = self._currentProPlayer || app.videoPlayer.create(
							ui.query('#subscription_upgradedialog_type_pro_video'),
							{
								autoplay : false,
								preload : true
							}
						);
						self._currentProPlayer = ui.player;



					}
					
				}
			});
		});

	}
	
});app.components.register('Chat', {
	load : function() {
		var exports = new tinydom.EventEmitter(),
			priv = {},
			data = {
				contextualized : false
			},
			ui = {};
		
		priv.init = function(config) {
			data.model = config.model;
			data.app = config.app;
			data.auth = data.app.auth;
			
			ui.base = config.uibase || tinydom.el('#chatbase');
			ui.toolbar = ui.base.query('.chattoolbar');
			ui.input = ui.base.query('.chatinput_message');
			ui.output = ui.base.query('.chatoutput');
			ui.outputInner = ui.output.query('.chatoutput_inner');
			ui.updateTpl = ui.base.query('.chatUpdateTemplate').hide(true).remove();
			
			ui.base.query('.chatclosebutton').on('click', priv.handlers.closeButton);
			
			ui.input.on('keydown', priv.handlers.inputkeydown);
			ui.input.on('keyup', priv.handlers.inputkeyup);
			
			exports.on('postsubmit', priv.handlers.postsubmit);
			exports.on('postcomplete', priv.handlers.postcomplete);
			
			data.app.on('sitechange,keywordchange', priv.updateChatContext);
			priv.updateChatContext();
			
			data.auth.addEventListener('change', priv.authChange);
			priv.authChange();
			
			exports.on('connectivityChange', priv.connectivityChanged);
			
			priv.history(function() {
				priv.poller.start();
			});
		};
		
		
		
		priv.handlers = {
			closeButton : function(e) {
				exports.close();
				return tinydom.cancelEvent(e);
			},
			postsubmit : function() {
				ui.input.disable();
				ui.base.classify('postingInProgress');
			},
			postcomplete : function() {
				ui.input.enable().value('');
				ui.base.declassify('postingInProgress');
			},
			inputkeydown : function(e) {
				var key = e.keyCode || e.which;
				if (key===13) {			// enter
					priv.postMessage(ui.input.value());
					return tinydom.cancelEvent(e);
				}
				else if (key===27) {			// esc
					ui.input.blur();
				}
			},
			inputkeyup : function(e) {
				var key = e.keyCode || e.which;
				if (key===13) {			// enter
					return tinydom.cancelEvent(e);
				}
			}
		};
		
		
		
		priv.authChange = function() {
			var info = data.auth.getInfo();

			data.session = info.session;
			data.profile = info.profile;
			if (data.loggedin!==info.loggedin) {
				data.loggedin = info.loggedin;
				priv.statusChanged(data.loggedin);
			}
		};
		
		priv.connectivityChanged = function(connected) {


				if (connected) {
					ui.base.declassify('chat_disconnected').classify('chat_connected');
				}
				else {
					ui.base.declassify('chat_connected').classify('chat_disconnected');
				}

		};
		
		priv.statusChanged = function(loggedin) {
			if (loggedin) {
				ui.base.declassify('loggedout').classify('loggedin');
				priv.login();
			}
			else {
				ui.base.declassify('loggedin').classify('loggedout');
				priv.logout();
			}
		};
		
		priv.login = function(callback) {
			data.model.api.chat.login({
				userid : data.session.userid || data.profile.id,
				callback : function() {
					data.chatLoggedin = true;
					if (callback){ 
						callback();
					}
				}
			});
		};
		priv.logout = function(callback) {
			data.model.api.chat.logout({
				callback : function() {
					data.chatLoggedin = false;
					if (callback) {
						callback();
					}
				}
			});
		};
		
		priv.updateChatContext = function() {
			var info = data.app.getSeekMetaInfo();
			if (info.isSite) {
				data.chatContext = {
					'site-id' : info.id
				};
			}
			else if (info.keywords) {
				data.chatContext = {
					'site-keywords' : info.keywords
				};
			}
			else {
				data.chatContext = null;
			}
		};
		
		priv.requireLogin = function(callback) {
			data.auth.requireLogin(function(loggedin) {
				if (loggedin) {
					if (!data.chatLoggedin) {
						priv.login(function() {
							callback(true);
						});
					}
					else {
						callback(true);
					}
				}
				else {
					callback(false);
				}
			});
		};
		
		priv.postMessage = function(message, callback) {
			var p;
			if (!message) {
				if (callback) {
					callback(false, {
						success : false,
						error : true
					});
				}
				return false;
			}
			else if (!data.loggedin) {
				priv.requireLogin(function(loggedin){
					if (loggedin) {
						priv.postMessage(message, callback);
					}
					else if (callback) {
						callback(false, {
							success : false,
							error : true,
							loggedin : false,
							authfail : true
						});
					}
					callback = message = null;
				});
			}
			else {
				p = tinydom.extend({}, data.contextualized && data.chatContext || {});
				p.body = message;
				p.callback = function(data) {
					console.log('postMessage::callback -> ', data);
					exports._fireEvent('postcomplete');
					if (callback) {
						callback(true, {
							success : true,
							error : false,
							response : data
						});
					}
					message = callback = p = null;
				};
				exports._fireEvent('postsubmit');
				data.model.api.chat.post(p);
			}
		};
		
		priv.addMessage = function(message) {
			var scroll = priv.shouldScrollToBottom();

			ui.updateTpl.clone(true).template(message).insertInto(ui.outputInner).show();
			if (scroll) {
				priv.scrollToBottom();
			}
		};
		
		priv.shouldScrollToBottom = function() {
			var st = Math.abs(ui.output.scrollTop()),
				sh = ui.output.height({padding:false,border:false}),
				th = ui.outputInner.height({margin:true,border:true});
			return Math.abs(st+sh-th)<5;
		};
		
		priv.scrollToBottom = function() {
			ui.output.scrollTop(ui.outputInner.height()-ui.output.height());
		};
		
		priv.setConnected = function(connected) {
			if (connected!==data.connected) {
				data.connected = connected;
				exports._fireEvent('connectivityChange', data.connected);
			}
		};
		
		priv.setOnlineCount = function(users) {
			ui.base.query('.chattitle_alt').html('('+users+')');
		};
		
		priv.restrictDisplayCount = function() {
			var list = ui.outputInner.children();
			if (list.count()>100) {
				list.first(list.count()-100).destroy();
			}
		};
		
		priv.handleMessages = function(messages) {
			var i;
			if (messages && messages.length>0) {
				for (i=messages.length; i--; ) {
					priv.addMessage(messages[i]);
				}
				priv.restrictDisplayCount();
			}
		};
		
		priv.history = function(callback) {
			var p = tinydom.extend({}, data.contextualized && data.chatContext || {});
			p.callback = function(success, response) {
				priv.handleMessages(success && response && response.messages);
				priv.scrollToBottom();
				if (callback) {
					callback();
				}
			};
			data.model.api.chat.history(p);
		};
		
		priv.update = function(callback) {
			var p = tinydom.extend({}, data.contextualized && data.chatContext || {});
			p.callback = function(success, response) {
				var successOrTimeout = success || (response && response.timedout===true);

				priv.setConnected(successOrTimeout);
				if (response.online_users) {
					priv.setOnlineCount(Math.round(response.online_users));
				}
				priv.handleMessages(success && response && response.messages);
				if (callback && typeof(callback)==='function') {
					callback({
						error : !successOrTimeout
					});
				}
			};
			data.model.api.chat.updates(p);
		};
		
		priv.poller = {
			start : function() {
				this.stop();
				this.enabled = true;
				priv.setConnected(true);
				priv.update(this._callback);
			},
			stop : function() {
				this.enabled = false;
				if (this.timer) {
					clearTimeout(this.timer);
				}
				if (this.request && this.request.cancel) {
					this.request.cancel();
				}
				this.request = null;
				priv.setConnected(false);
			},
			_callback : function(o) {
				var self = priv.poller;
				if (o && o.error===true) {
					self._interval = Math.min(self._maxInterval, Math.max(self._interval*2, 200));
				}
				else {
					self._interval = self._baseInterval;
				}

				priv.poller.timer = setTimeout(function() {
					if (priv.poller.enabled===true) {
						priv.update(priv.poller._callback);
					}
					self = null;
				}, self._interval);
			},
			_interval : 10,
			_baseInterval : 10,
			_maxInterval : 30000
		};
		
		
		exports.toggle = function() {
			exports[data.showing===true ? 'hide' : 'show']();
		};
		
		exports.open = exports.show = function() {
			if (data.showing!==true) {
				data.showing = true;
				ui.base.classify('sliding','slidingOpen');
				ui.base.show().css({
					bottom : '0%',
					opacity : 1
				}, {tween:'medium', callback:function() {
					ui.base.declassify('sliding','slidingOpen').classify('showing');
				}});
			}
		};
		exports.close = exports.hide = function() {
			if (data.showing===true) {
				data.showing = false;
				ui.base.declassify('showing').classify('sliding','slidingClosed');
				ui.base.css({
					bottom : '-50%',
					opacity : 0
				}, {tween:'medium', callback:function() {
					ui.base.hide(false);
					ui.base.declassify('sliding','slidingClosed');
				}});
			}
		};
		
		
		exports.setHeight = function(height) {
			var tbHeight = ui.toolbar.height({border:false});
			
			ui.output.css({
				top : tbHeight + 'px',
				height : (ui.base.height({padding:false}) - tbHeight - ui.input.height({border:true})) + 'px'
			});
		};
		
		
		priv.init.apply(priv,arguments);
		return exports;
	}
});(function() {
	
	function Menu() {
		tinydom.EventEmitter.apply(this,arguments);
	}
	tinydom.inherits(Menu, tinydom.EventEmitter);
	
	
	
	
	function MenuManager(params) {
		params = params || {};
		tinydom.EventEmitter.apply(this,arguments);
		tinydom.extend(this, {
			parent : params.baseArea || params.parent,
			showAnimations : params.showAnimations!==false
		});
		if (params.hasOwnProperty('fadeDuration')) {
			this.fadeInDuration = params.fadeDuration;
			this.fadeOutDuration = params.fadeDuration;
		}
		if (params.hasOwnProperty('fadeInDuration')) {
			this.fadeInDuration = params.fadeInDuration;
		}
		if (params.hasOwnProperty('fadeOutDuration')) {
			this.fadeOutDuration = params.fadeOutDuration;
		}
		if (params.showAnimations===false) {
			this.fadeInDuration = 0;
			this.fadeOutDuration = 0;
			this.fadeDuration = 0;
		}
		this.views = tinydom.extend({}, this.views, params.views);
	}
	
	tinydom.extend(MenuManager.prototype, {
		
		
		fadeInDuration : 'short',
		fadeOutDuration : 'short',
		fadeDuration : 0,
		activationTime : 600,
		
		
		
		createMenu : function() {
			var exports = new Menu(),
				data = {
					baseClassName : "genericMenu",
					clickHandlers : [],
					actionButtonHandlers : [],
					submenus : [],
					menuItemInfo : {},
					menuItemIdCounter : 0,
					showing : false,
					showAnimations : true,
					openedTime : new Date().getTime()
				},
				ui = {},
				priv = {
					itemEventHandlers : {}
				},
				manager = this;
			
			manager._menuidcounter = (parseInt(manager._menuidcounter, 10) || 0) + 1;
			exports.id = manager._menuidcounter;

			ui.init = function() {
				ui.overlay = tinydom.el({
					className : "shim menuListShim " + data.baseClassName+"Shim",
					onmouseup : function(e) {
						var timeOpen = new Date().getTime() - data.openedTime;
						if (timeOpen>(data.activationTime || manager.activationTime)) {
							exports._fireEvent('shimclicked');
							exports.close();
						}
						return tinydom.cancelEvent(e);
					},
					onmousedown : tinydom.cancelEvent,
					oncontextmenu : tinydom.cancelEvent
				});
				
				ui.menu = tinydom.el({
					className : "menuList " + data.baseClassName,

					css : 'visibility:hidden;',
					children : [
						{ className : "menuListInner" }
					],
					onmousedown : tinydom.cancelEvent,
					onmouseup : tinydom.cancelEvent,
					oncontextmenu : tinydom.cancelEvent
				});
				
				ui.itemParent = ui.menu.query('.menuListInner');
			};
			
			
			priv.init = function(config) {
				var openOptions;
				data.baseClassName = config.baseClassName || config.className || data.baseClassName;
				
				if (config.maxHeight) {
					data.maxHeight = config.maxHeight;
				}
				if (config.minWidth) {
					data.minWidth = config.minWidth;
				}
				
				ui.init();

				if (config.items || config.menuItems) {
					exports.addItems(config.items || config.menuItems);
				}
				ui.overlay.hide(true);
				ui.menu.hide(true);
				if (config.hasOwnProperty('showAnimations')) {
					data.showAnimations = config.showAnimations!==false;
				}
				if (config.parent || manager.parent || document.body) {
					ui.overlay.insertInto(config.parent || manager.parent || document.body);
					ui.menu.insertInto(config.parent || manager.parent || document.body);
				}
				if (config.show!==false) {
					openOptions = tinydom.extend({}, config);
					openOptions.show = openOptions.parent = openOptions.showAnimations = openOptions.items = openOptions.menuItems = null;
					exports.show(openOptions);
					
				}
			};

			
			priv.itemEventHandlers.mouseover = function(e) {
				var self = tinydom.el(this),
					id = self.attr('data-menuItemId'),
					itemData = data.menuItemInfo[id];
				for (var x=data.submenus.length; x--; ) {
					if (!itemData.submenu || data.submenus[x].id!==itemData.submenu.id) {
						data.submenus[x].close();
					}
				}
				self.classify('hover');
			};
			priv.itemEventHandlers.mouseout = function(e) {
				tinydom.el(this).declassify('hover');
			};
			
			priv.itemEventHandlers.click = function(e) {
				var self = tinydom.el(this),

					id = self.attr('data-menuItemId'),
					itemData = tinydom.extend({}, data.menuItemInfo[id], {
						event : e,
						menuItemId : id,
						menu : exports
					}),
					x, eventResponse, executeHandlers;
				executeHandlers = function() {
					for (x=data.clickHandlers.length; x--; ) {
						if (data.clickHandlers[x].id===id) {
							eventResponse = data.clickHandlers[x].handler.apply(self, [itemData]);
							if (eventResponse===false) {
								break;
							}
						}
					}
					if (eventResponse!==false) {
						exports._fireEvent('itemclicked', [itemData]);
						exports.close();
					}
					executeHandlers = self = itemData = id = eventResponse = e = null;
				};
				self.classify('clickedFlashOn').wait(50, function(){
					this.declassify('clickedFlashOn').wait(50, function() {
						executeHandlers();
					});
				});
				return tinydom.cancelEvent(e);
			};
			
			priv.itemEventHandlers.actionButton = function(e) {
				var self = tinydom.el(this).parent(),				// reference the menuItem, not the button itself.
					id = self.attr('data-menuItemId'),
					itemData = tinydom.extend({}, data.menuItemInfo[id], {
						event : e,
						menuItemId : id,
						menu : exports
					}),
					x, eventResponse;
				for (x=data.actionButtonHandlers.length; x--; ) {
					if (data.actionButtonHandlers[x].id===id) {
						eventResponse = data.actionButtonHandlers[x].handler.apply(self, [itemData]);
						if (eventResponse===false) {
							break;
						}
					}
				}
				if (eventResponse!==false) {
					exports._fireEvent('itemclicked', [itemData]);
					exports.close();
				}
				return tinydom.cancelEvent(e);
			};
			
			
			priv.itemEventHandlers.submenuMouseover = function(e) {
				var self = tinydom.el(this),
					id = self.attr('data-menuItemId'),
					itemData = data.menuItemInfo[id],
					delay;
				priv.itemEventHandlers.mouseover.apply(this,arguments);
				if (!itemData.submenu) {
					delay = parseInt(manager.submenuDelay,10) || 120;
					if (delay>0) {
						itemData.openSubmenuTimer = setTimeout(function() {
							priv.openSubmenu(id);
						}, delay);
					}
					else {
						priv.openSubmenu(id);
					}
				}
				itemData = self = null;
			};
			priv.itemEventHandlers.submenuMouseup = function(e) {
				var self = tinydom.el(this),
					id = self.attr('data-menuItemId'),
					itemData = data.menuItemInfo[id];
				if (!itemData.submenu) {
					priv.openSubmenu(id);
				}
			};
			priv.itemEventHandlers.submenuMouseout = function(e) {
				var self = tinydom.el(this),
					itemData = data.menuItemInfo[self.attr('data-menuItemId')];
				priv.itemEventHandlers.mouseout.apply(this,arguments);
				if (itemData.openSubmenuTimer) {
					clearTimeout(itemData.openSubmenuTimer);
					delete itemData.openSubmenuTimer;
				}
			};
			
			
			
			
			priv.openSubmenu = function(id) {
				var item = priv.getItemById(id),
					itemData = data.menuItemInfo[id+''],
					menuInner = ui.menu.query('.menuListInner');
				if (item && itemData) {
					itemData.submenu = manager.createMenu(tinydom.extend({
						dir : 'right',
						offsetX : -menuInner.x(),
						offsetY : -menuInner.y(),
						switchDirOnEdge : true,
						showAnimations : false
					}, itemData.submenuDefinition, {
						fromElement : item,
						showAnimations : false
					}));
					itemData.submenu._parentItemId = id+'';
					itemData.submenu.addEventListener('itemclicked,shimclicked', function() {
						setTimeout(function() {
							if (exports && exports.close) {
								exports.close();
							}
						}, 1);
					});
					itemData.submenu.addEventListener('beforeclose', function() {
						var parentItem = priv && priv.getItemById(this._parentItemId),
							parentItemData = data && data.menuItemInfo[this._parentItemId],
							x;

						if (parentItem) {
							parentItem.declassify('active');
						}
						if (parentItemData) {
							parentItemData.submenu = null;
							delete parentItemData.submenu;
						}
						if (data && data.submenus) {
							for (x=data.submenus.length; x--; ) {
								if (data.submenus[x].id===this.id) {
									data.submenus.splice(x, 1);
									break;
								}
							}
						}
					});
					data.submenus.push(itemData.submenu);
				}
				item = itemData = menuInner = null;
			};
			
			
			
			priv.getItemById = function(id) {
				var item;
				if (!id && id!==0) {
					return false;
				}
				id = id + '';
				ui.itemParent.children().each(function(node) {
					if (!item && node.attr('data-menuItemId')===id) {
						item = node;
					}
				});
				return item || false;
			};
			
			
			priv.sizeChanged = function() {
				var maxHeight = data.maxHeight || (ui.overlay.height()-ui.menu.y()),
					minWidth = data.minWidth || 0;

				if (data.showing===true) {
					if (minWidth && ui.menu.width()<minWidth) {
						ui.menu.width(minWidth);
					}
					if (maxHeight && ui.menu.height()>maxHeight) {

						ui.menu.css({
							height : maxHeight
						});
					}
					
					if (ui.menu.x()+ui.menu.width()+10>ui.overlay.width()) {
						ui.menu.x(ui.overlay.width() - ui.menu.width() - 10);
					}
				}
			};
			
			priv.getMaxWidth = function() {
				return ui.overlay.width() || tinydom.el(document.body).width();
			};
			
			priv.getMaxHeight = function() {
				return ui.overlay.height() || (Math.round(window.innerHeight) || Math.round(document.documentElement.offsetHeight) || Math.round(document.body.clientHeight) || Math.round(document.body.offsetHeight)) || 0;
			};

			
			exports.addItems = function(items) {
				var frag = document.createDocumentFragment(),
					i, item, node;
				
				if (!tinydom.isArray(items)) {
					items = [items];
				}
				
				for (i=0; i<items.length; i++) {
					item = items[i];
					data.menuItemIdCounter += 1;
					
					data.clickHandlers.push({
						id : data.menuItemIdCounter + '',
						inline : true,
						handler : item.onclick || item.action || item.clickHandler || function(){}
					});
					data.actionButtonHandlers.push({
						id : data.menuItemIdCounter + '',
						inline : true,
						handler : item.onActionButton || item.alternateAction || item.buttonAction || item.actionButtonHandler || function(){}
					});
					data.menuItemInfo[data.menuItemIdCounter+''] = {
						data : item.data
					};
					
					node = {
						className : "menuListItem",
						attributes : {
							'data-menuItemId' : data.menuItemIdCounter + ''
						},
						children : [
							{
								className : "label menuListItemLabel",
								innerHTML : item.label || ''
							}
						],
						onmouseover : priv.itemEventHandlers.mouseover,
						onmouseout : priv.itemEventHandlers.mouseout,
						onmousedown : tinydom.cancelEvent,
						onmouseup : priv.itemEventHandlers.click

					};
					
					if (item.className) {
						node.className += " " + item.className;
					}
					if (item.hoverEffect===false) {
						delete node.onmouseover;
						delete node.onmouseout;
					}
					if (item.type) {

						switch ((item.type+'').toLowerCase()) {
							case 'custom':
								node.className += ' menuListItem_type_custom';
								node.children = [
									item.base
								];
								break;
							
							case 'title':
							case 'group':
							case 'grouptitle':
								node.className += ' menuListItem_type_group_title';
								break;
							
							case 'separator':
								node.className += ' menuListItem_type_separator';
								break;
							
							case 'submenu':
								node.className += ' menuListItem_type_submenu';
								node.children.push({
									className : "menuListItemSubmenuIndicator",
									innerHTML : decodeURIComponent('%E2%96%B6'),				// right arrow char
									onmouseup : priv.itemEventHandlers.actionButton,
									onmousedown : tinydom.cancelEvent,
									click : tinydom.cancelEvent
								});
								data.menuItemInfo[data.menuItemIdCounter+''].submenuDefinition = item.submenu || item.menu || item.menuItems;
								node.onmouseover = priv.itemEventHandlers.submenuMouseover;
								node.onmouseup = priv.itemEventHandlers.submenuMouseup;
								node.onmouseout = priv.itemEventHandlers.submenuMouseout;
								delete node.onmousedown;

								break;
						}
					}
					
					if (item.actionButtonLabel) {
						node.children.push({
							className : "menuListItemActionButton",
							innerHTML : item.actionButtonLabel || '',
							onmouseup : priv.itemEventHandlers.actionButton,
							onmousedown : tinydom.cancelEvent,
							click : tinydom.cancelEvent
						});
					}
					
					tinydom.el(node, frag);
				}
				
				ui.itemParent.appendChild(frag);
				frag = item = node = items = null;
				
				priv.sizeChanged();
				
				return exports;
			};
			
			
			exports.removeItems = function(items) {
				var i, item, x, id;
				
				if (!tinydom.isArray(items)) {
					items = [items];
				}
				
				for (i=items.length; i--; ) {
					if (tinydom.typeOf(items[i])==='object' && items[i].id) {
						item = priv.getItemById(items[i].id);
					}
					else {
						item = priv.getItemById(items[i]);
					}
					if (item) {
						id = item.attr('data-menuItemId');
						data.menuItemInfo[id] = null;
						delete data.menuItemInfo[id];
						for (x=data.clickHandlers.length; x--; ) {
							if (data.clickHandlers[x].id===id) {
								data.clickHandlers.splice(x, 1);
							}
						}
						for (x=data.actionButtonHandlers.length; x--; ) {
							if (data.actionButtonHandlers[x].id===id) {
								data.actionButtonHandlers.splice(x, 1);
							}
						}
						item.remove();
					}
				}
				
				priv.sizeChanged();
				
				return exports;
			};
			
			
			exports.removeAllItems = function() {
				ui.itemParent.children().remove();
				
				return exports;
			};
			
			
			exports.getItems = function() {
				return ui.itemParent.children();
			};
			
			
			exports.getSelection = function() {
				var selection = [];
				ui.itemParent.children().each(function(item) {
					if (item.hasClass('active') || item.hasClass('hover')) {
						selection.push(
							data.menuItemInfo[item.attr('data-menuItemId')].data
						);
					}
				});
				return selection;
			};
			
			exports.getSelectedItems = function() {
				return ui.itemParent.query('.active, .hover');
			};
			
			
			exports.show = exports.open = function(options, callback) {
				var fromElement, maxWidth, maxHeight;
				exports._fireEvent('beforeopen');
				exports._fireEvent('beforeshow');
				data.showing = true;
				options = options || data.lastShowOptions || {};
				data.lastShowOptions = options;
				ui.menu.css({ opacity:0.01 }).show();
				if (tinydom.typeOf(options.x)!=='number' || tinydom.typeOf(options.y)!=='number') {
					if (options.fromElement) {
						fromElement = tinydom.el(options.fromElement);
						
						if (!data.minWidth && data.minWidth!==0) {
							data.minWidth = fromElement.width();
						}

						fromElement.classify('active','menuListOpen');
						exports._autoActivateFromElement = fromElement;
						exports._deactivateFromElement = function() {
							exports._autoActivateFromElement.declassify('active','menuListOpen');
							delete exports._autoActivateFromElement;
							exports.removeEventListener('beforehide', exports._deactivateFromElement);
						}
						exports.addEventListener('beforehide', exports._deactivateFromElement);
						
						options.x = fromElement.x(true, true);
						options.y = fromElement.y(true);
						
						if (options.dir==='right') {
							options.x += fromElement.width();
						}
						else {
							if (options.dir==='top') {
								options.y -= ui.menu.height();
							}
							else {
								options.y += fromElement.height();
							}
						}
					}
				}
				options.x += options.offsetX || 0;
				options.y += options.offsetY || 0;
				
				ui.overlay.show();
				maxWidth = priv.getMaxWidth();
				maxHeight = priv.getMaxHeight();

				if ((options.x+ui.menu.width())>maxWidth) {
					if (options.switchDirOnEdge===true && options.dir==='right') {
						options.x = options.x - fromElement.width() - ui.menu.width() - (options.offsetX || 0)*2;		// reverse the horizontal offset
					}
					else {
						options.x = maxWidth-ui.menu.width();
					}
				}
				if ((options.y+ui.menu.height())>maxHeight) {
					if (options.switchDirOnEdge===true && options.dir==='bottom') {
						options.y = options.y - fromElement.height() - ui.menu.height() - (options.offsetY || 0)*2;		// reverse the vertical offset
					}
					else {
						options.y = maxHeight-ui.menu.height();
					}
				}
				
				if (options.x<0) {
					options.x = 0;
				}
				if (options.y<0) {
					options.y = 0;
				}

				if (ui.menu.height()>maxHeight) {
					ui.menu.height(maxHeight);
				}
				
				ui.menu.position(options.x, options.y).fadeIn(data.showAnimations ? (manager.fadeInDuration || manager.fadeDuration) : false, function() {
					exports._fireEvent('open');
					exports._fireEvent('show');
					if (callback) {
						callback();
						callback = null;
					}
				});
				
				priv.sizeChanged();
				
				options = fromElement = null;
				
				return exports;
			};
			
			exports.hide = function(callback) {
				exports._fireEvent('beforehide');
				data.showing = false;

				for (var x=data.submenus.length; x--; ) {
					data.submenus[x].close();
				}
				
				ui.menu.fadeOut(data.showAnimations ? (manager.fadeOutDuration || manager.fadeDuration) : false, function() {
					ui.overlay.hide(true);
					exports._fireEvent('hide');
					if (callback) {
						callback();
					}
				}, true);
				return exports;
			};
			
			exports.close = exports.destroy = function(callback) {
				exports._fireEvent('beforeclose');
				exports.hide(function() {
					exports._fireEvent('close');
					for (var x=manager.menus.length; x--; ) {
						if (manager.menus[x].id===exports.id) {
							manager.menus.splice(x, 1);
							break;
						}
					}


					ui.menu.destroy();
					ui.overlay.destroy();
					ui = exports = priv = data = manager = null;
					if (callback) {
						callback();
					}
					callback = null;
				});
				return exports;
			};
			
			manager.menus.push(exports);
			
			priv.init.apply(priv, arguments);
			
			return exports;
		},
		
		
		
		get : function(id) {
			for (var x=this.menus.length; x--; ) {
				if (this.menus[x].id===id) {
					return this.menus[x];
				}
			}
			return false;
		},
		
		
		
		menus : []
		
	});

	tinydom.inherits(MenuManager, tinydom.EventEmitter);
	
	app.components.register('MenuManager', {
		load : function(opt) {
			return new MenuManager(opt);
		}
	});
}());(function() {
	
	function Dialog() {
		tinydom.EventEmitter.apply(this,arguments);
	}
	tinydom.inherits(Dialog, tinydom.EventEmitter);
	
	
	
	
	function DialogManager(params) {
		params = params || {};
		tinydom.EventEmitter.apply(this,arguments);
		tinydom.extend(this, {
			parent : params.baseArea || params.parent,
			configManager : params.configManager,
			showAnimations : params.showAnimations!==false
		});
		this.views = tinydom.extend({}, this.views, params.views);
	}
	
	tinydom.extend(DialogManager.prototype, {
		
		fillCSS : "position:fixed; left:0; top:0; width:100%; height:100%; *position:absolute;",
		
		
		
		restoreState : function(state) {

			var dialog, hasData=false, self=this, cb;
			this.disableStateUpdates();
			cb = function() {
				setTimeout(function() {
					self.enableStateUpdates();

					cb = state = self = dialog = null;
				}, 50);
			};
			if (state) {
				if (state.id) {
					hasData = true;
					SocialSeek.URLShortener.expand(state.id, function(longUrl) {
						var parts = tinydom.url.parse(longUrl),
							current = {},
							i;
						for (i in parts.querystringParsed) {
							if (parts.querystringParsed.hasOwnProperty(i) && i.substring(0,15)==='dialog.current.') {
								current[i.substring(15)] = parts.querystringParsed[i];
							}
						}
						console.log(parts, current);
						dialog = self.createDialog(current);
						if (dialog) {
							hasData = true;
							if (state.showing===false) {
								dialog.hide();
							}
							else {
								dialog.show();
							}
							cb();
						}
					});
				}
				else if (state.current ) {
					dialog = this.createDialog(state.current);
					if (dialog) {
						hasData = true;
						if (state.showing===false) {
							dialog.hide();
						}
						else {
							dialog.show();
						}
						cb();
					}
				}
			}
			if (!hasData) {

				this.reset(cb);
			}
		},
		
		
		
		disableStateUpdates : function() {
			this.stateUpdatesDisabled = true;
		},
		
		enableStateUpdates : function() {
			this.stateUpdatesDisabled = false;


		},
		
		
		doStateUpdate : function(state, callback) {
			var update = true;
			if (this.stateUpdatesDisabled===true) {
				update = false;
				if (callback) {
					callback(false);
				}
				return false;
			}
			if (!state) {
				state = this._currentState;
			}
			this._currentState = state;

			if (update) {
				this.setState(state, callback, !!callback);
			}
		},
		
		
		
		createDialog : function(type, config) {

			if (tinydom.typeOf(type)==='object') {
				config = type;

				type = null;
			}
			if (!type && config.type) {
				type = config.type;
			}

			if (type) {
				config = tinydom.extend({}, config, {
					type : type
				});
				if (this.configManager) {
					return this.configManager.load(type, {
						info : config,
						dialogManager : this
					});
				}
				else {
					throw(new Error("DialogManager: No configManager available for createTypedDialog."));
					return false;
				}

			}
			else {
				return this.createCustomDialog(config);
			}
		},
		
		
		
		
		createTypedDialog : function(type, config, creationInfo) {
			if (!creationInfo.type) {
				creationInfo.type = type;
			}
			config = tinydom.extend({}, config, {
				_typeDialogCreationInfo : creationInfo
			});
			return this.createCustomDialog(config);
		},
		
		
		
		
		
		createCustomDialog : function(config) {
			var exports = new Dialog(),
				data = {
					showing : false
				},
				ui = {},
				updateState,
				manager = this;
			
			manager._dialogidcounter = (parseInt(manager._dialogidcounter, 10) || 0) + 1;
			exports.id = manager._dialogidcounter;
			
			ui.base = tinydom.el({
				css : manager.fillCSS + " z-index:900; display:none;"
			}, config.parent || manager.parent || document.body);
			
			ui.overlay = tinydom.el({
				className : "dialog_overlay",
				css : manager.fillCSS + " display:none; z-index:940;"
			}, ui.base);
			data.maxOverlayOpacity = parseFloat(ui.overlay.getStyle('opacity'),10) || 0.5;
			ui.overlay.css({
				display : 'block',
				opacity : 0
			});
			
			ui.dialogWrap = tinydom.el({
				className : "dialog_wrap",
				css : manager.fillCSS + " top:-200%; z-index:950;"
			}, ui.base);
			
			ui.dialog = tinydom.el(config.dialogTemplate || manager.views.dialogTemplate, ui.dialogWrap);
			
			ui.dialogWrap.on('click', function(e) {
				e = e || window.event;
				var target = e.target || e.srcElement;
				if (target.nodeType===3) {
					target = target.parentNode;
				}
				if ((' '+target.className+' ').indexOf(' dialog_wrap ')>-1) {
					exports.close();
				}
			});
			ui.dialogWrap.query(".dialog_title_closeButton").on('click', function() {
				exports.close();
			});

			(function(tpl, templateField) {
				for (var i in tpl) {
					if (tpl.hasOwnProperty(i)) {
						templateField = ui.dialog.query('.templateField-'+i);
						if (templateField.exists()) {
							switch (templateField.prop('nodeName').toLowerCase()) {
								case 'iframe':
								case 'img':
								case 'video':
								case 'audio':
									templateField.attr('src', tpl[i]);
									break;
									
								default:
									if (tinydom.typeOf(tpl[i])==='string') {
										templateField.html(tpl[i]);
									}
									else if (tinydom.typeOf(tpl[i])==='object') {

										tinydom.el(tpl[i], templateField);
									}
							}
						}
					}
				}
			}(config.content || config.tpl || config.fields));
			
			
			
			ui.dialog.query('.dialogShortUrl').on('focus,mousedown,mouseup,click,selectstart,selectend,keydown,keyup,keypress', function(e){
				var el = tinydom.el(this),
					lockedValue = el.attr('data-lockedvalue');
				if (el.value()!==lockedValue) {
					el.value(lockedValue);
				}
				el.selectAll();
				el = lockedValue = null;
				if (!e.type.match(/^key/)) {
					return tinydom.cancelEvent(e);
				}
			});
			
			

			updateState = function(callback) {
				var state = {};
				if (manager.updateState) {
					if (config) {
						state.showing = data.showing===true;
						if (exports.dialogUniqueId) {
							state.id = exports.dialogUniqueId;
						}
						else {
							state.current = config._typeDialogCreationInfo || config;
						}
					}
					manager.doStateUpdate(state, callback);
				}
				else if(callback) {
	
