modularize oxui

This commit is contained in:
rolux 2011-04-23 00:03:10 +02:00
parent 2e3292e9ce
commit 0024af978c
106 changed files with 16127 additions and 47034 deletions

View file

@ -1 +1,2 @@
.DS_Store .DS_Store
build/js

4376
build/js/jquery-1.3.2.js vendored

File diff suppressed because it is too large Load diff

6078
build/js/jquery-1.4.1.js vendored

File diff suppressed because it is too large Load diff

View file

@ -1,152 +0,0 @@
/*!
* jQuery JavaScript Library v1.4.1
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Mon Jan 25 19:43:33 2010 -0500
*/
(function(z,v){function la(){if(!c.isReady){try{r.documentElement.doScroll("left")}catch(a){setTimeout(la,1);return}c.ready()}}function Ma(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var n in b)X(a,n,b[n],f,e,d);return a}if(d!==v){f=!i&&f&&c.isFunction(d);for(n=0;n<j;n++)e(a[n],b,f?d.call(a[n],n,e(a[n],b)):d,i);return a}return j?
e(a[0],b):null}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function ma(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function na(a){var b,d=[],f=[],e=arguments,i,j,n,o,m,s,x=c.extend({},c.data(this,"events").live);if(!(a.button&&a.type==="click")){for(o in x){j=x[o];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete x[o]}i=c(a.target).closest(f,
a.currentTarget);m=0;for(s=i.length;m<s;m++)for(o in x){j=x[o];n=i[m].elem;f=null;if(i[m].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==n)d.push({elem:n,fn:j})}}m=0;for(s=d.length;m<s;m++){i=d[m];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}}function oa(a,b){return"live."+(a?a+".":"")+b.replace(/\./g,"`").replace(/ /g,"&")}function pa(a){return!a||!a.parentNode||a.parentNode.nodeType===
11}function qa(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ra(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0&&(c.support.checkClone||!sa.test(a[0]))){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:r;f=b.createDocumentFragment();
c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=i?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(ta.concat.apply([],ta.slice(0,b)),function(){d[this]=a});return d}function ua(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Na=z.jQuery,Oa=z.$,r=z.document,S,Pa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Qa=/^.[^:#\[\.,]*$/,Ra=/\S/,Sa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Ta=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,O=navigator.userAgent,
va=false,P=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,Q=Array.prototype.slice,wa=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Pa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:r;if(a=Ta.exec(a))if(c.isPlainObject(b)){a=[r.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ra([d[1]],
[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=r.getElementById(d[2])){if(b.id!==d[2])return S.find(a);this.length=1;this[0]=b}this.context=r;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=r;a=r.getElementsByTagName(a)}else return!b||b.jquery?(b||S).find(a):c(b).find(a);else if(c.isFunction(a))return S.ready(a);if(a.selector!==v){this.selector=a.selector;this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,
this)},selector:"",jquery:"1.4.1",length:0,size:function(){return this.length},toArray:function(){return Q.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=0;ba.apply(this,a);return this},each:function(a,b){return c.each(this,
a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(r,c);else P&&P.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(Q.apply(this,arguments),"slice",Q.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};
c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,n;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];n=e[i];if(a!==n)if(f&&n&&(c.isPlainObject(n)||c.isArray(n))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(n)?[]:{};a[i]=c.extend(f,j,n)}else if(n!==v)a[i]=n}return a};c.extend({noConflict:function(a){z.$=
Oa;if(a)z.jQuery=Na;return c},isReady:false,ready:function(){if(!c.isReady){if(!r.body)return setTimeout(c.ready,13);c.isReady=true;if(P){for(var a,b=0;a=P[b++];)a.call(r,c);P=null}c.fn.triggerHandler&&c(r).triggerHandler("ready")}},bindReady:function(){if(!va){va=true;if(r.readyState==="complete")return c.ready();if(r.addEventListener){r.addEventListener("DOMContentLoaded",L,false);z.addEventListener("load",c.ready,false)}else if(r.attachEvent){r.attachEvent("onreadystatechange",L);z.attachEvent("onload",
c.ready);var a=false;try{a=z.frameElement==null}catch(b){}r.documentElement.doScroll&&a&&la()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===v||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;
return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return z.JSON&&z.JSON.parse?z.JSON.parse(a):(new Function("return "+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Ra.test(a)){var b=r.getElementsByTagName("head")[0]||
r.documentElement,d=r.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(r.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===v||c.isFunction(a);if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=
a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Sa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==
v;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=v}else if(b&&!c.isFunction(b)){d=b;b=v}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},
uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});O=c.uaMatch(O);if(O.browser){c.browser[O.browser]=true;c.browser.version=O.version}if(c.browser.webkit)c.browser.safari=true;if(wa)c.inArray=function(a,b){return wa.call(b,a)};S=c(r);if(r.addEventListener)L=function(){r.removeEventListener("DOMContentLoaded",
L,false);c.ready()};else if(r.attachEvent)L=function(){if(r.readyState==="complete"){r.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=r.documentElement,b=r.createElement("script"),d=r.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support=
{leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:r.createElement("select").appendChild(r.createElement("option")).selected,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};
b.type="text/javascript";try{b.appendChild(r.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,a.firstChild);if(z[f]){c.support.scriptEval=true;delete z[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function n(){c.support.noCloneEvent=false;d.detachEvent("onclick",n)});d.cloneNode(true).fireEvent("onclick")}d=r.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=r.createDocumentFragment();a.appendChild(d.firstChild);
c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var n=r.createElement("div");n.style.width=n.style.paddingLeft="1px";r.body.appendChild(n);c.boxModel=c.support.boxModel=n.offsetWidth===2;r.body.removeChild(n).style.display="none"});a=function(n){var o=r.createElement("div");n="on"+n;var m=n in o;if(!m){o.setAttribute(n,"return;");m=typeof o[n]==="function"}return m};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props=
{"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ua=0,xa={},Va={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var f=a[G],e=c.cache;if(!b&&!f)return null;f||(f=++Ua);if(typeof b==="object"){a[G]=f;e=e[f]=c.extend(true,
{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Va:(e[f]={});if(d!==v){a[G]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[G]}catch(i){a.removeAttribute&&a.removeAttribute(G)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,
a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===v){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===v&&this.length)f=c.data(this[0],a);return f===v&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);
return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===v)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||
a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var ya=/[\n\t]/g,ca=/\s+/,Wa=/\r/g,Xa=/href|src|style/,Ya=/(button|input)/i,Za=/(button|input|object|select|textarea)/i,$a=/^(a|area)$/i,za=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=
c(this);m.addClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,n=b.length;j<n;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=c(this);m.removeClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string"||a===v)for(var b=(a||"").split(ca),
d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(ya," "),j=0,n=b.length;j<n;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),n=b,o=
a.split(ca);e=o[i++];){n=f?n:!j.hasClass(e);j[n?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(ya," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===v){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||
{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(za.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Wa,"")}return v}var n=c.isFunction(a);return this.each(function(o){var m=c(this),s=a;if(this.nodeType===1){if(n)s=a.call(this,o,m.val());
if(typeof s==="number")s+="";if(c.isArray(s)&&za.test(this.type))this.checked=c.inArray(m.val(),s)>=0;else if(c.nodeName(this,"select")){var x=c.makeArray(s);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),x)>=0});if(!x.length)this.selectedIndex=-1}else this.value=s}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return v;if(f&&b in c.attrFn)return c(a)[b](d);
f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==v;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Xa.test(b);if(b in a&&f&&!i){if(e){b==="type"&&Ya.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Za.test(a.nodeName)||$a.test(a.nodeName)&&a.href?0:v;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=
""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?v:a}return c.style(a,b,d)}});var ab=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==z&&!a.frameElement)a=z;if(!d.guid)d.guid=c.guid++;if(f!==v){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=
function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):v};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var n,o=0;n=b[o++];){var m=n.split(".");n=m.shift();if(o>1){d=c.proxy(d);if(f!==v)d.data=f}d.type=m.slice(0).sort().join(".");var s=e[n],x=this.special[n]||{};if(!s){s=e[n]={};if(!x.setup||x.setup.call(a,f,m,d)===false)if(a.addEventListener)a.addEventListener(n,i,false);else a.attachEvent&&a.attachEvent("on"+n,i)}if(x.add)if((m=x.add.call(a,
d,f,m,s))&&c.isFunction(m)){m.guid=m.guid||d.guid;m.data=m.data||d.data;m.type=m.type||d.type;d=m}s[d.guid]=d;this.global[n]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===v||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);for(var n=0;i=b[n++];){var o=i.split(".");i=o.shift();var m=!o.length,s=c.map(o.slice(0).sort(),ab);s=new RegExp("(^|\\.)"+
s.join("\\.(?:.*\\.)?")+"(\\.|$)");var x=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var A in f[i])if(m||s.test(f[i][A].type))delete f[i][A];x.remove&&x.remove.call(a,o,j);for(e in f[i])break;if(!e){if(!x.teardown||x.teardown.call(a,o)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(A=c.data(a,"handle"))A.elem=null;c.removeData(a,
"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return v;a.result=v;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,
b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(i){}if(!a.isPropagationStopped()&&f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){d=a.target;var j;if(!(c.nodeName(d,"a")&&e==="click")&&!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){try{if(d[e]){if(j=d["on"+e])d["on"+e]=null;this.triggered=true;d[e]()}}catch(n){}if(j)d["on"+e]=j;this.triggered=false}}},handle:function(a){var b,
d;a=arguments[0]=c.event.fix(a||z.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==v){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||r;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=r.documentElement;d=r.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==v)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;b.liveProxy=a;c.event.add(this,b.live,na,b)},remove:function(a){if(a.length){var b=
0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],na)}},special:{}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};
c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y};var Aa=function(a){for(var b=
a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ba=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ba:Aa,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ba:Aa)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!==
"form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return ma("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return ma("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,
"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var da=/textarea|input|select/i;function Ca(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ea(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Ca(d);if(a.type!=="focusout"||
d.type!=="radio")c.data(d,"_change_data",e);if(!(f===v||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}}c.event.special.change={filters:{focusout:ea,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ea.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ea.call(this,a)},beforeactivate:function(a){a=
a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Ca(a))}},setup:function(a,b,d){for(var f in T)c.event.add(this,f+".specialChange."+d.guid,T[f]);return da.test(this.nodeName)},remove:function(a,b){for(var d in T)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),T[d]);return da.test(this.nodeName)}};var T=c.event.special.change.filters}r.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,
f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){e=f;f=v}var j=b==="one"?c.proxy(e,function(n){c(this).unbind(n,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,
b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+
a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e){var i,j=0;if(c.isFunction(f)){e=f;f=v}for(d=(d||"").split(/\s+/);(i=d[j++])!=null;){i=i==="focus"?"focusin":i==="blur"?"focusout":i==="hover"?d.push("mouseleave")&&"mouseenter":i;b==="live"?c(this.context).bind(oa(i,this.selector),{data:f,selector:this.selector,
live:i},e):c(this.context).unbind(oa(i,this.selector),e?{guid:e.guid+this.selector+i}:null)}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});z.attachEvent&&!z.addEventListener&&z.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
(function(){function a(g){for(var h="",k,l=0;g[l];l++){k=g[l];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===k){y=l[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=k;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}l[q]=y}}}function d(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===
k){y=l[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=k;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(o.filter(h,[t]).length>0){y=t;break}}t=t[g]}l[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,i=Object.prototype.toString,j=false,n=true;[0,0].sort(function(){n=false;return 0});var o=function(g,h,k,l){k=k||[];var q=h=h||r;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||
typeof g!=="string")return k;for(var p=[],u,t,y,R,H=true,M=w(h),I=g;(f.exec(""),u=f.exec(I))!==null;){I=u[3];p.push(u[1]);if(u[2]){R=u[3];break}}if(p.length>1&&s.exec(g))if(p.length===2&&m.relative[p[0]])t=fa(p[0]+p[1],h);else for(t=m.relative[p[0]]?[h]:o(p.shift(),h);p.length;){g=p.shift();if(m.relative[g])g+=p.shift();t=fa(g,t)}else{if(!l&&p.length>1&&h.nodeType===9&&!M&&m.match.ID.test(p[0])&&!m.match.ID.test(p[p.length-1])){u=o.find(p.shift(),h,M);h=u.expr?o.filter(u.expr,u.set)[0]:u.set[0]}if(h){u=
l?{expr:p.pop(),set:A(l)}:o.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=u.expr?o.filter(u.expr,u.set):u.set;if(p.length>0)y=A(t);else H=false;for(;p.length;){var D=p.pop();u=D;if(m.relative[D])u=p.pop();else D="";if(u==null)u=h;m.relative[D](y,u,M)}}else y=[]}y||(y=t);y||o.error(D||g);if(i.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))k.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&
y[g].nodeType===1&&k.push(t[g]);else k.push.apply(k,y);else A(y,k);if(R){o(R,q,k,l);o.uniqueSort(k)}return k};o.uniqueSort=function(g){if(C){j=n;g.sort(C);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};o.matches=function(g,h){return o(g,null,null,h)};o.find=function(g,h,k){var l,q;if(!g)return[];for(var p=0,u=m.order.length;p<u;p++){var t=m.order[p];if(q=m.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");l=m.find[t](q,
h,k);if(l!=null){g=g.replace(m.match[t],"");break}}}}l||(l=h.getElementsByTagName("*"));return{set:l,expr:g}};o.filter=function(g,h,k,l){for(var q=g,p=[],u=h,t,y,R=h&&h[0]&&w(h[0]);g&&h.length;){for(var H in m.filter)if((t=m.leftMatch[H].exec(g))!=null&&t[2]){var M=m.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(u===p)p=[];if(m.preFilter[H])if(t=m.preFilter[H](t,u,k,p,l,R)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=u[U])!=null;U++)if(D){I=M(D,t,U,u);var Da=
l^!!I;if(k&&I!=null)if(Da)y=true;else u[U]=false;else if(Da){p.push(D);y=true}}if(I!==v){k||(u=p);g=g.replace(m.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)o.error(g);else break;q=g}return u};o.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var m=o.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,h){var k=typeof h==="string",l=k&&!/\W/.test(h);k=k&&!l;if(l)h=h.toLowerCase();l=0;for(var q=g.length,
p;l<q;l++)if(p=g[l]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[l]=k||p&&p.nodeName.toLowerCase()===h?p||false:p===h}k&&o.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var l=0,q=g.length;l<q;l++){var p=g[l];if(p){k=p.parentNode;g[l]=k.nodeName.toLowerCase()===h?k:false}}}else{l=0;for(q=g.length;l<q;l++)if(p=g[l])g[l]=k?p.parentNode:p.parentNode===h;k&&o.filter(h,g,true)}},"":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=
h=h.toLowerCase();q=b}q("parentNode",h,l,g,p,k)},"~":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,l,g,p,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];h=h.getElementsByName(g[1]);for(var l=0,q=h.length;l<q;l++)h[l].getAttribute("name")===g[1]&&k.push(h[l]);return k.length===0?null:k}},
TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,l,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var u;(u=h[p])!=null;p++)if(u)if(q^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||l.push(u);else if(k)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&
"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,l,q,p){h=g[1].replace(/\\/g,"");if(!p&&m.attrMap[h])g[1]=m.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,l,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=o(g[3],null,null,h);else{g=o.filter(g[3],h,k,true^q);k||l.push.apply(l,g);return false}else if(m.match.POS.test(g[0])||m.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);
return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!o(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===
g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,h){return h===0},last:function(g,h,k,l){return h===l.length-1},even:function(g,h){return h%2===
0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,l){var q=h[1],p=m.filters[q];if(p)return p(g,k,h,l);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=h[3];k=0;for(l=h.length;k<l;k++)if(h[k]===g)return false;return true}else o.error("Syntax error, unrecognized expression: "+
q)},CHILD:function(g,h){var k=h[1],l=g;switch(k){case "only":case "first":for(;l=l.previousSibling;)if(l.nodeType===1)return false;if(k==="first")return true;l=g;case "last":for(;l=l.nextSibling;)if(l.nodeType===1)return false;return true;case "nth":k=h[2];var q=h[3];if(k===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var u=0;for(l=p.firstChild;l;l=l.nextSibling)if(l.nodeType===1)l.nodeIndex=++u;p.sizcache=h}g=g.nodeIndex-q;return k===0?g===0:g%k===0&&g/k>=
0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=m.attrHandle[k]?m.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var l=h[2];h=h[4];return g==null?l==="!=":l==="="?k===h:l==="*="?k.indexOf(h)>=0:l==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:l==="!="?k!==h:l==="^="?
k.indexOf(h)===0:l==="$="?k.substr(k.length-h.length)===h:l==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,l){var q=m.setFilters[h[2]];if(q)return q(g,k,h,l)}}},s=m.match.POS;for(var x in m.match){m.match[x]=new RegExp(m.match[x].source+/(?![^\[]*\])(?![^\(]*\))/.source);m.leftMatch[x]=new RegExp(/(^(?:.|\r|\n)*?)/.source+m.match[x].source.replace(/\\(\d+)/g,function(g,h){return"\\"+(h-0+1)}))}var A=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};
try{Array.prototype.slice.call(r.documentElement.childNodes,0)}catch(B){A=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,l=g.length;k<l;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var C;if(r.documentElement.compareDocumentPosition)C=function(g,h){if(!g.compareDocumentPosition||!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===
h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in r.documentElement)C=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(r.createRange)C=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),l=h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);l.setStart(h,0);l.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END,
l);if(g===0)j=true;return g};(function(){var g=r.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=r.documentElement;k.insertBefore(g,k.firstChild);if(r.getElementById(h)){m.find.ID=function(l,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(l[1]))?q.id===l[1]||typeof q.getAttributeNode!=="undefined"&&q.getAttributeNode("id").nodeValue===l[1]?[q]:v:[]};m.filter.ID=function(l,q){var p=typeof l.getAttributeNode!=="undefined"&&l.getAttributeNode("id");
return l.nodeType===1&&p&&p.nodeValue===q}}k.removeChild(g);k=g=null})();(function(){var g=r.createElement("div");g.appendChild(r.createComment(""));if(g.getElementsByTagName("*").length>0)m.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var l=0;k[l];l++)k[l].nodeType===1&&h.push(k[l]);k=h}return k};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")m.attrHandle.href=function(h){return h.getAttribute("href",
2)};g=null})();r.querySelectorAll&&function(){var g=o,h=r.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){o=function(l,q,p,u){q=q||r;if(!u&&q.nodeType===9&&!w(q))try{return A(q.querySelectorAll(l),p)}catch(t){}return g(l,q,p,u)};for(var k in g)o[k]=g[k];h=null}}();(function(){var g=r.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===
0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){m.order.splice(1,0,"CLASS");m.find.CLASS=function(h,k,l){if(typeof k.getElementsByClassName!=="undefined"&&!l)return k.getElementsByClassName(h[1])};g=null}}})();var E=r.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,h){return g!==h&&(g.contains?g.contains(h):true)},w=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},fa=function(g,h){var k=[],
l="",q;for(h=h.nodeType?[h]:h;q=m.match.PSEUDO.exec(g);){l+=q[0];g=g.replace(m.match.PSEUDO,"")}g=m.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)o(g,h[q],k);return o.filter(l,k)};c.find=o;c.expr=o.selectors;c.expr[":"]=c.expr.filters;c.unique=o.uniqueSort;c.getText=a;c.isXMLDoc=w;c.contains=E})();var bb=/Until$/,cb=/^(?:parents|prevUntil|prevAll)/,db=/,/;Q=Array.prototype.slice;var Ea=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a,
function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Qa.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=
0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ea(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ea(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i={},j;if(f&&a.length){e=0;for(var n=a.length;e<n;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)>
-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var o=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(m,s){for(;s&&s.ownerDocument&&s!==b;){if(o?o.index(s)>-1:c(s).is(a))return s;s=s.parentNode}return null})},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),
a);return this.pushStack(pa(a[0])||pa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},
nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);bb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):
e;if((this.length>1||db.test(f))&&cb.test(a))e=e.reverse();return this.pushStack(e,a,Q.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===v||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==
b&&d.push(a);return d}});var Fa=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ga=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,sa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ia=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],
col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==v)return this.empty().append((this[0]&&this[0].ownerDocument||r).createTextNode(a));return c.getText(this)},
wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?
d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,
false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&
!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Fa,"").replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){qa(this,b);qa(this.find("*"),b.find("*"))}return b},html:function(a){if(a===v)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Fa,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(Ha.exec(a)||
["",""])[1].toLowerCase()]){a=a.replace(Ga,Ia);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,
b,f))});else a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(s){return c.nodeName(s,"table")?s.getElementsByTagName("tbody")[0]||s.appendChild(s.ownerDocument.createElement("tbody")):s}var e,i,j=a[0],n=[];if(!c.support.checkClone&&arguments.length===3&&typeof j===
"string"&&sa.test(j))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(j))return this.each(function(s){var x=c(this);a[0]=j.call(this,s,b?x.html():v);x.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ra(a,this,n);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var o=0,m=this.length;o<m;o++)d.call(b?f(this[o],i):this[o],e.cacheable||this.length>1||o>0?e.fragment.cloneNode(true):e.fragment)}n&&c.each(n,
Ma)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){c.cleanData(this.getElementsByTagName("*"));c.cleanData([this])}this.parentNode&&
this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&c.cleanData(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||r;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||r;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j===
"string"){j=j.replace(Ga,Ia);var n=(Ha.exec(j)||["",""])[1].toLowerCase(),o=F[n]||F._default,m=o[0];i=b.createElement("div");for(i.innerHTML=o[1]+j+o[2];m--;)i=i.lastChild;if(!c.support.tbody){m=fb.test(j);n=n==="table"&&!m?i.firstChild&&i.firstChild.childNodes:o[1]==="<table>"&&!m?i.childNodes:[];for(o=n.length-1;o>=0;--o)c.nodeName(n[o],"tbody")&&!n[o].childNodes.length&&n[o].parentNode.removeChild(n[o])}!c.support.leadingWhitespace&&V.test(j)&&i.insertBefore(b.createTextNode(V.exec(j)[0]),i.firstChild);
j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()==="text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e},cleanData:function(a){for(var b=0,d;(d=a[b])!=null;b++){c.event.remove(d);c.removeData(d)}}});var hb=/z-?index|font-?weight|opacity|zoom|line-?height/i,
Ja=/alpha\([^)]*\)/,Ka=/opacity=([^)]*)/,ga=/float/i,ha=/-([a-z])/ig,ib=/([A-Z])/g,jb=/^-?\d+(?:px)?$/i,kb=/^-?\d/,lb={position:"absolute",visibility:"hidden",display:"block"},mb=["Left","Right"],nb=["Top","Bottom"],ob=r.defaultView&&r.defaultView.getComputedStyle,La=c.support.cssFloat?"cssFloat":"styleFloat",ia=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===v)return c.curCSS(d,f);if(typeof e==="number"&&!hb.test(f))e+="px";c.style(d,f,e)})};
c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return v;if((b==="width"||b==="height")&&parseFloat(d)<0)d=v;var f=a.style||a,e=d!==v;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ja.test(a)?a.replace(Ja,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ka.exec(f.filter)[1])/100+"":""}if(ga.test(b))b=La;b=b.replace(ha,ia);if(e)f[b]=d;return f[b]},css:function(a,
b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?mb:nb;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,lb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&
a.currentStyle){f=Ka.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ga.test(b))b=La;if(!d&&e&&e[b])f=e[b];else if(ob){if(ga.test(b))b="float";b=b.replace(ib,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ha,ia);f=a.currentStyle[b]||a.currentStyle[d];if(!jb.test(f)&&kb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left=
a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var pb=
J(),qb=/<script(.|\s)*?\/script>/gi,rb=/select|textarea/i,sb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ja=/\?/,tb=/(\?|&)_=.*?(&|$)/,ub=/^(\w+:)?\/\/([^\/?#]+)/,vb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=
c.param(b,c.ajaxSettings.traditional);f="POST"}var i=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(j,n){if(n==="success"||n==="notmodified")i.html(e?c("<div />").append(j.responseText.replace(qb,"")).find(e):j.responseText);d&&i.each(d,[j.responseText,n,j])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&
(this.checked||rb.test(this.nodeName)||sb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,
b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:z.XMLHttpRequest&&(z.location.protocol!=="file:"||!z.ActiveXObject)?function(){return new z.XMLHttpRequest}:
function(){try{return new z.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(o,n,j,w);e.global&&f("ajaxSuccess",[w,e])}function d(){e.complete&&e.complete.call(o,w,j);e.global&&f("ajaxComplete",[w,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}
function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,n,o=a&&a.context||e,m=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(m==="GET")N.test(e.url)||(e.url+=(ja.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||
N.test(e.url))){i=e.jsonpCallback||"jsonp"+pb++;if(e.data)e.data=(e.data+"").replace(N,"="+i+"$1");e.url=e.url.replace(N,"="+i+"$1");e.dataType="script";z[i]=z[i]||function(q){n=q;b();d();z[i]=v;try{delete z[i]}catch(p){}A&&A.removeChild(B)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&m==="GET"){var s=J(),x=e.url.replace(tb,"$1_="+s+"$2");e.url=x+(x===e.url?(ja.test(e.url)?"&":"?")+"_="+s:"")}if(e.data&&m==="GET")e.url+=(ja.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&
c.event.trigger("ajaxStart");s=(s=ub.exec(e.url))&&(s[1]&&s[1]!==location.protocol||s[2]!==location.host);if(e.dataType==="script"&&m==="GET"&&s){var A=r.getElementsByTagName("head")[0]||r.documentElement,B=r.createElement("script");B.src=e.url;if(e.scriptCharset)B.charset=e.scriptCharset;if(!i){var C=false;B.onload=B.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;b();d();B.onload=B.onreadystatechange=null;A&&B.parentNode&&
A.removeChild(B)}}}A.insertBefore(B,A.firstChild);return v}var E=false,w=e.xhr();if(w){e.username?w.open(m,e.url,e.async,e.username,e.password):w.open(m,e.url,e.async);try{if(e.data||a&&a.contentType)w.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&w.setRequestHeader("If-None-Match",c.etag[e.url])}s||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",
e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(fa){}if(e.beforeSend&&e.beforeSend.call(o,w,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");w.abort();return false}e.global&&f("ajaxSend",[w,e]);var g=w.onreadystatechange=function(q){if(!w||w.readyState===0||q==="abort"){E||d();E=true;if(w)w.onreadystatechange=c.noop}else if(!E&&w&&(w.readyState===4||q==="timeout")){E=true;w.onreadystatechange=c.noop;j=q==="timeout"?"timeout":!c.httpSuccess(w)?
"error":e.ifModified&&c.httpNotModified(w,e.url)?"notmodified":"success";var p;if(j==="success")try{n=c.httpData(w,e.dataType,e)}catch(u){j="parsererror";p=u}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,w,j,p);d();q==="timeout"&&w.abort();if(e.async)w=null}};try{var h=w.abort;w.abort=function(){w&&h.call(w);g("abort")}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){w&&!E&&g("timeout")},e.timeout);try{w.send(m==="POST"||m==="PUT"||m==="DELETE"?e.data:null)}catch(l){c.handleError(e,
w,null,l);d()}e.async||g();return w}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=
f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(j,n){if(c.isArray(n))c.each(n,
function(o,m){b?f(j,m):d(j+"["+(typeof m==="object"||c.isArray(m)?o:"")+"]",m)});else!b&&n!=null&&typeof n==="object"?c.each(n,function(o,m){d(j+"["+o+"]",m)}):f(j,n)}function f(j,n){n=c.isFunction(n)?n():n;e[e.length]=encodeURIComponent(j)+"="+encodeURIComponent(n)}var e=[];if(b===v)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var i in a)d(i,a[i]);return e.join("&").replace(vb,"+")}});var ka={},wb=/toggle|show|hide/,xb=/^([+-]=)?([\d+-.]+)(.*)$/,
W,ta=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(ka[d])f=ka[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();
ka[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&
c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,n=this.nodeType===1&&c(this).is(":hidden"),
o=this;for(j in a){var m=j.replace(ha,ia);if(j!==m){a[m]=a[j];delete a[j];j=m}if(a[j]==="hide"&&n||a[j]==="show"&&!n)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(s,x){var A=new c.fx(o,i,s);if(wb.test(x))A[x==="toggle"?n?"show":"hide":x](a);
else{var B=xb.exec(x),C=A.cur(true)||0;if(B){x=parseFloat(B[2]);var E=B[3]||"px";if(E!=="px"){o.style[s]=(x||1)+E;C=(x||1)/A.cur(true)*C;o.style[s]=C+E}if(B[1])x=(B[1]==="-="?-1:1)*x+C;A.custom(C,x,E)}else A.custom(C,x,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",
1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,
b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==
null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop===
"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=
this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=
c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=
null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in r.documentElement?function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),
f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(s){c.offset.setOffset(this,a,s)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=
b,e=b.ownerDocument,i,j=e.documentElement,n=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var o=b.offsetTop,m=b.offsetLeft;(b=b.parentNode)&&b!==n&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;o-=b.scrollTop;m-=b.scrollLeft;if(b===d){o+=b.offsetTop;m+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){o+=parseFloat(i.borderTopWidth)||
0;m+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){o+=parseFloat(i.borderTopWidth)||0;m+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){o+=n.offsetTop;m+=n.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){o+=Math.max(j.scrollTop,n.scrollTop);m+=Math.max(j.scrollLeft,n.scrollLeft)}return{top:o,left:m}};c.offset={initialize:function(){var a=r.body,b=r.createElement("div"),
d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);
d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop},
bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left-
e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=
this.offsetParent||r.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==v)return this.each(function(){if(i=ua(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=ua(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}});
c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(i){var j=c(this);j[d](f.call(this,i,j[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||
e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===v?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});z.jQuery=z.$=c})(window);

6240
build/js/jquery-1.4.2.js vendored

File diff suppressed because it is too large Load diff

5999
build/js/jquery-1.4.js vendored

File diff suppressed because it is too large Load diff

View file

@ -1,151 +0,0 @@
/*!
* jQuery JavaScript Library v1.4
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://docs.jquery.com/License
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Wed Jan 13 15:23:05 2010 -0500
*/
(function(A,w){function oa(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(oa,1);return}c.ready()}}function La(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function $(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var o in b)$(a,o,b[o],f,e,d);return a}if(d!==w){f=!i&&f&&c.isFunction(d);for(o=0;o<j;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,i);return a}return j?
e(a[0],b):null}function K(){return(new Date).getTime()}function aa(){return false}function ba(){return true}function pa(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function qa(a){var b=true,d=[],f=[],e=arguments,i,j,o,p,n,t=c.extend({},c.data(this,"events").live);for(p in t){j=t[p];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete t[p]}i=c(a.target).closest(f,a.currentTarget);
n=0;for(l=i.length;n<l;n++)for(p in t){j=t[p];o=i[n].elem;f=null;if(i[n].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==o)d.push({elem:o,fn:j})}}n=0;for(l=d.length;n<l;n++){i=d[n];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}function ra(a,b){return["live",a,b.replace(/\./g,"`").replace(/ /g,"&")].join(".")}function sa(a){return!a||!a.parentNode||a.parentNode.nodeType===
11}function ta(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ua(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:s;f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=
i?f:1;return{fragment:f,cacheable:e}}function T(a){for(var b=0,d,f;(d=a[b])!=null;b++)if(!c.noData[d.nodeName.toLowerCase()]&&(f=d[H]))delete c.cache[f]}function L(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ma=A.jQuery,Na=A.$,s=A.document,U,Oa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Pa=/^.[^:#\[\.,]*$/,Qa=/\S/,
Ra=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Sa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],M,ca=Object.prototype.toString,da=Object.prototype.hasOwnProperty,ea=Array.prototype.push,R=Array.prototype.slice,V=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Oa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Sa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];
c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ua([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return U.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a)}else return!b||b.jquery?(b||U).find(a):c(b).find(a);else if(c.isFunction(a))return U.ready(a);if(a.selector!==w){this.selector=a.selector;
this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,this)},selector:"",jquery:"1.4",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=
0;ea.apply(this,a);return this},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||
c(null)},push:ea,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];o=e[i];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(o)?[]:{};a[i]=c.extend(f,j,o)}else if(o!==w)a[i]=
o}return a};c.extend({noConflict:function(a){A.$=Na;if(a)A.jQuery=Ma;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",M,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",
M);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&oa()}}},isFunction:function(a){return ca.call(a)==="[object Function]"},isArray:function(a){return ca.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||ca.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!da.call(a,"constructor")&&!da.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===w||da.call(a,b)},
isEmptyObject:function(a){for(var b in a)return false;return true},noop:function(){},globalEval:function(a){if(a&&Qa.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===w||c.isFunction(a);
if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Ra,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ea.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=
0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b===
"string"){d=a;a=d[b];b=w}else if(b&&!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){var b={browser:""};a=a.toLowerCase();if(/webkit/.test(a))b={browser:"webkit",version:/webkit[\/ ]([\w.]+)/};else if(/opera/.test(a))b={browser:"opera",version:/version/.test(a)?/version[\/ ]([\w.]+)/:/opera[\/ ]([\w.]+)/};else if(/msie/.test(a))b={browser:"msie",version:/msie ([\w.]+)/};else if(/mozilla/.test(a)&&
!/compatible/.test(a))b={browser:"mozilla",version:/rv:([\w.]+)/};b.version=(b.version&&b.version.exec(a)||[0,"0"])[1];return b},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=true;if(V)c.inArray=function(a,b){return V.call(b,a)};U=c(s);if(s.addEventListener)M=function(){s.removeEventListener("DOMContentLoaded",M,false);c.ready()};else if(s.attachEvent)M=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",
M);c.ready()}};if(V)c.inArray=function(a,b){return V.call(b,a)};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+K();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,
htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,
a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function o(){c.support.noCloneEvent=false;d.detachEvent("onclick",o)});d.cloneNode(true).fireEvent("onclick")}c(function(){var o=s.createElement("div");o.style.width=o.style.paddingLeft="1px";s.body.appendChild(o);c.boxModel=c.support.boxModel=o.offsetWidth===2;s.body.removeChild(o).style.display="none"});a=function(o){var p=s.createElement("div");o="on"+o;var n=o in
p;if(!n){p.setAttribute(o,"return;");n=typeof p[o]==="function"}return n};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var H="jQuery"+K(),Ta=0,ya={},Ua={};c.extend({cache:{},expando:H,noData:{embed:true,object:true,applet:true},data:function(a,
b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var f=a[H],e=c.cache;if(!b&&!f)return null;f||(f=++Ta);if(typeof b==="object"){a[H]=f;e=e[f]=c.extend(true,{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Ua:(e[f]={});if(d!==w){a[H]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var d=a[H],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[H]}catch(i){a.removeAttribute&&
a.removeAttribute(H)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,
a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,
a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var za=/[\n\t]/g,fa=/\s+/,Va=/\r/g,Wa=/href|src|style/,Xa=/(button|input)/i,Ya=/(button|input|object|select|textarea)/i,Za=/^(a|area)$/i,Aa=/radio|checkbox/;c.fn.extend({attr:function(a,
b){return $(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(p){var n=c(this);n.addClass(a.call(this,p,n.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(fa),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,o=b.length;j<o;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=
" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(p){var n=c(this);n.removeClass(a.call(this,p,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(fa),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(za," "),j=0,o=b.length;j<o;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,
b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),o=b,p=a.split(fa);e=p[i++];){o=f?o:!j.hasClass(e);j[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=
" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(za," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(Aa.test(b.type)&&
!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Va,"")}return w}var o=c.isFunction(a);return this.each(function(p){var n=c(this),t=a;if(this.nodeType===1){if(o)t=a.call(this,p,n.val());if(typeof t==="number")t+="";if(c.isArray(t)&&Aa.test(this.type))this.checked=c.inArray(n.val(),t)>=0;else if(c.nodeName(this,"select")){var z=c.makeArray(t);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),z)>=0});if(!z.length)this.selectedIndex=
-1}else this.value=t}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Wa.test(b);if(b in a&&f&&!i){if(e){if(b==="type"&&Xa.test(a.nodeName)&&a.parentNode)throw"type property can't be changed";a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;
if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Ya.test(a.nodeName)||Za.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var $a=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===
3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;if(!d.guid)d.guid=c.guid++;if(f!==w){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):w};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var o,p=0;o=b[p++];){var n=o.split(".");o=n.shift();d.type=n.slice(0).sort().join(".");var t=e[o],z=this.special[o]||{};if(!t){t=e[o]={};
if(!z.setup||z.setup.call(a,f,n,d)===false)if(a.addEventListener)a.addEventListener(o,i,false);else a.attachEvent&&a.attachEvent("on"+o,i)}if(z.add)if((n=z.add.call(a,d,f,n,t))&&c.isFunction(n)){n.guid=n.guid||d.guid;d=n}t[d.guid]=d;this.global[o]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===w||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);
for(var o=0;i=b[o++];){var p=i.split(".");i=p.shift();var n=!p.length,t=c.map(p.slice(0).sort(),$a);t=new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.)?")+"(\\.|$)");var z=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var B in f[i])if(n||t.test(f[i][B].type))delete f[i][B];z.remove&&z.remove.call(a,p,j);for(e in f[i])break;if(!e){if(!z.teardown||z.teardown.call(a,p)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+
i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(B=c.data(a,"handle"))B.elem=null;c.removeData(a,"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[H]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;var i=c.data(d,"handle");i&&i.apply(d,b);var j,o;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){j=d[e];o=d["on"+e]}}catch(p){}i=c.nodeName(d,"a")&&e==="click";if(!f&&j&&!a.isDefaultPrevented()&&!i){this.triggered=true;try{d[e]()}catch(n){}}else if(o&&d["on"+e].apply(d,b)===false)a.result=false;this.triggered=false;if(!a.isPropagationStopped())(d=d.parentNode||d.ownerDocument)&&c.event.trigger(a,b,d,true)},
handle:function(a){var b,d;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},
props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[H])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||
s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&
a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;c.event.add(this,b.live,qa,b)},remove:function(a){if(a.length){var b=0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],qa)}},special:{}},beforeunload:{setup:function(a,
b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=K();this[H]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ba;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=
ba;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ba;this.stopPropagation()},isDefaultPrevented:aa,isPropagationStopped:aa,isImmediatePropagationStopped:aa};var Ba=function(a){for(var b=a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ca=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",
mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ca:Ba,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ca:Ba)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return pa("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+
d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return pa("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var ga=/textarea|input|select/i;function Da(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>
-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ha(a,b){var d=a.target,f,e;if(!(!ga.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Da(d);if(e!==f){if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",e);if(d.type!=="select"&&(f!=null||e)){a.type="change";return c.event.trigger(a,b,this)}}}}c.event.special.change={filters:{focusout:ha,click:function(a){var b=a.target,d=b.type;if(d===
"radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ha.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ha.call(this,a)},beforeactivate:function(a){a=a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Da(a))}},setup:function(a,b,d){for(var f in W)c.event.add(this,f+".specialChange."+d.guid,W[f]);return ga.test(this.nodeName)},
remove:function(a,b){for(var d in W)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),W[d]);return ga.test(this.nodeName)}};var W=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,
f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){thisObject=e;e=f;f=w}var j=b==="one"?c.proxy(e,function(o){c(this).unbind(o,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e,thisObject):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,
b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||
a)},live:function(a,b,d){if(c.isFunction(b)){d=b;b=w}c(this.context).bind(ra(a,this.selector),{data:b,selector:this.selector,live:a},d);return this},die:function(a,b){c(this.context).unbind(ra(a,this.selector),b?{guid:b.guid+this.selector+a}:null);return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?
this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",k,m=0;g[m];m++){k=g[m];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,m,r,q){r=0;for(var v=m.length;r<v;r++){var u=m[r];if(u){u=u[g];for(var y=false;u;){if(u.sizcache===
k){y=m[u.sizset];break}if(u.nodeType===1&&!q){u.sizcache=k;u.sizset=r}if(u.nodeName.toLowerCase()===h){y=u;break}u=u[g]}m[r]=y}}}function d(g,h,k,m,r,q){r=0;for(var v=m.length;r<v;r++){var u=m[r];if(u){u=u[g];for(var y=false;u;){if(u.sizcache===k){y=m[u.sizset];break}if(u.nodeType===1){if(!q){u.sizcache=k;u.sizset=r}if(typeof h!=="string"){if(u===h){y=true;break}}else if(p.filter(h,[u]).length>0){y=u;break}}u=u[g]}m[r]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,i=Object.prototype.toString,j=false,o=true;[0,0].sort(function(){o=false;return 0});var p=function(g,h,k,m){k=k||[];var r=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return k;for(var q=[],v,u,y,S,I=true,N=x(h),J=g;(f.exec(""),v=f.exec(J))!==null;){J=v[3];q.push(v[1]);if(v[2]){S=v[3];break}}if(q.length>1&&t.exec(g))if(q.length===2&&n.relative[q[0]])u=ia(q[0]+q[1],h);else for(u=n.relative[q[0]]?[h]:p(q.shift(),h);q.length;){g=q.shift();if(n.relative[g])g+=q.shift();
u=ia(g,u)}else{if(!m&&q.length>1&&h.nodeType===9&&!N&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){v=p.find(q.shift(),h,N);h=v.expr?p.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:q.pop(),set:B(m)}:p.find(q.pop(),q.length===1&&(q[0]==="~"||q[0]==="+")&&h.parentNode?h.parentNode:h,N);u=v.expr?p.filter(v.expr,v.set):v.set;if(q.length>0)y=B(u);else I=false;for(;q.length;){var E=q.pop();v=E;if(n.relative[E])v=q.pop();else E="";if(v==null)v=h;n.relative[E](y,v,N)}}else y=[]}y||(y=u);if(!y)throw"Syntax error, unrecognized expression: "+
(E||g);if(i.call(y)==="[object Array]")if(I)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&F(h,y[g])))k.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&k.push(u[g]);else k.push.apply(k,y);else B(y,k);if(S){p(S,r,k,m);p.uniqueSort(k)}return k};p.uniqueSort=function(g){if(D){j=o;g.sort(D);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};p.matches=function(g,h){return p(g,null,null,h)};p.find=function(g,h,k){var m,r;if(!g)return[];
for(var q=0,v=n.order.length;q<v;q++){var u=n.order[q];if(r=n.leftMatch[u].exec(g)){var y=r[1];r.splice(1,1);if(y.substr(y.length-1)!=="\\"){r[1]=(r[1]||"").replace(/\\/g,"");m=n.find[u](r,h,k);if(m!=null){g=g.replace(n.match[u],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};p.filter=function(g,h,k,m){for(var r=g,q=[],v=h,u,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var I in n.filter)if((u=n.leftMatch[I].exec(g))!=null&&u[2]){var N=n.filter[I],J,E;E=u[1];y=false;u.splice(1,1);if(E.substr(E.length-
1)!=="\\"){if(v===q)q=[];if(n.preFilter[I])if(u=n.preFilter[I](u,v,k,q,m,S)){if(u===true)continue}else y=J=true;if(u)for(var X=0;(E=v[X])!=null;X++)if(E){J=N(E,u,X,v);var Ea=m^!!J;if(k&&J!=null)if(Ea)y=true;else v[X]=false;else if(Ea){q.push(E);y=true}}if(J!==w){k||(v=q);g=g.replace(n.match[I],"");if(!y)return[];break}}}if(g===r)if(y==null)throw"Syntax error, unrecognized expression: "+g;else break;r=g}return v};var n=p.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var k=typeof h==="string",m=k&&!/\W/.test(h);k=k&&!m;if(m)h=h.toLowerCase();m=0;for(var r=g.length,q;m<r;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=k||q&&q.nodeName.toLowerCase()===h?q||false:q===h}k&&p.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,r=g.length;m<r;m++){var q=g[m];if(q){k=q.parentNode;g[m]=k.nodeName.toLowerCase()===h?k:false}}}else{m=0;for(r=g.length;m<r;m++)if(q=g[m])g[m]=
k?q.parentNode:q.parentNode===h;k&&p.filter(h,g,true)}},"":function(g,h,k){var m=e++,r=d;if(typeof h==="string"&&!/\W/.test(h)){var q=h=h.toLowerCase();r=b}r("parentNode",h,m,g,q,k)},"~":function(g,h,k){var m=e++,r=d;if(typeof h==="string"&&!/\W/.test(h)){var q=h=h.toLowerCase();r=b}r("previousSibling",h,m,g,q,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];
h=h.getElementsByName(g[1]);for(var m=0,r=h.length;m<r;m++)h[m].getAttribute("name")===g[1]&&k.push(h[m]);return k.length===0?null:k}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,m,r,q){g=" "+g[1].replace(/\\/g,"")+" ";if(q)return g;q=0;for(var v;(v=h[q])!=null;q++)if(v)if(r^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||m.push(v);else if(k)h[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,m,r,q){h=g[1].replace(/\\/g,"");if(!q&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,m,r){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=p(g[3],null,null,h);else{g=p.filter(g[3],h,k,true^r);k||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!p(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,k,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,m){var r=h[1],q=n.filters[r];if(q)return q(g,k,h,m);else if(r==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(r==="not"){h=
h[3];k=0;for(m=h.length;k<m;k++)if(h[k]===g)return false;return true}else throw"Syntax error, unrecognized expression: "+r;},CHILD:function(g,h){var k=h[1],m=g;switch(k){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(k==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":k=h[2];var r=h[3];if(k===1&&r===0)return true;h=h[0];var q=g.parentNode;if(q&&(q.sizcache!==h||!g.nodeIndex)){var v=0;for(m=q.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;q.sizcache=h}g=g.nodeIndex-r;return k===0?g===0:g%k===0&&g/k>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=n.attrHandle[k]?n.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?k===h:m==="*="?k.indexOf(h)>=0:m==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:m==="!="?k!==h:m==="^="?k.indexOf(h)===0:m==="$="?k.substr(k.length-h.length)===h:m==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,m){var r=n.setFilters[h[2]];if(r)return r(g,k,h,m)}}},t=n.match.POS;for(var z in n.match){n.match[z]=new RegExp(n.match[z].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[z]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[z].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var B=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){B=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,m=g.length;k<m;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var D;if(s.documentElement.compareDocumentPosition)D=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in s.documentElement)D=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(s.createRange)D=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)j=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=s.documentElement;k.insertBefore(g,k.firstChild);if(s.getElementById(h)){n.find.ID=function(m,r,q){if(typeof r.getElementById!=="undefined"&&!q)return(r=r.getElementById(m[1]))?r.id===m[1]||typeof r.getAttributeNode!=="undefined"&&
r.getAttributeNode("id").nodeValue===m[1]?[r]:w:[]};n.filter.ID=function(m,r){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===r}}k.removeChild(g);k=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;k[m];m++)k[m].nodeType===1&&h.push(k[m]);k=h}return k};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=p,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){p=function(m,r,q,v){r=r||s;if(!v&&r.nodeType===9&&!x(r))try{return B(r.querySelectorAll(m),q)}catch(u){}return g(m,r,q,v)};for(var k in g)p[k]=g[k];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,k,m){if(typeof k.getElementsByClassName!=="undefined"&&!m)return k.getElementsByClassName(h[1])};g=null}}})();var F=s.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,
h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ia=function(g,h){var k=[],m="",r;for(h=h.nodeType?[h]:h;r=n.match.PSEUDO.exec(g);){m+=r[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;r=0;for(var q=h.length;r<q;r++)p(g,h[r],k);return p.filter(m,k)};c.find=p;c.expr=p.selectors;c.expr[":"]=c.expr.filters;c.unique=p.uniqueSort;c.getText=a;c.isXMLDoc=x;c.contains=F})();var ab=/Until$/,bb=/^(?:parents|prevUntil|prevAll)/,
cb=/,/;R=Array.prototype.slice;var Fa=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Pa.test(b))return c.filter(b,f,!d);else b=c.filter(b,a)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Fa(this,a,false),"not",a)},filter:function(a){return this.pushStack(Fa(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i=
{},j;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var p=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,t){for(;t&&t.ownerDocument&&t!==b;){if(p?p.index(t)>-1:c(t).is(a))return t;t=t.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(sa(a[0])||sa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);ab.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||cb.test(f))&&bb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ga=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,db=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,hb=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},G={option:[1,"<select multiple='multiple'>","</select>"],
legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};G.optgroup=G.option;G.tbody=G.tfoot=G.colgroup=G.caption=G.thead;G.th=G.td;if(!c.support.htmlSerialize)G._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);
return d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.getText(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&
this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,
"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ga,"").replace(Y,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ta(this,b);ta(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===
1?this[0].innerHTML.replace(Ga,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!Y.test(a))&&!G[(Ha.exec(a)||["",""])[1].toLowerCase()])try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){T(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){c.isFunction(a)||(a=c(a).detach());return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(t){return c.nodeName(t,"table")?t.getElementsByTagName("tbody")[0]||t.appendChild(t.ownerDocument.createElement("tbody")):t}var e,i,j=a[0],o=[];if(c.isFunction(j))return this.each(function(t){var z=
c(this);a[0]=j.call(this,t,b?z.html():w);return z.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ua(a,this,o);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var p=0,n=this.length;p<n;p++)d.call(b?f(this[p],i):this[p],e.cacheable||this.length>1||p>0?e.fragment.cloneNode(true):e.fragment)}o&&c.each(o,La)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},
function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){T(this.getElementsByTagName("*"));T([this])}this.parentNode&&this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&T(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},
function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j==="string"){j=j.replace(db,hb);var o=(Ha.exec(j)||["",""])[1].toLowerCase(),p=G[o]||G._default,n=p[0];i=b.createElement("div");for(i.innerHTML=p[1]+j+p[2];n--;)i=i.lastChild;
if(!c.support.tbody){n=fb.test(j);o=o==="table"&&!n?i.firstChild&&i.firstChild.childNodes:p[1]==="<table>"&&!n?i.childNodes:[];for(p=o.length-1;p>=0;--p)c.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!c.support.leadingWhitespace&&Y.test(j)&&i.insertBefore(b.createTextNode(Y.exec(j)[0]),i.firstChild);j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()===
"text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e}});var ib=/z-?index|font-?weight|opacity|zoom|line-?height/i,Ia=/alpha\([^)]*\)/,Ja=/opacity=([^)]*)/,ja=/float/i,ka=/-([a-z])/ig,jb=/([A-Z])/g,kb=/^-?\d+(?:px)?$/i,lb=/^-?\d/,mb={position:"absolute",visibility:"hidden",display:"block"},nb=["Left","Right"],ob=["Top","Bottom"],pb=s.defaultView&&
s.defaultView.getComputedStyle,Ka=c.support.cssFloat?"cssFloat":"styleFloat",la=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return $(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!ib.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""===
"NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ia.test(a)?a.replace(Ia,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ja.exec(f.filter)[1])/100+"":""}if(ja.test(b))b=Ka;b=b.replace(ka,la);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?nb:ob;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=
parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,mb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Ja.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ja.test(b))b=Ka;if(!d&&e&&e[b])f=e[b];else if(pb){if(ja.test(b))b="float";b=b.replace(jb,"-$1").toLowerCase();e=
a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ka,la);f=a.currentStyle[b]||a.currentStyle[d];if(!kb.test(f)&&lb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=
f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var qb=K(),rb=/<script(.|\s)*?\/script>/gi,sb=/select|textarea/i,tb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,O=/=\?(&|$)/,ma=/\?/,ub=/(\?|&)_=.*?(&|$)/,vb=/^(\w+:)?\/\/([^\/?#]+)/,
wb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}c.ajax({url:a,type:f,dataType:"html",data:b,context:this,complete:function(i,j){if(j==="success"||j==="notmodified")this.html(e?c("<div />").append(i.responseText.replace(rb,
"")).find(e):i.responseText);d&&this.each(d,[i.responseText,j,i])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||sb.test(this.nodeName)||tb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});
c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},
ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",
text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(p,o,j,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(p,x,j);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(r,q){(e.context?c(e.context):c.event).trigger(r,q)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,o,p=e.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,
e.traditional);if(e.dataType==="jsonp"){if(n==="GET")O.test(e.url)||(e.url+=(ma.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!O.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&O.test(e.data)||O.test(e.url))){i=e.jsonpCallback||"jsonp"+qb++;if(e.data)e.data=(e.data+"").replace(O,"="+i+"$1");e.url=e.url.replace(O,"="+i+"$1");e.dataType="script";A[i]=A[i]||function(r){o=r;b();d();A[i]=w;try{delete A[i]}catch(q){}B&&
B.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&n==="GET"){var t=K(),z=e.url.replace(ub,"$1_="+t+"$2");e.url=z+(z===e.url?(ma.test(e.url)?"&":"?")+"_="+t:"")}if(e.data&&n==="GET")e.url+=(ma.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");t=(t=vb.exec(e.url))&&(t[1]&&t[1]!==location.protocol||t[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&t){var B=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");
C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!i){var D=false;C.onload=C.onreadystatechange=function(){if(!D&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){D=true;b();d();C.onload=C.onreadystatechange=null;B&&C.parentNode&&B.removeChild(C)}}}B.insertBefore(C,B.firstChild);return w}var F=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",
e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}t||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ia){}if(e.beforeSend&&e.beforeSend.call(p,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",
[x,e]);var g=x.onreadystatechange=function(r){if(!x||x.readyState===0){F||d();F=true;if(x)x.onreadystatechange=c.noop}else if(!F&&x&&(x.readyState===4||r==="timeout")){F=true;x.onreadystatechange=c.noop;j=r==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";if(j==="success")try{o=c.httpData(x,e.dataType,e)}catch(q){j="parsererror"}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,x,j);d();r==="timeout"&&x.abort();if(e.async)x=
null}};try{var h=x.abort;x.abort=function(){if(x){h.call(x);if(x)x.readyState=0}g()}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){x&&!F&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||A,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol===
"file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;if(e&&a.documentElement.nodeName==="parsererror")throw"parsererror";if(d&&
d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))a=A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+a))();else throw"Invalid JSON: "+a;else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(e,i){i=
c.isFunction(i)?i():i;f[f.length]=encodeURIComponent(e)+"="+encodeURIComponent(i)}var f=[];if(b===w)b=c.ajaxSettings.traditional;c.isArray(a)||a.jquery?c.each(a,function(){d(this.name,this.value)}):c.each(a,function e(i,j){if(c.isArray(j))c.each(j,function(o,p){b?d(i,p):e(i+"["+(typeof p==="object"||c.isArray(p)?o:"")+"]",p)});else!b&&j!=null&&typeof j==="object"?c.each(j,function(o,p){e(i+"["+o+"]",p)}):d(i,j)});return f.join("&").replace(wb,"+")}});var na={},xb=/toggle|show|hide/,yb=/^([+-]=)?([\d+-.]+)(.*)$/,
Z,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a!=null)return this.animate(L("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(na[d])f=na[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();
na[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a!=null)return this.animate(L("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&
c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(L("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,o=this.nodeType===1&&c(this).is(":hidden"),
p=this;for(j in a){var n=j.replace(ka,la);if(j!==n){a[n]=a[j];delete a[j];j=n}if(a[j]==="hide"&&o||a[j]==="show"&&!o)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(t,z){var B=new c.fx(p,i,t);if(xb.test(z))B[z==="toggle"?o?"show":"hide":z](a);
else{var C=yb.exec(z),D=B.cur(true)||0;if(C){z=parseFloat(C[2]);var F=C[3]||"px";if(F!=="px"){p.style[t]=(z||1)+F;D=(z||1)/B.cur(true)*D;p.style[t]=D+F}if(C[1])z=(C[1]==="-="?-1:1)*z+D;B.custom(D,z,F)}else B.custom(D,z,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:L("show",1),slideUp:L("hide",1),slideToggle:L("toggle",
1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,
b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==
null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=K();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!Z)Z=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop===
"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=K(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=
this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=
c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(Z);Z=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=
null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),
f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(t){c.offset.setOffset(this,a,t)});if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=
b,e=b.ownerDocument,i,j=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var p=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;p-=b.scrollTop;n-=b.scrollLeft;if(b===d){p+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){p+=parseFloat(i.borderTopWidth)||
0;n+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){p+=parseFloat(i.borderTopWidth)||0;n+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){p+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){p+=Math.max(j.scrollTop,o.scrollTop);n+=Math.max(j.scrollLeft,o.scrollLeft)}return{top:p,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),
d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);
d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop},
bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left-
e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=
this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==w)return this.each(function(){if(i=wa(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=wa(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}});
c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+
b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

File diff suppressed because it is too large Load diff

View file

@ -1,110 +0,0 @@
/*
################################################################################
ox.geo.js
requires
jquery.js
ox.js
################################################################################
*/
(function() {
var earthRadius = 6378137,
earthCircumference = 2 * Math.PI * earthRadius
latMax = Ox.deg(Math.atan(Ox.sinh(Math.PI))),
latMin = -latMax;
/*
map = {
width: window.innerWidth,
height: window.innerHeight,
margin: 16
};
*/
Ox.getLatLng = (function() {
/*
returns {lat, lng} for a given (x, y)
*/
function getLatLng(xy) {
return (xy - 0.5) * 2 * Math.PI;
}
return function(x, y) {
return {
lat: -Ox.deg(Math.atan(Ox.sinh(getLatLng(y)))),
lng: Ox.deg(getLatLng(x))
};
};
})();
Ox.getPlacemarks = (function() {
/*
Ox.getPlacemarks(name, callback)
Ox.getPlacemarks(lat, lng, callback)
*/
var cache = {};
return function() {
// $.getScript("http://maps.google.com/maps/api/js?sensor=false", function() {
// getPlacemarks(args);
// });
// var args = arguments;
var reverse = typeof arguments[0] == "number",
query = $.extend({
language: "en"
}, !reverse ? {
address: arguments[0]
} : {
latLng: new google.maps.LatLng(arguments[0], arguments[1])
}),
id = JSON.stringify(query),
callback = arguments[arguments.length - 1],
geocoder = new google.maps.Geocoder();
if (cache[id]) {
callback(cache[id]);
} else {
geocoder.geocode(query, function(results, status) {
var data = {
results: results,
status: status
};
cache[id] = data;
callback(data);
});
}
};
})();
Ox.getXY = (function() {
/*
returns {x, y} for a given (lat, lng), between 0 and 1
*/
function getXY(xy) {
return (xy / (2 * Math.PI) + 0.5);
}
return function(lat, lng) {
return {
x: getXY(Ox.rad(lng)),
y: getXY(Ox.asinh(Math.tan(Ox.rad(-lat))))
};
};
})();
/*
Ox.getZ = function(placemark, map) {
// returns zoom level at which placemark is fully included
map.width -= 2 * map.margin;
map.height -= 2 * map.margin;
var northEast = getXY(placemark.northEast),
southWest = getXY(placemark.southWest),
width = (northEast.x - southWest.x),
height = (northEast.y - southWest.y),
return parseInt(Ox.log(width / height > map.width / map.height ?
map.width / width : map.height / height, 2));
};
*/
})();

View file

@ -1,162 +0,0 @@
$(function() {
var $body = $('body'),
$div = $('<div>')
.css({
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
background: 'rgb(240, 240, 240)',
opacity: 1,
zIndex: 1000
})
.appendTo($body),
css = {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
margin: 'auto',
MozUserSelect: 'none',
WebkitUserSelect: 'none'
},
file = 'js/ox.load.js',
path = $('script[src*="' + file + '"]').attr('src').replace(file, ''),
userAgent,
userAgents = {
'Chrome': 'http://www.google.com/chrome/',
'Firefox': 'http://www.mozilla.org/firefox/',
'Internet Explorer': '',
'Opera': 'http://www.opera.com/',
'Safari': 'http://www.apple.com/safari/'
};
userAgent = getUserAgent();
userAgents[userAgent] ? start() : stop();
function getUserAgent() {
var userAgent = '';
$.each(userAgents, function(name, link) {
if (navigator.userAgent.indexOf(name) > -1) {
userAgent = name;
return false;
}
});
if (!userAgent && $.browser.mozilla) {
userAgent = 'Firefox';
}
if (!userAgent && $.browser.webkit) {
userAgent = 'Chrome';
}
return userAgent;
}
function start() {
var image = new Image(),
src = path + 'svg/ox.ui.classic/symbolLoading.svg';
image.src = src;
image.onload = function() {
var $img = $('<img>')
.attr({
src: src
})
.css($.extend(css, {
width: '32px',
height: '32px'
}))
.mousedown(function(e) {
e.preventDefault();
})
.appendTo($div);
/*
deg = 0,
interval = setInterval(function() {
deg = (deg + 30) % 360;
$img.css({
MozTransform: 'rotate(' + deg + 'deg)',
WebkitTransform: 'rotate(' + deg + 'deg)',
});
}, 83);
*/
};
}
function stop() {
var counter = 0,
length = 0,
src = {};
Ox.forEach(userAgents, function(link, name) {
if (link) {
length++;
}
});
Ox.forEach(userAgents, function(link, name) {
var image;
if (link) {
image = new Image();
src[name] = path + 'png/ox.ui/browser' + name + '128.png';
image.src = src[name];
image.onload = function() {
if (++counter == length) {
loaded();
}
}
}
});
function loaded() {
var $div_ = $('<div>')
.css($.extend(css, {
width: (length * 72) + 'px',
height: '72px'
})),
i = 0;
$.each(src, function(name, src) {
$('<a>')
.attr({
href: userAgents[name],
title: name
})
.css({
position: 'absolute',
left: (i++ * 72) + 'px',
width: '72px',
height: '72px',
})
.append(
$('<img>')
.attr({
src: src
})
.css($.extend(css, {
width: '64px',
height: '64px',
border: 0,
cursor: 'pointer'
}))
.mousedown(function(e) {
e.preventDefault();
})
.mouseenter(function() {
$(this).animate({
width: '72px',
height: '72px',
}, 250);
})
.mouseleave(function() {
$(this).animate({
width: '64px',
height: '64px',
}, 250);
})
)
.appendTo($div_);
});
$div_.appendTo($div);
//throw new Error('User Agent not supported.');
}
}
});

View file

@ -1,362 +0,0 @@
Ox.COUNTRIES = [
// 304 countries (see http://en.wikipedia.org/wiki/Table_of_administrative_divisions_by_country)
// 193 sovereign countries (see http://en.wikipedia.org/wiki/List_of_sovereign_states)
// 11 unrecognized countries (see http://en.wikipedia.org/wiki/List_of_sovereign_states#Other_states)
// 62 dependent countries (6 Australia, 2 China, 2 Denmark, 1 Finland, 13 France, 4 Netherlands,
// 3 New Zealand, 2 Norway, 2 Spain, 22 United Kingdom, 6 United States, plus Antarctica)
// 34 former countries (http://en.wikipedia.org/wiki/ISO_3166-3, http://www.imdb.com/country/)
// 2 other countries (EU, UK)
// also see http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2,
// http://en.wikipedia.org/wiki/Borders_of_the_continents
// and http://unstats.un.org/unsd/methods/m49/m49regin.htm
{code: 'AF', continent: 'Asia', name: 'Afghanistan', region: 'Southern Asia', type: 'sovereign'},
{code: 'AL', continent: 'Europe', name: 'Albania', region: 'Southern Europe', type: 'sovereign'},
{code: 'DZ', continent: 'Africa', name: 'Algeria', region: 'Northern Africa', type: 'sovereign'},
{code: 'AD', continent: 'Europe', name: 'Andorra', region: 'Southern Europe', type: 'sovereign'},
{code: 'AO', continent: 'Africa', name: 'Angola', region: 'Middle Africa', type: 'sovereign'},
{code: 'AG', continent: 'North America', name: 'Antigua and Barbuda', region: 'Caribbean', type: 'sovereign'},
{code: 'AR', continent: 'South America', name: 'Argentina', type: 'sovereign'},
{code: 'AM', continent: 'Asia', name: 'Armenia', region: 'Western Asia', type: 'sovereign'},
{code: 'AU', continent: 'Oceania', name: 'Australia', region: 'Australia and New Zealand', type: 'sovereign'},
{code: 'AT', continent: 'Europe', name: 'Austria', region: 'Western Europe', type: 'sovereign'},
{code: 'AZ', continent: 'Asia', name: 'Azerbaijan', region: 'Western Asia', type: 'sovereign'},
{code: 'BS', continent: 'North America', name: 'Bahamas', region: 'Caribbean', type: 'sovereign'},
{code: 'BH', continent: 'Asia', name: 'Bahrain', region: 'Western Asia', type: 'sovereign'},
{code: 'BD', continent: 'Asia', name: 'Bangladesh', region: 'Southern Asia', type: 'sovereign'},
{code: 'BB', continent: 'North America', name: 'Barbados', region: 'Caribbean', type: 'sovereign'},
{code: 'BY', continent: 'Europe', name: 'Belarus', region: 'Eastern Europe', type: 'sovereign'},
{code: 'BE', continent: 'Europe', name: 'Belgium', region: 'Western Europe', type: 'sovereign'},
{code: 'BZ', continent: 'North America', name: 'Belize', region: 'Central America', type: 'sovereign'},
{code: 'BJ', continent: 'Africa', name: 'Benin', region: 'Western Africa', type: 'sovereign'},
{code: 'BT', continent: 'Asia', name: 'Bhutan', region: 'Southern Asia', type: 'sovereign'},
{code: 'BO', continent: 'South America', name: 'Bolivia', type: 'sovereign'},
{code: 'BA', continent: 'Europe', name: 'Bosnia and Herzegovina', region: 'Southern Europe', type: 'sovereign'},
{code: 'BW', continent: 'Africa', name: 'Botswana', region: 'Southern Africa', type: 'sovereign'},
{code: 'BR', continent: 'South America', name: 'Brazil', type: 'sovereign'},
{code: 'BN', continent: 'Asia', name: 'Brunei', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'BG', continent: 'Europe', name: 'Bulgaria', region: 'Eastern Europe', type: 'sovereign'},
{code: 'BF', continent: 'Africa', name: 'Burkina Faso', region: 'Western Africa', type: 'sovereign'},
{code: 'BI', continent: 'Africa', name: 'Burundi', region: 'Eastern Africa', type: 'sovereign'},
{code: 'KH', continent: 'Asia', name: 'Cambodia', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'CM', continent: 'Africa', name: 'Cameroon', region: 'Middle Africa', type: 'sovereign'},
{code: 'CA', continent: 'North America', name: 'Canada', region: 'Northern America', type: 'sovereign'},
{code: 'CV', continent: 'Africa', name: 'Cape Verde', region: 'Western Africa', type: 'sovereign'},
{code: 'CF', continent: 'Africa', name: 'Central African Republic', region: 'Middle Africa', type: 'sovereign'},
{code: 'TD', continent: 'Africa', name: 'Chad', region: 'Middle Africa', type: 'sovereign'},
{code: 'CL', continent: 'South America', name: 'Chile', type: 'sovereign'},
{code: 'CN', continent: 'Asia', name: 'China', region: 'Eastern Asia', type: 'sovereign'},
{code: 'CO', continent: 'South America', name: 'Colombia', type: 'sovereign'},
{code: 'KM', continent: 'Africa', name: 'Comoros', region: 'Eastern Africa', type: 'sovereign'},
{code: 'CR', continent: 'North America', name: 'Costa Rica', region: 'Central America', type: 'sovereign'},
{code: 'CI', continent: 'Africa', name: 'Côte d\'Ivoire', region: 'Western Africa', type: 'sovereign'},
{code: 'HR', continent: 'Europe', name: 'Croatia', region: 'Southern Europe', type: 'sovereign'},
{code: 'CU', continent: 'North America', name: 'Cuba', region: 'Caribbean', type: 'sovereign'},
{code: 'CY', continent: 'Asia', name: 'Cyprus', region: 'Western Asia', type: 'sovereign'},
{code: 'CZ', continent: 'Europe', name: 'Czech Republic', region: 'Eastern Europe', type: 'sovereign'},
{code: 'CD', continent: 'Africa', name: 'Democratic Republic of the Congo', region: 'Middle Africa', type: 'sovereign'},
{code: 'DK', continent: 'Europe', name: 'Denmark', region: 'Northern Europe', type: 'sovereign'},
{code: 'DJ', continent: 'Africa', name: 'Djibouti', region: 'Eastern Africa', type: 'sovereign'},
{code: 'DM', continent: 'North America', name: 'Dominica', region: 'Caribbean', type: 'sovereign'},
{code: 'DO', continent: 'North America', name: 'Dominican Republic', region: 'Caribbean', type: 'sovereign'},
{code: 'EC', continent: 'South America', name: 'Ecuador', type: 'sovereign'},
{code: 'EG', continent: 'Africa', name: 'Egypt', region: 'Northern Africa', type: 'sovereign'},
{code: 'SV', continent: 'North America', name: 'El Salvador', region: 'Central America', type: 'sovereign'},
{code: 'GQ', continent: 'Africa', name: 'Equatorial Guinea', region: 'Middle Africa', type: 'sovereign'},
{code: 'ER', continent: 'Africa', name: 'Eritrea', region: 'Eastern Africa', type: 'sovereign'},
{code: 'EE', continent: 'Europe', name: 'Estonia', region: 'Northern Europe', type: 'sovereign'},
{code: 'ET', continent: 'Africa', name: 'Ethiopia', region: 'Eastern Africa', type: 'sovereign'},
{code: 'FJ', continent: 'Oceania', name: 'Fiji', region: 'Melanesia', type: 'sovereign'},
{code: 'FI', continent: 'Europe', name: 'Finland', region: 'Northern Europe', type: 'sovereign'},
{code: 'FR', continent: 'Europe', name: 'France', region: 'Western Europe', type: 'sovereign'},
{code: 'GA', continent: 'Africa', name: 'Gabon', region: 'Middle Africa', type: 'sovereign'},
{code: 'GM', continent: 'Africa', name: 'Gambia', region: 'Western Africa', type: 'sovereign'},
{code: 'GE', continent: 'Asia', name: 'Georgia', region: 'Western Asia', type: 'sovereign'},
{code: 'DE', continent: 'Europe', name: 'Germany', region: 'Western Europe', type: 'sovereign'},
{code: 'GH', continent: 'Africa', name: 'Ghana', region: 'Western Africa', type: 'sovereign'},
{code: 'GR', continent: 'Europe', name: 'Greece', region: 'Southern Europe', type: 'sovereign'},
{code: 'GD', continent: 'North America', name: 'Grenada', region: 'Caribbean', type: 'sovereign'},
{code: 'GT', continent: 'North America', name: 'Guatemala', region: 'Central America', type: 'sovereign'},
{code: 'GN', continent: 'Africa', name: 'Guinea', region: 'Western Africa', type: 'sovereign'},
{code: 'GW', continent: 'Africa', name: 'Guinea-Bissau', region: 'Western Africa', type: 'sovereign'},
{code: 'GY', continent: 'South America', name: 'Guyana', type: 'sovereign'},
{code: 'HT', continent: 'North America', name: 'Haiti', region: 'Caribbean', type: 'sovereign'},
{code: 'VA', continent: 'Europe', name: 'Holy See', region: 'Southern Europe', type: 'sovereign'},
{code: 'HN', continent: 'North America', name: 'Honduras', region: 'Central America', type: 'sovereign'},
{code: 'HU', continent: 'Europe', name: 'Hungary', region: 'Eastern Europe', type: 'sovereign'},
{code: 'IS', continent: 'Europe', name: 'Iceland', region: 'Northern Europe', type: 'sovereign'},
{code: 'IN', continent: 'Asia', name: 'India', region: 'Southern Asia', type: 'sovereign'},
{code: 'ID', continent: 'Asia', name: 'Indonesia', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'IR', continent: 'Asia', name: 'Iran', region: 'Southern Asia', type: 'sovereign'},
{code: 'IQ', continent: 'Asia', name: 'Iraq', region: 'Western Asia', type: 'sovereign'},
{code: 'IE', continent: 'Europe', name: 'Ireland', region: 'Northern Europe', type: 'sovereign'},
{code: 'IL', continent: 'Asia', name: 'Israel', region: 'Western Asia', type: 'sovereign'},
{code: 'IT', continent: 'Europe', name: 'Italy', region: 'Southern Europe', type: 'sovereign'},
{code: 'JM', continent: 'North America', name: 'Jamaica', region: 'Caribbean', type: 'sovereign'},
{code: 'JP', continent: 'Asia', name: 'Japan', region: 'Eastern Asia', type: 'sovereign'},
{code: 'JO', continent: 'Asia', name: 'Jordan', region: 'Western Asia', type: 'sovereign'},
{code: 'KZ', continent: 'Asia', name: 'Kazakhstan', region: 'Central Asia', type: 'sovereign'},
{code: 'KE', continent: 'Africa', name: 'Kenya', region: 'Eastern Africa', type: 'sovereign'},
{code: 'KI', continent: 'Oceania', name: 'Kiribati', region: 'Micronesia', type: 'sovereign'},
{code: 'KW', continent: 'Asia', name: 'Kuwait', region: 'Western Asia', type: 'sovereign'},
{code: 'KG', continent: 'Asia', name: 'Kyrgyzstan', region: 'Central Asia', type: 'sovereign'},
{code: 'LA', continent: 'Asia', name: 'Laos', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'LV', continent: 'Europe', name: 'Latvia', region: 'Northern Europe', type: 'sovereign'},
{code: 'LB', continent: 'Asia', name: 'Lebanon', region: 'Western Asia', type: 'sovereign'},
{code: 'LS', continent: 'Africa', name: 'Lesotho', region: 'Southern Africa', type: 'sovereign'},
{code: 'LR', continent: 'Africa', name: 'Liberia', region: 'Western Africa', type: 'sovereign'},
{code: 'LY', continent: 'Africa', name: 'Libya', region: 'Northern Africa', type: 'sovereign'},
{code: 'LI', continent: 'Europe', name: 'Liechtenstein', region: 'Western Europe', type: 'sovereign'},
{code: 'LT', continent: 'Europe', name: 'Lithuania', region: 'Northern Europe', type: 'sovereign'},
{code: 'LU', continent: 'Europe', name: 'Luxembourg', region: 'Western Europe', type: 'sovereign'},
{code: 'MK', continent: 'Europe', name: 'Macedonia', region: 'Southern Europe', type: 'sovereign'},
{code: 'MG', continent: 'Africa', name: 'Madagascar', region: 'Eastern Africa', type: 'sovereign'},
{code: 'MW', continent: 'Africa', name: 'Malawi', region: 'Eastern Africa', type: 'sovereign'},
{code: 'MY', continent: 'Asia', name: 'Malaysia', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'MV', continent: 'Asia', name: 'Maldives', region: 'Southern Asia', type: 'sovereign'},
{code: 'ML', continent: 'Africa', name: 'Mali', region: 'Western Africa', type: 'sovereign'},
{code: 'MT', continent: 'Europe', name: 'Malta', region: 'Southern Europe', type: 'sovereign'},
{code: 'MH', continent: 'Oceania', name: 'Marshall Islands', region: 'Micronesia', type: 'sovereign'},
{code: 'MR', continent: 'Africa', name: 'Mauritania', region: 'Western Africa', type: 'sovereign'},
{code: 'MU', continent: 'Africa', name: 'Mauritius', region: 'Eastern Africa', type: 'sovereign'},
{code: 'MX', continent: 'North America', name: 'Mexico', region: 'Central America', type: 'sovereign'},
{code: 'FM', continent: 'Oceania', name: 'Micronesia', region: 'Micronesia', type: 'sovereign'},
{code: 'MD', continent: 'Europe', name: 'Moldova', region: 'Eastern Europe', type: 'sovereign'},
{code: 'MC', continent: 'Europe', name: 'Monaco', region: 'Western Europe', type: 'sovereign'},
{code: 'MN', continent: 'Asia', name: 'Mongolia', region: 'Eastern Asia', type: 'sovereign'},
{code: 'ME', continent: 'Europe', name: 'Montenegro', region: 'Southern Europe', type: 'sovereign'},
{code: 'MA', continent: 'Africa', name: 'Morocco', region: 'Northern Africa', type: 'sovereign'},
{code: 'MZ', continent: 'Africa', name: 'Mozambique', region: 'Eastern Africa', type: 'sovereign'},
{code: 'MM', continent: 'Asia', name: 'Myanmar', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'NA', continent: 'Africa', name: 'Namibia', region: 'Southern Africa', type: 'sovereign'},
{code: 'NR', continent: 'Oceania', name: 'Nauru', region: 'Micronesia', type: 'sovereign'},
{code: 'NP', continent: 'Asia', name: 'Nepal', region: 'Southern Asia', type: 'sovereign'},
{code: 'NL', continent: 'Europe', name: 'Netherlands', region: 'Western Europe', type: 'sovereign'},
{code: 'NZ', continent: 'Oceania', name: 'New Zealand', region: 'Australia and New Zealand', type: 'sovereign'},
{code: 'NI', continent: 'North America', name: 'Nicaragua', region: 'Central America', type: 'sovereign'},
{code: 'NE', continent: 'Africa', name: 'Niger', region: 'Western Africa', type: 'sovereign'},
{code: 'NG', continent: 'Africa', name: 'Nigeria', region: 'Western Africa', type: 'sovereign'},
{code: 'KP', continent: 'Asia', name: 'North Korea', region: 'Eastern Asia', type: 'sovereign'},
{code: 'NO', continent: 'Europe', name: 'Norway', region: 'Northern Europe', type: 'sovereign'},
{code: 'OM', continent: 'Asia', name: 'Oman', region: 'Western Asia', type: 'sovereign'},
{code: 'PK', continent: 'Asia', name: 'Pakistan', region: 'Southern Asia', type: 'sovereign'},
{code: 'PW', continent: 'Oceania', name: 'Palau', region: 'Micronesia', type: 'sovereign'},
{code: 'PA', continent: 'North America', name: 'Panama', region: 'Central America', type: 'sovereign'},
{code: 'PG', continent: 'Oceania', name: 'Papua New Guinea', region: 'Melanesia', type: 'sovereign'},
{code: 'PY', continent: 'South America', name: 'Paraguay', type: 'sovereign'},
{code: 'PE', continent: 'South America', name: 'Peru', type: 'sovereign'},
{code: 'PH', continent: 'Asia', name: 'Philippines', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'PL', continent: 'Europe', name: 'Poland', region: 'Eastern Europe', type: 'sovereign'},
{code: 'PT', continent: 'Europe', name: 'Portugal', region: 'Southern Europe', type: 'sovereign'},
{code: 'QA', continent: 'Asia', name: 'Qatar', region: 'Western Asia', type: 'sovereign'},
{code: 'CD', continent: 'Africa', name: 'Republic of the Congo', region: 'Middle Africa', type: 'sovereign'},
{code: 'RO', continent: 'Europe', name: 'Romania', region: 'Eastern Europe', type: 'sovereign'},
{code: 'RU', continent: 'Europe', name: 'Russia', region: 'Eastern Europe', type: 'sovereign'},
{code: 'RW', continent: 'Africa', name: 'Rwanda', region: 'Eastern Africa', type: 'sovereign'},
{code: 'KN', continent: 'North America', name: 'Saint Kitts and Nevis', region: 'Caribbean', type: 'sovereign'},
{code: 'LC', continent: 'North America', name: 'Saint Lucia', region: 'Caribbean', type: 'sovereign'},
{code: 'VC', continent: 'North America', name: 'Saint Vincent and the Grenadines', region: 'Caribbean', type: 'sovereign'},
{code: 'WS', continent: 'Oceania', name: 'Samoa', region: 'Polynesia', type: 'sovereign'},
{code: 'SM', continent: 'Europe', name: 'San Marino', region: 'Southern Europe', type: 'sovereign'},
{code: 'ST', continent: 'Africa', name: 'São Tomé and Príncipe', region: 'Middle Africa', type: 'sovereign'},
{code: 'SA', continent: 'Asia', name: 'Saudi Arabia', region: 'Western Asia', type: 'sovereign'},
{code: 'SN', continent: 'Africa', name: 'Senegal', region: 'Western Africa', type: 'sovereign'},
{code: 'RS', continent: 'Europe', name: 'Serbia', region: 'Southern Europe', type: 'sovereign'},
{code: 'SC', continent: 'Africa', name: 'Seychelles', region: 'Eastern Africa', type: 'sovereign'},
{code: 'SL', continent: 'Africa', name: 'Sierra Leone', region: 'Western Africa', type: 'sovereign'},
{code: 'SG', continent: 'Asia', name: 'Singapore', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'SK', continent: 'Europe', name: 'Slovakia', region: 'Eastern Europe', type: 'sovereign'},
{code: 'SI', continent: 'Europe', name: 'Slovenia', region: 'Southern Europe', type: 'sovereign'},
{code: 'SB', continent: 'Oceania', name: 'Solomon Islands', region: 'Melanesia', type: 'sovereign'},
{code: 'SO', continent: 'Africa', name: 'Somalia', region: 'Eastern Africa', type: 'sovereign'},
{code: 'ZA', continent: 'Africa', name: 'South Africa', region: 'Southern Africa', type: 'sovereign'},
{code: 'KR', continent: 'Asia', name: 'South Korea', region: 'Eastern Asia', type: 'sovereign'},
{code: 'ES', continent: 'Europe', name: 'Spain', region: 'Southern Europe', type: 'sovereign'},
{code: 'LK', continent: 'Asia', name: 'Sri Lanka', region: 'Southern Asia', type: 'sovereign'},
{code: 'SD', continent: 'Africa', name: 'Sudan', region: 'Northern Africa', type: 'sovereign'},
{code: 'SR', continent: 'South America', name: 'Suriname', type: 'sovereign'},
{code: 'SZ', continent: 'Africa', name: 'Swaziland', region: 'Southern Africa', type: 'sovereign'},
{code: 'SE', continent: 'Europe', name: 'Sweden', region: 'Northern Europe', type: 'sovereign'},
{code: 'CH', continent: 'Europe', name: 'Switzerland', region: 'Western Europe', type: 'sovereign'},
{code: 'SY', continent: 'Asia', name: 'Syria', region: 'Western Asia', type: 'sovereign'},
{code: 'TJ', continent: 'Asia', name: 'Tajikistan', region: 'Central Asia', type: 'sovereign'},
{code: 'TZ', continent: 'Africa', name: 'Tanzania', region: 'Eastern Africa', type: 'sovereign'},
{code: 'TH', continent: 'Asia', name: 'Thailand', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'TL', continent: 'Asia', name: 'Timor-Leste', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'TG', continent: 'Africa', name: 'Togo', region: 'Western Africa', type: 'sovereign'},
{code: 'TO', continent: 'Oceania', name: 'Tonga', region: 'Polynesia', type: 'sovereign'},
{code: 'TT', continent: 'North America', name: 'Trinidad and Tobago', region: 'Caribbean', type: 'sovereign'},
{code: 'TN', continent: 'Africa', name: 'Tunisia', region: 'Northern Africa', type: 'sovereign'},
{code: 'TR', continent: 'Asia', name: 'Turkey', region: 'Western Asia', type: 'sovereign'},
{code: 'TM', continent: 'Asia', name: 'Turkmenistan', region: 'Central Asia', type: 'sovereign'},
{code: 'TV', continent: 'Oceania', name: 'Tuvalu', region: 'Polynesia', type: 'sovereign'},
{code: 'UG', continent: 'Africa', name: 'Uganda', region: 'Eastern Africa', type: 'sovereign'},
{code: 'UA', continent: 'Europe', name: 'Ukraine', region: 'Eastern Europe', type: 'sovereign'},
{code: 'AE', continent: 'Asia', name: 'United Arab Emirates', region: 'Western Asia', type: 'sovereign'},
{code: 'GB', continent: 'Europe', name: 'United Kingdom', region: 'Northern Europe', type: 'sovereign'},
{code: 'US', continent: 'North America', name: 'United States', region: 'Northern America', type: 'sovereign'},
{code: 'UY', continent: 'South America', name: 'Uruguay', type: 'sovereign'},
{code: 'UZ', continent: 'Asia', name: 'Uzbekistan', region: 'Central Asia', type: 'sovereign'},
{code: 'VU', continent: 'Oceania', name: 'Vanuatu', region: 'Melanesia', type: 'sovereign'},
{code: 'VE', continent: 'South America', name: 'Venezuela', type: 'sovereign'},
{code: 'VN', continent: 'Asia', name: 'Vietnam', region: 'South-Eastern Asia', type: 'sovereign'},
{code: 'YE', continent: 'Asia', name: 'Yemen', region: 'Western Asia', type: 'sovereign'},
{code: 'ZM', continent: 'Africa', name: 'Zambia', region: 'Eastern Africa', type: 'sovereign'},
{code: 'ZW', continent: 'Africa', name: 'Zimbabwe', region: 'Eastern Africa', type: 'sovereign'},
{code: 'GE-AB', continent: 'Asia', name: 'Abkhazia', region: 'Western Asia', type: 'unrecognized'},
{code: 'RS-KO', continent: 'Europe', name: 'Kosovo', region: 'Southern Europe', type: 'unrecognized'},
{code: 'AZ-NK', continent: 'Asia', name: 'Nagorno-Karabakh', region: 'Western Asia', type: 'unrecognized'},
{code: 'CY-NC', continent: 'Asia', name: 'Northern Cyprus', region: 'Western Asia', type: 'unrecognized'},
{code: 'PS', continent: 'Asia', name: 'Palestine', region: 'Western Asia', region: 'Western Asia', type: 'unrecognized'},
{code: 'EH', continent: 'Aftica', name: 'Sahrawi', region: 'Northern Africa', type: 'unrecognized'},
{code: 'SO-SO', continent: 'Africa', name: 'Somaliland', region: 'Eastern Aftica', type: 'unrecognized'},
{code: 'GE-SO', continent: 'Asia', name: 'South Ossetia', region: 'Western Asia', type: 'unrecognized'},
{code: 'SD-SS', continent: 'Aftica', name: 'South Sudan', region: 'Northern Africa', type: 'unrecognized'},
{code: 'TW', continent: 'Asia', name: 'Taiwan', region: 'Eastern Asia', type: 'unrecognized'},
{code: 'MD-TR', continent: 'Europe', name: 'Transnistria', region: 'Eastern Europe', type: 'unrecognized'},
{code: 'AQ', continent: 'Antarctica', country: ['Argentina', 'Australia', 'Chile', 'France', 'New Zealand', 'Norway', 'United Kingdom'], name: 'Antarctica'},
{code: 'AU-AC', continent: 'Asia', country: 'Australia', name: 'Ashmore and Cartier Islands', type: 'dependent'},
{code: 'CX', continent: 'Asia', country: 'Australia', name: 'Christmas Island', region: 'South-Eastern Asia', type: 'dependent'},
{code: 'CC', continent: 'Asia', country: 'Australia', name: 'Cocos Islands', region: 'South-Eastern Asia', type: 'dependent'},
{code: 'AU-CS', continent: 'Oceania', country: 'Australia', name: 'Coral Sea Islands', type: 'dependent'},
{code: 'HM', continent: 'Antarctica', country: 'Australia', name: 'Heard Island and McDonald Islands', type: 'dependent'},
{code: 'NF', continent: 'Oceania', country: 'Australia', name: 'Norfolk Island', region: 'Australia and New Zealand', type: 'dependent'},
{code: 'HK', continent: 'Asia', country: 'China', name: 'Hong Kong', region: 'Eastern Asia', type: 'dependent'},
{code: 'MO', continent: 'Asia', country: 'China', name: 'Macau', region: 'Eastern Asia', type: 'dependent'},
{code: 'FO', continent: 'Europe', country: 'Denmark', name: 'Faroe Islands', region: 'Northern Europe', type: 'dependent'},
{code: 'GL', continent: 'North America', country: 'Denmark', name: 'Greenland', region: 'Northern America', type: 'dependent'},
{code: 'AX', continent: 'Europe', country: 'Finland', name: 'Åland', region: 'Northern Europe', type: 'dependent'},
{code: 'CP', country: 'France', name: 'Clipperton Island', type: 'dependent'},
{code: 'GF', continent: 'South America', country: 'France', name: 'French Guiana', type: 'dependent'},
{code: 'PF', continent: 'Oceania', country: 'France', name: 'French Polynesia', region: 'Polynesia', type: 'dependent'},
{code: 'TF', country: 'France', name: 'French Southern Territories', type: 'dependent'},
{code: 'GP', continent: 'North America', country: 'France', name: 'Guadeloupe', region: 'Caribbean', type: 'dependent'},
{code: 'MQ', continent: 'North America', country: 'France', name: 'Martinique', region: 'Caribbean', type: 'dependent'},
{code: 'YT', continent: 'Africa', country: 'France', name: 'Mayotte', region: 'Eastern Africa', type: 'dependent'},
{code: 'NC', continent: 'Oceania', country: 'France', name: 'New Caledonia', region: 'Melanesia', type: 'dependent'},
{code: 'RE', continent: 'Africa', country: 'France', name: 'Réunion', region: 'Eastern Africa', type: 'dependent', flag: 'png'},
{code: 'BL', continent: 'North America', country: 'France', name: 'Saint Barthélemy', region: 'Caribbean', type: 'dependent'},
{code: 'MF', continent: 'North America', country: 'France', name: 'Saint Martin', region: 'Caribbean', type: 'dependent'},
{code: 'PM', continent: 'North America', country: 'France', name: 'Saint Pierre and Miquelon', region: 'Northern America', type: 'dependent'},
{code: 'WF', continent: 'Oceania', country: 'France', name: 'Wallis and Futuna', region: 'Polynesia', type: 'dependent'},
{code: 'AW', continent: 'North America', country: 'Netherlands', name: 'Aruba', region: 'Caribbean', type: 'dependent'},
{code: 'BQ', continent: 'North America', country: 'Netherlands', name: 'Bonaire, Saint Eustatius and Saba', region: 'Caribbean', type: 'dependent'},
{code: 'CW', continent: 'North America', country: 'Netherlands', name: 'Curaçao', region: 'Caribbean', type: 'dependent'},
{code: 'SX', continent: 'North America', country: 'Netherlands', name: 'Sint Maarten', region: 'Caribbean', type: 'dependent'},
{code: 'CK', continent: 'Oceania', country: 'New Zealand', name: 'Cook Islands', region: 'Polynesia', type: 'dependent'},
{code: 'NU', continent: 'Oceania', country: 'New Zealand', name: 'Niue', region: 'Polynesia', type: 'dependent'},
{code: 'TK', continent: 'Oceania', country: 'New Zealand', name: 'Tokelau', region: 'Polynesia', type: 'dependent'},
{code: 'BV', continent: 'Antarctica', country: 'Norway', name: 'Bouvet Island', type: 'dependent'},
{code: 'SJ', continent: 'Europe', country: 'Norway', name: 'Svalbard and Jan Mayen', region: 'Northern Europe', type: 'dependent'},
{code: 'IC', continent: 'Africa', country: 'Spain', name: 'Canary Islands', region: 'Northern Africa', type: 'dependent'},
{code: 'EA', continent: 'Africa', country: 'Spain', name: 'Ceuta and Melilla', region: 'Northern Africa', type: 'dependent'},
{code: 'AI', continent: 'North America', country: 'United Kingdom', name: 'Anguilla', region: 'Caribbean', type: 'dependent'},
{code: 'AC', continent: 'Africa', country: 'United Kingdom', name: 'Ascension', region: 'Western Africa', type: 'dependent'},
{code: 'BM', continent: 'North America', country: 'United Kingdom', name: 'Bermuda', region: 'Northern America', type: 'dependent'},
{code: 'IO', country: 'United Kingdom', name: 'British Indian Ocean Territory', type: 'dependent'},
{code: 'VG', continent: 'North America', country: 'United Kingdom', name: 'British Virgin Islands', region: 'Caribbean', type: 'dependent'},
{code: 'KY', continent: 'North America', country: 'United Kingdom', name: 'Cayman Islands', region: 'Caribbean', type: 'dependent'},
{code: 'DG', country: 'United Kingdom', name: 'Diego Garcia', type: 'dependent'},
{code: 'GB-ENG', continent: 'Europe', country: 'United Kingdom', name: 'England', region: 'Northern Europe', type: 'dependent'},
{code: 'FK', continent: 'South America', country: 'United Kingdom', name: 'Falkland Islands', type: 'dependent'},
{code: 'GI', continent: 'Europe', country: 'United Kingdom', name: 'Gibraltar', region: 'Southern Europe', type: 'dependent'},
{code: 'GG', continent: 'Europe', country: 'United Kingdom', name: 'Guernsey', region: 'Northern Europe', type: 'dependent'},
{code: 'IM', continent: 'Europe', country: 'United Kingdom', name: 'Isle of Man', region: 'Northern Europe', type: 'dependent'},
{code: 'JE', continent: 'Europe', country: 'United Kingdom', name: 'Jersey', region: 'Northern Europe', type: 'dependent'},
{code: 'MS', continent: 'North America', country: 'United Kingdom', name: 'Montserrat', region: 'Caribbean', type: 'dependent'},
{code: 'GB-NIR', continent: 'Europe', country: 'United Kingdom', name: 'Northern Ireland', region: 'Northern Europe', type: 'dependent'},
{code: 'PN', continent: 'Oceania', country: 'United Kingdom', name: 'Pitcairn', region: 'Polynesia', type: 'dependent'},
{code: 'SH', continent: 'Africa', country: 'United Kingdom', name: 'Saint Helena', region: 'Western Africa', type: 'dependent'},
{code: 'GB-SCT', continent: 'Europe', country: 'United Kingdom', name: 'Scotland', region: 'Northern Europe', type: 'dependent'},
{code: 'GS', continent: 'South America', country: 'United Kingdom', name: 'South Georgia and the South Sandwich Islands', type: 'dependent'},
{code: 'TA', continent: 'Africa', country: 'United Kingdom', name: 'Tristan da Cunha', region: 'Western Africa', type: 'dependent'},
{code: 'TC', continent: 'Oceania', country: 'United Kingdom', name: 'Turks and Caicos Islands', region: 'Caribbean', type: 'dependent'},
{code: 'GB-WLS', continent: 'Europe', country: 'United Kingdom', name: 'Wales', region: 'Northern Europe', type: 'dependent'},
{code: 'AS', continent: 'Oceania', country: 'United States', name: 'American Samoa', region: 'Polynesia', type: 'dependent'},
{code: 'GU', continent: 'Oceania', country: 'United States', name: 'Guam', region: 'Micronesia', type: 'dependent'},
{code: 'MP', continent: 'Oceania', country: 'United States', name: 'Northern Mariana Islands', region: 'Micronesia', type: 'dependent'},
{code: 'PR', continent: 'North America', country: 'United States', name: 'Puerto Rico', region: 'Caribbean', type: 'dependent'},
{code: 'UM', country: 'United States', name: 'United States Minor Outlying Islands', type: 'dependent'},
{code: 'VI', continent: 'North America', country: 'United States', name: 'United States Virgin Islands', region: 'Caribbean', type: 'dependent'},
{code: 'BUMM', continent: 'Asia', name: 'Burma', region: 'South-Eastern Asia', type: 'former'},
{code: 'BYAA', continent: 'Europe', name: 'Byelorussian Soviet Socialist Republic', region: 'Eastern Europe', type: 'former'},
{code: 'CTKI', continent: 'Oceania', name: 'Canton and Enderbury Islands', region: 'Micronesia', type: 'former'},
{code: 'CSHH', continent: 'Europe', name: 'Czechoslovakia', region: 'Eastern Europe', type: 'former'},
{code: 'DYBJ', continent: 'Africa', name: 'Dahomey', region: 'Western Africa', type: 'former'},
{code: 'TPTL', continent: 'Asia', name: 'East Timor', region: 'South-Eastern Asia', type: 'former'},
{code: 'DDDE', continent: 'Europe', name: 'East Germany', region: 'Eastern Europe', type: 'former'},
{code: 'GEHH', name: 'Gilbert and Ellice Islands', type: 'former'},
{code: 'KOHH', continent: 'Asia', name: 'Korea', region: 'Eastern Asia', type: 'former'},
{code: 'NTHH', continent: 'Asia', name: 'Neutral Zone', region: 'Western Asia', type: 'former'},
{code: 'VDVN', continent: 'Asia', name: 'North Vietnam', region: 'South-Eastern Asia', type: 'former'},
{code: 'RHZW', continent: 'Africa', name: 'Rhodesia', region: 'Eastern Africa', type: 'former'},
{code: 'CSXX', continent: 'Europe', name: 'Serbia and Montenegro', type: 'former'},
{code: 'SITH', continent: 'Asia', name: 'Siam', region: 'South-Eastern Asia', type: 'former'},
{code: 'SKIN', continent: 'Asia', name: 'Sikkim', region: 'Southern Asia', type: 'former'},
{code: 'YDYE', continent: 'Asia', name: 'South Yemen', region: 'Western Asia', type: 'former'},
{code: 'SUHH', continent: 'Europe', name: 'Soviet Union', region: 'Eastern Europe', type: 'former'},
{code: 'HVBF', continent: 'Africa', name: 'Upper Volta', region: 'Western Africa', type: 'former'},
{code: 'DEDE', continent: 'Europe', name: 'West Germany', region: 'Western Europe', type: 'former'},
{code: 'YUCS', continent: 'Europe', name: 'Yugoslavia', region: 'Southern Europe', type: 'former'},
{code: 'ZRCD', continent: 'Africa', name: 'Zaire', region: 'Middle Africa', type: 'former'},
{code: 'AIDJ', continent: 'Africa', country: 'France', name: 'French Afar and Issas', region: 'Eastern Africa', type: 'former'},
{code: 'FQHH', continent: 'Antarctica', country: 'France', name: 'French Southern and Antarctic Territories', type: 'former'},
{code: 'FXFR', continent: 'Europe', country: 'France', name: 'Metropolitan France', type: 'former'},
{code: 'NHVU', country: ['France', 'United Kingdom'], name: 'New Hebrides', region: 'Melanesia', type: 'former'},
{code: 'ANHH', continent: 'North America', country: 'Netherlands', name: 'Netherlands Antilles', region: 'Caribbean', type: 'former'},
{code: 'NQAQ', continent: 'Antarctica', country: 'Norway', name: 'Dronning Maud Land', type: 'former'},
{code: 'BQAQ', continent: 'Antarctica', country: 'United Kingdom', name: 'British Antarctic Territory', type: 'former'},
{code: 'JTUM', continent: 'Oceania', country: 'United States', name: 'Johnston Island', region: 'Mictonesia', type: 'former'},
{code: 'MIUM', continent: 'Oceania', country: 'United States', name: 'Midway Islands', type: 'former'},
{code: 'PCHH', continent: 'Oceania', country: 'United States', name: 'Pacific Islands', region: 'Micronesia', type: 'former'},
{code: 'PZPA', continent: 'North America', country: 'United States', name: 'Panama Canal Zone', region: 'Central America', type: 'former', flag: 'png'},
{code: 'PUUM', continent: 'Oceania', country: 'United States', name: 'United States Miscellaneous Pacific Islands', type: 'former'},
{code: 'WKUM', continent: 'Oceania', country: 'United States', name: 'Wake Island', region: 'Micronesia', type: 'former'},
{code: 'EU', continent: 'Europe', name: 'European Union', type: 'other'},
{code: 'UK', continent: 'Europe', name: 'United Kingdom', region: 'Northern Europe', type: 'other'}
];
Ox.COUNTRY_CODES = Ox.map(Ox.COUNTRIES, function(country) {
return country.code.length == 2 && ['EU', 'UK'].indexOf(country.code) == -1 ? country.code : null;
}).sort();
Ox.getCountryCode = (function() {
var aliases = {
'Cocos (Keeling) Islands': 'Cocos Islands',
'Congo': 'Republic of the Congo',
'French Southern and Antarctic Lands': 'French Southern Territories',
'Macedonia (FYROM)': 'Macedonia',
'Pitcairn Islands': 'Pitcairn',
'Reunion': 'Réunion',
'St Barthélemy': 'Saint Barthélemy',
'St Helena': 'Saint Helena',
'St Kitts and Nevis': 'Saint Kitts and Nevis',
'St Lucia': 'Saint Lucia',
'St Pierre and Miquelon': 'Saint Pierre and Miquelon',
'St Vincent and the Grenadines': 'Saint Vincent and the Grenadines',
'The Bahamas': 'Bahamas',
'The Gambia': 'Gambia',
'The Netherlands': 'Netherlands',
'Trinidad & Tobago': 'Trinidad and Tobago',
'UK': 'United Kingdom',
'US Virgin Islands': 'United States Virgin Islands',
'USA': 'United States',
'Western Sahara': 'Sahrawi'
};
return function(geoname) {
var countryCode = '',
countryName = geoname.split(', ').pop();
Ox.forEach(aliases, function(val, key) {
if (countryName == key) {
countryName = val;
return false;
}
});
Ox.forEach(Ox.COUNTRIES, function(country) {
if (country.name == countryName) {
countryCode = country.code;
return false;
}
});
return countryCode;
};
}());

View file

@ -1,57 +0,0 @@
onmessage = function(e) {
if (e.data.message) {
} else {
}
}
function encode() {
str = Ox.encodeUTF8(str);
var c = Ox.canvas(img), len = str.length;
if (len > maxLength(img.width, img.height)) {
throw new RangeError("PNG codec can't encode " + len +
" bytes into " + (img.width * img.height) + " pixels");
}
len = Ox.pad(Ox.encodeBase256(len), 4, Ox.char(0));
Ox.each(Ox.map(len + str, function(byte) {
return Ox.map(new Array(8), function(v, i) {
return byte.charCodeAt(0) >> 7 - i & 1;
}).join("");
}).join(""), function(i, bit) {
var index, byte = c.data[index = parseInt(i * 4/3)];
c.data[index] = bit == xor(byte) ? byte :
byte & 254 | !(byte & 1);
});
c.context.putImageData(c.imageData, 0, 0);
postMessage(c.canvas.toDataURL());
}
function decode() {
var c = Ox.canvas(img), bits = "", str = "", i = 0; len = 4, flag = false;
do {
bits += xor(c.data[parseInt(i * 4/3)]);
if (++i % 8 == 0) {
str += Ox.char(parseInt(bits, 2));
bits = "";
len--;
if (len == 0 && !flag) {
if ((len = Ox.decodeBase256(str)) >
maxLength(img.width, img.height)) {
throwPNGError();
}
str = "";
flag = true;
}
}
} while (len);
try {
return Ox.decodeUTF8(str);
} catch(e) {
throwPNGError();
}
}
function throwError() {
throw new RangeError("PNG codec can't decode image");
}

File diff suppressed because it is too large Load diff

View file

@ -1,442 +0,0 @@
[
"png/ox.map/marker.png",
"png/ox.map/markerEditing.png",
"png/ox.map/markerResize.png",
"png/ox.map/markerResult.png",
"png/ox.map/markerResultEditing.png",
"png/ox.map/markerResultSelected.png",
"png/ox.map/markerSelected.png",
"png/ox.ui/browserChrome128.png",
"png/ox.ui/browserFirefox128.png",
"png/ox.ui/browserInternetExplorer128.png",
"png/ox.ui/browserOpera128.png",
"png/ox.ui/browserSafari128.png",
"png/ox.ui/icon16.png",
"png/ox.ui/transparent.png",
"png/ox.ui/videoMarkerCut.png",
"png/ox.ui/videoMarkerIn.png",
"png/ox.ui/videoMarkerInBottom.png",
"png/ox.ui/videoMarkerInTop.png",
"png/ox.ui/videoMarkerOut.png",
"png/ox.ui/videoMarkerOutBottom.png",
"png/ox.ui/videoMarkerOutTop.png",
"png/ox.ui/videoMarkerPlay.png",
"png/ox.ui.classic/scrollbarHorizontalDecrement.png",
"png/ox.ui.classic/scrollbarHorizontalIncrement.png",
"png/ox.ui.classic/scrollbarVerticalDecrement.png",
"png/ox.ui.classic/scrollbarVerticalIncrement.png",
"png/ox.ui.modern/scrollbarHorizontalDecrement.png",
"png/ox.ui.modern/scrollbarHorizontalIncrement.png",
"png/ox.ui.modern/scrollbarVerticalDecrement.png",
"png/ox.ui.modern/scrollbarVerticalIncrement.png",
"svg/ox.map/AC.svg",
"svg/ox.map/AD.svg",
"svg/ox.map/AE.svg",
"svg/ox.map/AF.svg",
"svg/ox.map/AG.svg",
"svg/ox.map/AI.svg",
"svg/ox.map/AIDJ.svg",
"svg/ox.map/AL.svg",
"svg/ox.map/AM.svg",
"svg/ox.map/ANHH.svg",
"svg/ox.map/AO.svg",
"svg/ox.map/AQ.svg",
"svg/ox.map/AR.svg",
"svg/ox.map/AS.svg",
"svg/ox.map/AT.svg",
"svg/ox.map/AU-AC.svg",
"svg/ox.map/AU-CS.svg",
"svg/ox.map/AU.svg",
"svg/ox.map/AW.svg",
"svg/ox.map/AX.svg",
"svg/ox.map/AZ-NK.svg",
"svg/ox.map/AZ.svg",
"svg/ox.map/BA.svg",
"svg/ox.map/BB.svg",
"svg/ox.map/BD.svg",
"svg/ox.map/BE.svg",
"svg/ox.map/BF.svg",
"svg/ox.map/BG.svg",
"svg/ox.map/BH.svg",
"svg/ox.map/BI.svg",
"svg/ox.map/BJ.svg",
"svg/ox.map/BL.svg",
"svg/ox.map/BM.svg",
"svg/ox.map/BN.svg",
"svg/ox.map/BO.svg",
"svg/ox.map/BQ.svg",
"svg/ox.map/BQAQ.svg",
"svg/ox.map/BR.svg",
"svg/ox.map/BS.svg",
"svg/ox.map/BT.svg",
"svg/ox.map/BUMM.svg",
"svg/ox.map/BV.svg",
"svg/ox.map/BW.svg",
"svg/ox.map/BY.svg",
"svg/ox.map/BYAA.svg",
"svg/ox.map/BZ.svg",
"svg/ox.map/CA.svg",
"svg/ox.map/CC.svg",
"svg/ox.map/CD.svg",
"svg/ox.map/CF.svg",
"svg/ox.map/CG.svg",
"svg/ox.map/CH.svg",
"svg/ox.map/CI.svg",
"svg/ox.map/CK.svg",
"svg/ox.map/CL.svg",
"svg/ox.map/CM.svg",
"svg/ox.map/CN.svg",
"svg/ox.map/CO.svg",
"svg/ox.map/CP.svg",
"svg/ox.map/CR.svg",
"svg/ox.map/CSHH.svg",
"svg/ox.map/CSXX.svg",
"svg/ox.map/CTKI.svg",
"svg/ox.map/CU.svg",
"svg/ox.map/CV.svg",
"svg/ox.map/CW.svg",
"svg/ox.map/CX.svg",
"svg/ox.map/CY-NC.svg",
"svg/ox.map/CY.svg",
"svg/ox.map/CZ.svg",
"svg/ox.map/DDDE.svg",
"svg/ox.map/DE.svg",
"svg/ox.map/DEDE.svg",
"svg/ox.map/DG.svg",
"svg/ox.map/DJ.svg",
"svg/ox.map/DK.svg",
"svg/ox.map/DM.svg",
"svg/ox.map/DO.svg",
"svg/ox.map/DYBJ.svg",
"svg/ox.map/DZ.svg",
"svg/ox.map/EA.svg",
"svg/ox.map/EC.svg",
"svg/ox.map/EE.svg",
"svg/ox.map/EG.svg",
"svg/ox.map/EH.svg",
"svg/ox.map/ER.svg",
"svg/ox.map/ES.svg",
"svg/ox.map/ET.svg",
"svg/ox.map/EU.svg",
"svg/ox.map/FI.svg",
"svg/ox.map/FJ.svg",
"svg/ox.map/FK.svg",
"svg/ox.map/FM.svg",
"svg/ox.map/FO.svg",
"svg/ox.map/FQHH.svg",
"svg/ox.map/FR.svg",
"svg/ox.map/FXFR.svg",
"svg/ox.map/GA.svg",
"svg/ox.map/GB-ENG.svg",
"svg/ox.map/GB-NIR.svg",
"svg/ox.map/GB-SCT.svg",
"svg/ox.map/GB-WLS.svg",
"svg/ox.map/GB.svg",
"svg/ox.map/GD.svg",
"svg/ox.map/GE-AB.svg",
"svg/ox.map/GE-SO.svg",
"svg/ox.map/GE.svg",
"svg/ox.map/GEHH.svg",
"svg/ox.map/GF.svg",
"svg/ox.map/GG.svg",
"svg/ox.map/GH.svg",
"svg/ox.map/GI.svg",
"svg/ox.map/GL.svg",
"svg/ox.map/GM.svg",
"svg/ox.map/GN.svg",
"svg/ox.map/GP.svg",
"svg/ox.map/GQ.svg",
"svg/ox.map/GR.svg",
"svg/ox.map/GS.svg",
"svg/ox.map/GT.svg",
"svg/ox.map/GU.svg",
"svg/ox.map/GW.svg",
"svg/ox.map/GY.svg",
"svg/ox.map/HK.svg",
"svg/ox.map/HM.svg",
"svg/ox.map/HN.svg",
"svg/ox.map/HR.svg",
"svg/ox.map/HT.svg",
"svg/ox.map/HU.svg",
"svg/ox.map/HVBF.svg",
"svg/ox.map/IC.svg",
"svg/ox.map/ID.svg",
"svg/ox.map/IE.svg",
"svg/ox.map/IL.svg",
"svg/ox.map/IM.svg",
"svg/ox.map/IN.svg",
"svg/ox.map/IO.svg",
"svg/ox.map/IQ.svg",
"svg/ox.map/IR.svg",
"svg/ox.map/IS.svg",
"svg/ox.map/IT.svg",
"svg/ox.map/JE.svg",
"svg/ox.map/JM.svg",
"svg/ox.map/JO.svg",
"svg/ox.map/JP.svg",
"svg/ox.map/JTUM.svg",
"svg/ox.map/KE.svg",
"svg/ox.map/KG.svg",
"svg/ox.map/KH.svg",
"svg/ox.map/KI.svg",
"svg/ox.map/KM.svg",
"svg/ox.map/KN.svg",
"svg/ox.map/KOHH.svg",
"svg/ox.map/KP.svg",
"svg/ox.map/KR.svg",
"svg/ox.map/KW.svg",
"svg/ox.map/KY.svg",
"svg/ox.map/KZ.svg",
"svg/ox.map/LA.svg",
"svg/ox.map/LB.svg",
"svg/ox.map/LC.svg",
"svg/ox.map/LI.svg",
"svg/ox.map/LK.svg",
"svg/ox.map/LR.svg",
"svg/ox.map/LS.svg",
"svg/ox.map/LT.svg",
"svg/ox.map/LU.svg",
"svg/ox.map/LV.svg",
"svg/ox.map/LY.svg",
"svg/ox.map/MA.svg",
"svg/ox.map/MC.svg",
"svg/ox.map/MD-TR.svg",
"svg/ox.map/MD.svg",
"svg/ox.map/ME.svg",
"svg/ox.map/MF.svg",
"svg/ox.map/MG.svg",
"svg/ox.map/MH.svg",
"svg/ox.map/MIUM.svg",
"svg/ox.map/MK.svg",
"svg/ox.map/ML.svg",
"svg/ox.map/MM.svg",
"svg/ox.map/MN.svg",
"svg/ox.map/MO.svg",
"svg/ox.map/MP.svg",
"svg/ox.map/MQ.svg",
"svg/ox.map/MR.svg",
"svg/ox.map/MS.svg",
"svg/ox.map/MT.svg",
"svg/ox.map/MU.svg",
"svg/ox.map/MV.svg",
"svg/ox.map/MW.svg",
"svg/ox.map/MX.svg",
"svg/ox.map/MY.svg",
"svg/ox.map/MZ.svg",
"svg/ox.map/NA.svg",
"svg/ox.map/NC.svg",
"svg/ox.map/NE.svg",
"svg/ox.map/NF.svg",
"svg/ox.map/NG.svg",
"svg/ox.map/NHVU.svg",
"svg/ox.map/NI.svg",
"svg/ox.map/NL.svg",
"svg/ox.map/NO.svg",
"svg/ox.map/NP.svg",
"svg/ox.map/NQAQ.svg",
"svg/ox.map/NR.svg",
"svg/ox.map/NTHH.svg",
"svg/ox.map/NU.svg",
"svg/ox.map/NZ.svg",
"svg/ox.map/OM.svg",
"svg/ox.map/PA.svg",
"svg/ox.map/PCHH.svg",
"svg/ox.map/PE.svg",
"svg/ox.map/PF.svg",
"svg/ox.map/PG.svg",
"svg/ox.map/PH.svg",
"svg/ox.map/PK.svg",
"svg/ox.map/PL.svg",
"svg/ox.map/PM.svg",
"svg/ox.map/PN.svg",
"svg/ox.map/PR.svg",
"svg/ox.map/PS.svg",
"svg/ox.map/PT.svg",
"svg/ox.map/PUUM.svg",
"svg/ox.map/PW.svg",
"svg/ox.map/PY.svg",
"svg/ox.map/PZPA.png",
"svg/ox.map/QA.svg",
"svg/ox.map/RE.png",
"svg/ox.map/RHZW.svg",
"svg/ox.map/RO.svg",
"svg/ox.map/RS-KO.svg",
"svg/ox.map/RS.svg",
"svg/ox.map/RU.svg",
"svg/ox.map/RW.svg",
"svg/ox.map/SA.svg",
"svg/ox.map/SB.svg",
"svg/ox.map/SC.svg",
"svg/ox.map/SD-SS.svg",
"svg/ox.map/SD.svg",
"svg/ox.map/SE.svg",
"svg/ox.map/SG.svg",
"svg/ox.map/SH.svg",
"svg/ox.map/SI.svg",
"svg/ox.map/SITH.svg",
"svg/ox.map/SJ.svg",
"svg/ox.map/SK.svg",
"svg/ox.map/SKIN.svg",
"svg/ox.map/SL.svg",
"svg/ox.map/SM.svg",
"svg/ox.map/SN.svg",
"svg/ox.map/SO-SO.svg",
"svg/ox.map/SO.svg",
"svg/ox.map/SR.svg",
"svg/ox.map/ST.svg",
"svg/ox.map/SUHH.svg",
"svg/ox.map/SV.svg",
"svg/ox.map/SX.svg",
"svg/ox.map/SY.svg",
"svg/ox.map/SZ.svg",
"svg/ox.map/TA.svg",
"svg/ox.map/TC.svg",
"svg/ox.map/TD.svg",
"svg/ox.map/TF.svg",
"svg/ox.map/TG.svg",
"svg/ox.map/TH.svg",
"svg/ox.map/TJ.svg",
"svg/ox.map/TK.svg",
"svg/ox.map/TL.svg",
"svg/ox.map/TM.svg",
"svg/ox.map/TN.svg",
"svg/ox.map/TO.svg",
"svg/ox.map/TPTL.svg",
"svg/ox.map/TR.svg",
"svg/ox.map/TT.svg",
"svg/ox.map/TV.svg",
"svg/ox.map/TW.svg",
"svg/ox.map/TZ.svg",
"svg/ox.map/UA.svg",
"svg/ox.map/UG.svg",
"svg/ox.map/UK.svg",
"svg/ox.map/UM.svg",
"svg/ox.map/US.svg",
"svg/ox.map/UY.svg",
"svg/ox.map/UZ.svg",
"svg/ox.map/VA.svg",
"svg/ox.map/VC.svg",
"svg/ox.map/VDVN.svg",
"svg/ox.map/VE.svg",
"svg/ox.map/VG.svg",
"svg/ox.map/VI.svg",
"svg/ox.map/VN.svg",
"svg/ox.map/VU.svg",
"svg/ox.map/WF.svg",
"svg/ox.map/WKUM.svg",
"svg/ox.map/WS.svg",
"svg/ox.map/YDYE.svg",
"svg/ox.map/YE.svg",
"svg/ox.map/YT.svg",
"svg/ox.map/YUCS.svg",
"svg/ox.map/ZA.svg",
"svg/ox.map/ZM.svg",
"svg/ox.map/ZRCD.svg",
"svg/ox.map/ZW.svg",
"svg/ox.ui.classic/symbolAdd.svg",
"svg/ox.ui.classic/symbolArrowDown.svg",
"svg/ox.ui.classic/symbolArrowLeft.svg",
"svg/ox.ui.classic/symbolArrowRight.svg",
"svg/ox.ui.classic/symbolArrowUp.svg",
"svg/ox.ui.classic/symbolBracket.svg",
"svg/ox.ui.classic/symbolCenter.svg",
"svg/ox.ui.classic/symbolCheck.svg",
"svg/ox.ui.classic/symbolClose.svg",
"svg/ox.ui.classic/symbolDelete.svg",
"svg/ox.ui.classic/symbolDown.svg",
"svg/ox.ui.classic/symbolDownload.svg",
"svg/ox.ui.classic/symbolEdit.svg",
"svg/ox.ui.classic/symbolFill.svg",
"svg/ox.ui.classic/symbolFind.svg",
"svg/ox.ui.classic/symbolFit.svg",
"svg/ox.ui.classic/symbolFlag.svg",
"svg/ox.ui.classic/symbolGoToIn.svg",
"svg/ox.ui.classic/symbolGoToOut.svg",
"svg/ox.ui.classic/symbolGrow.svg",
"svg/ox.ui.classic/symbolHelp.svg",
"svg/ox.ui.classic/symbolInfo.svg",
"svg/ox.ui.classic/symbolLeft.svg",
"svg/ox.ui.classic/symbolLike.svg",
"svg/ox.ui.classic/symbolLoading.svg",
"svg/ox.ui.classic/symbolLock.svg",
"svg/ox.ui.classic/symbolMount.svg",
"svg/ox.ui.classic/symbolMute.svg",
"svg/ox.ui.classic/symbolNone.svg",
"svg/ox.ui.classic/symbolPause.svg",
"svg/ox.ui.classic/symbolPlayInToOut.svg",
"svg/ox.ui.classic/symbolPublish.svg",
"svg/ox.ui.classic/symbolRedo.svg",
"svg/ox.ui.classic/symbolRemove.svg",
"svg/ox.ui.classic/symbolRight.svg",
"svg/ox.ui.classic/symbolSelect.svg",
"svg/ox.ui.classic/symbolSet.svg",
"svg/ox.ui.classic/symbolSetIn.svg",
"svg/ox.ui.classic/symbolSetOut.svg",
"svg/ox.ui.classic/symbolShrink.svg",
"svg/ox.ui.classic/symbolStar.svg",
"svg/ox.ui.classic/symbolSync.svg",
"svg/ox.ui.classic/symbolUndo.svg",
"svg/ox.ui.classic/symbolUnlock.svg",
"svg/ox.ui.classic/symbolUnmount.svg",
"svg/ox.ui.classic/symbolUnmute.svg",
"svg/ox.ui.classic/symbolUp.svg",
"svg/ox.ui.classic/symbolUser.svg",
"svg/ox.ui.classic/symbolView.svg",
"svg/ox.ui.classic/symbolVolumeDown.svg",
"svg/ox.ui.classic/symbolVolumeUp.svg",
"svg/ox.ui.classic/symbolWarning.svg",
"svg/ox.ui.classic/symbolZoom.svg",
"svg/ox.ui.modern/symbolAdd.svg",
"svg/ox.ui.modern/symbolArrowDown.svg",
"svg/ox.ui.modern/symbolArrowLeft.svg",
"svg/ox.ui.modern/symbolArrowRight.svg",
"svg/ox.ui.modern/symbolArrowUp.svg",
"svg/ox.ui.modern/symbolBracket.svg",
"svg/ox.ui.modern/symbolCenter.svg",
"svg/ox.ui.modern/symbolCheck.svg",
"svg/ox.ui.modern/symbolClose.svg",
"svg/ox.ui.modern/symbolDelete.svg",
"svg/ox.ui.modern/symbolDown.svg",
"svg/ox.ui.modern/symbolDownload.svg",
"svg/ox.ui.modern/symbolEdit.svg",
"svg/ox.ui.modern/symbolFill.svg",
"svg/ox.ui.modern/symbolFind.svg",
"svg/ox.ui.modern/symbolFit.svg",
"svg/ox.ui.modern/symbolFlag.svg",
"svg/ox.ui.modern/symbolGoToIn.svg",
"svg/ox.ui.modern/symbolGoToOut.svg",
"svg/ox.ui.modern/symbolGrow.svg",
"svg/ox.ui.modern/symbolHelp.svg",
"svg/ox.ui.modern/symbolInfo.svg",
"svg/ox.ui.modern/symbolLeft.svg",
"svg/ox.ui.modern/symbolLike.svg",
"svg/ox.ui.modern/symbolLoading.svg",
"svg/ox.ui.modern/symbolLock.svg",
"svg/ox.ui.modern/symbolMount.svg",
"svg/ox.ui.modern/symbolMute.svg",
"svg/ox.ui.modern/symbolNone.svg",
"svg/ox.ui.modern/symbolPause.svg",
"svg/ox.ui.modern/symbolPlayInToOut.svg",
"svg/ox.ui.modern/symbolPublish.svg",
"svg/ox.ui.modern/symbolRedo.svg",
"svg/ox.ui.modern/symbolRemove.svg",
"svg/ox.ui.modern/symbolRight.svg",
"svg/ox.ui.modern/symbolSelect.svg",
"svg/ox.ui.modern/symbolSet.svg",
"svg/ox.ui.modern/symbolSetIn.svg",
"svg/ox.ui.modern/symbolSetOut.svg",
"svg/ox.ui.modern/symbolShrink.svg",
"svg/ox.ui.modern/symbolStar.svg",
"svg/ox.ui.modern/symbolSync.svg",
"svg/ox.ui.modern/symbolUndo.svg",
"svg/ox.ui.modern/symbolUnlock.svg",
"svg/ox.ui.modern/symbolUnmount.svg",
"svg/ox.ui.modern/symbolUnmute.svg",
"svg/ox.ui.modern/symbolUp.svg",
"svg/ox.ui.modern/symbolUser.svg",
"svg/ox.ui.modern/symbolView.svg",
"svg/ox.ui.modern/symbolVolumeDown.svg",
"svg/ox.ui.modern/symbolVolumeUp.svg",
"svg/ox.ui.modern/symbolWarning.svg",
"svg/ox.ui.modern/symbolZoom.svg"
]

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<g stroke="#404040" stroke-width="48"> <g stroke="#404040" stroke-width="48">
<line x1="128" y1="16" x2="128" y2="240"/> <line x1="128" y1="0" x2="128" y2="256"/>
<line x1="16" y1="128" x2="240" y2="128"/> <line x1="0" y1="128" x2="256" y2="128"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 229 B

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<polygon points="32,48 224,48 128,240" fill="#404040"/> <polygon points="32,56 224,56 128,248" fill="#404040"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 132 B

After

Width:  |  Height:  |  Size: 132 B

View file

@ -1,3 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<line x1="16" y1="128" x2="240" y2="128" stroke="#404040" stroke-width="48"/> <g stroke="#404040" stroke-width="48" stroke-linecap="round">
<line x1="0" y1="128" x2="256" y2="128"/>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 154 B

After

Width:  |  Height:  |  Size: 197 B

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<polygon points="32,208 128,16 224,208" fill="#404040"/> <polygon points="32,200 128,8 224,200" fill="#404040"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 132 B

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<g stroke="#FFFFFF" stroke-width="48"> <g stroke="#FFFFFF" stroke-width="48">
<line x1="128" y1="16" x2="128" y2="240"/> <line x1="128" y1="0" x2="128" y2="256"/>
<line x1="16" y1="128" x2="240" y2="128"/> <line x1="0" y1="128" x2="256" y2="128"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 229 B

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<polygon points="32,48 224,48 128,240" fill="#FFFFFF"/> <polygon points="32,56 224,56 128,248" fill="#FFFFFF"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 132 B

After

Width:  |  Height:  |  Size: 132 B

View file

@ -1,3 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<line x1="16" y1="128" x2="240" y2="128" stroke="#FFFFFF" stroke-width="48"/> <g stroke="#FFFFFF" stroke-width="48" stroke-linecap="round">
<line x1="0" y1="128" x2="256" y2="128"/>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 154 B

After

Width:  |  Height:  |  Size: 197 B

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
<polygon points="32,208 128,16 224,208" fill="#FFFFFF"/> <polygon points="32,200 128,8 224,200" fill="#FFFFFF"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 132 B

View file

@ -4,10 +4,7 @@
<title>ox.js calendar demo</title> <title>ox.js calendar demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" href="../../build/css/ox.ui.css"/> <link rel="stylesheet" type="text/css" href="../../build/css/ox.ui.css"/>
<script type="text/javascript" src="../../build/js/jquery-1.5.js"></script> <script type="text/javascript" src="../../build/js/OxUI.js"></script>
<script type="text/javascript" src="../../build/js/jquery.mousewheel.js"></script>
<script type="text/javascript" src="../../build/js/ox.js"></script>
<script type="text/javascript" src="../../build/js/ox.ui.js"></script>
<script type="text/javascript" src="js/calendar.js"></script> <script type="text/javascript" src="js/calendar.js"></script>
</head> </head>
<body></body> <body></body>

View file

@ -1,7 +1,11 @@
$(function() { Ox.UI(function() {
Ox.UI.ready(function() {
Ox.theme('modern'); Ox.theme('modern');
Ox.print('$$$$', Ox.Calendar)
new Ox.Calendar({ new Ox.Calendar({
date: new Date(0), date: new Date(0),
dates: [ dates: [
@ -131,3 +135,5 @@ $(function() {
}).appendTo(Ox.UI.$body); }).appendTo(Ox.UI.$body);
}); });
});

View file

@ -0,0 +1,117 @@
Ox.AnnotationPanel = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
id: '',
items: [],
title: '',
type: 'text',
width: 0
})
.options(options || {});
self.selected = -1;
that.$element = new Ox.CollapsePanel({
collapsed: false,
extras: [
new Ox.Button({
id: 'add',
style: 'symbol',
title: 'Add',
type: 'image'
}).bindEvent({
click: function(event, data) {
that.triggerEvent('add', {value: ''});
}
})
],
size: 16,
title: self.options.title
})
.addClass('OxAnnotationPanel')
.bindEvent({
toggle: togglePanel
});
that.$content = that.$element.$content;
self.$annotations = new Ox.List({
construct: function(data) {
return new Ox.Element('div')
.addClass('OxAnnotation OxEditable OxTarget')
.html(Ox.parseHTML(data.value));
},
items: $.map(self.options.items, function(v, i) {
return {
id: v.id || i + '',
value: v.value
};
}),
unique: 'id'
})
.bindEvent({
open: function(event, data) {
if (data.ids.length == 1) {
var pos = Ox.getPositionById(self.$annotations.options('items'), data.ids[0]);
self.$annotations.editItem(pos);
}
},
'delete': function(event, data) {
that.triggerEvent('delete', data);
},
select: selectAnnotation,
submit: updateAnnotation
})
.appendTo(that.$content);
/*
self.$annotations = new Ox.Element('div')
.appendTo(that.$content);
self.$annotation = [];
self.options.items.forEach(function(item, i) {
self.$annotation[i] = new Ox.Element('div')
.addClass('OxAnnotation')
.html(item.value.replace(/\n/g, '<br/>'))
.click(function() {
clickAnnotation(i);
})
.appendTo(self.$annotations);
});
*/
function selectAnnotation(event, data) {
var item = Ox.getObjectById(self.options.items, data.ids[0]);
that.triggerEvent('select', {
'in': item['in'],
'out': item.out,
'layer': self.options.id
});
}
function updateAnnotation(event, data) {
var item = Ox.getObjectById(self.options.items, data.id);
item.value = data.value;
that.triggerEvent('submit', item);
}
function togglePanel() {
}
that.addItem = function(item) {
var pos = 0;
self.options.items.splice(pos, 0, item);
self.$annotations.addItems(pos, [item]);
self.$annotations.editItem(pos);
}
that.removeItems = function(ids) {
self.$annotations.removeItems(ids);
}
that.deselectItems = function() {
if(self.$annotations.options('selected'))
self.$annotations.options('selected',[]);
}
return that;
};

200
source/js/Ox.App.js Normal file
View file

@ -0,0 +1,200 @@
/*
============================================================================
Application
============================================================================
*/
// fixme: get rid og launch, fire load event
Ox.App = (function() {
/***
Ox.App
Basic application instance that communicates with a JSON API.
The JSON API should support at least the following actions:
api returns all api methods
init returns {config: {...}, user: {...}}
Options
timeout API timeout in msec
type 'GET' or 'POST'
url URL of the API
Methods
api[action] make a request
api.cancel cancel a request
launch launch the App
options get or set options
***/
return function(options) {
options = options || {};
var self = {},
that = this;
self.time = +new Date();
self.options = $.extend({
timeout: 60000,
type: 'POST',
url: '/api/',
}, options);
that.$element = new Ox.Element('body');
function getUserAgent() {
var userAgent = '';
Ox.forEach(['Chrome', 'Firefox', 'Internet Explorer', 'Opera', 'Safari'], function(v) {
if (navigator.userAgent.indexOf(v) > -1) {
userAgent = v;
return false;
}
});
if (!userAgent && $.browser.mozilla) {
userAgent = 'Firefox';
}
if (!userAgent && $.browser.webkit) {
userAgent = 'Chrome';
}
return userAgent;
}
function getUserData() {
return {
document: {
referrer: document.referrer
},
history: {
length: history.length
},
navigator: {
cookieEnabled: navigator.cookieEnabled,
plugins: $.map(navigator.plugins, function(plugin, i) {
return plugin.name;
}),
userAgent: navigator.userAgent
},
screen: screen,
time: (+new Date() - self.time) / 1000,
window: {
innerHeight: window.innerHeight,
innerWidth: window.innerWidth,
outerHeight: window.outerHeight,
outerWidth: window.outerWidth,
screenLeft: window.screenLeft,
screenTop: window.screenTop
}
};
}
function loadImages(callback) {
window.OxImageCache = [];
$.getJSON(Ox.UI.PATH + 'json/ox.ui.images.json', function(data) {
// fixme: find a better way to not wait for flags
data = data.filter(function(image) {
return !Ox.startsWith(image, 'svg/ox.map/')
});
var counter = 0,
length = data.length;
data.forEach(function(src, i) {
var image = new Image();
image.src = Ox.UI.PATH + src;
image.onload = function() {
(++counter == length) && callback();
}
window.OxImageCache.push(image); // fixme: global var???
});
});
}
self.change = function(key, value) {
};
that.api = {
api: function(callback) {
Ox.Request.send({
url: self.options.url,
data: {
action: 'api'
},
callback: callback
});
},
cancel: function(id) {
Ox.Request.cancel(id);
}
};
that.bindEvent = function() {
};
// fixme: use $.when()
that.launch = function(callback) {
var time = +new Date(),
userAgent = getUserAgent(),
userAgents = ['Chrome', 'Firefox', 'Opera', 'Safari'];
$.ajaxSetup({
timeout: self.options.timeour,
type: self.options.type,
url: self.options.url
});
userAgents.indexOf(userAgent) > -1 ? start() : stop();
function start() {
// fixme: rename config to site?
var counter = 0, config, user;
that.api.api(function(result) {
Ox.forEach(result.data.actions, function(val, key) {
that.api[key] = function(data, callback) {
if (arguments.length == 1 && Ox.isFunction(data)) {
callback = data;
data = {};
}
return Ox.Request.send($.extend({
url: self.options.url,
data: {
action: key,
data: JSON.stringify(data)
},
callback: callback
}, !val.cache ? {age: 0}: {}));
};
});
that.api.init(getUserData(), function(result) {
config = result.data.config;
user = result.data.user;
// fixme: not generic
document.title = config.site.name;
launchCallback();
});
});
loadImages(launchCallback);
function launchCallback() {
++counter == 2 && $(function() {
var $div = Ox.UI.$body.find('div');
Ox.UI.$body.find('img').remove();
$div.animate({
opacity: 0
}, 1000, function() {
$div.remove();
});
// fixme: not generic enough, just pass data
callback({config: config, user: user});
});
}
}
function stop() {
that.request.send(self.options.init, getUserData(), function() {});
}
return that;
};
that.options = function() {
return Ox.getset(self.options, Array.prototype.slice.call(arguments), self.change, that);
};
return that;
};
}());

18
source/js/Ox.Bar.js Normal file
View file

@ -0,0 +1,18 @@
/**
*/
Ox.Bar = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
orientation: 'horizontal',
size: 'medium' // can be int
})
.options(options || {})
.addClass('OxBar Ox' + Ox.toTitleCase(self.options.orientation)),
dimensions = Ox.UI.DIMENSIONS[self.options.orientation];
self.options.size = Ox.isString(self.options.size) ?
Ox.UI.getBarSize(self.options.size) : self.options.size;
that.css(dimensions[0], '100%')
.css(dimensions[1], self.options.size + 'px');
return that;
};

View file

@ -0,0 +1,363 @@
Ox.BlockTimeline = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
cuts: [],
duration: 0,
find: '',
matches: [],
points: [0, 0],
position: 0,
subtitles: [],
videoId: '',
width: 0
})
.options(options || {})
.addClass('OxTimelineSmall')
.mousedown(mousedown)
.mouseleave(mouseleave)
.mousemove(mousemove)
.bindEvent({
drag: function(event, e) {
mousedown(e);
}
});
$.extend(self, {
$images: [],
$lines: [],
$markerPoint: [],
$selection: [],
$subtitles: [],
$tooltip: new Ox.Tooltip({
animate: false
}).css({
textAlign: 'center'
}),
hasSubtitles: self.options.subtitles.length,
height: 16,
lines: Math.ceil(self.options.duration / self.options.width),
margin: 8
});
that.css({
width: (self.options.width + self.margin) + 'px',
height: ((self.height + self.margin) * self.lines + 4) + 'px'
});
getTimelineImageURL(function(url) {
self.timelineImageURL = url;
Ox.range(0, self.lines).forEach(function(i) {
addLine(i);
});
self.$markerPosition = $('<img>')
.addClass('OxMarkerPosition')
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarkerPlay.png'
})
.css({
position: 'absolute',
width: '9px',
height: '5px',
zIndex: 10
})
.appendTo(that.$element);
setPosition();
['in', 'out'].forEach(function(v, i) {
var titleCase = Ox.toTitleCase(v);
self.$markerPoint[i] = $('<img>')
.addClass('OxMarkerPoint' + titleCase)
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarker' + titleCase + '.png'
})
.appendTo(that.$element);
setMarkerPoint(i);
});
});
function addLine(i) {
// fixme: get URLs once, not once for every line
self.$lines[i] = new Ox.Element('div')
.css({
top: i * (self.height + self.margin) + 'px',
width: self.options.width + 'px'
})
.appendTo(that);
self.$images[i] = $('<img>')
.addClass('OxTimelineSmallImage')
.attr({
src: self.timelineImageURL
})
.css({
marginLeft: (-i * self.options.width) + 'px'
})
.appendTo(self.$lines[i].$element)
if (self.hasSubtitles) {
self.subtitlesImageURL = getSubtitlesImageURL();
self.$subtitles[i] = $('<img>')
.addClass('OxTimelineSmallSubtitles')
.attr({
src: self.subtitlesImageURL
})
.css({
marginLeft: (-i * self.options.width) + 'px'
})
.appendTo(self.$lines[i].$element);
}
if (self.options.points[0] != self.options.points[1]) {
addSelection[i];
}
}
function addSelection(i) {
self.selectionImageURL = getSelectionImageURL();
self.$selection[i] && self.$selection[i].remove();
self.$selection[i] = $('<img>')
.addClass('OxTimelineSmallSelection')
.attr({
src: self.selectionImageURL
})
.css({
marginLeft: (-i * self.options.width) + 'px'
})
.appendTo(self.$lines[i].$element);
}
function getPosition(e) {
//FIXME: this might still be broken in opera according to http://acko.net/blog/mouse-handling-and-absolute-positions-in-javascript
return (e.offsetX ? e.offsetX : e.clientX - $(e.target).offset().left);
}
function getSelectionImageURL() {
var height = 18,
width = Math.ceil(self.options.duration),
$canvas = $('<canvas>')
.attr({
height: height,
width: width
}),
canvas = $canvas[0],
context = canvas.getContext('2d'),
imageData = context.createImageData(width, height),
data = imageData.data,
points = $.map(self.options.points, function(v, i) {
return Math.round(v) + i;
}),
top = 0,
bottom = 18;
Ox.range(points[0], points[1]).forEach(function(x) {
Ox.range(top, bottom).forEach(function(y) {
var color = (y == top || y == bottom - 1) ? [255, 255, 255, 255] : [255, 255, 255, 64],
index = x * 4 + y * 4 * width;
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = color[3]
});
});
context.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
function getSubtitle(position) {
var subtitle = null;
Ox.forEach(self.options.subtitles, function(v) {
if (v['in'] <= position && v['out'] >= position) {
subtitle = v;
return false;
}
});
return subtitle;
}
function getSubtitlesImageURL() {
var height = 18,
width = Math.ceil(self.options.duration),
$canvas = $('<canvas>')
.attr({
height: height,
width: width
}),
canvas = $canvas[0],
context = canvas.getContext('2d'),
imageData = context.createImageData(width, height),
data = imageData.data;
self.options.subtitles.forEach(function(v) {
//var color = self.options.matches.indexOf(i) > -1 ? [255, 255, 0] : [255, 255, 255]
var inPoint = Math.round(v['in']),
outPoint = Math.round(v.out) + 1,
lines = v.value.split('\n').length,
bottom = 15,
top = bottom - lines - 2;
Ox.range(inPoint, outPoint).forEach(function(x) {
Ox.range(top, bottom).forEach(function(y) {
var color = (y == top || y == bottom - 1) ? [0, 0, 0] : [255, 255, 255],
index = x * 4 + y * 4 * width;
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = 128
});
});
});
context.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
function getTimelineImageURL(callback) {
var height = 16,
images = Math.ceil(self.options.duration / 3600),
loaded = 0,
width = Math.ceil(self.options.duration),
$canvas = $('<canvas>')
.attr({
height: height,
width: width
}),
canvas = $canvas[0],
context = canvas.getContext('2d');
Ox.range(images).forEach(function(i) {
var $img = $('<img>')
.attr({
src: '/' + self.options.videoId + '/timelines/timeline.16.' + i + '.png'
})
.load(function() {
context.drawImage($img[0], i * 3600, 0);
//Ox.print('loaded, images', loaded, images, $img[0])
if (++loaded == images) {
//Ox.print('callback', canvas.toDataURL().length)
callback(canvas.toDataURL());
}
});
});
}
function mousedown(e) {
var $target = $(e.target);
if (
$target.hasClass('OxTimelineSmallImage') ||
$target.hasClass('OxTimelineSmallSubtitles') ||
$target.hasClass('OxTimelineSmallSelection')
) {
self.options.position = getPosition(e);
setPosition();
that.triggerEvent('change', {
position: self.options.position
});
}
e.preventDefault();
}
function mouseleave(e) {
self.$tooltip.hide();
}
function mousemove(e) {
var $target = $(e.target),
position,
subtitle;
if (
$target.hasClass('OxTimelineSmallImage') ||
$target.hasClass('OxTimelineSmallSubtitles') ||
$target.hasClass('OxTimelineSmallSelection')
) {
position = getPosition(e),
subtitle = getSubtitle(position);
self.$tooltip.options({
title: subtitle ?
'<span class=\'OxBright\'>' +
Ox.highlight(subtitle.value, self.options.find).replace(/\n/g, '<br/>') + '</span><br/>' +
Ox.formatDuration(subtitle['in'], 3) + ' - ' + Ox.formatDuration(subtitle['out'], 3) :
Ox.formatDuration(position, 3)
})
.show(e.clientX, e.clientY);
} else {
self.$tooltip.hide();
}
}
function setMarker() {
self.$markerPosition
.css({
left: (self.options.position % self.options.width) + 'px',
top: (parseInt(self.options.position / self.options.width) * (self.height + self.margin) + 2) + 'px',
});
}
function setMarkerPoint(i) {
var position = Math.round(self.options.points[i]);
self.$markerPoint[i]
.css({
left: (position % self.options.width) + 'px',
top: (parseInt(position / self.options.width) * (self.height + self.margin) + 16) + 'px',
});
}
function setPosition() {
self.options.position = Ox.limit(self.options.position, 0, self.options.duration);
setMarker();
}
function setWidth() {
self.lines = Math.ceil(self.options.duration / self.options.width);
that.css({
width: (self.options.width + self.margin) + 'px',
height: ((self.height + self.margin) * self.lines + 4) + 'px'
});
Ox.range(self.lines).forEach(function(i) {
if (self.$lines[i]) {
self.$lines[i].css({
width: self.options.width + 'px'
});
self.$images[i].css({
marginLeft: (-i * self.options.width) + 'px'
});
if (self.hasSubtitles) {
self.$subtitles[i].css({
marginLeft: (-i * self.options.width) + 'px'
});
}
} else {
addLine(i);
}
});
while (self.$lines.length > self.lines) {
self.$lines[self.$lines.length - 1].removeElement();
self.$lines.pop();
}
setMarker();
setMarkerPoint(0);
setMarkerPoint(1);
}
function updateSelection() {
self.$lines.forEach(function($line, i) {
addSelection(i);
});
}
self.onChange = function(key, value) {
//Ox.print('onChange:', key, value)
if (key == 'points') {
//Ox.print('key', key, 'value', value)
setMarkerPoint(0);
setMarkerPoint(1);
updateSelection()
} else if (key == 'position') {
setPosition();
} else if (key == 'width') {
setWidth();
}
};
return that;
};

163
source/js/Ox.Button.js Normal file
View file

@ -0,0 +1,163 @@
Ox.Button = function(options, self) {
/**
methods:
toggleDisabled enable/disable button
toggleSelected select/unselect button
toggleTitle if more than one title was provided,
toggle to next title.
events:
click non-selectable button was clicked
deselect selectable button was deselected
select selectable button was selected
*/
var self = self || {},
that = new Ox.Element('input', self)
.defaults({
disabled: false,
group: false,
id: '',
overlap: 'none',
selectable: false,
selected: false,
size: 'medium',
// fixme: 'default' or ''?
style: 'default', // can be default, checkbox, symbol, or tab
title: '',
tooltip: '',
type: 'text',
width: 'auto'
})
.options(options || {})
.attr({
disabled: self.options.disabled ? 'disabled' : '',
type: self.options.type == 'text' ? 'button' : 'image'
})
.addClass('OxButton Ox' + Ox.toTitleCase(self.options.size) +
(self.options.disabled ? ' OxDisabled': '') +
(self.options.selected ? ' OxSelected': '') +
(self.options.style != 'default' ? ' Ox' + Ox.toTitleCase(self.options.style) : '') +
(self.options.overlap != 'none' ? ' OxOverlap' + Ox.toTitleCase(self.options.overlap) : ''))
.css(self.options.width == 'auto' ? {} : {
width: (self.options.width - 14) + 'px'
})
.mousedown(mousedown)
.click(click);
$.extend(self, Ox.isArray(self.options.title) ? {
selectedTitle: Ox.setPropertyOnce(self.options.title, 'selected'),
titles: self.options.title
} : {
selectedTitle: 0,
titles: [{
id: '',
title: self.options.title
}]
});
setTitle(self.titles[self.selectedTitle].title);
if (self.options.tooltip) {
self.tooltips = Ox.isArray(self.options.tooltip) ? self.options.tooltip : [self.options.tooltip];
self.$tooltip = new Ox.Tooltip({
title: self.tooltips[self.selectedTitle]
});
that.mouseenter(mouseenter)
.mouseleave(mouseleave);
}
function click() {
if (!self.options.disabled) {
var data = self.titles[self.selectedTitle];
if (!self.options.selectable) {
that.triggerEvent('click', data);
} else {
//self.options.selected = !self.options.selected;
//that.toggleClass('OxSelected');
if (self.options.group) {
that.triggerEvent('select', data);
} else {
that.toggleSelected();
//that.triggerEvent('change', {selected: self.options.selected});
}
}
if (self.titles.length == 2) {
that.toggleTitle();
}
}
}
function mousedown(e) {
if (self.options.type == 'image' && $.browser.safari) {
// keep image from being draggable
e.preventDefault();
}
}
function mouseenter(e) {
self.$tooltip.show(e.clientX, e.clientY);
}
function mouseleave() {
self.$tooltip.hide();
}
function setTitle(title) {
self.title = title;
if (self.options.type == 'image') {
that.attr({
src: Ox.UI.getImagePath(
'symbol' + title[0].toUpperCase() + title.substr(1) + '.svg'
)
});
} else {
that.val(title);
}
}
self.onChange = function(key, value) {
if (key == 'disabled') {
that.attr({
disabled: value ? 'disabled' : ''
})
.toggleClass('OxDisabled');
} else if (key == 'selected') {
if (value != that.hasClass('OxSelected')) { // fixme: neccessary?
that.toggleClass('OxSelected');
}
that.triggerEvent('change');
} else if (key == 'title') {
setTitle(value);
} else if (key == 'width') {
that.$element.css({
width: (value - 14) + 'px'
});
}
}
that.toggleDisabled = function() {
that.options({
enabled: !self.options.disabled
});
//self.options.disabled = !self.options.disabled;
}
that.toggleSelected = function() {
that.options({
selected: !self.options.selected
});
//self.options.selected = !self.options.selected;
}
that.toggleTitle = function() {
self.selectedTitle = 1 - self.selectedTitle;
setTitle(self.titles[self.selectedTitle].title);
self.$tooltip && self.$tooltip.options({
title: self.tooltips[self.selectedTitle]
});
}
return that;
};

View file

@ -0,0 +1,74 @@
Ox.ButtonGroup = function(options, self) {
/**
options
buttons array of buttons
max integer, maximum number of selected buttons, 0 for all
min integer, minimum number of selected buttons, 0 for none
selectable if true, buttons are selectable
type string, 'image' or 'text'
methods:
events:
change {id, value} selection within a group changed
*/
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
buttons: [],
max: 1,
min: 1,
selectable: false,
size: 'medium',
style: '',
type: 'text',
})
.options(options || {})
.addClass('OxButtonGroup');
if (self.options.selectable) {
self.optionGroup = new Ox.OptionGroup(
self.options.buttons,
self.options.min,
self.options.max,
'selected'
);
self.options.buttons = self.optionGroup.init();
}
self.$buttons = [];
self.options.buttons.forEach(function(button, position) {
var id = self.options.id + Ox.toTitleCase(button.id)
self.$buttons[position] = Ox.Button({
disabled: button.disabled,
group: true,
id: id,
selectable: self.options.selectable,
selected: button.selected,
size: self.options.size,
style: self.options.style,
title: button.title,
type: self.options.type
})
.bindEvent('select', function() {
selectButton(position);
})
.appendTo(that);
});
function selectButton(pos) {
var toggled = self.optionGroup.toggle(pos);
if (toggled.length) {
toggled.forEach(function(pos, i) {
self.$buttons[pos].toggleSelected();
});
that.triggerEvent('change', {
selected: $.map(self.optionGroup.selected(), function(v, i) {
return self.options.buttons[v].id;
})
});
}
}
return that;
};

711
source/js/Ox.Calendar.js Normal file
View file

@ -0,0 +1,711 @@
Ox.Calendar = function(options, self) {
self = self || {};
var that = new Ox.Element({}, self)
.defaults({
date: new Date(),
dates: [],
height: 512,
range: [100, 5101],
width: 512,
zoom: 8
})
.options(options || {})
.addClass('OxCalendar')
.css({
width: self.options.width + 'px',
height: self.options.height + 'px'
});
self.maxZoom = 32;
self.minLabelWidth = 80;
self.overlayWidths = [Math.round(self.options.width / 16)];
self.overlayWidths = [
Math.floor((self.options.width - self.overlayWidths[0]) / 2),
self.overlayWidths[0],
Math.ceil((self.options.width - self.overlayWidths[0]) / 2),
];
self.units = [
{
id: 'millennium',
seconds: 365242.5 * 86400,
date: function(i) {
return new Date((i + 1) + '000');
},
name: function(i) {
return Ox.formatOrdinal(i + 2) + ' millennium';
},
value: function(date) {
return Math.floor(date.getFullYear() / 1000) - 1;
}
},
{
id: 'century',
seconds: 36524.25 * 86400,
date: function(i) {
return new Date((i + 19) + '00');
},
name: function(i) {
return Ox.formatOrdinal(i + 20) + ' century';
},
value: function(date) {
return Math.floor(date.getFullYear() / 100) - 19;
}
},
{
id: 'decade',
seconds: 3652.425 * 86400,
date: function(i) {
return (i + 197) + '0'
},
name: function(i) {
return (i + 197) + '0s'
},
value: function(date) {
return Math.floor(date.getFullYear() / 10) - 197;
}
},
{
id: 'year',
seconds: 365.2425 * 86400,
date: function(i) {
return (i + 1970) + '';
},
name: function(i) {
return (i + 1970) + '';
},
value: function(date) {
return date.getFullYear() - 1970;
}
},
{
id: 'month',
seconds: 365.2425 / 12 * 86400,
date: function(i) {
return (Math.floor(i / 12) + 1970) + '-' + (Ox.mod(i, 12) + 1);
},
name: function(i) {
return Ox.SHORT_MONTHS[Ox.mod(i, 12)] + ' ' + Math.floor(i / 12 + 1970)
},
value: function(date) {
return (date.getFullYear() - 1970) * 12 + date.getMonth();
}
},
{
id: 'week',
seconds: 7 * 86400,
date: function(i) {
return (i * 7 - 3) * 86400000;
},
name: function(i) {
return Ox.formatDate(new Date((i * 7 - 3) * 86400000), '%a, %b %e');
},
value: function(date) {
return Math.floor((+date / 86400000 + 4) / 7);
}
},
{
id: 'day',
seconds: 86400,
date: function(i) {
// adjust for timezone difference
// fixme: may still be off
return i * 86400000 + Ox.TIMEZONE_OFFSET;
},
name: function(i) {
return Ox.formatDate(new Date(i * 86400000), '%b %e, %Y');
},
value: function(date) {
return Math.floor(date / 86400000);
}
},
{
id: 'six_hours',
seconds: 21600,
date: function(i) {
return i * 21600000 + Ox.TIMEZONE_OFFSET;
},
name: function(i) {
return Ox.formatDate(new Date(i * 21600000 + Ox.TIMEZONE_OFFSET), '%b %e, %H:00');
},
value: function(date) {
return Math.floor((date - Ox.TIMEZONE_OFFSET) / 21600000);
}
},
{
id: 'hour',
seconds: 3600,
date: function(i) {
return i * 3600000;
},
name: function(i) {
return Ox.formatDate(new Date(i * 3600000), '%b %e, %H:00');
},
value: function(date) {
return Math.floor(date / 3600000);
}
},
{
id: 'five_minutes',
seconds: 300,
date: function(i) {
return i * 300000;
},
name: function(i) {
return Ox.formatDate(new Date(i * 300000), '%b %e, %H:%M');
},
value: function(date) {
return Math.floor(date / 300000);
}
},
{
id: 'minute',
seconds: 60,
date: function(i) {
return i * 60000;
},
name: function(i) {
return Ox.formatDate(new Date(i * 60000), '%b %e, %H:%M');
},
value: function(date) {
return Math.floor(date / 60000);
}
},
{
id: 'five_seconds',
seconds: 5,
date: function(i) {
return i * 5000;
},
name: function(i) {
return Ox.formatDate(new Date(i * 5000), '%H:%M:%S');
},
value: function(date) {
return Math.floor(date / 5000);
}
},
{
id: 'second',
seconds: 1,
date: function(i) {
return i * 1000;
},
name: function(i) {
return Ox.formatDate(new Date(i * 1000), '%H:%M:%S');
},
value: function(date) {
return Math.floor(date / 1000);
}
}
];
self.$container = new Ox.Element()
.addClass('OxCalendarContainer')
.css({
top: '24px',
bottom: '40px'
})
.bind({
mouseleave: mouseleave,
mousemove: mousemove,
mousewheel: mousewheel
})
.bindEvent({
doubleclick: doubleclick,
dragstart: dragstart,
drag: drag,
dragpause: dragpause,
dragend: dragend,
singleclick: singleclick
})
.appendTo(that);
self.$content = new Ox.Element()
.addClass('OxCalendarContent')
.appendTo(self.$container);
self.$background = new Ox.Element()
.addClass('OxBackground')
.appendTo(self.$content);
self.$scalebar = new Ox.Element()
.addClass('OxTimeline')
.css({
posision: 'absolute',
})
.appendTo(self.$content);
self.$scrollbar = new Ox.Element()
.addClass('OxTimeline')
.css({
posision: 'absolute',
bottom: '40px'
})
.appendTo(that);
self.$overlay = new Ox.Element()
.addClass('OxOverlay')
.css({
bottom: '40px'
})
.append(
$('<div>').css({
width: self.overlayWidths[0] + 'px'
})
)
.append(
$('<div>').css({
left: self.overlayWidths[0] + 'px',
width: self.overlayWidths[1] + 'px'
})
)
.append(
$('<div>').css({
left: (self.overlayWidths[0] + self.overlayWidths[1]) + 'px',
width: self.overlayWidths[2] + 'px'
})
)
.bindEvent({
dragstart: dragstartScrollbar,
drag: dragScrollbar,
dragpause: dragpauseScrollbar,
dragend: dragendScrollbar
})
.appendTo(that);
self.$zoombar = new Ox.Element()
.css({
position: 'absolute',
bottom: 24 + 'px',
height: '16px'
})
.appendTo(that);
self.$zoomInput = new Ox.Range({
arrows: true,
max: self.maxZoom,
min: 0,
size: self.options.width,
thumbSize: 32,
thumbValue: true,
value: self.options.zoom
})
.bindEvent({
change: changeZoom
})
.appendTo(self.$zoombar);
self.$statusbar = new Ox.Bar({
size: 24
})
.css({
// fixme: no need to set position absolute with map statusbar
position: 'absolute',
bottom: 0,
textAlign: 'center'
})
.appendTo(that);
self.$tooltip = new Ox.Tooltip({
animate: false
})
.css({
textAlign: 'center'
});
renderCalendar();
function changeDate() {
}
function changeZoom(event, data) {
self.options.zoom = data.value;
renderCalendar();
}
function doubleclick(event, e) {
if ($(e.target).is(':not(.OxLine > .OxDate)')) {
if (self.options.zoom < self.maxZoom) {
self.options.date = new Date(
(+self.options.date + +getMouseDate(e)) / 2
);
self.options.zoom++;
}
renderCalendar();
}
}
function dragstart(event, e) {
if ($(e.target).is(':not(.OxLine > .OxDate)')) {
self.drag = {x: e.clientX};
}
}
function drag(event, e) {
if (self.drag) {
///*
self.$content.css({
marginLeft: (e.clientX - self.drag.x) + 'px'
});
self.$scrollbar.css({
marginLeft: Math.round((e.clientX - self.drag.x) / 16) + 'px'
});
//*/
/*
self.options.date = new Date(
+self.options.date - e.clientDX * getSecondsPerPixel() * 1000
);
*/
//self.drag = {x: e.clientX};
}
}
function dragpause(event, e) {
if (self.drag) {
dragafter(e);
self.drag = {x: e.clientX};
}
}
function dragend(event, e) {
if (self.drag) {
dragafter(e);
self.drag = null;
}
}
function dragafter(e) {
self.options.date = new Date(
+self.options.date - (e.clientX - self.drag.x) * getSecondsPerPixel() * 1000
);
self.$content.css({
marginLeft: 0
});
self.$scrollbar.css({
marginLeft: 0
});
renderCalendar();
}
function dragstartScrollbar(event, e) {
self.drag = {x: e.clientX};
}
function dragScrollbar(event, e) {
self.$content.css({
marginLeft: ((e.clientX - self.drag.x) * 16) + 'px'
});
self.$scrollbar.css({
marginLeft: (e.clientX - self.drag.x) + 'px'
});
}
function dragpauseScrollbar(event, e) {
dragafterScrollbar(e);
self.drag = {x: e.clientX};
}
function dragendScrollbar(event, e) {
dragafterScrollbar(e);
self.drag = null;
}
function dragafterScrollbar(e) {
self.options.date = new Date(
+self.options.date + (self.drag.x - e.clientX) * getSecondsPerPixel() * 1000 * 16
);
// fixme: duplicated
self.$content.css({
marginLeft: 0
});
self.$scrollbar.css({
marginLeft: 0
});
renderCalendar();
}
function formatDate(date) {
var isFullDays = Ox.formatDate(date.start, '%H:%M:%S') == '00:00:00' &&
Ox.formatDate(date.stop, '%H:%M:%S') == '00:00:00',
isOneDay = isFullDays && date.stop - date.start == 86400000, // fixme: wrong, DST
isSameDay = Ox.formatDate(date.start, '%Y-%m-%d') ==
Ox.formatDate(date.stop, '%Y-%m-%d'),
isSameYear = date.start.getFullYear() == date.stop.getFullYear(),
timeFormat = isFullDays ? '' : ', %H:%M:%S',
str = Ox.formatDate(date.start, '%a, %b %e');
if (isOneDay || isSameDay || !isSameYear) {
str += Ox.formatDate(date.start, ', %Y' + timeFormat);
}
if (!isOneDay && !isSameDay) {
str += Ox.formatDate(date.stop, ' - %a, %b %e, %Y' + timeFormat);
}
if (isSameDay) {
str += Ox.formatDate(date.stop, ' - ' + timeFormat.replace(', ', ''));
}
return str;
}
function getCalendarDate() {
var ms = self.options.width * getSecondsPerPixel() * 1000;
return {
start: new Date(+self.options.date - ms / 2),
stop: new Date(+self.options.date + ms / 2)
};
}
function getDateByName(name) {
var date = {};
Ox.forEach(self.options.dates, function(v) {
if (v.name == name) {
date = v;
return false;
}
});
return date;
}
function getDateElement(date, zoom) {
var left = getPosition(date.start, zoom),
width = Math.max(getPosition(date.stop, zoom) - left, 1);
return new Ox.Element()
.addClass('OxDate')
.css({
left: left + 'px',
width: width + 'px'
})
.data({
name: date.name
})
.html('&nbsp;' + date.name);
}
function getMouseDate(e) {
return new Date(+self.options.date + (
e.clientX - that.offset().left - self.options.width / 2 - 1
) * getSecondsPerPixel() * 1000);
}
function getPixelsPerSecond(zoom) {
return Math.pow(2, (zoom || self.options.zoom) - (self.maxZoom - 4));
}
function getPosition(date, zoom) {
return Math.round(
self.options.width / 2 +
(date - self.options.date) / 1000 *
getPixelsPerSecond(zoom || self.options.zoom)
);
}
function getSecondsPerPixel(zoom) {
return 1 / getPixelsPerSecond(zoom);
}
function getBackgroundElements(zoom) {
// fixme: duplicated
var $elements = [],
units = getUnits(zoom),
n, value, width;
[1, 0].forEach(function(u) {
var unit = units[u],
value = unit.value(self.options.date),
width = unit.seconds * getPixelsPerSecond(zoom),
n = Math.ceil(self.options.width * 1.5/* * 16*/ / width);
Ox.loop(-n, n + 1, function(i) {
$elements.push(
new Ox.Element()
.addClass(
u == 0 ? 'line' : Ox.mod(value + i, 2) == 0 ? 'even' : 'odd'
)
.css({
left: getPosition(new Date(unit.date(value + i)), zoom) + 'px',
width: (u == 0 ? 1 : width) + 'px'
})
);
});
});
return $elements;
}
function getTimelineElements(zoom) {
var $elements = [],
unit = getUnits(zoom)[0],
value = unit.value(self.options.date),
width = unit.seconds * getPixelsPerSecond(zoom);
n = Math.ceil(self.options.width * 1.5/* * 16*/ / width);
Ox.loop(-n, n + 1, function(i) {
$elements.push(
getDateElement({
name: unit.name(value + i),
start: new Date(unit.date(value + i)),
stop: new Date(unit.date(value + i + 1))
}, zoom)
.addClass(Ox.mod(value + i, 2) == 0 ? 'even' : 'odd')
);
});
return $elements;
}
function getUnits(zoom) {
// returns array of 2 units
// units[0] for timeline
// units[1] for background
var pixelsPerSecond = getPixelsPerSecond(zoom),
units;
self.units = self.units.reverse();
Ox.forEach(self.units, function(v, i) {
width = Math.round(v.seconds * pixelsPerSecond);
if (width >= self.minLabelWidth) {
units = [self.units[i], self.units[i - 1]];
return false;
}
});
self.units = self.units.reverse();
return units;
}
function mouseleave() {
self.$tooltip.hide();
}
function mousemove(e) {
var $target = $(e.target),
date, title;
if ($target.is('.OxLine > .OxDate')) {
date = getDateByName($target.data('name'));
title = '<span class="OxBright">' + date.name + '</span><br/>' +
formatDate(date);
} else {
title = Ox.formatDate(getMouseDate(e), '%a, %b %e, %Y, %H:%M:%S');
}
self.$tooltip.options({
title: title
})
.show(e.clientX, e.clientY);
}
function mousewheel(e, delta, deltaX, deltaY) {
//Ox.print('mousewheel', delta, deltaX, deltaY);
var deltaZ = 0;
if (!self.mousewheel && deltaY && Math.abs(deltaY) > Math.abs(deltaX)) {
if (deltaY < 0 && self.options.zoom > 0) {
deltaZ = -1
} else if (deltaY > 0 && self.options.zoom < self.maxZoom) {
deltaZ = 1
}
if (deltaZ) {
self.options.date = deltaZ == -1 ?
new Date(2 * +self.options.date - +getMouseDate(e)) :
new Date((+self.options.date + +getMouseDate(e)) / 2)
self.options.zoom += deltaZ;
self.$zoomInput.options({value: self.options.zoom});
renderCalendar();
}
}
self.mousewheel = true;
setTimeout(function() {
self.mousewheel = false;
}, 250);
}
function overlaps(date0, date1) {
return (
date0.start >= date1.start && date0.start < date1.stop
) || (
date1.start >= date0.start && date1.start < date0.stop
);
}
function renderCalendar() {
$('.OxBackground').empty();
$('.OxDate').remove();
renderBackground();
renderTimelines();
renderDates();
self.$statusbar.html(
Ox.formatDate(self.options.date, '%Y-%m-%d %H:%M:%S %s')
);
}
function renderBackground() {
getBackgroundElements(self.options.zoom).forEach(function($element) {
$element.appendTo(self.$background);
});
}
function renderDates() {
var calendarDate = getCalendarDate();
lineDates = [];
self.options.dates.filter(function(date) {
// filter out dates outside the visible area
return overlaps(date, calendarDate);
}).sort(function(a, b) {
// sort dates by duration, descending
return (b.stop - b.start) - (a.stop - a.start);
}).forEach(function(date, i) {
var line = lineDates.length;
// traverse lines
Ox.forEach(lineDates, function(dates, line_) {
var fits = true;
// traverse dates in line
Ox.forEach(dates, function(date_) {
// if overlaps, check next line
if (overlaps(date, date_)) {
fits = false;
return false;
}
});
if (fits) {
line = line_;
return false;
}
});
if (line == lineDates.length) {
lineDates[line] = [];
}
lineDates[line].push(date);
});
$('.OxLine').remove();
lineDates.forEach(function(dates, line) {
var $line = new Ox.Element()
.addClass('OxLine')
.css({
top: ((line + 1) * 16) + 'px'
})
.appendTo(self.$content);
dates.sort(function(a, b) {
// sort dates by start, ascending
return a.start - b.start;
}).forEach(function(date) {
getDateElement(date).appendTo($line);
});
});
}
function renderTimelines() {
Ox.print(self.options.zoom, Math.max(self.options.zoom - 4, 0))
getTimelineElements(self.options.zoom).forEach(function($element) {
$element.appendTo(self.$scalebar.$element);
});
getTimelineElements(Math.max(self.options.zoom - 4, 0)).forEach(function($element) {
$element.appendTo(self.$scrollbar.$element);
});
}
function singleclick(event, e) {
if ($(e.target).is(':not(.OxLine > .OxDate)')) {
self.options.date = getMouseDate(e);
renderCalendar();
}
}
self.onChange = function(key, val) {
if (key == 'date') {
} else if (key == 'zoom') {
}
};
return that;
};

View file

@ -0,0 +1,25 @@
Ox.CalendarDate = function(options) {
var self = {},
that = this;
['start', 'stop'].forEach(function(v) {
var date = self.options[v];
if (Ox.isString(date)) {
date = new Date(self.options[v]);
}
});
self.duration = self.options.stop - self.options.start;
that.format = function() {
};
that.formatDuration = function() {
};
return that;
};

104
source/js/Ox.Checkbox.js Normal file
View file

@ -0,0 +1,104 @@
Ox.Checkbox = function(options, self) {
/**
options
disabled boolean, if true, checkbox is disabled
id element id
group boolean, if true, checkbox is part of a group
checked boolean, if true, checkbox is checked
title string, text on label
width integer, width in px
methods:
toggleChecked function()
toggles checked property
returns that
events:
change triggered when checked property changes
passes {checked, id, title}
*/
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
disabled: false,
id: '',
group: false,
checked: false,
overlap: 'none',
title: '',
width: 'auto'
})
.options(options || {})
.addClass('OxCheckbox' +
(self.options.overlap == 'none' ? '' : ' OxOverlap' +
Ox.toTitleCase(self.options.overlap))
)
.attr(self.options.disabled ? {
disabled: 'disabled'
} : {});
if (self.options.title) {
self.options.width != 'auto' && that.css({
width: self.options.width + 'px'
});
self.$title = new Ox.Label({
disabled: self.options.disabled,
id: self.options.id + 'Label',
overlap: 'left',
title: self.options.title,
width: self.options.width - 16
})
.css({
float: 'right'
})
.click(clickTitle)
.appendTo(that);
}
self.$button = new Ox.Button({
disabled: self.options.disabled,
id: self.options.id + 'Button',
title: [
{id: 'none', title: 'none', selected: !self.options.checked},
{id: 'check', title: 'check', selected: self.options.checked}
],
type: 'image'
})
.addClass('OxCheckbox')
.click(clickButton)
.appendTo(that);
function clickButton() {
self.options.checked = !self.options.checked;
// click will have toggled the button,
// if it is part of a group, we have to revert that
self.options.group && that.toggleChecked();
that.triggerEvent('change', {
checked: self.options.checked,
id: self.options.id,
title: self.options.title
});
}
function clickTitle() {
!self.options.disabled && self.$button.trigger('click');
}
self.onChange = function(key, value) {
if (key == 'checked') {
that.toggleChecked();
}
};
that.checked = function() {
return self.options.checked;
}
that.toggleChecked = function() {
self.$button.toggleTitle();
return that;
}
return that;
};

View file

@ -0,0 +1,70 @@
Ox.CheckboxGroup = function(options, self) {
/**
options
checkboxes [] array of checkboxes
max 1 integer
min 1 integer
width integer, width in px
events:
change triggered when checked property changes
passes {checked, id, title}
*/
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
checkboxes: [],
max: 1,
min: 1,
width: 256
})
.options(options || {})
.addClass('OxCheckboxGroup');
self.optionGroup = new Ox.OptionGroup(
self.options.checkboxes,
self.options.min,
self.options.max);
self.options.checkboxes = self.optionGroup.init();
$.extend(self, {
$checkboxes: [],
checkboxWidth: $.map(Ox.divideInt(
self.options.width + (self.options.checkboxes.length - 1) * 6,
self.options.checkboxes.length
), function(v, i) {
return v + (i < self.options.checkboxes.length - 1 ? 10 : 0);
})
});
self.options.checkboxes.forEach(function(checkbox, position) {
var id = self.options.id + Ox.toTitleCase(checkbox.id)
self.$checkboxes[position] = new Ox.Checkbox($.extend(checkbox, {
group: true,
id: id,
width: self.checkboxWidth[position]
}))
.bindEvent('change', function() {
change(position);
})
.appendTo(that);
});
function change(pos) {
var toggled = self.optionGroup.toggle(pos);
//Ox.print('change', pos, 'toggled', toggled)
if (toggled.length) {
toggled.forEach(function(pos, i) {
self.$checkboxes[pos].toggleChecked();
});
that.triggerEvent('change', {
checked: $.map(self.optionGroup.checked(), function(v, i) {
return self.options.checkboxes[v].id;
})
});
}
}
return that;
};

22
source/js/Ox.Clipboard.js Normal file
View file

@ -0,0 +1,22 @@
Ox.Clipboard = function() {
/***
Ox.Clipboard
Basic clipboard handler
Methods
copy(data) copy data to clipboard
paste paste data from clipboard
***/
var clipboard = {};
return {
_print: function() {
Ox.print(JSON.stringify(clipboard));
},
copy: function(data) {
clipboard = data;
Ox.print('copy', JSON.stringify(clipboard));
},
paste: function(type) {
return clipboard;
}
};
}();

View file

@ -0,0 +1,83 @@
/**
*/
Ox.CollapsePanel = function(options, self) {
var self = self || {},
that = new Ox.Panel({}, self)
.defaults({
collapsed: false,
extras: [],
size: 16,
title: ''
})
.options(options)
.addClass('OxCollapsePanel'),
// fixme: the following should all be self.foo
title = self.options.collapsed ?
[{id: 'expand', title: 'right'}, {id: 'collapse', title: 'down'}] :
[{id: 'collapse', title: 'down'}, {id: 'expand', title: 'right'}],
$titlebar = new Ox.Bar({
orientation: 'horizontal',
size: self.options.size,
})
.dblclick(dblclickTitlebar)
.appendTo(that),
$switch = new Ox.Button({
style: 'symbol',
title: title,
type: 'image',
})
.click(toggleCollapsed)
.appendTo($titlebar),
$title = new Ox.Element()
.addClass('OxTitle')
.html(self.options.title/*.toUpperCase()*/)
.appendTo($titlebar),
$extras;
if (self.options.extras.length) {
$extras = new Ox.Element()
.addClass('OxExtras')
.appendTo($titlebar);
self.options.extras.forEach(function($extra) {
$extra.appendTo($extras);
});
}
that.$content = new Ox.Element()
.addClass('OxContent')
.appendTo(that);
// fixme: doesn't work, content still empty
// need to hide it if collapsed
if (self.options.collapsed) {
that.$content.css({
marginTop: -that.$content.height() + 'px'
});
}
function dblclickTitlebar(e) {
if (!$(e.target).hasClass('OxButton')) {
$switch.trigger('click');
}
}
function toggleCollapsed() {
var marginTop;
self.options.collapsed = !self.options.collapsed;
marginTop = self.options.collapsed ? -that.$content.height() : 0;
that.$content.animate({
marginTop: marginTop + 'px'
}, 200);
that.triggerEvent('toggle', {
collapsed: self.options.collapsed
});
}
self.onChange = function(key, value) {
if (key == 'collapsed') {
} else if (key == 'title') {
$title.html(self.options.title);
}
};
that.update = function() { // fixme: used anywhere?
self.options.collapsed && that.$content.css({
marginTop: -that.$content.height()
});
};
return that;
};

View file

@ -0,0 +1,71 @@
Ox.ColorInput = function(options, self) {
var self = $.extend(self || {}, {
options: $.extend({
id: '',
value: '0, 0, 0'
}, options)
}),
that;
self.values = self.options.value.split(', ');
self.$inputs = [];
['red', 'green', 'blue'].forEach(function(v, i) {
self.$inputs[i] = new Ox.Input({
id: v,
max: 255,
type: 'integer',
value: self.values[i],
width: 36
})
.bindEvent('autovalidate', change);
});
self.$inputs[3] = new Ox.Label({
id: 'color',
width: 36
})
.css({
background: 'rgb(' + self.options.value + ')'
});
self.$inputs[4] = new Ox.ColorPicker({
id: 'picker'
})
.bindEvent('change', function(event, data) {
//Ox.print('change function called');
self.options.value = data.value;
self.values = data.value.split(', ');
Ox.range(3).forEach(function(i) {
self.$inputs[i].options({
value: self.values[i]
});
});
})
.options({
width: 16 // this is just a hack to make the InputGroup layout work
});
that = new Ox.InputGroup({
id: self.options.id,
inputs: self.$inputs,
separators: [
{title: ',', width: 8},
{title: ',', width: 8},
{title: '', width: 8},
{title: '', width: 8}
],
value: self.options.value // fixme: it'd be nicer if this would be taken care of by passing self
}, self)
.bindEvent('change', change);
function change() {
self.options.value = $.map(self.$inputs, function(v, i) {
return v.options('value');
}).join(', ');
self.$inputs[3].css({
background: 'rgb(' + self.options.value + ')'
});
}
return that;
};

View file

@ -0,0 +1,91 @@
Ox.ColorPicker = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
id: '',
value: '0, 0, 0'
})
.options(options || {});
//Ox.print(self)
self.$ranges = [];
self.rgb = ['red', 'green', 'blue'];
self.values = self.options.value.split(', ');
Ox.range(3).forEach(function(i) {
self.$ranges[i] = new Ox.Range({
arrows: true,
id: self.options.id + Ox.toTitleCase(self.rgb[i]),
max: 255,
size: 328, // 256 + 16 + 40 + 16
thumbSize: 40,
thumbValue: true,
trackColors: getColors(i),
value: self.values[i]
})
.css({
position: 'absolute',
top: (i * 15) + 'px'
})
.bindEvent('change', function(event, data) {
change(i, data.value);
})
.appendTo(that);
// fixme: make self.$ranges[i].children() work
if (i == 0) {
self.$ranges[i].$element.children('input.OxOverlapRight').css({
MozBorderRadius: 0,
WebkitBorderRadius: 0
});
self.$ranges[i].$element.children('input.OxOverlapLeft').css({
MozBorderRadius: '0 8px 0 0',
WebkitBorderRadius: '0 8px 0 0'
});
} else {
self.$ranges[i].$element.children('input').css({
MozBorderRadius: 0,
WebkitBorderRadius: 0
});
}
});
that = new Ox.Picker({
element: that,
elementHeight: 46,
elementWidth: 328,
id: self.options.id
});
function change(index, value) {
self.values[index] = value;
self.options.value = self.values.join(', ');
that.$label.css({
background: 'rgb(' + self.options.value + ')'
});
Ox.range(3).forEach(function(i) {
if (i != index) {
self.$ranges[i].options({
trackColors: getColors(i)
});
}
});
that.triggerEvent('change', {
value: self.options.value
});
}
function getColors(index) {
return [
'rgb(' + $.map(Ox.range(3), function(v) {
return v == index ? 0 : self.values[v];
}).join(', ') + ')',
'rgb(' + $.map(Ox.range(3), function(v) {
return v == index ? 255 : self.values[v];
}).join(', ') + ')'
]
}
return that;
};

16
source/js/Ox.Container.js Normal file
View file

@ -0,0 +1,16 @@
// fixme: wouldn't it be better to let the elements be,
// rather then $element, $content, and potentially others,
// 0, 1, 2, etc, so that append would append 0, and appendTo
// would append (length - 1)?
Ox.Container = function(options, self) {
// fixme: to be deprecated
var that = new Ox.Element('div', self)
.options(options || {})
.addClass('OxContainer');
that.$content = new Ox.Element('div', self)
.options(options || {})
.addClass('OxContent')
.appendTo(that);
return that;
};

217
source/js/Ox.DateInput.js Normal file
View file

@ -0,0 +1,217 @@
Ox.DateInput = function(options, self) {
/**
options:
format: 'short'
value: date value
weekday: false
width: {
day: 32,
month: options.format == 'long' ? 80 : (options.format == 'medium' ? 40 : 32),
weekday: options.format == 'long' ? 80 : 40,
year: 48
}
*/
var self = $.extend(self || {}, {
options: $.extend({
format: 'short',
value: Ox.formatDate(new Date(), '%F'),
weekday: false,
width: {
day: 32,
month: options.format == 'long' ? 80 : (options.format == 'medium' ? 40 : 32),
weekday: options.format == 'long' ? 80 : 40,
year: 48
}
}, options)
}),
that;
$.extend(self, {
date: new Date(self.options.value.replace(/-/g, '/')),
formats: {
day: '%d',
month: self.options.format == 'short' ? '%m' :
(self.options.format == 'medium' ? '%b' : '%B'),
weekday: self.options.format == 'long' ? '%A' : '%a',
year: '%Y'
},
months: self.options.format == 'long' ? Ox.MONTHS : $.map(Ox.MONTHS, function(v, i) {
return v.substr(0, 3);
}),
weekdays: self.options.format == 'long' ? Ox.WEEKDAYS : $.map(Ox.WEEKDAYS, function(v, i) {
return v.substr(0, 3);
})
});
self.$input = $.extend(self.options.weekday ? {
weekday: new Ox.Input({
autocomplete: self.weekdays,
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'weekday',
value: Ox.formatDate(self.date, self.formats.weekday),
width: self.options.width.weekday
})
.bindEvent('autocomplete', changeWeekday),
} : {}, {
day: new Ox.Input({
autocomplete: $.map(Ox.range(1, Ox.getDaysInMonth(
parseInt(Ox.formatDate(self.date, '%Y'), 10),
parseInt(Ox.formatDate(self.date, '%m'), 10)
) + 1), function(v, i) {
return self.options.format == 'short' ? Ox.pad(v, 2) : v.toString();
}),
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'day',
value: Ox.formatDate(self.date, self.formats.day),
textAlign: 'right',
width: self.options.width.day
})
.bindEvent('autocomplete', changeDay),
month: new Ox.Input({
autocomplete: self.options.format == 'short' ? $.map(Ox.range(1, 13), function(v, i) {
return Ox.pad(v, 2);
}) : self.months,
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'month',
value: Ox.formatDate(self.date, self.formats.month),
textAlign: self.options.format == 'short' ? 'right' : 'left',
width: self.options.width.month
})
.bindEvent('autocomplete', changeMonthOrYear),
year: new Ox.Input({
autocomplete: $.map($.merge(Ox.range(1900, 3000), Ox.range(1000, 1900)), function(v, i) {
return v.toString();
}),
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'year',
value: Ox.formatDate(self.date, self.formats.year),
textAlign: 'right',
width: self.options.width.year
})
.bindEvent('autocomplete', changeMonthOrYear)
});
that = new Ox.InputGroup($.extend(self.options, {
id: self.options.id,
inputs: $.merge(self.options.weekday ? [
self.$input.weekday
] : [], self.options.format == 'short' ? [
self.$input.year, self.$input.month, self.$input.day
] : [
self.$input.month, self.$input.day, self.$input.year
]),
separators: $.merge(self.options.weekday ? [
{title: self.options.format == 'short' ? '' : ',', width: 8},
] : [], self.options.format == 'short' ? [
{title: '-', width: 8}, {title: '-', width: 8}
] : [
{title: '', width: 8}, {title: ',', width: 8}
]),
width: 0
}), self);
//Ox.print('SELF', self)
function changeDay() {
self.options.weekday && self.$input.weekday.options({
value: Ox.formatDate(new Date([
self.$input.month.options('value'),
self.$input.day.options('value'),
self.$input.year.options('value')
].join(' ')), self.formats.weekday)
});
setValue();
}
function changeMonthOrYear() {
var day = self.$input.day.options('value'),
month = self.$input.month.options('value'),
year = self.$input.year.options('value'),
days = Ox.getDaysInMonth(year, self.options.format == 'short' ? parseInt(month, 10) : month);
day = day <= days ? day : days;
//Ox.print(year, month, 'day days', day, days)
self.options.weekday && self.$input.weekday.options({
value: Ox.formatDate(new Date([month, day, year].join(' ')), self.formats.weekday)
});
self.$input.day.options({
autocomplete: $.map(Ox.range(1, days + 1), function(v, i) {
return self.options.format == 'short' ? Ox.pad(v, 2) : v.toString();
}),
value: self.options.format == 'short' ? Ox.pad(day, 2) : day.toString()
});
setValue();
}
function changeWeekday() {
var date = getDateInWeek(
self.$input.weekday.options('value'),
self.$input.month.options('value'),
self.$input.day.options('value'),
self.$input.year.options('value')
);
self.$input.month.options({value: date.month});
self.$input.day.options({
autocomplete: $.map(Ox.range(1, Ox.getDaysInMonth(date.year, date.month) + 1), function(v, i) {
return self.options.format == 'short' ? Ox.pad(v, 2) : v.toString();
}),
value: date.day
});
self.$input.year.options({value: date.year});
setValue();
}
function getDateInWeek(weekday, month, day, year) {
//Ox.print([month, day, year].join(' '))
var date = new Date([month, day, year].join(' '));
date = Ox.getDateInWeek(date, weekday);
return {
day: Ox.formatDate(date, self.formats.day),
month: Ox.formatDate(date, self.formats.month),
year: Ox.formatDate(date, self.formats.year)
};
}
function setValue() {
self.options.value = Ox.formatDate(new Date(self.options.format == 'short' ? [
self.$input.year.options('value'),
self.$input.month.options('value'),
self.$input.day.options('value')
].join('/') : [
self.$input.month.options('value'),
self.$input.day.options('value'),
self.$input.year.options('value')
].join(' ')), '%F');
}
/*
function normalize() {
var year = that.getInputById('year').options('value'),
month = that.getInputById('month').options('value'),
day = that.getInputById('day').options('value')
return {
year: year,
month: self.options.format == 'short' ? month :
Ox.pad((format == 'medium' ? Ox.WEEKDAYS.map(function(v, i) {
return v.substr(0, 3);
}) : Ox.WEEKDAYS).indexOf(month), 2),
day: Ox.pad(day, 2)
}
}
*/
/*
that.serialize = function() {
var normal = normalize();
return [normal.year, normal.month, normal.day].join('-');
}
*/
return that;
};

View file

@ -0,0 +1,48 @@
Ox.DateTimeInput = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
ampm: false,
format: 'short',
seconds: false,
value: Ox.formatDate(new Date(), '%F %T'),
weekday: false
})
.options(options || {});
self.values = self.options.value.split(' ');
//Ox.print(self.values)
that = new Ox.InputGroup({
inputs: [
new Ox.DateInput({
format: self.options.format,
id: 'date',
value: self.values[0],
weekday: self.options.weekday
}),
new Ox.TimeInput({
ampm: self.options.ampm,
id: 'time',
value: self.values[1],
seconds: self.options.seconds
})
],
separators: [
{title: '', width: 8}
],
value: self.options.value
})
.bindEvent('change', setValue);
function setValue() {
self.options.value = [
self.options('inputs')[0].options('value'),
self.options('inputs')[1].options('value')
].join(' ');
}
return that;
};

387
source/js/Ox.Dialog.js Normal file
View file

@ -0,0 +1,387 @@
Ox.Dialog = function(options, self) {
// fixme: dialog should be derived from a generic draggable
// fixme: buttons should have a close attribute, or the dialog a close id
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
title: '',
buttons: [],
content: null,
height: 216,
keys: {},
minHeight: 144,
minWidth: 256,
movable: true,
padding: 16,
resizable: true,
width: 384
})
.options(options || {})
.addClass('OxDialog')
.bindEvent({
key_enter: function() {
keypress('enter');
},
key_escape: function() {
//Ox.print('KEY ESCAPE')
keypress('escape');
}
});
$.extend(self, {
initialWidth: self.options.width,
initialHeight: self.options.height
})
that.$titlebar = new Ox.Bar({
size: 'medium'
})
.addClass('OxTitleBar')
.appendTo(that);
self.options.movable && that.$titlebar
.dblclick(center)
.bindEvent({
dragstart: dragstart,
drag: drag
});
that.$title = new Ox.Element()
.addClass('OxTitle')
.html(self.options.title)
.appendTo(that.$titlebar);
that.$content = new Ox.Element()
.addClass('OxContent')
.css({
padding: self.options.padding + 'px',
overflow: 'auto'
})
.append(self.options.content)
.appendTo(that);
that.$buttonsbar = new Ox.Bar({})
.addClass('OxButtonsBar')
.appendTo(that);
loadButtons();
//that.$buttons[0].focus();
that.$layer = new Ox.Element() // fixme: Layer widget that would handle click?
.addClass('OxLayer')
.mousedown(mousedownLayer)
.mouseup(mouseupLayer);
function center() {
var documentHeight = Ox.UI.$document.height();
that.css({
left: 0,
top: Math.max(parseInt(-documentHeight / 10), self.options.height - documentHeight + 40) + 'px',
right: 0,
bottom: 0,
margin: 'auto'
});
}
function dragstart(event, e) {
self.drag = {
bodyWidth: Ox.UI.$body.width(),
bodyHeight: Ox.UI.$document.height(),
elementWidth: that.width(),
offset: that.offset(),
x: e.clientX,
y: e.clientY
};
that.css({
margin: 0
});
}
function drag(event, e) {
var left = Ox.limit(
self.drag.offset.left - self.drag.x + e.clientX,
24 - self.drag.elementWidth, self.drag.bodyWidth - 24
//0, self.drag.documentWidth - self.drag.elementWidth
),
top = Ox.limit(
self.drag.offset.top - self.drag.y + e.clientY,
24, self.drag.bodyHeight - 24
//24, self.drag.documentHeight - self.drag.elementHeight
);
that.css({
left: left + 'px',
top: top + 'px'
});
}
function dragstartResize(event, e) {
self.drag = {
documentWidth: Ox.UI.$document.width(),
documentHeight: Ox.UI.$document.height(),
elementWidth: that.width(),
elementHeight: that.height(),
offset: that.offset(),
x: e.clientX,
y: e.clientY
};
$.extend(self.drag, {
ratio: self.drag.elementWidth / self.drag.elementHeight
});
that.css({
left: self.drag.offset.left,
top: self.drag.offset.top,
margin: 0
});
}
function dragResize(event, e) {
if (!e.shiftKey) {
self.drag.ratio = self.options.width / self.options.height;
}
self.options.width = Ox.limit(
self.drag.elementWidth - self.drag.x + e.clientX,
self.options.minWidth,
Math.min(
self.drag.documentWidth,
self.drag.documentWidth - self.drag.offset.left
)
);
self.options.height = Ox.limit(
self.drag.elementHeight - self.drag.y + e.clientY,
self.options.minHeight,
Math.min(
self.drag.documentHeight,
self.drag.documentHeight - self.drag.offset.top
)
);
if (e.shiftKey) {
self.options.height = Ox.limit(
self.options.width / self.drag.ratio,
self.options.minHeight,
Math.min(
self.drag.documentHeight,
self.drag.documentHeight - self.drag.offset.top
)
);
self.options.width = self.options.height * self.drag.ratio;
}
that.width(self.options.width);
that.height(self.options.height);
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
}
function dragendResize(event, e) {
triggerResizeEvent();
}
function getButtonById(id) {
var ret = null;
//Ox.print('that.$buttons', that.$buttons, id)
Ox.forEach(that.$buttons, function(button) {
if (button.options('id') == id) {
ret = button;
return false;
}
});
return ret;
}
function keypress(key) {
var id = self.options.keys[key];
//Ox.print('X', key, self.options.keys)
id && getButtonById(id).$element.trigger('click');
}
function loadButtons() {
/*Ox.print('loadButtons', $.map(self.options.buttons, function(v) {
return v;
}));*/
if (that.$buttons) {
that.$buttons.forEach(function($button) {
$button.removeElement();
});
that.$resize.removeElement();
// that.$buttonsbar.empty();
}
that.$buttons = [];
if (!Ox.isArray(self.options.buttons[0])) {
self.options.buttons = [[], self.options.buttons];
}
self.options.buttons[0].forEach(function(button, i) {
that.$buttons[i] = button
.addClass('OxLeft')
.appendTo(that.$buttonsbar);
});
if (self.options.resizable) {
that.$resize = new Ox.Element()
.addClass('OxResize')
.dblclick(reset)
.bindEvent({
dragstart: dragstartResize,
drag: dragResize,
dragend: dragendResize
})
.appendTo(that.$buttonsbar);
}
self.options.buttons[1].reverse().forEach(function(button) {
that.$buttons[that.$buttons.length] = button
.addClass('OxRight')
.appendTo(that.$buttonsbar);
});
}
function mousedownLayer() {
that.$layer.stop().animate({
opacity: 0.5
}, 0);
}
function mouseupLayer() {
that.$layer.stop().animate({
opacity: 0
}, 0);
}
function reset() {
$.extend(self.options, {
height: self.initialHeight,
width: self.initialWidth
});
that/*.css({
left: Math.max(that.offset().left, 24 - that.width())
})*/
.width(self.options.width)
.height(self.options.height);
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
triggerResizeEvent();
}
function triggerResizeEvent() {
that.triggerEvent('resize', {
width: self.options.width,
height: self.options.height
});
}
self.onChange = function(key, value) {
if (key == 'buttons') {
loadButtons();
/*
that.$buttonsbar.children().animate({
opacity: 0
}, 100, function() {
loadButtons();
that.$buttonsbar.children().animate({
opacity: 1
}, 100);
});
*/
} else if (key == 'content') {
that.$content.html(value);
} else if (key == 'height' || key == 'width') {
that.animate({
height: self.options.height + 'px',
width: self.options.width + 'px'
}, 100);
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
} else if (key == 'title') {
that.$title.animate({
opacity: 0
}, 100, function() {
that.$title.html(value).animate({
opacity: 1
}, 100);
});
}
}
that.center = function() {
};
that.close = function(callback) {
callback = callback || function() {};
that.animate({
opacity: 0
}, 200, function() {
that.$buttons.forEach(function($button) {
$button.removeElement();
});
that.loseFocus();
that.$layer.removeElement();
that.removeElement();
callback();
});
Ox.UI.$window.unbind('mouseup', mouseupLayer)
return that;
};
that.content = function($element) {
that.$content.empty().append($element);
return that;
}
that.disable = function() {
// to be used on submit of form, like login
that.$layer.addClass('OxFront');
return that;
};
that.disableButton = function(id) {
getButtonById(id).options({
disabled: true
});
return that;
};
that.enable = function() {
that.$layer.removeClass('OxFront');
return that;
};
that.enableButton = function(id) {
getButtonById(id).options({
disabled: false
});
return that;
};
that.open = function() {
//Ox.print('before open')
that.$layer.appendTo(Ox.UI.$body);
that.css({
opacity: 0
}).appendTo(Ox.UI.$body).animate({
opacity: 1
}, 200);
center();
reset();
// fixme: the following line prevents preview-style dialog
that.gainFocus();
Ox.UI.$window.bind('mouseup', mouseupLayer)
//Ox.print('after open')
return that;
};
that.size = function(width, height, callback) {
$.extend(self, {
initialWidth: width,
initialHeight: height
});
$.extend(self.options, {
width: width,
height: height
});
// fixme: duplicated
that.animate({
height: self.options.height + 'px',
width: self.options.width + 'px'
}, 100, function() {
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
callback();
});
}
return that;
};

324
source/js/Ox.Element.js Normal file
View file

@ -0,0 +1,324 @@
// check out http://ejohn.org/apps/learn/#36 (-#38, making fns work w/o new)
Ox.Element = function() {
/***
Basic element object
***/
/*
tooltip option can be any of the following:
string
function(e), returns string
{mousemove: true, title: function(e)}
*/
return function(options, self) {
if (!(this instanceof arguments.callee)) {
return new arguments.callee(options, self);
}
self = self || {};
self.options = options || {};
// allow for Ox.Element('tagname', self)
if (typeof self.options == 'string') {
self.options = {
element: self.options
};
}
if (!self.$eventHandler) {
self.$eventHandler = $('<div>');
}
var that = new Ox.JQueryElement(
$('<' + (self.options.element || 'div') + '>')
)
.mousedown(mousedown);
/*
self.options.tooltip && that.bind(Ox.extend({
mouseenter: mouseenter,
mouseleave: mouseleave
}, self.options.tooltip.mousemove ? {
mousemove: mousemove
} : {}));
*/
function mousedown(e) {
/*
better mouse events
mousedown:
trigger mousedown
within 250 msec:
mouseup: trigger anyclick ("click" would collide with click events of certain widgets)
mouseup + mousedown: trigger doubleclick
after 250 msec:
mouseup + no mousedown within 250 msec: trigger singleclick
no mouseup within 250 msec:
trigger mouserepeat every 50 msec
trigger dragstart
mousemove: trigger drag
no mousemove within 250 msec:
trigger dragpause
mouseup: trigger dragend
*/
var clientX, clientY,
dragTimeout = 0,
mouseInterval = 0;
if (!self.mouseTimeout) {
// first mousedown
that.triggerEvent('mousedown', e);
self.mouseup = false;
self.mouseTimeout = setTimeout(function() {
self.mouseTimeout = 0;
if (self.mouseup) {
// singleclick
that.triggerEvent('singleclick', e);
} else {
// mouserepeat, drag
clientX = e.clientX;
clientY = e.clientY;
that.triggerEvent('dragstart', e);
mouserepeat();
mouseInterval = setInterval(mouserepeat, 50);
Ox.UI.$window.unbind('mouseup', mouseup)
.mousemove(mousemove)
.one('mouseup', function(e) {
clearInterval(mouseInterval);
clearTimeout(dragTimeout);
Ox.UI.$window.unbind('mousemove', mousemove);
that.triggerEvent('dragend', extend(e));
});
that.one('mouseleave', function() {
clearInterval(mouseInterval);
});
}
}, 250);
} else {
// second mousedown
clearTimeout(self.mouseTimeout);
self.mouseTimeout = 0;
that.triggerEvent('doubleclick', e);
}
Ox.UI.$window.one('mouseup', mouseup);
function extend(e) {
return Ox.extend({
clientDX: e.clientX - clientX,
clientDY: e.clientY - clientY
}, e);
}
function mousemove(e) {
e = extend(e);
clearTimeout(dragTimeout);
dragTimeout = setTimeout(function() {
that.triggerEvent('dragpause', e);
}, 250);
that.triggerEvent('drag', e);
}
function mouserepeat() {
that.triggerEvent('mouserepeat');
}
function mouseup(e) {
// only trigger on firse mouseup
if (!self.mouseup) {
that.triggerEvent('anyclick', e);
self.mouseup = true;
}
}
}
/*
function mouseenter(e) {
self.$tooltip = new Ox.Tooltip({
title: Ox.isString(self.options.tooltip) ?
self.options.tooltip : Ox.isFunction(self.options.tooltip) ?
self.options.tooltip(e) : self.options.tooltip.title(e)
}).show();
}
function mouseleave(e) {
self.$tooltip.hide();
}
function mousemove(e) {
self.$tooltip.options({
title: self.options.tooltip.title(e)
});
}
*/
self.onChange = function() {
// self.onChange(key, value)
// is called when an option changes
// (to be implemented by widget)
// fixme: rename to self.setOption
};
that._leakSelf = function() { // fixme: remove
return self;
}
that.bindEvent = function() {
/***
binds a function to an event triggered by this object
Usage
bindEvent(event, fn) or bindEvent({event0: fn0, event1: fn1, ...})
***/
if (arguments.length == 1) {
Ox.forEach(arguments[0], function(fn, event) {
// Ox.print(that.id, 'bind', event);
self.$eventHandler.bind('ox_' + event, fn);
});
} else {
// Ox.print(that.id, 'bind', arguments[0]);
self.$eventHandler.bind('ox_' + arguments[0], arguments[1]);
}
return that;
}
that.bindEventOnce = function() {
if (arguments.length == 1) {
Ox.forEach(arguments[0], function(fn, event) {
self.$eventHandler.one('ox_' + event, fn);
});
} else {
self.$eventHandler.one('ox_' + arguments[0], arguments[1]);
}
return that;
};
that.defaults = function(defaults) {
/***
sets the default options
Usage
that.defaults({key0: value0, key1: value1, ...})
***/
self.defaults = defaults;
delete self.options; // fixme: hackish fix for that = Ox.Foo({...}, self).defaults({...}).options({...})
return that;
};
that.gainFocus = function() {
/***
make this object gain focus
***/
Ox.Focus.focus(that.id);
return that;
};
that.hasFocus = function() {
/***
returns true if this object has focus
***/
return Ox.Focus.focused() == that.id;
};
that.loseFocus = function() {
/***
make this object lose focus
***/
Ox.Focus.blur(that.id);
return that;
};
that.options = function() { // fixme: use Ox.getset
/***
get or set options
Usage
that.options() returns self.options
that.options('foo') returns self.options.foo
that.options('foo', x) sets self.options.foo,
returns that
that.options({foo: x, bar: y}) sets self.options.foo
and self.options.bar,
returns that
***/
var args,
length = arguments.length,
oldOptions,
ret;
if (length == 0) {
// options()
ret = self.options;
} else if (length == 1 && typeof arguments[0] == 'string') {
// options(str)
ret = self.options ? self.options[arguments[0]] : options[arguments[0]];
} else {
// options (str, val) or options({str: val, ...})
// translate (str, val) to ({str: val})
args = Ox.makeObject.apply(that, arguments || {});
oldOptions = $.extend({}, self.options);
// if options have not been set, extend defaults,
// otherwise, extend options
//self.options = $.extend(self.options, self.options ? {} : self.defaults, args);
self.options = $.extend({}, self.defaults, self.options, args);
//self.options = $.extend(self.options || self.defaults, args);
Ox.forEach(args, function(val, key) {
// key == 'id' && id && Ox.Event.changeId(id, value);
/*!Ox.equals(value, oldOptions[key]) &&*/ self.onChange(key, val);
});
ret = that;
}
return ret;
};
that.removeElement = function() {
/***
remove this element, including its event handler
***/
that.loseFocus();
delete self.$eventHandler;
that.remove();
delete Ox.UI.elements[that.id];
return that;
};
that.triggerEvent = function() {
/***
triggers an event
Usage
triggerEvent(event)
triggerEvent(event, data)
triggerEvent({event0: data0, event1: data1, ...})
***/
if (Ox.isObject(arguments[0])) {
Ox.forEach(arguments[0], function(data, event) {
if (['mousedown', 'mouserepeat', 'anyclick', 'singleclick', 'doubleclick', 'dragstart', 'drag', 'dragpause', 'dragend', 'playing'].indexOf(event) == -1) {
Ox.print(that.id, self.options.id, 'trigger', event, data);
}
self.$eventHandler.trigger('ox_' + event, data);
});
} else {
if (['mousedown', 'mouserepeat', 'anyclick', 'singleclick', 'doubleclick', 'dragstart', 'drag', 'dragpause', 'dragend', 'playing'].indexOf(arguments[0]) == -1) {
Ox.print(that.id, self.options ? self.options.id : '', 'trigger', arguments[0], arguments[1] || {});
}
self.$eventHandler.trigger('ox_' + arguments[0], arguments[1] || {});
}
return that;
};
that.unbindEvent = function() {
/***
unbinds a function from an event triggered by this element
Usage
unbindEvent(event, fn)
unbindEvent({event0: fn0, event1: fn1, ...})
***/
if (arguments.length == 1) {
Ox.forEach(arguments[0], function(fn, event) {
// Ox.print(that.id, 'unbind', arguments[0]);
self.$eventHandler.unbind('ox_' + event, fn);
});
} else {
// Ox.print(that.id, 'unbind', arguments[0]);
self.$eventHandler.unbind('ox_' + arguments[0], arguments[1]);
}
return that;
};
return that;
}
}();

182
source/js/Ox.FilesView.js Normal file
View file

@ -0,0 +1,182 @@
// fixme: this is not necessarily part of OxUI
/*
============================================================================
Pan.do/ra
============================================================================
*/
Ox.FilesView = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
id: ''
})
.options(options || {});
self.$toolbar = new Ox.Bar({
size: 24
});
self.$orderButton = new Ox.Button({
title: 'Change Order of Users...'
})
.css({
float: 'left',
margin: '4px'
})
.appendTo(self.$toolbar);
self.$moveButton = new Ox.Button({
disabled: 'true',
title: 'Move Selected Files...'
})
.css({
float: 'right',
margin: '4px'
})
.appendTo(self.$toolbar);
self.$filesList = new Ox.TextList({
columns: [
{
align: 'left',
id: 'users',
operator: '+',
title: 'Users',
visible: true,
width: 120
},
{
align: 'left',
id: 'folder',
operator: '+',
title: 'Folder',
visible: true,
width: 180
},
{
align: 'left',
id: 'name',
operator: '+',
title: 'Name',
visible: true,
width: 360
},
{
align: 'left',
id: 'type',
operator: '+',
title: 'Type',
visible: true,
width: 60
},
{
align: 'right',
id: 'part',
operator: '+',
title: 'Part',
visible: true,
width: 60
},
{
align: 'right',
format: {type: 'value', args: ['B']},
id: 'size',
operator: '-',
title: 'Size',
visible: true,
width: 90
},
{
align: 'right',
format: {type: 'resolution', args: ['px']},
id: 'resolution',
operator: '-',
title: 'Resolution',
visible: true,
width: 90
},
{
align: 'right',
format: {type: 'duration', args: [0, 'short']},
id: 'duration',
operator: '-',
title: 'Duration',
visible: true,
width: 90
},
{
align: 'left',
id: 'oshash',
operator: '+',
title: 'Hash',
unique: true,
visible: false,
width: 120
},
{
align: 'left',
id: 'instances',
operator: '+',
title: 'Instances',
visible: false,
width: 120
}
],
columnsMovable: true,
columnsRemovable: true,
columnsResizable: true,
columnsVisible: true,
id: 'files',
items: function(data, callback) {
pandora.api.findFiles($.extend(data, {
query: {
conditions: [{
key: 'id',
value: self.options.id,
operator: '='
}]
}
}), callback);
},
scrollbarVisible: true,
sort: [{key: 'name', operator:'+'}]
})
.bindEvent({
open: openFiles,
select: selectFiles
});
self.$instancesList = new Ox.Element()
.html('No files selected');
that.$element = new Ox.SplitPanel({
elements: [
{
element: self.$toolbar,
size: 24
},
{
element: self.$filesList
},
{
element: self.$instancesList,
size: 80
}
],
orientation: 'vertical'
});
function openFiles(event, data) {
//alert(JSON.stringify(self.$filesList.value(data.ids[0], 'instances')))
}
function selectFiles(event, data) {
//alert(JSON.stringify(self.$filesList.value(data.ids[0], 'instances')))
}
return that;
};

403
source/js/Ox.Filter.js Normal file
View file

@ -0,0 +1,403 @@
Ox.Filter = function(options, self) {
/***
Options:
Methods:
Events:
***/
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
findKeys: [],
query: {
conditions: [],
operator: '&'
},
sortKeys: [],
viewKeys: []
})
.options(options || {});
Ox.print('Ox.Filter self.options', self.options)
$.extend(self, {
conditionOperators: {
date: [
{id: '', title: 'is'},
{id: '!', title: 'is not'},
{id: '<', title: 'is before'},
{id: '>', title: 'is after'},
{id: '>&<', title: 'is between'},
{id: '<|>', title: 'is not between'}
],
list: [
{id: '', title: 'is'},
{id: '!', title: 'is not'}
],
number: [
{id: '', title: 'is'},
{id: '!', title: 'is not'},
{id: '<', title: 'is less than'},
{id: '>', title: 'is greater than'},
{id: '>&<', title: 'is between'},
{id: '<|>', title: 'is not between'}
],
string: [
{id: '=', title: 'is'},
{id: '!=', title: 'is not'},
{id: '^', title: 'begins with'},
{id: '$', title: 'ends with'},
{id: '', title: 'contains'},
{id: '!', title: 'does not contain'}
],
text: [
{id: '', title: 'contains'},
{id: '!', title: 'does not contain'}
]
},
operators: [
{id: '&', title: 'all'},
{id: '|', title: 'any'}
]
});
if (!self.options.query.conditions.length) {
self.options.query.conditions = [{
key: self.options.findKeys[0].id,
value: '',
operator: self.conditionOperators[
getConditionType(self.options.findKeys[0].type)
][0].id
}];
}
self.$operator = new Ox.FormElementGroup({
elements: [
new Ox.Label({
title: 'Match',
overlap: 'right',
width: 48
}),
new Ox.FormElementGroup({
elements: [
new Ox.Select({
items: self.operators,
width: 48
})
.bindEvent({
change: changeOperator
}),
new Ox.Label({
overlap: 'left',
title: 'of the following conditions',
width: 160
})
],
float: 'right',
width: 208
})
],
float: 'left',
});
self.$buttons = [];
self.$conditions = $.map(self.options.query.conditions, function(condition, i) {
return constructCondition(condition, i);
});
self.$limit = new Ox.InputGroup({
inputs: [
new Ox.Checkbox({
width: 16
}),
new Ox.FormElementGroup({
elements: [
new Ox.Input({
width: 56
}),
new Ox.Select({
items: [
{id: 'items', title: 'items'},
{},
{id: 'hours', title: 'hours'},
{id: 'days', title: 'days'},
{},
{id: 'GB', title: 'GB'}
],
overlap: 'left',
width: 64
})
],
float: 'right',
width: 120
}),
new Ox.Select({
items: self.options.sortKeys,
width: 128
}),
new Ox.FormElementGroup({
elements: [
new Ox.Select({
items: [
{id: 'ascending', title: 'ascending'},
{id: 'descending', title: 'descending'}
],
width: 96
}),
new Ox.Label({
overlap: 'left',
title: 'order',
width: 72
})
],
float: 'right',
width: 168
})
],
separators: [
{title: 'Limit to', width: 56},
{title: 'sorted by', width: 64},
{title: 'in', width: 32}
]
});
self.$view = new Ox.InputGroup({
inputs: [
new Ox.Checkbox({
width: 16
}),
new Ox.Select({
items: self.options.viewKeys,
width: 128
})
],
separators: [
{title: 'By default, view', width: 112}
]
});
self.$save = new Ox.InputGroup({
inputs: [
new Ox.Checkbox({
width: 16
}),
new Ox.Input({
id: 'list',
width: 128
})
],
separators: [
{title: 'Save as Smart List', width: 112}
]
});
self.$items = $.merge($.merge([self.$operator], self.$conditions), [self.$limit, self.$view, self.$save]);
self.$form = new Ox.Form({
items: self.$items
});
that.$element = self.$form.$element;
function addCondition(pos) {
var key = self.options.findKeys[0];
self.options.query.conditions.splice(pos, 0, {
key: key.id,
value: '',
operator: self.conditionOperators[key.type][0].id
});
self.$conditions.splice(pos, 0, constructCondition({}, pos));
updateConditions();
self.$form.addItem(pos + 1, self.$conditions[pos]);
}
function addGroup(pos) {
self.$form.addItem(pos + 1, constructGroup(pos))
}
function changeConditionKey(pos, key) {
Ox.print('changeConditionKey', pos, key);
var oldOperator = self.options.query.conditions[pos].operator,
oldType = Ox.getObjectById(
self.options.findKeys, self.options.query.conditions[pos].key
).type,
newType = Ox.getObjectById(
self.options.findKeys, key
).type,
oldConditionType = getConditionType(oldType),
newConditionType = getConditionType(newType);
changeConditionType = oldConditionType != newConditionType;
Ox.print('old new', oldConditionType, newConditionType)
self.options.query.conditions[pos].key = key;
if (changeConditionType) {
self.$conditions[pos].replaceElement(1, constructConditionOperator(pos, oldOperator));
}
}
function changeConditionOperator(pos, operator) {
self.options.query.conditions[pos].operator = operator;
}
function changeOperator(event, data) {
self.options.query.operator = data.selected[0].id;
}
function constructCondition(condition, pos) {
var $condition;
return $condition = new Ox.FormElementGroup({
elements: [
new Ox.Select({
items: $.map(self.options.findKeys, function(key) {
return {
id: key.id,
title: key.title
};
}),
//items: $.extend({}, self.options.findKeys), // fixme: Ox.Menu messes with keys
overlap: 'right',
width: 128
})
.bindEvent({
change: function(event, data) {
Ox.print('event', event)
changeConditionKey($condition.data('position'), data.selected[0].id);
}
}),
constructConditionOperator(pos),
new Ox.Input({
width: 256
}),
new Ox.Button({
disabled: self.options.query.conditions.length == 1,
id: 'remove',
title: 'remove',
type: 'image'
})
.css({margin: '0 4px 0 8px'})
.bindEvent({
click: function() {
removeCondition($condition.data('position'));
}
}),
new Ox.Button({
id: 'add',
title: 'add',
type: 'image'
})
.css({margin: '0 4px 0 4px'})
.bindEvent({
click: function() {
Ox.print('add', $(this).parent().parent().data('position'))
addCondition($condition.data('position') + 1)
}
}),
new Ox.Button({
id: 'addgroup',
title: 'more',
type: 'image'
})
.css({margin: '0 0 0 4px'})
.bindEvent({
click: function() {
addGroup($condition.data('position') + 1)
}
})
]
})
.data({position: pos});
}
function constructConditionOperator(pos, selected) {
return new Ox.Select({
items: $.map(self.conditionOperators[getConditionType(
Ox.getObjectById(
self.options.findKeys,
self.options.query.conditions[pos].key
).type
)], function(operator) {
return {
checked: operator.id == selected, // fixme: should be "selected", not "checked"
id: operator.operator,
title: operator.title
};
}),
overlap: 'right',
width: 128
})
.bindEvent({
change: function(event, data) {
changeConditionOperator(/*$condition.data('position')*/ pos, data.selected[0].id)
}
});
}
function constructGroup() {
// fixme: duplicated
return new Ox.FormElementGroup({
elements: [
new Ox.Label({
title: self.options.operator == '&' ? 'and' : 'or',
overlap: 'right',
width: 48
}),
new Ox.FormElementGroup({
elements: [
new Ox.Select({
items: $.map(self.operators, function(operator) {
Ox.print('!!!!', {
checked: operator.id != self.options.operator,
id: operator.id,
title: operator.title
});
return {
//checked: operator.id != self.options.operator,
id: operator.id,
title: operator.title
}
}),
width: 48
})
.bindEvent({
change: changeOperator
}),
new Ox.Label({
overlap: 'left',
title: 'of the following conditions',
width: 160
})
],
float: 'right',
width: 208
})
],
float: 'left',
});
}
function getConditionType(type) {
type = Ox.isArray(type) ? type[0] : type;
if (['float', 'integer', 'year'].indexOf(type) > -1) {
type = 'number';
}
return type;
}
function removeCondition(pos) {
self.options.query.conditions.splice(pos, 1);
self.$conditions.splice(pos, 1);
updateConditions();
self.$form.removeItem(pos + 1);
}
function updateConditions() {
self.$conditions.forEach(function(condition, pos) {
condition.data({position: pos});
});
self.$conditions[0].options('elements')[3].options({
disabled: self.options.query.conditions.length == 1
});
}
return that;
};

98
source/js/Ox.Flipbook.js Normal file
View file

@ -0,0 +1,98 @@
// fixme: rename!
Ox.Flipbook = function(options, self) {
var self = self || {},
frame = $('<img>').css({
'position': 'absolute',
'width': '100%',
'height': 'auto'
})
.hide(),
icon = $('<img>').css({
'position': 'absolute',
'width': '100%',
'height': 'auto'
}),
frames = {},
timestamp = $('<div>').css({
'position': 'absolute',
'text-align': 'center',
'width': '100%',
})
.hide(),
that = new Ox.Element('div', self)
.defaults({
frames: {},
duration: 0,
icon: '',
})
.options(options || {})
.append(icon)
.append(frame)
.append(timestamp)
.mouseover(function() {
frame.show();
timestamp.show();
icon.hide();
})
.mousemove(function(event) {
var position = getPosition(event),
image = getFrame(position),
frameHeight = image?image.height:that.height();
frame.attr('src', image.src);
timestamp.html(Ox.formatDuration(position, 'short'));
var height = (that.height() - frameHeight)/2;
frame.css({'top': height + 'px'});
timestamp.css({'top': (frameHeight + height) + 'px'});
})
.mouseout(function() {
frame.hide();
timestamp.hide();
icon.show();
})
.mousedown(function(event) {
that.triggerEvent('click', {
'position': getPosition(event)
});
});
function getPosition(event) {
var position = Math.floor(event.clientX - that.offset().left);
position = (position / that.width()) * self.options.duration;
return position;
}
function getFrame(position) {
var frame;
frames.forEach(function(img, i) {
if (!frame || i <= position)
frame = img;
});
return frame;
}
function cacheFrames() {
Ox.forEach(self.options.frames, function(src, i) {
frames[i] = new Image();
frames[i].onload = function() {
frameHeight = frames[i].height / frames[i].width * that.width();
}
frames[i].src = src;
});
}
self.onChange = function(key, value) {
if (key == 'frames') {
cacheFrames();
} else if (key == 'icon') {
icon.attr('src', value);
}
}
if(options.icon)
icon.attr('src', options.icon);
cacheFrames();
return that;
};

40
source/js/Ox.Focus.js Normal file
View file

@ -0,0 +1,40 @@
Ox.Focus = function() {
/***
Ox.Focus
Basic focus handler
Methods
blur(id) blur element
focus(id) focus element
focused() return id of focused element, or null
***/
var stack = [];
return {
_print: function() {
Ox.print(stack);
},
blur: function(id) {
var index = stack.indexOf(id);
if (index > -1 && index == stack.length - 1) {
stack.length == 1 ? stack.pop() :
stack.splice(stack.length - 2, 0, stack.pop());
//$elements[id].removeClass('OxFocus');
$('.OxFocus').removeClass('OxFocus'); // fixme: the above is better, and should work
stack.length && Ox.UI.elements[stack[stack.length - 1]].addClass('OxFocus');
Ox.print('blur', id, stack);
}
},
focus: function(id) {
var index = stack.indexOf(id);
if (index == -1 || index < stack.length - 1) {
index > -1 && stack.splice(index, 1);
stack.push(id);
$('.OxFocus').removeClass('OxFocus'); // fixme: see above
Ox.UI.elements[id].addClass('OxFocus');
Ox.print('focus', id, stack);
}
},
focused: function() {
return stack.length ? stack[stack.length - 1] : null;
}
};
}();

121
source/js/Ox.Form.js Normal file
View file

@ -0,0 +1,121 @@
Ox.Form = function(options, self) {
/**
*/
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
error: '',
id: '',
items: [],
submit: null
})
.options(options || {}) // fixme: the || {} can be done once, in the options function
.addClass('OxForm');
$.extend(self, {
$items: [],
$messages: [],
formIsValid: false,
itemIds: [],
itemIsValid: []
});
// fixme: form isn't necessarily empty/invalid
self.options.items.forEach(function(item, i) {
self.itemIds[i] = item.options('id') || item.id;
self.itemIsValid[i] = !!item.value().length;
that.append(self.$items[i] = new Ox.FormItem({element: item}));
item.bindEvent({
/*
blur: function(event, data) {
validate(i, data.valid);
if (data.valid) {
self.$messages[i].html('').hide();
} else {
self.$messages[i].html(data.message).show();
}
},
*/
autovalidate: function(event, data) {
data.valid = !!data.value.length;
validate(i, data.valid);
data.valid && self.$items[i].setMessage('');
},
submit: function(event, data) {
self.formIsValid && that.submit();
},
validate: function(event, data) {
validate(i, data.valid);
self.$items[i].setMessage(data.valid ? '' : data.message);
}
});
});
function getItemPositionById(id) {
return self.itemIds.indexOf(id);
}
function submitCallback(data) {
data.forEach(function(v, i) {
self.$items[i].setMessage(v.message);
});
}
function validate(pos, valid) {
//Ox.print('FORM validate', pos, valid)
self.itemIsValid[pos] = valid;
if (Ox.every(self.itemIsValid) != self.formIsValid) {
self.formIsValid = !self.formIsValid;
that.triggerEvent('validate', {
valid: self.formIsValid
});
}
}
that.addItem = function(pos, item) {
Ox.print('addItem', pos)
self.options.items.splice(pos, 0, item);
self.$items.splice(pos, 0, new Ox.FormItem({element: item}));
pos == 0 ?
self.$items[pos].insertBefore(self.$items[0]) :
self.$items[pos].insertAfter(self.$items[pos - 1]);
}
that.removeItem = function(pos) {
Ox.print('removeItem', pos);
self.$items[pos].removeElement();
self.options.items.splice(pos, 1);
self.$items.splice(pos, 1);
}
that.submit = function() {
//Ox.print('---- that.values()', that.values())
self.options.submit(that.values(), submitCallback);
};
that.values = function() { // fixme: can this be private?
/*
get/set form values
call without arguments to get current form values
pass values as array to set values (not implemented)
*/
var values = {};
if (arguments.length == 0) {
self.$items.forEach(function($item, i) {
values[self.itemIds[i]] = self.$items[i].value();
});
//Ox.print('VALUES', values)
return values;
} else {
Ox.each(arguments[0], function(val, key) {
});
return that;
}
};
return that;
};

View file

@ -0,0 +1,73 @@
Ox.FormElementGroup = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
id: '',
elements: [],
float: 'left',
separators: [],
width: 0
})
.options(options || {})
.addClass('OxInputGroup');
(
self.options.float == 'left' ?
self.options.elements : self.options.elements.reverse()
).forEach(function($element, i) {
$element.css({
float: self.options.float // fixme: make this a class
})
.bindEvent({
validate: function(event, data) {
that.triggerEvent({
validate: data
});
}
})
.appendTo(that);
});
/*
if (self.options.width) {
setWidths();
} else {
self.options.width = getWidth();
}
that.css({
width: self.options.width + 'px'
});
*/
function getWidth() {
}
function setWidth() {
}
self.onChange = function(key, value) {
};
that.replaceElement = function(pos, element) {
Ox.print('Ox.FormElementGroup replaceElement', pos, element)
self.options.elements[pos].replaceWith(element.$element);
self.options.elements[pos] = element;
};
that.value = function() {
return $.map(self.options.elements, function(element) {
var ret = null;
['checked', 'selected', 'value'].forEach(function(v) {
element[v] && (ret = element[v]());
});
return ret;
});
};
return that;
};

27
source/js/Ox.FormItem.js Normal file
View file

@ -0,0 +1,27 @@
Ox.FormItem = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
element: null,
error: '',
})
.options(options || {})
.addClass('OxFormItem')
.append(self.options.element);
self.$message = new Ox.Element()
.addClass('OxFormMessage')
.appendTo(that);
that.setMessage = function(message) {
self.$message.html(message)[message !== '' ? 'show' : 'hide']();
}
that.value = function() {
return self.options.element.value();
};
return that;
}

4
source/js/Ox.History.js Normal file
View file

@ -0,0 +1,4 @@
/***
Ox.History
***/

155
source/js/Ox.IconItem.js Normal file
View file

@ -0,0 +1,155 @@
Ox.IconItem = function(options, self) {
//Ox.print('IconItem', options, self)
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
height: 128,
id: '',
info: '',
size: 128,
title: '',
width: 128,
url: ''
})
.options(options || {})
$.extend(self, {
fontSize: self.options.size == 64 ? 6 : 9,
height: self.options.size * 1.5,
lineLength: self.options.size == 64 ? 15 : 23,
lines: self.options.size == 64 ? 4 : 5,
url: Ox.UI.PATH + '/png/ox.ui/transparent.png',
width: self.options.size
});
self.title = formatText(self.options.title, self.lines - 1, self.lineLength);
self.info = formatText(self.options.info, 5 - self.title.split('<br/>').length, self.lineLength);
that.css({
width: self.width + 'px',
height: self.height + 'px'
});
that.$icon = $('<div>')
.addClass('OxIcon')
.css({
top: self.options.size == 64 ? -64 : -124,
width: (self.options.size + 4) + 'px',
height: (self.options.size + 4) + 'px'
});
that.$iconImage = $('<img>')
.addClass('OxLoading OxTarget')
.attr({
src: self.url
})
.css({
width: self.options.width + 'px',
height: self.options.height + 'px'
})
.mousedown(mousedown)
.mouseenter(mouseenter)
.mouseleave(mouseleave);
self.options.url && that.$iconImage.one('load', load);
that.$textBox = $('<div>')
.addClass('OxText')
.css({
top: (self.options.size / 2) + 'px',
width: (self.options.size + 4) + 'px',
height: (self.options.size == 64 ? 30 : 58) + 'px'
})
that.$text = $('<div>')
.addClass('OxTarget')
.css({
fontSize: self.fontSize + 'px'
})
.html(
self.title + '<br/><span class="OxInfo">' + self.info + '</span>'
)
.mouseenter(mouseenter)
.mouseleave(mouseleave);
that.$reflection = $('<div>')
.addClass('OxReflection')
.css({
top: self.options.size + 'px',
width: (self.options.size + 4) + 'px',
height: (self.options.size / 2) + 'px'
});
that.$reflectionImage = $('<img>')
.addClass('OxLoading')
.attr({
src: self.url
})
.css({
width: self.options.width + 'px',
height: self.options.height + 'px',
// firefox is 1px off when centering images with odd width and scaleY(-1)
paddingLeft: ($.browser.mozilla && self.options.width % 2 ? 1 : 0) + 'px'
});
that.$gradient = $('<div>')
.css({
//top: (-self.options.size / 2) + 'px',
width: self.options.width + 'px',
height: (self.options.size / 2) + 'px'
});
that.append(
that.$reflection.append(
that.$reflectionImage
).append(
that.$gradient
)
).append(
that.$textBox.append(
that.$text
)
).append(
that.$icon.append(
that.$iconImage
)
);
function formatText(text, maxLines, maxLength) {
var lines = Ox.wordwrap(text, maxLength, '<br/>', true, false).split('<br/>');
return $.map(lines, function(line, i) {
if (i < maxLines - 1) {
return line;
} else if (i == maxLines - 1) {
return lines.length == maxLines ? line : Ox.truncate($.map(lines, function(line, i) {
return i < maxLines - 1 ? null : line;
}).join(' '), maxLength, '...', 'center');
} else {
return null;
}
}).join('<br/>');
}
function load() {
that.$iconImage.attr({
src: self.options.url
})
.one('load', function() {
that.$iconImage.removeClass('OxLoading');
that.$reflectionImage
.attr({
src: self.options.url
})
.removeClass('OxLoading');
});
}
function mousedown(e) {
// fixme: preventDefault keeps image from being draggable in safari - but also keeps the list from getting focus
// e.preventDefault();
}
function mouseenter() {
that.addClass('OxHover');
}
function mouseleave() {
that.removeClass('OxHover');
}
return that;
};

138
source/js/Ox.IconList.js Normal file
View file

@ -0,0 +1,138 @@
Ox.IconList = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
centerSelection: false,
draggable: true,
id: '',
item: null,
items: null,
keys: [],
max: -1,
min: 0,
orientation: 'both',
selected: [],
size: 128,
sort: [],
})
.options(options || {});
$.extend(self, {
itemHeight: self.options.size * 1.5,
itemWidth: self.options.size
});
that.$element = new Ox.List({
centered: self.options.centered,
construct: constructItem,
draggable: self.options.draggable,
id: self.options.id,
itemHeight: self.itemHeight,
items: self.options.items,
itemWidth: self.itemWidth,
keys: self.options.keys,
orientation: self.options.orientation,
keys: self.options.keys,
max: self.options.max,
min: self.options.min,
selected: self.options.selected,
size: self.options.size,
sort: self.options.sort,
type: 'icon',
unique: self.options.unique
}, $.extend({}, self)) // pass event handler
.addClass('OxIconList Ox' + Ox.toTitleCase(self.options.orientation))
.click(click)
.dblclick(dblclick)
.scroll(scroll);
updateKeys();
function click() {
}
function constructItem(data) {
var data = !$.isEmptyObject(data) ?
self.options.item(data, self.options.sort, self.options.size) :
{height: 8, width: 5},
ratio = data.width / data.height;
return new Ox.IconItem($.extend(data, {
height: Math.round(self.options.size / (ratio <= 1 ? 1 : ratio)),
size: self.options.size,
width: Math.round(self.options.size * (ratio >= 1 ? 1 : ratio))
}));
}
function dblclick() {
}
function scroll() {
}
function updateKeys() {
self.options.keys = Ox.unique($.merge(self.options.keys, [self.options.sort[0].key]));
that.$element.options({
keys: self.options.keys
});
}
self.onChange = function(key, value) {
if (key == 'items') {
that.$element.options(key, value);
} else if (key == 'paste') {
that.$element.options(key, value);
} else if (key == 'selected') {
that.$element.options(key, value);
}
}
that.closePreview = function() {
that.$element.closePreview();
};
that.paste = function(data) {
that.$element.paste(data);
return that;
};
that.reloadList = function() {
that.$element.reloadList();
return that;
};
that.scrollToSelection = function() {
that.$element.scrollToSelection();
};
that.size = function() {
that.$element.size();
};
that.sortList = function(key, operator) {
self.options.sort = [{
key: key,
operator: operator
}];
updateKeys();
that.$element.sortList(key, operator);
};
that.value = function(id, key, value) {
// fixme: make this accept id, {k: v, ...}
if (arguments.length == 1) {
return that.$element.value(id);
} else if (arguments.length == 2) {
return that.$element.value(id, key);
} else {
that.$element.value(id, key, value);
return that;
}
}
return that;
};

1762
source/js/Ox.Input.js Normal file

File diff suppressed because it is too large Load diff

133
source/js/Ox.InputGroup.js Normal file
View file

@ -0,0 +1,133 @@
Ox.InputGroup = function(options, self) {
/***
Ox.InputGroup
Options:
Methods:
Events:
***/
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
id: '',
inputs: [],
separators: [],
width: 0
})
.options(options || {})
.addClass('OxInputGroup')
.click(click);
if (self.options.width) {
setWidths();
} else {
self.options.width = getWidth();
}
that.css({
width: self.options.width + 'px'
});
$.extend(self, {
//$input: [],
$separator: []
});
self.options.separators.forEach(function(v, i) {
self.options.id == 'debug' && Ox.print('separator #' + i + ' ' + self.options.inputs[i].options('id') + ' ' + self.options.inputs[i].options('width'))
self.$separator[i] = new Ox.Label({
textAlign: 'center',
title: v.title,
width: v.width + 32
})
.addClass('OxSeparator')
.css({
marginLeft: (self.options.inputs[i].options('width') - (i == 0 ? 16 : 32)) + 'px'
})
.appendTo(that);
});
self.options.inputs.forEach(function($input, i) {
$input.options({
id: self.options.id + Ox.toTitleCase($input.options('id')),
parent: that
})
.css({
marginLeft: -Ox.sum($.map(self.options.inputs, function(v_, i_) {
return i_ > i ? self.options.inputs[i_ - 1].options('width') +
self.options.separators[i_ - 1].width : (i_ == i ? 16 : 0);
})) + 'px'
})
.bindEvent({
change: change,
submit: change,
validate: validate
})
.appendTo(that);
});
function change(event, data) {
//Ox.print('InputGroup change')
// fixme: would be good to pass a value here
that.triggerEvent('change');
}
function click(event) {
if ($(event.target).hasClass('OxSeparator')) {
self.options.inputs[0].focusInput();
}
}
function getWidth() {
return Ox.sum($.map(self.options.inputs, function(v, i) {
return v.options('width');
})) + Ox.sum($.map(self.options.separators, function(v, i) {
return v.width;
})) + 2; // fixme: why + 2?
}
function setWidths() {
var length = self.options.inputs.length,
inputWidths = Ox.divideInt(
self.options.width - Ox.sum($.map(self.options.separators, function(v, i) {
return v.width;
})), length
);
self.options.inputs.forEach(function(v) {
v.options({
width: inputWidths[1]
});
});
}
function validate(event, data) {
//Ox.print('INPUTGROUP TRIGGER VALIDATE')
that.triggerEvent('validate', data);
}
// fixme: is this used?
that.getInputById = function(id) {
var input = null;
Ox.forEach(self.options.inputs, function(v, i) {
//Ox.print(v, v.options('id'), id)
if (v.options('id') == self.options.id + Ox.toTitleCase(id)) {
input = v;
return false;
}
});
return input;
};
that.value = function() {
return $.map(self.options.inputs, function(input) {
var ret = null;
['checked', 'selected', 'value'].forEach(function(v) {
input[v] && (ret = input[v]());
});
return ret;
});
};
return that;
};

54
source/js/Ox.ItemInput.js Normal file
View file

@ -0,0 +1,54 @@
Ox.ItemInput = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
type: 'textarea',
value: '',
height: 300,
width: 100
})
.options(options || {}),
$input;
that.append(
$input = new Ox.Input({
height: self.options.height,
style: 'square',
type: self.options.type,
value: self.options.value,
width: self.options.width + 6
})
.bind({
mousedown: function(e) {
// keep mousedown from reaching list
e.stopPropagation();
}
})
)
.append(new Ox.Element()
.append(new Ox.Button({type: 'text', title: 'Cancel'})
.css('width', '42%')
.bindEvent({
'click': function() {
that.triggerEvent('cancel');
}
}))
.append(new Ox.Button({type: 'text', title: 'Save'})
.css('width', '42%')
.bindEvent({
'click': function() {
that.triggerEvent('save', {
value: $input.value()
});
}
}))
.css({
'margin-top': self.options.height-8,
'height': '16px',
'text-align': 'right',
})
);
Ox.print($input);
return that;
}

View file

@ -0,0 +1,32 @@
// Basic jQuery element
Ox.JQueryElement = function($element) {
var that = this;
that.id = Ox.uid();
that.ox = Ox.VERSION;
that.$element = $element.data({
oxid: that.id
});
Ox.UI.elements[that.id] = that;
return that;
};
Ox.forEach($('<div>'), function(val, key) {
if (Ox.isFunction(val)) {
Ox.JQueryElement.prototype[key] = function() {
var args = arguments, id, ret, that = this;
Ox.forEach(args, function(arg, i) {
// if an ox object was passed
// then pass its $element instead
// so that we can do oxObj.jqFn(oxObj)
if (arg && arg.ox) {
args[i] = arg.$element;
}
});
ret = that.$element[key].apply(that.$element, args);
// if the $element of an ox object was returned
// then return the ox object instead
// so that we can do oxObj.jqFn().oxFn()
return ret.jquery && Ox.UI.elements[id = ret.data('oxid')] ?
Ox.UI.elements[id] : ret;
};
}
});

196
source/js/Ox.Keyboard.js Normal file
View file

@ -0,0 +1,196 @@
/***
Ox.Keyboard
***/
(function() {
var buffer = '',
bufferTime = 0,
bufferTimeout = 1000,
// wrapped in function so it can be collapsed in text editor
keyNames = (function() {
return {
0: 'section',
8: 'backspace',
9: 'tab',
12: 'clear',
13: 'enter',
16: 'shift',
17: 'control',
18: 'alt',
20: 'capslock',
27: 'escape',
32: 'space',
33: 'pageup',
34: 'pagedown',
35: 'end',
36: 'home',
37: 'left',
38: 'up',
39: 'right',
40: 'down',
45: 'insert',
46: 'delete',
47: 'help',
48: '0',
49: '1',
50: '2',
51: '3',
52: '4',
53: '5',
54: '6',
55: '7',
56: '8',
57: '9',
65: 'a',
66: 'b',
67: 'c',
68: 'd',
69: 'e',
70: 'f',
71: 'g',
72: 'h',
73: 'i',
74: 'j',
75: 'k',
76: 'l',
77: 'm',
78: 'n',
79: 'o',
80: 'p',
81: 'q',
82: 'r',
83: 's',
84: 't',
85: 'u',
86: 'v',
87: 'w',
88: 'x',
89: 'y',
90: 'z',
//91: 'meta.left',
//92: 'meta.right',
91: 'meta',
//92: 'meta',
93: 'meta',
96: '0.numpad',
97: '1.numpad',
98: '2.numpad',
99: '3.numpad',
100: '4.numpad',
101: '5.numpad',
102: '6.numpad',
103: '7.numpad',
104: '8.numpad',
105: '9.numpad',
106: 'asterisk.numpad',
107: 'plus.numpad',
109: 'minus.numpad',
108: 'enter.numpad',
110: 'dot.numpad',
111: 'slash.numpad',
112: 'f1',
113: 'f2',
114: 'f3',
115: 'f4',
116: 'f5',
117: 'f6',
118: 'f7',
119: 'f8',
120: 'f9',
121: 'f10',
122: 'f11',
123: 'f12',
124: 'f13',
125: 'f14',
126: 'f15',
127: 'f16',
144: 'numlock',
145: 'scrolllock',
186: 'semicolon',
187: 'equal',
188: 'comma',
189: 'minus',
190: 'dot',
191: 'slash',
192: 'backtick',
219: 'openbracket',
220: 'backslash',
221: 'closebracket',
222: 'quote'
// see dojo, for ex.
};
})(),
modifierNames = {
altKey: 'alt', // mac: option
ctrlKey: 'control',
// metaKey: 'meta', // mac: command
shiftKey: 'shift'
};
Ox.UI.ready(function() {
// fixme: how to do this better?
// in firefox on mac, keypress doesn't fire for up/down
// if the cursor is at the start/end of an input element
// on linux, it doesn't seem to fire if the input element has focus
if ($.browser.mozilla) {
Ox.UI.$document.keypress(keypress);
Ox.UI.$document.keydown(function(event) {
var $element = $('input:focus');
if ($element.length) {
if (
(
keyNames[event.keyCode] == 'up' &&
$element[0].selectionStart + $element[0].selectionEnd == 0
) || (
keyNames[event.keyCode] == 'down' &&
$element[0].selectionStart == $element.val().length &&
$element[0].selectionEnd == $element.val().length
)
) {
keypress(event);
}
}
});
} else {
Ox.UI.$document.keydown(keypress);
}
});
function keypress(event) {
var focused = Ox.Focus.focused(),
key,
keys = [],
//ret = true,
time;
Ox.forEach(modifierNames, function(v, k) {
event[k] && keys.push(v);
});
// avoid pushing modifier twice
if (keyNames[event.keyCode] && keys.indexOf(keyNames[event.keyCode]) == -1) {
keys.push(keyNames[event.keyCode]);
}
key = keys.join('_');
if (key.match(/^[\w\d\-]$|SPACE/)) {
time = Ox.getTime();
if (time - bufferTime > bufferTimeout) {
buffer = '';
}
buffer += key == 'SPACE' ? ' ' : key;
bufferTime = time;
}
focused !== null && Ox.UI.elements[focused].triggerEvent('key_' + key);
if (['down', 'space', 'up'].indexOf(key) > -1 && !Ox.UI.elements[focused].hasClass('OxInput')) {
// prevent chrome from scrolling
return false;
}
/*
stack.forEach(function(v) {
// fixme: we dont get the return value!
ret = Ox.event.trigger(keyboard + Ox.toCamelCase(key) + '.' + v);
return ret;
});
*/
}
})();

34
source/js/Ox.Label.js Normal file
View file

@ -0,0 +1,34 @@
Ox.Label = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
disabled: false,
id: '',
overlap: 'none',
textAlign: 'left',
title: '',
width: 'auto'
})
.options(options)
.addClass(
'OxLabel' + (self.options.disabled ? ' OxDisabled' : '') +
(self.options.overlap != 'none' ?
' OxOverlap' + Ox.toTitleCase(self.options.overlap) : '')
)
.css($.extend(self.options.width == 'auto' ? {} : {
width: (self.options.width - 14) + 'px'
}, {
textAlign: self.options.textAlign
}))
.html(self.options.title);
self.onChange = function(key, value) {
if (key == 'title') {
that.html(value);
}
}
return that;
};

View file

@ -0,0 +1,212 @@
Ox.LargeTimeline = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
cuts: [],
duration: 0,
find: '',
matches: [],
points: [0, 0],
position: 0,
style: 'default',
subtitles: [],
videoId: '',
width: 0
})
.options(options || {})
.addClass('OxTimelineLarge')
.mouseleave(mouseleave)
.mousemove(mousemove)
.bindEvent({
anyclick: click,
dragstart: dragstart,
drag: drag
});
$.extend(self, {
$cuts: [],
$markerPoint: [],
$subtitles: [],
$tiles: {},
$tooltip: new Ox.Tooltip({
animate: false
}),
center: parseInt(self.options.width / 2),
element: that.$element[0],
fps: 25,
height: 64,
tileWidth: 1500
});
self.tiles = self.options.duration * self.fps / self.tileWidth;
self.$timeline = $('<div>')
.css({
left: self.center + 'px'
})
.appendTo(that.$element)
self.options.subtitles.forEach(function(v, i) {
self.$subtitles[i] = $('<div>')
.addClass('OxSubtitle' + (self.options.matches.indexOf(i) > -1 ? ' OxHighlight' : ''))
.css({
left: (v['in'] * self.fps) + 'px',
width: (((v['out'] - v['in']) * self.fps) - 2) + 'px'
})
.html(Ox.highlight(v.value, self.options.find))
.appendTo(self.$timeline)
});
self.options.cuts.forEach(function(v, i) {
self.$cuts[i] = $('<img>')
.addClass('OxCut')
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarkerCut.png'
})
.css({
left: (v * self.fps) + 'px'
})
.appendTo(self.$timeline)
});
self.$markerPosition = $('<img>')
.addClass('OxMarkerPosition')
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarkerPlay.png'
})
.appendTo(that.$element);
setMarker();
['In', 'Out'].forEach(function(v, i) {
self.$markerPoint[i] = $('<img>')
.addClass('OxMarkerPoint' + v)
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarker' + v + '.png'
})
.appendTo(self.$timeline);
setMarkerPoint(i);
});
setWidth();
setPosition();
function click(event, e) {
self.options.position = Ox.limit(
getPosition(e), 0, self.options.duration
);
setPosition();
triggerChangeEvent();
}
function dragstart(event, e) {
self.drag = {x: e.clientX};
}
function drag(event, e) {
self.options.position = Ox.limit(
self.options.position + (self.drag.x - e.clientX) / self.fps,
0, self.options.duration
);
self.drag.x = e.clientX;
setPosition();
triggerChangeEvent();
}
function getPosition(e) {
return self.options.position + (e.clientX - that.offset().left - self.center - 1) / self.fps
}
function mouseleave(e) {
self.clientX = 0;
self.clientY = 0;
self.$tooltip.hide();
}
function mousemove(e) {
self.clientX = e.clientX;
self.clientY = e.clientY;
updateTooltip();
}
function setMarkerPoint(i) {
self.$markerPoint[i].css({
left: (self.options.points[i] * self.fps) + 'px'
});
}
function setMarker() {
self.$markerPosition.css({
left: (self.center - 4) + 'px',
});
}
function setPosition() {
self.tile = parseInt(self.options.position * self.fps / self.tileWidth);
self.$timeline.css({
marginLeft: (-self.options.position * self.fps) + 'px'
});
Ox.range(
Math.max(self.tile - 1, 0), Math.min(self.tile + 2, self.tiles)
).forEach(function(v) {
if (!self.$tiles[v]) {
self.$tiles[v] = $('<img>')
.attr({
src: '/' + self.options.videoId + '/timelines/' + (
self.options.style == 'default' ? 'timeline' : self.options.style
) + '.64.' + v + '.png'
})
.css({
left: (v * self.tileWidth) + 'px'
})
.appendTo(self.$timeline);
}
});
if (self.clientX && self.clientY) {
updateTooltip();
}
}
function setWidth() {
self.center = parseInt(self.options.width / 2);
that.css({
width: self.options.width + 'px'
});
self.$timeline.css({
left: self.center + 'px'
});
setMarker();
}
function triggerChangeEvent() {
that.triggerEvent('change', {
position: self.options.position
});
}
function updateTooltip() {
var position = getPosition(self);
if (position >= 0 && position <= self.options.duration) {
self.$tooltip
.options({
title: Ox.formatDuration(position, 3)
})
.show(self.clientX, self.clientY);
} else {
self.$tooltip.hide();
}
}
self.onChange = function(key, value) {
if (key == 'points') {
setMarkerPoint(0);
setMarkerPoint(1);
} else if (key == 'position') {
setPosition();
} else if (key == 'width') {
setWidth();
}
};
return that;
};

1422
source/js/Ox.List.js Normal file

File diff suppressed because it is too large Load diff

41
source/js/Ox.ListItem.js Normal file
View file

@ -0,0 +1,41 @@
Ox.ListItem = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
construct: function() {},
data: {},
draggable: false,
position: 0,
unique: ''
})
.options(options || {});
constructItem();
function constructItem(update) {
var $element = self.options.construct(self.options.data)
.addClass('OxItem')
.attr({
draggable: self.options.draggable
})
.data({
id: self.options.data[self.options.unique],
position: self.options.position
});
if (update) {
that.$element.hasClass('OxSelected') && $element.addClass('OxSelected');
that.$element.replaceWith($element);
}
that.$element = $element;
}
self.onChange = function(key, value) {
if (key == 'data') {
constructItem(true);
}
}
return that;
};

357
source/js/Ox.ListMap.js Normal file
View file

@ -0,0 +1,357 @@
Ox.ListMap = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
addPlace: null,
height: 256,
labels: false,
places: null,
selected: [],
width: 256
})
.addClass('OxListMap')
.options(options || {})
.css({
width: self.options.width + 'px',
height: self.options.height + 'px'
});
self.columns = [
{
addable: false, // fixme: implement
id: 'id',
unique: true,
visible: false
},
{
editable: true,
id: 'name',
operator: '+',
removable: false,
title: 'Name',
visible: true,
width: 144
},
{
editable: true,
id: 'geoname',
removable: false,
operator: '+',
title: 'Geoname',
visible: true,
width: 192
},
{
format: function(value) {
return $('<img>')
.attr({
// fixme: not the right place to do these
src: Ox.UI.PATH + 'svg/ox.map/' + (value || 'NTHH') + '.' + (value == 'RE' ? 'png' : 'svg')
})
.load(function() {
$(this).css({
width: '21px',
height: '14px',
padding: '1px 0 0 1px'
})
});
},
id: 'countryCode',
operator: '+',
title: 'Flag',
visible: true,
width: 48
},
{
align: 'right',
format: {type: 'area', args: [0]},
id: 'size',
operator: '-',
title: 'Size',
visible: true,
width: 128
},
{
align: 'right',
format: toFixed,
id: 'lat',
operator: '+',
title: 'Latitude',
visible: true,
width: 96
},
{
align: 'right',
format: toFixed,
id: 'lng',
operator: '+',
title: 'Longitude',
visible: true,
width: 96
},
{
align: 'right',
format: toFixed,
id: 'south',
operator: '+',
title: 'South',
visible: false,
width: 96
},
{
align: 'right',
id: 'west',
operator: '+',
title: 'West',
visible: false,
width: 96
},
{
align: 'right',
format: toFixed,
id: 'north',
operator: '+',
title: 'North',
visible: false,
width: 96
},
{
align: 'right',
format: toFixed,
id: 'east',
operator: '+',
title: 'East',
visible: false,
width: 96
},
{
id: 'user',
operator: '+',
title: 'User',
visible: false,
width: 96
},
{
format: 'date',
id: 'created',
operator: '-',
title: 'Date Created',
visible: false,
width: 96,
},
{
format: 'date',
id: 'modified',
operator: '-',
title: 'Date Modified',
visible: false,
width: 96,
},
{
align: 'right',
id: 'matches',
operator: '-',
title: 'Matches',
visible: false,
width: 96,
}
];
self.$toolbar = new Ox.Bar({
size: 24
});
self.$findElement = new Ox.FormElementGroup({
elements: [
self.$findSelect = new Ox.Select({
items: [
{id: 'all', title: 'Find: All'},
{id: 'name', title: 'Find: Name'},
{id: 'geoname', title: 'Find: Geoname'},
{id: 'country', title: 'Find: Country'}
],
overlap: 'right',
width: 128
}),
self.$findInput = new Ox.Input({
clear: true,
width: 192
})
]
})
.css({float: 'right', margin: '4px'})
.appendTo(self.$toolbar)
self.$list = new Ox.TextList({
columns: self.columns,
columnsRemovable: true,
columnsVisible: true,
items: self.options.places,
pageLength: 100,
scrollbarVisible: true,
sort: [
{key: 'name', operator: '+'}
]
})
.bindEvent({
'delete': removeItem,
init: initList,
load: function() {
that.triggerEvent('loadlist');
},
open: openItem,
select: selectItem
});
self.$statusbar = new Ox.Bar({
size: 24
});
self.$status = new Ox.Element()
.css({paddingTop: '4px', margin: 'auto', textAlign: 'center'})
.appendTo(self.$statusbar);
self.mapResize = [
Math.round(self.options.width * 0.25),
Math.round(self.options.width * 0.5),
Math.round(self.options.width * 0.75)
];
if (Ox.isArray(self.options.places)) {
init(self.options.places)
} else {
self.options.places({}, function(result) {
Ox.print('$$$$', result.data.items)
self.options.places({
keys: self.columns.map(function(column) {
return column.id
}),
range: [0, result.data.items]
}, function(result) {
Ox.print('DATA', result)
init(result.data.items);
});
});
}
function init(places) {
Ox.print('PLACES', places)
self.$map = new Ox.Map({
clickable: true,
editable: true,
findPlaceholder: 'Find on Map',
height: self.options.height,
places: places,
statusbar: true,
toolbar: true,
width: self.mapResize[1],
zoombar: true
})
.bindEvent({
addplace: function(event, data) {
that.triggerEvent('addplace', data);
},
resize: function() {
self.$map.resizeMap(); // fixme: don't need event
},
selectplace: selectPlace
});
that.$element.replaceWith(
that.$element = new Ox.SplitPanel({
elements: [
{
element: new Ox.SplitPanel({
elements: [
{
element: self.$toolbar,
size: 24
},
{
element: self.$list
},
{
element: self.$statusbar,
size: 24
}
],
orientation: 'vertical'
})
},
{
element: self.$map,
resizable: true,
resize: self.mapResize,
size: self.mapResize[1]
}
],
orientation: 'horizontal'
}).$element
);
}
function initList(event, data) {
self.$status.html(data.items + ' place' + (data.items == 1 ? '' : 's'))
}
function openItem(event, data) {
selectItem(event, data);
self.$map.zoomToPlace(data.ids[0]);
}
function removeItem(event, data) {
var id = data.ids[0];
that.triggerEvent('removeplace', {id: id});
self.$map.removePlace(id);
}
function selectItem(event, data) {
Ox.print('selectItem', data.ids[0])
var id = data.ids.length ? data.ids[0] : null;
self.$map.options({selected: id});
id && self.$map.panToPlace();
}
function selectPlace(event, data) {
Ox.print('selectPlace', data, data.id)
data.id && data.id[0] != '_' && self.$list.options({
selected: data.id ? [data.id] : []
});
}
function toFixed(val) {
return val.toFixed(8);
}
self.onChange = function(key, value) {
Ox.print('ONCHANGE')
if (key == 'height' || key == 'width') {
Ox.print('ONCHANGE...')
self.$map.options({
height: self.options.height,
width: self.options.width
})
} else if (key == 'selected') {
self.$list.options({selected: value});
}
}
that.focusList = function() {
self.$list.gainFocus();
return that;
}
that.reloadList = function() {
self.$list.reloadList();
return that;
}
that.resizeMap = function() {
Ox.print('Ox.ListMap.resizeMap()')
self.$map.resizeMap();
return that;
};
return that;
};

6
source/js/Ox.ListPage.js Normal file
View file

@ -0,0 +1,6 @@
Ox.ListPage = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.addClass('OxPage');
return that;
};

View file

@ -0,0 +1,27 @@
Ox.LoadingIcon = function(options, self) {
var self = self || {},
that = new Ox.Element('img', self)
.defaults({
size: 'medium'
})
.options(options || {})
.attr({
src: Ox.UI.getImagePath('symbolLoading.svg')
})
.addClass(
'OxLoadingIcon Ox' + Ox.toTitleCase(self.options.size)
);
that.start = function() {
that.animate({
opacity: 1
}, 250);
return that;
};
that.stop = function() {
that.animate({
opacity: 0
}, 250);
return that;
}
return that;
}

184
source/js/Ox.MainMenu.js Normal file
View file

@ -0,0 +1,184 @@
/**
*/
Ox.MainMenu = function(options, self) {
var self = self || {},
that = new Ox.Bar({}, self)
.defaults({
extras: [],
menus: [],
size: 'medium'
})
.options(options || {})
.addClass('OxMainMenu Ox' + Ox.toTitleCase(self.options.size)) // fixme: bar should accept small/medium/large ... like toolbar
.click(click)
.mousemove(mousemove);
self.focused = false;
self.selected = -1;
that.menus = [];
that.titles = [];
that.layer = $('<div>').addClass('OxLayer');
self.options.menus.forEach(function(menu, position) {
that.titles[position] = $('<div>')
.addClass('OxTitle')
.html(menu.title)
.data('position', position)
.appendTo(that.$element);
that.menus[position] = new Ox.Menu($.extend(menu, {
element: that.titles[position],
mainmenu: that,
size: self.options.size
}))
.bindEvent({
hide: onHideMenu
});
});
if (self.options.extras.length) {
that.extras = $('<div>')
.addClass('OxExtras')
.appendTo(that.$element);
self.options.extras.forEach(function(extra) {
extra.css({
float: 'left' // fixme: need class!
}).appendTo(that.extras);
});
}
function click(event) {
var $target = $(event.target),
position = typeof $target.data('position') != 'undefined' ?
$target.data('position') : -1;
clickTitle(position);
}
function clickTitle(position) {
var selected = self.selected;
if (self.selected > -1) {
that.menus[self.selected].hideMenu();
}
if (position > -1) {
if (position != selected) {
self.focused = true;
self.selected = position;
that.titles[self.selected].addClass('OxSelected');
that.menus[self.selected].showMenu();
}
}
}
function mousemove(event) {
var $target = $(event.target),
focused,
position = typeof $target.data('position') != 'undefined' ?
$target.data('position') : -1;
if (self.focused && position != self.selected) {
if (position > -1) {
clickTitle(position);
} else {
focused = self.focused;
that.menus[self.selected].hideMenu();
self.focused = focused;
}
}
}
function onHideMenu() {
if (self.selected > -1) {
that.titles[self.selected].removeClass('OxSelected');
self.selected = -1;
}
self.focused = false;
}
self.onChange = function(key, value) {
};
that.addMenuAfter = function(id) {
};
that.addMenuBefore = function(id) {
};
that.checkItem = function(id) {
var ids = id.split('_'),
itemId = ids.pop(),
menuId = ids.join('_');
that.getMenu(menuId).checkItem(itemId);
};
that.disableItem = function(id) {
that.getItem(id).options({
disabled: true
});
};
that.enableItem = function(id) {
Ox.print('ENABLE ITEM', id)
that.getItem(id).options({
disabled: false
});
};
that.getItem = function(id) {
var ids = id.split('_'),
item;
if (ids.length == 1) {
Ox.forEach(that.menus, function(menu) {
item = menu.getItem(id);
return !item;
});
} else {
item = that.getMenu(ids.shift()).getItem(ids.join('_'));
}
Ox.print('getItem', id, item);
return item;
};
that.getMenu = function(id) {
var ids = id.split('_'),
menu;
if (ids.length == 1) {
Ox.forEach(that.menus, function(v) {
if (v.options('id') == id) {
menu = v;
return false;
}
});
} else {
menu = that.getMenu(ids.shift()).getSubmenu(ids.join('_'));
}
//Ox.print('getMenu', id, menu);
return menu;
};
that.removeMenu = function() {
};
that.selectNextMenu = function() {
if (self.selected < self.options.menus.length - 1) {
clickTitle(self.selected + 1);
}
};
that.selectPreviousMenu = function() {
if (self.selected) {
clickTitle(self.selected - 1);
}
};
that.uncheckItem = function(id) {
that.getItem(id).options({
checked: false
});
};
return that;
};

950
source/js/Ox.Map.js Normal file
View file

@ -0,0 +1,950 @@
Ox.Map = function(options, self) {
var self = self || {}
that = new Ox.Element('div', self)
.defaults({
// fixme: isClickable? hasZoombar?
clickable: false,
editable: false,
findPlaceholder: 'Find',
labels: false,
markers: 100,
places: [],
selected: null,
statusbar: false,
toolbar: false,
zoombar: false
})
.options(options || {})
.addClass('OxMap')
.click(function(e) {
!$(e.target).is('input') && that.gainFocus();
})
.bindEvent({
key_0: function() {
that.panToPlace()
},
key_down: function() {
pan(0, 1);
},
key_enter: pressEnter,
key_escape: pressEscape,
key_equal: function() {
zoom(1);
},
key_l: toggleLabels,
key_left: function() {
pan(-1, 0);
},
key_meta: function() {
self.metaKey = true;
$(document).one({
keyup: function() {
self.metaKey = false;
}
});
},
key_minus: function() {
zoom(-1);
},
key_right: function() {
pan(1, 0);
},
key_shift: function() {
self.shiftKey = true;
$(document).one({
keyup: function() {
self.shiftKey = false;
}
});
},
key_shift_down: function() {
pan(0, 2);
},
key_shift_0: function() {
that.zoomToPlace();
},
key_shift_equal: function() {
zoom(2)
},
key_shift_left: function() {
pan(-2, 0);
},
key_shift_minus: function() {
zoom(-2);
},
key_shift_right: function() {
pan(2, 0);
},
key_shift_up: function() {
pan(0, -2);
},
key_up: function() {
pan(0, -1);
},
key_z: undo
});
self.mapHeight = getMapHeight();
self.minZoom = getMinZoom();
self.scaleMeters = [
50000000, 20000000, 10000000,
5000000, 2000000, 1000000,
500000, 200000, 100000,
50000, 20000, 10000,
5000, 2000, 1000,
500, 200, 100,
50, 20, 10
];
Ox.extend(self, {
metaKey: false,
resultPlace: null,
shiftKey: false
});
if (self.options.toolbar) {
self.$toolbar = new Ox.Bar({
size: 24
})
.appendTo(that);
self.$labelsButton = new Ox.Button({
title: 'Show Labels',
width: 96
})
.css({float: 'left', margin: '4px'})
.bindEvent({
click: toggleLabels
})
.appendTo(self.$toolbar)
self.$findInput = new Ox.Input({
clear: true,
placeholder: self.options.findPlaceholder,
width: 192
})
.css({float: 'right', margin: '4px'})
.bindEvent({
submit: submitFind
})
.appendTo(self.$toolbar)
}
self.$map = new Ox.Element('div')
.css({
left: 0,
top: self.options.toolbar * 24 + 'px',
right: 0,
bottom: self.options.zoombar * 16 + self.options.statusbar * 24 + 'px'
})
.appendTo(that);
if (self.options.zoombar) {
self.$zoombar = new Ox.Bar({
size: 16
})
.css({
bottom: self.options.statusbar * 24 + 'px'
})
.appendTo(that);
}
if (self.options.statusbar) {
self.$statusbar = new Ox.Bar({
size: 24
})
.css({
bottom: 0
})
.appendTo(that);
self.$placeNameInput = new Ox.Input({
placeholder: 'Name',
width: 96
})
//.css({position: 'absolute', left: 4, top: 4})
.css({float: 'left', margin: '4px 1px 4px 4px'})
.appendTo(self.$statusbar);
self.$placeGeonameInput = new Ox.Input({
placeholder: 'Geoname',
width: 96
})
//.css({position: 'absolute', left: 104, top: 4})
.css({float: 'left', margin: '4px 1px 4px 4px'})
.appendTo(self.$statusbar);
self.$placeButton = new Ox.Button({
title: 'New Place',
width: 96
})
.css({float: 'right', margin: '4px 4px 4px 2px'})
.bindEvent({
click: clickPlaceButton
})
.appendTo(self.$statusbar);
}
self.$navigationButtons = {
'center': new Ox.Button({
title: 'close',
type: 'image'
})
.addClass('OxMapButton')
.css({
left: '24px',
top: '24px'
}),
'east': new Ox.Button({
title: 'right',
type: 'image'
})
.addClass('OxMapButton')
.css({
left: '44px',
top: '24px',
}),
'north': new Ox.Button({
title: 'up',
type: 'image'
})
.addClass('OxMapButton')
.css({
left: '24px',
top: '4px',
}),
'south': new Ox.Button({
title: 'down',
type: 'image'
})
.addClass('OxMapButton')
.css({
left: '24px',
top: '44px',
}),
'west': new Ox.Button({
title: 'left',
type: 'image'
})
.addClass('OxMapButton')
.css({
left: '4px',
top: '24px',
})
};
self.$scaleLabel = new Ox.Label({
textAlign: 'center',
title: '...'
})
.addClass('OxMapLabel')
.css({
right: '4px',
top: '4px'
});
if (!window.googleCallback) {
window.googleCallback = function() {
delete window.googleCallback;
initMap();
};
$.getScript('http://maps.google.com/maps/api/js?callback=googleCallback&sensor=false');
} else {
(function interval() {
window.google ? initMap() : setTimeout(interval, 100);
}());
}
function addPlaceToMap(place) {
// via find, click, or new place button
var exists = false;
if (!place) {
var bounds = self.map.getBounds(),
center = self.map.getCenter(),
southwest = new google.maps.LatLngBounds(
bounds.getSouthWest(), center
).getCenter(),
northeast = new google.maps.LatLngBounds(
center, bounds.getNorthEast()
).getCenter(),
place = new Ox.MapPlace({
countryCode: '',
editable: true,
geoname: '',
id: '_' + Ox.uid(), // fixme: stupid
lat: center.lat(),
lng: center.lng(),
map: that,
name: '',
south: southwest.lat(),
west: southwest.lng(),
north: northeast.lat(),
east: northeast.lng()
});
}
Ox.forEach(self.places, function(p, i) {
if (place.bounds.equals(p.bounds)) {
place = p;
exists = true;
return false;
}
});
if (!exists) {
self.resultPlace && self.resultPlace.removeElement();
self.resultPlace = place;
place.add();
}
selectPlace(place.id);
}
function addPlaceToPlaces() {
var place = getSelectedPlace();
if (self.options.selected == place.id) {
self.options.selected = place.id.substr(1);
}
place.id = place.id.substr(1); // fixme: NOT SAFE!
place.name = self.$placeNameInput.value();
place.geoname = self.$placeGeonameInput.value();
place.countryCode = Ox.getCountryCode(place.geoname);
place.marker.update();
self.places.push(place);
self.resultPlace = null;
that.triggerEvent('addplace', place)
Ox.print('SSSS', self.options.selected)
}
function boundsChanged() {
setScale();
self.boundsChanged = true;
}
function canContain(outerBounds, innerBounds) {
var outerSpan = outerBounds.toSpan(),
innerSpan = innerBounds.toSpan();
return outerSpan.lat() > innerSpan.lat() &&
outerSpan.lng() > innerSpan.lng();
}
function centerChanged() {
self.center = self.map.getCenter();
self.centerChanged = true;
}
function changeZoom(event, data) {
self.map.setZoom(data.value);
}
function clickMap(event) {
Ox.print('Ox.Map clickMap')
if (self.options.clickable/* && !editing()*/) {
getPlaceByLatLng(event.latLng, self.map.getBounds(), function(place) {
if (place) {
addPlaceToMap(place);
//selectPlace(place.id);
} else {
selectPlace(null);
}
});
}
}
function clickPlaceButton() {
var place = getSelectedPlace(),
title = self.$placeButton.options('title');
if (title == 'New Place') {
addPlaceToMap();
} else if (title == 'Add Place') {
addPlaceToPlaces();
} else if (title == 'Remove Place') {
}
}
function constructZoomInput() {
Ox.print('constructZoomInput', self.minZoom, self.maxZoom)
if (self.options.zoombar) {
self.$zoomInput && self.$zoomInput.removeElement();
self.$zoomInput = new Ox.Range({
arrows: true,
max: self.maxZoom,
min: self.minZoom,
size: that.width(),
thumbSize: 32,
thumbValue: true,
value: self.map.getZoom()
})
.bindEvent({
change: changeZoom
})
.appendTo(self.$zoombar);
}
}
function editing() {
var place = getSelectedPlace();
return place && place.editing;
}
function getElevation(point, callback) {
// fixme: unused
if (arguments.length == 1) {
callback = point;
point = self.map.getCenter();
}
self.elevationService.getElevationForLocations({
locations: [point]
}, function(data) {
callback(data.elevation);
});
}
function getMapHeight() {
return self.options.height -
self.options.statusbar * 24 -
self.options.toolbar * 24 -
self.options.zoombar * 16;
}
function getMapType() {
return self.options.labels ? 'HYBRID' : 'SATELLITE'
}
function getMaxZoom(point, callback) {
if (arguments.length == 1) {
callback = point;
point = self.map.getCenter();
}
self.maxZoomService.getMaxZoomAtLatLng(point, function(data) {
callback(data.status == 'OK' ? data.zoom : null);
});
}
function getMinZoom() {
return 0;
return Math.ceil(
Ox.log(self.mapHeight / Ox.MAP_TILE_SIZE, 2)
);
}
function getPlaceById(id) {
var place = Ox.getObjectById(self.places, id);
if (!place && self.resultPlace && self.resultPlace.id == id) {
place = self.resultPlace;
}
Ox.print('getPlaceById', id, place)
return place;
}
function getPlaceByLatLng(latlng, bounds, callback) {
Ox.print('ll b', latlng, bounds)
var callback = arguments.length == 3 ? callback : bounds,
bounds = arguments.length == 3 ? bounds : null;
self.geocoder.geocode({
latLng: latlng
}, function(results, status) {
Ox.print('results', results)
var length = results.length;
if (status == google.maps.GeocoderStatus.OK) {
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
if (bounds) {
Ox.forEach(results.reverse(), function(result, i) {
if (
i == length - 1 ||
canContain(bounds, result.geometry.bounds || result.geometry.viewport)
) {
callback(new Ox.MapPlace(parseGeodata(results[i])));
return false;
}
});
} else {
callback(new Ox.MapPlace(parseGeodata(results[0])));
}
} else {
callback(null);
}
} else {
//Ox.print('geocode failed:', status);
callback(null);
}
});
}
function getPlaceByName(name, callback) {
self.geocoder.geocode({
address: name
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
Ox.print('GEOCODER RESULT', results[0])
callback(new Ox.MapPlace(parseGeodata(results[0])));
} else {
callback(null);
}
} else {
Ox.print('geocode failed:', status);
callback(null);
}
});
}
function getPositionByName(name) {
var position = -1;
Ox.forEach(self.options.places, function(place, i) {
if (place.name == name) {
position = i;
return false;
}
});
return position;
}
function getSelectedMarker() {
// needed in case self.options.selected
// is changed from outside
var id = null;
if (self.resultPlace && self.resultPlace.selected) {
id = self.resultPlace.id;
} else {
Ox.forEach(self.places, function(place) {
if (place.selected) {
id = place.id;
return false;
}
});
}
return id;
}
function getSelectedPlace() {
return self.options.selected ?
getPlaceById(self.options.selected) : null;
}
function initMap() {
var mapBounds;
updateFormElements();
self.elevationService = new google.maps.ElevationService();
self.geocoder = new google.maps.Geocoder();
self.maxZoomService = new google.maps.MaxZoomService();
self.places = [];
self.options.places.forEach(function(place, i) {
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(place.south, place.west),
new google.maps.LatLng(place.north, place.east)
);
if (Ox.isUndefined(place.id)) {
place.id = Ox.uid();
}
mapBounds = i == 0 ? bounds : mapBounds.union(bounds);
});
self.center = mapBounds ? mapBounds.getCenter() : new google.maps.LatLng(0, 0);
self.zoom = 1; // fixme: should depend on height
that.map = self.map = new google.maps.Map(self.$map.$element[0], {
center: self.center,
disableDefaultUI: true,
disableDoubleClickZoom: true,
mapTypeId: google.maps.MapTypeId[getMapType()],
zoom: self.zoom
});
google.maps.event.addListener(self.map, 'bounds_changed', boundsChanged);
google.maps.event.addListener(self.map, 'center_changed', centerChanged);
google.maps.event.addListener(self.map, 'click', clickMap);
google.maps.event.addListener(self.map, 'idle', mapChanged);
google.maps.event.addListener(self.map, 'zoom_changed', zoomChanged);
google.maps.event.addListenerOnce(self.map, 'tilesloaded', tilesLoaded);
mapBounds && self.map.fitBounds(mapBounds);
/*
setTimeout(function() {
}, 1000);
*/
self.options.places.forEach(function(place, i) {
self.places[i] = new Ox.MapPlace(Ox.extend({
map: that
}, place))/*.add()*/;
});
google.maps.event.trigger(self.map, 'resize');
//that.gainFocus();
that.triggerEvent('load');
function tilesLoaded() {
// fixme: can add earlier, use don't replace map contents option
Ox.forEach(self.$navigationButtons, function(button) {
button.appendTo(self.$map);
});
self.$scaleLabel.appendTo(self.$map);
}
}
function mapChanged() {
// gets called after panning or zooming
Ox.print('mapChanged');
var bounds;
if (self.boundsChanged) {
bounds = self.map.getBounds();
self.places.sort(function(a, b) {
var sort = {
a: a.selected ? Infinity :
(bounds.contains(a.center) ? a.size : -Infinity),
b: b.selected ? Infinity :
(bounds.contains(b.center) ? b.size : -Infinity),
};
return sort.b - sort.a;
}).forEach(function(place, i) {
if (i < self.options.markers && !place.visible) {
place.add();
} else if (i >= self.options.markers && place.visible) {
place.remove();
}
});
self.boundsChanged = false;
}
if (self.centerChanged) {
getMaxZoom(function(zoom) {
if (zoom != self.maxZoom) {
self.maxZoom = zoom;
if (self.map.getZoom() > zoom) {
self.map.setZoom(zoom);
}
constructZoomInput();
}
});
self.centerChanged = false;
}
if (self.zoomChanged) {
self.zoomChanged = false;
}
}
function pan(x, y) {
self.map.panBy(x * self.$map.width() / 2, y * self.$map.height() / 2);
};
function parseGeodata(data) {
var bounds = data.geometry.bounds || data.geometry.viewport,
place = {
components: data.address_components,
countryCode: getCountryCode(data.address_components),
east: bounds.getNorthEast().lng(),
editable: self.options.editable,
fullGeoname: getFullGeoname(data.address_components),
geoname: data.formatted_address,
id: '_' + Ox.uid(),
map: that,
name: data.formatted_address.split(', ')[0],
north: bounds.getNorthEast().lat(),
south: bounds.getSouthWest().lat(),
types: data.types.map(function(type) {
return Ox.toTitleCase(type.replace(/_/g, ' '));
}),
west: bounds.getSouthWest().lng()
};
function getCountryCode(components) {
countryCode = '';
Ox.forEach(components, function(component) {
if (component.types.indexOf('country') > -1) {
countryCode = component.short_name;
return false;
}
});
return countryCode;
}
function getFullGeoname(components) {
var country = false;
return components.map(function(component, i) {
var name = component.long_name;
if (i && components[i - 1].types.indexOf('country') > -1) {
country = true;
}
return !country && (
i == 0 || name != components[i - 1].long_name
) ? name : null;
}).join(', ')
}
return place;
}
function pressEnter() {
var place = getSelectedPlace();
if (place) {
if (place.editing) {
place.submit();
} else {
place.edit();
}
} else if (self.resultPlace) {
selectPlace(self.resultPlace.id)
}
}
function pressEscape() {
var place = getSelectedPlace();
if (place) {
if (place.editing) {
place.cancel();
} else {
selectPlace(null);
}
} else if (self.resultPlace) {
self.resultPlace.remove();
self.resultPlace = null;
}
}
function removePlace(id) {
}
function reset() {
//Ox.print(self.map.getZoom(), self.zoom);
self.map.getZoom() == self.zoom ?
self.map.panTo(self.center) :
self.map.fitBounds(self.bounds);
}
function resizeMap() {
/*
Ox.print('resizeMap', self.options.width, self.options.height);
var center = self.map.getCenter();
self.mapHeight = getMapHeight();
self.minZoom = getMinZoom();
that.css({
height: self.options.height + 'px',
width: self.options.width + 'px'
});
self.$map.css({
height: self.mapHeight + 'px',
width: self.options.width + 'px'
});
google.maps.event.trigger(self.map, 'resize');
self.map.setCenter(center);
*/
}
function selectPlace(id) {
var place,
selected = getSelectedMarker();
Ox.print('Ox.Map selectPlace()', id, selected);
if (id != selected) {
place = getPlaceById(selected);
place && place.deselect();
place = getPlaceById(id);
place && place.select();
self.options.selected = id;
setStatus();
that.triggerEvent('selectplace', place);
}
};
function getMetersPerPixel() {
var mapWidth = self.$map.width(),
span = self.map.getBounds().toSpan().lng();
if (span >= 360) {
span = 360 * mapWidth / Ox.MAP_TILE_SIZE;
}
return span * Ox.getMetersPerDegree(self.map.getCenter().lat()) / mapWidth;
}
function setScale() {
var metersPerPixel = getMetersPerPixel();
Ox.forEach(self.scaleMeters, function(meters) {
var scaleWidth = Math.round(meters / metersPerPixel);
if (scaleWidth <= 256) {
self.$scaleLabel
.options({
title: '\u2190 ' + (
meters > 1000 ? Ox.formatNumber(meters / 1000) + ' k' : meters + ' '
) + 'm \u2192'
})
.css({
width: (scaleWidth - 10) + 'px'
})
return false;
}
});
}
function setStatus() {
Ox.print('setStatus()', self.options.selected)
var disabled, place, title;
if (self.options.statusbar) {
place = getSelectedPlace();
if (place) {
title = place.id[0] == '_' ? 'Add Place' : 'Remove Place';
} else {
title = 'New Place';
}
disabled = place && !place.editable;
self.$placeNameInput.options({
disabled: disabled,
value: place ? place.name : ''
});
self.$placeGeonameInput.options({
disabled: disabled,
value: place ? place.geoname : ''
});
self.$placeButton.options({
disabled: disabled,
title: title
});
}
Ox.print('STATUS DONE');
}
function submitFind(event, data) {
that.findPlace(data.value, function(place) {
setStatus(place);
});
}
function toggleLabels() {
self.options.labels = !self.options.labels
self.map.setMapTypeId(google.maps.MapTypeId[getMapType()]);
self.$labelsButton.options({
title: self.$labelsButton.options('title') == 'Show Labels' ?
'Hide Labels' : 'Show Labels'
});
}
function undo() {
Ox.print('Map undo')
var place = getSelectedPlace();
place.editing && place.undo();
}
function updateFormElements() {
var width = that.width();
self.$zoomInput && constructZoomInput();
self.$placeNameInput.options({
width: Math.floor((width - 112) / 2)
});
self.$placeGeonameInput.options({
width: Math.ceil((width - 112) / 2)
});
}
function zoom(z) {
self.map.setZoom(self.map.getZoom() + z);
}
function zoomChanged() {
var zoom = self.map.getZoom();
if (zoom < self.minZoom) {
self.map.setZoom(self.minZoom);
} else if (self.maxZoom && zoom > self.maxZoom) {
self.map.setZoom(self.maxZoom);
} else {
self.zoomChanged = true;
self.$zoomInput && self.$zoomInput.options({value: zoom});
that.triggerEvent('zoom', {
value: zoom
});
}
}
function zoomToPlace() {
Ox.print('zoomToPlace')
if (self.options.selected !== null) {
self.map.fitBounds(getPlaceById(self.options.selected).bounds);
}
}
self.onChange = function(key, value) {
/*if (key == 'height' || key == 'width') {
resizeMap();
} else */if (key == 'places') {
loadPlaces();
} else if (key == 'selected') {
selectPlace(value);
} else if (key == 'type') {
}
};
that.getKey = function() {
var key = null;
if (self.shiftKey) {
key = 'shift'
} else if (self.metaKey) {
key = 'meta'
}
return key;
}
that.editPlace = function() {
getPlaceById(self.options.selected).edit();
return that;
}
that.findPlace = function(name, callback) {
getPlaceByName(name, function(place) {
if (place) {
addPlaceToMap(place);
self.map.fitBounds(place.bounds);
}
callback(place);
});
};
that.panToPlace = function() {
Ox.print('panToPlace:', self.options.selected)
var place = getSelectedPlace();
place && self.map.panTo(place.center);
return that;
};
that.removePlace = function(id) {
return that;
};
that.resizeMap = function() {
/*
Ox.print('resizeMap', self.options.width, self.options.height);
var center = self.map.getCenter();
self.mapHeight = getMapHeight();
self.minZoom = getMinZoom();
that.css({
height: self.options.height + 'px',
width: self.options.width + 'px'
});
self.$map.css({
height: self.mapHeight + 'px',
width: self.options.width + 'px'
});
google.maps.event.trigger(self.map, 'resize');
self.map.setCenter(center);
*/
/*
Ox.print('Ox.Map.resizeMap()');
var center = self.map.getCenter();
self.options.height = that.$element.height();
self.options.width = that.$element.width();
Ox.print(self.options.width, self.options.height)
self.$map.css({
height: self.mapHeight + 'px',
width: self.options.width + 'px'
});
google.maps.event.trigger(self.map, 'resize');
self.map.setCenter(center);
self.options.zoombar && self.$zoomInput.options({
size: self.options.width
});
*/
updateFormElements();
google.maps.event.trigger(self.map, 'resize');
return that;
}
that.zoomToPlace = function() {
Ox.print('zoomToPlace')
var place = getSelectedPlace();
place && self.map.fitBounds(place.bounds);
return that;
};
that.zoom = function(value) {
self.map.setZoom(value);
return that;
};
return that;
};

67
source/js/Ox.MapImage.js Normal file
View file

@ -0,0 +1,67 @@
Ox.MapImage = function(options, self) {
/**
options
height image height (px)
places array of either names (''), points ([0, 0]),
or objects ({name, point, highlight})
type map type ('hybrid', 'roadmap', 'satellite', 'terrain')
width image width (px)
*/
var self = self || {},
that = new Ox.Element('img', self)
.defaults({
height: 360,
markerColorHighlight: 'yellow',
markerColorNormal: 'blue',
places: [],
type: 'satellite',
width: 640
})
.options(options || {})
$.extend(self, {
markers: {
highlight: [],
normal: []
},
src: 'http://maps.google.com/maps/api/staticmap?sensor=false' +
'&size=' + self.options.width + 'x' + self.options.height +
'&maptype=' + self.options.type
});
if (self.options.places.length) {
self.options.places.forEach(function(place) {
if (Ox.isString(place)) {
self.markers.normal.push(place);
} else if (Ox.isArray(place)) {
self.markers.normal.push(place.join(','));
} else {
self.markers[place.highlight ? 'highlight' : 'normal']
.push('point' in place ? place.point.join(',') : place.name)
}
});
Ox.forEach(self.markers, function(markers, k) {
if (markers.length) {
self.src += '&markers=icon:' + 'http://dev.pan.do:8000' +
Ox.UI.PATH + 'png/ox.map/marker' +
Ox.toTitleCase(self.options['markerColor' + Ox.toTitleCase(k)]) +
'.png|' + markers.join('|')
}
});
} else {
self.src += '&center=0,0&zoom=2'
}
that.attr({
src: self.src
});
self.onChange = function(key, value) {
};
return that;
};

130
source/js/Ox.MapMarker.js Normal file
View file

@ -0,0 +1,130 @@
Ox.MapMarker = function(options) {
var options = Ox.extend({
map: null,
place: null
}, options),
that = this;
Ox.forEach(options, function(val, key) {
that[key] = val;
});
that.marker = new google.maps.Marker({
raiseOnDrag: false,
shape: {coords: [8, 8, 8], type: 'circle'},
title: that.place.name,
//zIndex: 1000
});
setOptions();
function click() {
if (!that.place.selected) {
that.map.options({selected: that.place.id});
} else if (that.map.getKey() == 'meta') {
that.map.options({selected: null});
} else if (that.map.getKey() == 'shift') {
that.map.zoomToPlace();
} else {
that.map.panToPlace();
}
}
function dragstart(e) {
}
function drag(e) {
var northSouth = (that.place.north - that.place.south) / 2,
lat = Ox.limit(
e.latLng.lat(),
Ox.MIN_LATITUDE + northSouth,
Ox.MAX_LATITUDE - northSouth
),
lng = e.latLng.lng(),
span = Math.min(
that.place.sizeEastWest * Ox.getDegreesPerMeter(lat) / 2, 179.99999999
);
degreesPerMeter = Ox.getDegreesPerMeter(lat);
that.place.south += lat - that.place.lat;
that.place.north += lat - that.place.lat;
that.place.west = lng - span;
that.place.east = lng + span;
if (that.place.west < -180) {
that.place.west += 360;
} else if (that.place.east > 180) {
that.place.east -= 360;
}
Ox.print('west', that.place.west, 'east', that.place.east, 'span', span);
that.place.update();
that.marker.setOptions({
position: that.place.center
})
that.place.rectangle.update();
}
function dragend(e) {
}
function setOptions() {
// workaround to prevent marker from appearing twice
// after setting draggable from true to false
var fix = that.marker.getDraggable() && !that.place.editing;
that.marker.setOptions({
// fixme: cursor remains pointer
cursor: that.place.editing ? 'move' : 'pointer',
draggable: that.place.editing,
icon: new google.maps.MarkerImage(
Ox.UI.PATH + 'png/ox.map/marker' +
(that.place.id[0] == '_' ? 'Result' : '') +
(that.place.editing ? 'Editing' : (
that.place.selected ? 'Selected' : ''
)) + '.png',
new google.maps.Size(16, 16),
new google.maps.Point(0, 0),
new google.maps.Point(8, 8)
),
position: that.place.center
});
if (fix) {
that.marker.setVisible(false);
setTimeout(function() {
that.marker.setVisible(true);
}, 0);
}
}
that.add = function() {
//Ox.print('MapMarker add', that)
that.marker.setMap(that.map.map);
google.maps.event.addListener(that.marker, 'click', click);
return that;
};
that.edit = function() {
setOptions();
google.maps.event.addListener(that.marker, 'dragstart', dragstart);
google.maps.event.addListener(that.marker, 'drag', drag);
google.maps.event.addListener(that.marker, 'dragend', dragend);
};
that.remove = function() {
that.marker.setMap(null);
google.maps.event.clearListeners(that.marker);
return that;
};
that.submit = function() {
google.maps.event.clearListeners(that.marker, 'dragstart');
google.maps.event.clearListeners(that.marker, 'drag');
google.maps.event.clearListeners(that.marker, 'dragend');
}
that.update = function() {
setOptions();
}
return that;
};

156
source/js/Ox.MapPlace.js Normal file
View file

@ -0,0 +1,156 @@
Ox.MapPlace = function(options) {
options = Ox.extend({
east: 0,
editing: false,
geoname: '',
map: null,
name: '',
north: 0,
selected: false,
south: 0,
type: [],
visible: false,
west: 0
}, options);
var that = this;
Ox.forEach(options, function(val, key) {
that[key] = val;
});
update();
function update() {
that.points = {
ne: new google.maps.LatLng(that.north, that.east),
sw: new google.maps.LatLng(that.south, that.west)
};
that.bounds = new google.maps.LatLngBounds(that.points.sw, that.points.ne);
that.center = that.bounds.getCenter();
that.lat = that.center.lat();
that.lng = that.center.lng();
Ox.extend(that.points, {
e: new google.maps.LatLng(that.lat, that.east),
s: new google.maps.LatLng(that.south, that.lng),
se: new google.maps.LatLng(that.south, that.east),
n: new google.maps.LatLng(that.north, that.lng),
nw: new google.maps.LatLng(that.north, that.west),
w: new google.maps.LatLng(that.lat, that.west),
});
// fixme: use bounds.toSpan()
that.sizeNorthSouth = (that.north - that.south) *
Ox.EARTH_CIRCUMFERENCE / 360;
that.sizeEastWest = (that.east + (that.west > that.east ? 360 : 0) - that.west) *
Ox.getMetersPerDegree(that.lat);
that.size = Ox.getArea(
{lat: that.south, lng: that.west},
{lat: that.north, lng: that.east}
);
if (!that.marker) {
that.marker = new Ox.MapMarker({
map: that.map,
place: that
});
that.rectangle = new Ox.MapRectangle({
map: that.map,
place: that
});
}
//Ox.print('PLACE', that)
}
function editable() {
return that.map.options('editable') && that.editable;
}
that.add = function() {
//Ox.print('MapPlace add', that)
that.visible = true;
that.marker.add();
return that;
};
that.cancel = function() {
if (editable()) {
that.undo();
that.editing = false;
that.marker.update();
that.rectangle.deselect();
}
return that;
};
that.crossesDateline = function() {
return that.west > that.east;
}
that.deselect = function() {
that.editing && that.submit();
that.selected = false;
that.marker.update();
that.rectangle.remove();
return that;
};
that.edit = function() {
if (editable()) {
that.editing = true;
that.original = {
south: that.south,
west: that.west,
north: that.north,
east: that.east
};
that.marker.edit();
that.rectangle.select();
}
return that;
}
that.remove = function() {
that.editing && that.submit();
that.selected && that.deselect();
that.visible = false;
that.marker.remove();
return that;
};
that.select = function() {
that.selected = true;
!that.visible && that.add();
that.marker.update();
that.rectangle.add();
return that;
};
that.submit = function() {
if (editable()) {
that.editing = false;
that.marker.update();
that.rectangle.deselect();
}
return that;
};
that.update = function() {
update();
return that;
};
that.undo = function() {
if (editable()) {
Ox.forEach(that.original, function(v, k) {
that[k] = v;
});
that.update();
that.marker.update();
that.rectangle.update();
}
return that;
};
return that;
};

View file

@ -0,0 +1,88 @@
Ox.MapRectangle = function(options, self) {
var options = Ox.extend({
map: null,
place: null
}, options),
that = this;
Ox.forEach(options, function(val, key) {
that[key] = val;
});
that.rectangle = new google.maps.Rectangle({
clickable: true,
bounds: that.place.bounds,
});
that.markers = Ox.map(that.place.points, function(point, position) {
return new Ox.MapRectangleMarker({
map: that.map,
place: that.place,
position: position
});
});
setOptions();
function click() {
if (that.map.options('editable') && that.place.editable && !that.place.editing) {
that.place.edit();
} else if (that.map.getKey() == 'meta') {
that.place.submit();
} else if (that.map.getKey() == 'shift') {
that.map.zoomToPlace();
} else {
that.map.panToPlace();
}
}
function setOptions() {
var color = that.place.editing ? '#8080FF' : '#FFFFFF';
that.rectangle.setOptions({
fillColor: color,
fillOpacity: that.place.editing ? 0.1 : 0,
strokeColor: color,
strokeOpacity: 1,
strokeWeight: 2
})
}
that.add = function() {
that.rectangle.setMap(that.map.map);
google.maps.event.addListener(that.rectangle, 'click', click);
return that;
};
that.deselect = function() {
setOptions();
Ox.print('MARKERS', that.markers)
Ox.forEach(that.markers, function(marker) {
marker.remove();
});
};
that.remove = function() {
that.rectangle.setMap(null);
google.maps.event.clearListeners(that.rectangle);
return that
}
that.select = function() {
setOptions();
Ox.forEach(that.markers, function(marker) {
marker.add();
});
};
that.update = function() {
that.rectangle.setOptions({
bounds: that.place.bounds
});
Ox.forEach(that.markers, function(marker) {
marker.update();
});
}
return that;
};

View file

@ -0,0 +1,95 @@
Ox.MapRectangleMarker = function(options, self) {
var options = Ox.extend({
map: null,
place: null,
position: ''
}, options),
that = this;
Ox.forEach(options, function(val, key) {
that[key] = val;
});
that.markerImage = new google.maps.MarkerImage
that.marker = new google.maps.Marker({
cursor: that.position + '-resize',
draggable: true,
icon: new google.maps.MarkerImage(
Ox.UI.PATH + 'png/ox.map/markerResize.png',
new google.maps.Size(16, 16),
new google.maps.Point(0, 0),
new google.maps.Point(8, 8)
),
position: that.place.points[that.position],
raiseOnDrag: false
});
function dragstart(e) {
that.drag = {
lat: e.latLng.lat(),
lng: e.latLng.lng()
};
}
function drag(e) {
// fixme: implement shift+drag (center stays the same)
Ox.print(e.pixel.x, e.pixel.y)
var lat = Ox.limit(e.latLng.lat(), Ox.MIN_LATITUDE, Ox.MAX_LATITUDE),
lng = e.latLng.lng();
that.drag = {
lat: lat,
lng: lng
};
if (that.position.indexOf('s') > -1) {
that.place.south = lat;
}
if (that.position.indexOf('n') > -1) {
that.place.north = lat;
}
if (that.position.indexOf('w') > -1) {
that.place.west = lng;
}
if (that.position.indexOf('e') > -1) {
that.place.east = lng;
}
Ox.print('west', that.place.west, 'east', that.place.east);
Ox.print('south', that.place.south, 'north', that.place.north);
that.place.update();
that.place.marker.update();
that.place.rectangle.update();
}
function dragend(e) {
var south;
if (that.place.south > that.place.north) {
south = that.place.south;
that.place.south = that.place.north;
that.place.north = south;
that.place.update();
that.place.marker.update();
that.place.rectangle.update();
}
}
that.add = function() {
that.marker.setMap(that.map.map);
google.maps.event.addListener(that.marker, 'dragstart', dragstart);
google.maps.event.addListener(that.marker, 'drag', drag);
google.maps.event.addListener(that.marker, 'dragend', dragend);
};
that.remove = function() {
that.marker.setMap(null);
google.maps.event.clearListeners(that.marker);
};
that.update = function() {
that.marker.setOptions({
position: that.place.points[that.position]
});
};
return that;
};

687
source/js/Ox.Menu.js Normal file
View file

@ -0,0 +1,687 @@
/**
options
element the element the menu is attached to
id the menu id
items array of menu items
mainmenu the main menu this menu is part of, if any
offset offset of the menu, in px
parent the supermenu, if any
selected the position of the selected item
side open to 'bottom' or 'right'
size 'large', 'medium' or 'small'
events:
change_groupId {id, value} checked item of a group has changed
click_itemId item not belonging to a group was clicked
click_menuId {id, value} item not belonging to a group was clicked
deselect_menuId {id, value} item was deselected not needed, not implemented
hide_menuId menu was hidden
select_menuId {id, value} item was selected
*/
Ox.Menu = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
element: null,
id: '',
items: [],
mainmenu: null,
offset: {
left: 0,
top: 0
},
parent: null,
selected: -1,
side: 'bottom',
size: 'medium',
})
.options(options || {})
.addClass(
'OxMenu Ox' + Ox.toTitleCase(self.options.side) +
' Ox' + Ox.toTitleCase(self.options.size)
)
.click(click)
.mouseenter(mouseenter)
.mouseleave(mouseleave)
.mousemove(mousemove)
.bindEvent({
key_up: selectPreviousItem,
key_down: selectNextItem,
key_left: selectSupermenu,
key_right: selectSubmenu,
key_escape: hideMenu,
key_enter: clickSelectedItem
}),
itemHeight = self.options.size == 'small' ? 12 : (self.options.size == 'medium' ? 16 : 20),
// menuHeight,
scrollSpeed = 1,
$item; // fixme: used?
// fixme: attach all private vars to self
// construct
that.items = [];
that.submenus = {};
that.$scrollbars = [];
that.$top = $('<div>')
.addClass('OxTop')
.appendTo(that.$element);
that.$scrollbars.up = constructScrollbar('up')
.appendTo(that.$element);
that.$container = $('<div>')
.addClass('OxContainer')
.appendTo(that.$element);
that.$content = $('<table>')
.addClass('OxContent')
.appendTo(that.$container);
constructItems(self.options.items);
that.$scrollbars.down = constructScrollbar('down')
.appendTo(that.$element);
that.$bottom = $('<div>')
.addClass('OxBottom')
.appendTo(that.$element);
that.$layer = $('<div>')
.addClass(self.options.mainmenu ? 'OxMainMenuLayer' : 'OxMenuLayer')
.click(click);
function click(event) {
var item,
position,
$target = $(event.target),
$parent = $target.parent();
// necessary for highlight
if ($parent.is('.OxCell')) {
$target = $parent;
$parent = $target.parent();
}
if ($target.is('.OxCell')) {
position = $parent.data('position');
item = that.items[position];
if (!item.options('disabled')) {
clickItem(position);
} else {
that.hideMenu();
}
} else {
that.hideMenu();
}
}
function clickItem(position) {
var item = that.items[position],
menu = self.options.mainmenu || self.options.parent || that,
toggled;
that.hideMenu();
if (!item.options('items').length) {
if (that.options('parent')) {
that.options('parent').hideMenu().triggerEvent('click');
}
if (item.options('checked') !== null) {
if (item.options('group')) {
//Ox.print('has group', item.options('group'))
toggled = self.optionGroups[item.options('group')].toggle(position);
//Ox.print('toggled', toggled)
if (toggled.length) {
toggled.forEach(function(pos) {
that.items[pos].toggleChecked();
});
//Ox.print('--triggering change event--');
menu.triggerEvent('change', {
id: item.options('group'),
checked: $.map(self.optionGroups[item.options('group')].checked(), function(v, i) {
return {
id: that.items[v].options('id'),
title: Ox.stripTags(that.items[v].options('title')[0])
};
})
});
}
} else {
item.toggleChecked();
menu.triggerEvent('change', {
checked: item.options('checked'),
id: item.options('id'),
title: Ox.stripTags(item.options('title')[0])
});
}
} else {
menu.triggerEvent('click', {
id: item.options('id'),
title: Ox.stripTags(item.options('title')[0])
});
}
if (item.options('title').length == 2) {
item.toggleTitle();
}
}
}
function clickSelectedItem() {
// called on key.enter
if (self.options.selected > -1) {
clickItem(self.options.selected);
} else {
that.hideMenu();
}
}
function constructItems(items) {
that.$content.empty();
scrollMenuUp();
self.optionGroups = {};
items.forEach(function(item, i) {
if (item.group) {
items[i] = $.map(item.items, function(v, i) {
return $.extend(v, {
group: item.group
});
});
self.optionGroups[item.group] = new Ox.OptionGroup(
items[i],
'min' in item ? item.min : 1,
'max' in item ? item.max : 1
);
}
});
items = Ox.flatten(items);
that.items = [];
items.forEach(function(item) {
var position;
if ('id' in item) {
that.items.push(new Ox.MenuItem($.extend(item, {
menu: that,
position: position = that.items.length
})).data('position', position).appendTo(that.$content)); // fixme: jquery bug when passing {position: position}? does not return the object?;
if (item.items) {
that.submenus[item.id] = new Ox.Menu({
element: that.items[position],
id: Ox.toCamelCase(self.options.id + '/' + item.id),
items: item.items,
mainmenu: self.options.mainmenu,
offset: {
left: 0,
top: -4
},
parent: that,
side: 'right',
size: self.options.size,
});
}
} else {
that.$content.append(constructSpace());
that.$content.append(constructLine());
that.$content.append(constructSpace());
}
});
if (!that.is(':hidden')) {
that.hideMenu();
that.showMenu();
}
}
function constructLine() {
return $('<tr>').append(
$('<td>', {
'class': 'OxLine',
colspan: 5
})
);
}
function constructScrollbar(direction) {
var interval,
speed = direction == 'up' ? -1 : 1;
return $('<div/>', {
'class': 'OxScrollbar Ox' + Ox.toTitleCase(direction),
html: Ox.UI.symbols['triangle_' + direction],
click: function() { // fixme: do we need to listen to click event?
return false;
},
mousedown: function() {
scrollSpeed = 2;
return false;
},
mouseenter: function() {
var $otherScrollbar = that.$scrollbars[direction == 'up' ? 'down' : 'up'];
$(this).addClass('OxSelected');
if ($otherScrollbar.is(':hidden')) {
$otherScrollbar.show();
that.$container.height(that.$container.height() - itemHeight);
if (direction == 'down') {
that.$content.css({
top: -itemHeight + 'px'
});
}
}
scrollMenu(speed);
interval = setInterval(function() {
scrollMenu(speed);
}, 100);
},
mouseleave: function() {
$(this).removeClass('OxSelected');
clearInterval(interval);
},
mouseup: function() {
scrollSpeed = 1;
return false;
}
});
}
function constructSpace() {
return $('<tr>').append(
$('<td>', {
'class': 'OxSpace',
colspan: 5
})
);
}
function getElement(id) {
// fixme: needed?
return $('#' + Ox.toCamelCase(options.id + '/' + id));
}
function getItemPositionById(id) {
var position;
Ox.forEach(that.items, function(item, i) {
if (item.options('id') == id) {
position = i;
return false;
}
});
return position;
}
function hideMenu() {
// called on key_escape
that.hideMenu();
}
function isFirstEnabledItem() {
var ret = true;
Ox.forEach(that.items, function(item, i) {
if (i < self.options.selected && !item.options('disabled')) {
return ret = false;
}
});
return ret;
}
function isLastEnabledItem() {
var ret = true;
Ox.forEach(that.items, function(item, i) {
if (i > self.options.selected && !item.options('disabled')) {
return ret = false;
}
});
return ret;
}
function mouseenter() {
that.gainFocus();
}
function mouseleave() {
if (self.options.selected > -1 && !that.items[self.options.selected].options('items').length) {
selectItem(-1);
}
}
function mousemove(event) {
var item,
position,
$target = $(event.target);
$parent = $target.parent();
if ($parent.is('.OxCell')) {
$target = $parent;
$parent = $target.parent();
}
if ($target.is('.OxCell')) {
position = $parent.data('position');
item = that.items[position];
if (!item.options('disabled') && position != self.options.selected) {
selectItem(position);
}
} else {
mouseleave();
}
}
function scrollMenu(speed) {
var containerHeight = that.$container.height(),
contentHeight = that.$content.height(),
top = parseInt(that.$content.css('top')) || 0,
min = containerHeight - contentHeight + itemHeight,
max = 0;
top += speed * scrollSpeed * -itemHeight;
if (top <= min) {
top = min;
that.$scrollbars.down.hide().trigger('mouseleave');
that.$container.height(containerHeight + itemHeight);
that.items[that.items.length - 1].trigger('mouseover');
} else if (top >= max - itemHeight) {
top = max;
that.$scrollbars.up.hide().trigger('mouseleave');
that.$container.height(containerHeight + itemHeight);
that.items[0].trigger('mouseover');
}
that.$content.css({
top: top + 'px'
});
}
function scrollMenuUp() {
if (that.$scrollbars.up.is(':visible')) {
that.$content.css({
top: '0px'
});
that.$scrollbars.up.hide();
if (that.$scrollbars.down.is(':hidden')) {
that.$scrollbars.down.show();
} else {
that.$container.height(that.$container.height() + itemHeight);
}
}
}
function selectItem(position) {
var item;
if (self.options.selected > -1) {
//Ox.print('s.o.s', self.options.selected, that.items)
item = that.items[self.options.selected]
item.removeClass('OxSelected');
/* disabled
that.triggerEvent('deselect', {
id: item.options('id'),
title: Ox.stripTags(item.options('title')[0])
});
*/
}
if (position > -1) {
item = that.items[position];
Ox.forEach(that.submenus, function(submenu, id) {
if (!submenu.is(':hidden')) {
submenu.hideMenu();
return false;
}
});
item.options('items').length && that.submenus[item.options('id')].showMenu(); // fixme: do we want to switch to this style?
item.addClass('OxSelected');
/* disabled
that.triggerEvent('select', {
id: item.options('id'),
title: Ox.stripTags(item.options('title')[0])
});
*/
}
self.options.selected = position;
}
function selectNextItem() {
var offset,
selected = self.options.selected;
//Ox.print('sNI', selected)
if (!isLastEnabledItem()) {
if (selected == -1) {
scrollMenuUp();
} else {
that.items[selected].removeClass('OxSelected');
}
do {
selected++;
} while (that.items[selected].options('disabled'))
selectItem(selected);
offset = that.items[selected].offset().top + itemHeight -
that.$container.offset().top - that.$container.height();
if (offset > 0) {
if (that.$scrollbars.up.is(':hidden')) {
that.$scrollbars.up.show();
that.$container.height(that.$container.height() - itemHeight);
offset += itemHeight;
}
if (selected == that.items.length - 1) {
that.$scrollbars.down.hide();
that.$container.height(that.$container.height() + itemHeight);
} else {
that.$content.css({
top: ((parseInt(that.$content.css('top')) || 0) - offset) + 'px'
});
}
}
}
}
function selectPreviousItem() {
var offset,
selected = self.options.selected;
//Ox.print('sPI', selected)
if (selected > - 1) {
if (!isFirstEnabledItem()) {
that.items[selected].removeClass('OxSelected');
do {
selected--;
} while (that.items[selected].options('disabled'))
selectItem(selected);
}
offset = that.items[selected].offset().top - that.$container.offset().top;
if (offset < 0) {
if (that.$scrollbars.down.is(':hidden')) {
that.$scrollbars.down.show();
that.$container.height(that.$container.height() - itemHeight);
}
if (selected == 0) {
that.$scrollbars.up.hide();
that.$container.height(that.$container.height() + itemHeight);
}
that.$content.css({
top: ((parseInt(that.$content.css('top')) || 0) - offset) + 'px'
});
}
}
}
function selectSubmenu() {
//Ox.print('selectSubmenu', self.options.selected)
if (self.options.selected > -1) {
var submenu = that.submenus[that.items[self.options.selected].options('id')];
//Ox.print('submenu', submenu, that.submenus);
if (submenu && submenu.hasEnabledItems()) {
submenu.gainFocus();
submenu.selectFirstItem();
} else if (self.options.mainmenu) {
self.options.mainmenu.selectNextMenu();
}
} else if (self.options.mainmenu) {
self.options.mainmenu.selectNextMenu();
}
}
function selectSupermenu() {
//Ox.print('selectSupermenu', self.options.selected)
if (self.options.parent) {
self.options.selected > -1 && that.items[self.options.selected].trigger('mouseleave');
scrollMenuUp();
self.options.parent.gainFocus();
} else if (self.options.mainmenu) {
self.options.mainmenu.selectPreviousMenu();
}
}
self.onChange = function(key, value) {
if (key == 'items') {
constructItems(value);
} else if (key == 'selected') {
that.$content.find('.OxSelected').removeClass('OxSelected');
selectItem(value);
}
}
that.addItem = function(item, position) {
};
that.addItemAfter = function(item, id) {
};
that.addItemBefore = function(item, id) {
};
that.checkItem = function(id) {
var item = that.getItem(id);
if (item.options('group')) {
var position = getItemPositionById(id),
toggled = self.optionGroups[item.options('group')].toggle(position);
if (toggled.length) {
toggled.forEach(function(pos) {
that.items[pos].toggleChecked();
});
}
} else {
item.options({
checked: true
});
}
};
that.getItem = function(id) {
//Ox.print('id', id)
var ids = id.split('_'),
item;
if (ids.length == 1) {
Ox.forEach(that.items, function(v) {
if (v.options('id') == id) {
item = v;
return false;
}
});
if (!item) {
Ox.forEach(that.submenus, function(submenu) {
item = submenu.getItem(id);
return !item;
});
}
} else {
item = that.submenus[ids.shift()].getItem(ids.join('_'));
}
return item;
};
that.getSubmenu = function(id) {
var ids = id.split('_'),
submenu;
if (ids.length == 1) {
submenu = that.submenus[id];
} else {
submenu = that.submenus[ids.shift()].getSubmenu(ids.join('_'));
}
//Ox.print('getSubmenu', id, submenu);
return submenu;
}
that.hasEnabledItems = function() {
var ret = false;
Ox.forEach(that.items, function(item) {
if (!item.options('disabled')) {
return ret = true;
}
});
return ret;
};
that.hideMenu = function() {
if (that.is(':hidden')) {
return;
}
Ox.forEach(that.submenus, function(submenu) {
if (submenu.is(':visible')) {
submenu.hideMenu();
return false;
}
});
selectItem(-1);
scrollMenuUp();
that.$scrollbars.up.is(':visible') && that.$scrollbars.up.hide();
that.$scrollbars.down.is(':visible') && that.$scrollbars.down.hide();
if (self.options.parent) {
//self.options.element.removeClass('OxSelected');
self.options.parent.options({
selected: -1
});
}
that.hide()
.loseFocus()
.triggerEvent('hide');
that.$layer.hide();
return that;
};
that.removeItem = function() {
};
that.selectFirstItem = function() {
selectNextItem();
};
that.showMenu = function() {
if (!that.is(':hidden')) {
return;
}
if (!self.options.parent && !that.$layer.parent().length) {
that.$layer.appendTo(Ox.UI.$body);
}
that.parent().length == 0 && that.appendTo(Ox.UI.$body);
that.css({
left: '-1000px',
top: '-1000px',
}).show();
var offset = self.options.element.offset(),
width = self.options.element.outerWidth(),
height = self.options.element.outerHeight(),
left = Ox.limit(
offset.left + self.options.offset.left + (self.options.side == 'bottom' ? 0 : width),
0, Ox.UI.$window.width() - that.width()
),
top = offset.top + self.options.offset.top + (self.options.side == 'bottom' ? height : 0),
menuHeight = that.$content.outerHeight(); // fixme: why is outerHeight 0 when hidden?
menuMaxHeight = Math.floor(Ox.UI.$window.height() - top - 16);
if (self.options.parent) {
if (menuHeight > menuMaxHeight) {
top = Ox.limit(top - menuHeight + menuMaxHeight, self.options.parent.offset().top, top);
menuMaxHeight = Math.floor(Ox.UI.$window.height() - top - 16);
}
}
that.css({
left: left + 'px',
top: top + 'px'
});
if (menuHeight > menuMaxHeight) {
that.$container.height(menuMaxHeight - itemHeight - 8); // margin
that.$scrollbars.down.show();
} else {
that.$container.height(menuHeight);
}
if (!self.options.parent) {
that.gainFocus();
}
that.$layer.show();
return that;
//that.triggerEvent('show');
};
that.toggleMenu = function() {
that.is(':hidden') ? that.showMenu() : that.hideMenu();
};
return that;
};

117
source/js/Ox.MenuItem.js Normal file
View file

@ -0,0 +1,117 @@
Ox.MenuItem = function(options, self) {
var self = self || {},
that = new Ox.Element('tr', self)
.defaults({
bind: [], // fixme: what's this?
checked: null,
disabled: false,
group: '',
icon: '',
id: '',
items: [],
keyboard: '',
menu: null, // fixme: is passing the menu to 100s of menu items really memory-neutral?
position: 0,
title: [],
})
.options($.extend(options, {
keyboard: parseKeyboard(options.keyboard || self.defaults.keyboard),
title: Ox.toArray(options.title || self.defaults.title)
}))
.addClass('OxItem' + (self.options.disabled ? ' OxDisabled' : ''))
/*
.attr({
id: Ox.toCamelCase(self.options.menu.options('id') + '/' + self.options.id)
})
*/
.data('group', self.options.group); // fixme: why?
if (self.options.group && self.options.checked === null) {
self.options.checked = false;
}
// construct
that.append(
that.$status = $('<td>', {
'class': 'OxCell OxStatus',
html: self.options.checked ? Ox.UI.symbols.check : ''
})
)
.append(
that.$icon = $('<td>', {
'class': 'OxCell OxIcon'
})
.append(self.options.icon ?
$('<img>', {
src: self.options.icon
}) : null
)
)
.append(
that.$title = $('<td>', {
'class': 'OxCell OxTitle',
html: self.options.title[0]
})
)
.append(
$('<td>', {
'class': 'OxCell OxModifiers',
html: $.map(self.options.keyboard.modifiers, function(modifier) {
return Ox.UI.symbols[modifier];
}).join('')
})
)
.append(
$('<td>', {
'class': 'OxCell Ox' + (self.options.items.length ? 'Submenu' : 'Key'),
html: self.options.items.length ? Ox.UI.symbols.triangle_right :
Ox.UI.symbols[self.options.keyboard.key] ||
self.options.keyboard.key.toUpperCase()
})
);
function parseKeyboard(str) {
var modifiers = str.split(' '),
key = modifiers.pop();
return {
modifiers: modifiers,
key: key
};
}
self.onChange = function(key, value) {
if (key == 'checked') {
that.$status.html(value ? Ox.UI.symbols.check : '')
} else if (key == 'disabled') {
that.toggleClass('OxDisabled'); // fixme: this will only work if onChange is only invoked on actual change
} else if (key == 'title') {
self.options.title = Ox.toArray(value);
that.$title.html(self.options.title[0]);
}
}
that.toggle = function() {
// toggle id and title
};
that.toggleChecked = function() {
that.options({
checked: !self.options.checked
});
};
that.toggleDisabled = function() {
};
that.toggleTitle = function() {
//Ox.print('s.o.t', self.options.title)
that.options({
title: self.options.title.reverse()
});
};
return that;
};

103
source/js/Ox.OptionGroup.js Normal file
View file

@ -0,0 +1,103 @@
Ox.OptionGroup = function(items, min, max, property) {
/*
to be used by ButtonGroup, CheckboxGroup, Select and Menu
*/
var property = property || 'checked'
length = items.length,
max = max == -1 ? length : max;
function getLastBefore(pos) {
// returns the position of the last checked item before position pos
var last = -1;
/*Ox.print(items, items.length, length, $.merge(
pos > 0 ? Ox.range(pos - 1, -1, -1) : [],
pos < items.length - 1 ? Ox.range(items.length - 1, pos, -1) : []
))*/
// fixme: why is length not == items.length here?
Ox.forEach($.merge(
pos > 0 ? Ox.range(pos - 1, -1, -1) : [],
pos < items.length - 1 ? Ox.range(items.length - 1, pos, -1) : []
), function(v) {
//Ox.print(pos, v)
if (items[v][property]) {
last = v;
return false;
}
});
return last;
}
function getNumber() {
// returns the number of checked items
var num = 0;
items.forEach(function(item) {
if (item[property]) {
num++;
}
})
return num;
}
this[property] = function() {
// returns an array with the positions of all checked item
var checked = [];
items.forEach(function(item, i) {
if (item[property]) {
checked.push(i);
}
})
return checked;
};
this.init = function() {
var num = getNumber(),
count = 0;
//if (num < min || num > max) {
items.forEach(function(item) {
if (Ox.isUndefined(item[property])) {
item[property] = false;
}
if (item[property]) {
count++;
if (count > max) {
item[property] = false;
}
} else {
if (num < min) {
item[property] = true;
num++;
}
}
});
//}
return items;
};
this.toggle = function(pos) {
var last,
num = getNumber(),
toggled = [];
if (!items[pos][property]) { // check
if (num >= max) {
last = getLastBefore(pos);
items[last][property] = false;
toggled.push(last);
}
if (!items[pos][property]) {
items[pos][property] = true;
toggled.push(pos);
}
} else { // uncheck
if (num > min) {
items[pos][property] = false;
toggled.push(pos);
}
}
return toggled;
}
return this;
}

8
source/js/Ox.Panel.js Normal file
View file

@ -0,0 +1,8 @@
/**
*/
Ox.Panel = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.addClass('OxPanel');
return that;
};

92
source/js/Ox.Picker.js Normal file
View file

@ -0,0 +1,92 @@
Ox.Picker = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
element: null,
elementHeight: 128,
elementWidth: 256,
id: '',
overlap: 'none'
})
.options(options || {});
self.$selectButton = new Ox.Button({
overlap: self.options.overlap,
title: 'select',
type: 'image'
})
.click(showMenu)
.appendTo(that);
self.$menu = new Ox.Element('div')
.addClass('OxPicker')
.css({
width: self.options.elementWidth + 'px',
height: (self.options.elementHeight + 24) + 'px'
});
self.options.element
.css({
width: self.options.elementWidth + 'px',
height: self.options.elementHeight + 'px'
})
.appendTo(self.$menu);
self.$bar = new Ox.Bar({
orientation: 'horizontal',
size: 24
})
.appendTo(self.$menu);
that.$label = new Ox.Label({
width: self.options.elementWidth - 60
})
.appendTo(self.$bar);
self.$doneButton = new Ox.Button({
title: 'Done',
width: 48
})
.click(hideMenu)
.appendTo(self.$bar);
self.$layer = $('<div>')
.addClass('OxLayer')
.click(hideMenu);
function hideMenu() {
self.$menu.detach();
self.$layer.detach();
self.$selectButton
.removeClass('OxSelected')
.css({
MozBorderRadius: '8px',
WebkitBorderRadius: '8px'
});
that.triggerEvent('hide');
};
function showMenu() {
var offset = that.offset(),
left = offset.left,
top = offset.top + 15;
self.$selectButton
.addClass('OxSelected')
.css({
MozBorderRadius: '8px 8px 0 0',
WebkitBorderRadius: '8px 8px 0 0'
});
self.$layer.appendTo(Ox.UI.$body);
self.$menu
.css({
left: left + 'px',
top: top + 'px'
})
.appendTo(Ox.UI.$body);
that.triggerEvent('show');
};
return that;
};

View file

@ -0,0 +1,34 @@
Ox.PlaceInput = function(options, self) {
var self = $.extend(self || {}, {
options: $.extend({
id: '',
value: 'United States'
}, options)
}),
that;
that = new Ox.FormElementGroup({
id: self.options.id,
elements: [
new Ox.Input({
id: 'input',
value: self.options.value
}),
new Ox.PlacePicker({
id: 'picker',
overlap: 'left',
value: self.options.value
})
],
float: 'right'
}, self)
.bindEvent('change', change);
function change() {
}
return that;
};

142
source/js/Ox.PlacePicker.js Normal file
View file

@ -0,0 +1,142 @@
Ox.PlacePicker = function(options, self) {
var self = $.extend(self || {}, {
options: $.extend({
id: '',
value: 'United States'
}, options)
}),
that;
self.$element = new Ox.Element('div')
.css({
width: '256px',
height: '192px'
})
.append(
self.$topBar = new Ox.Bar({
size: 16
})
.css({
MozBorderRadius: '0 8px 0 0',
WebkitBorderRadius: '0 8px 0 0'
})
.append(
self.$input = new Ox.Input({
clear: true,
id: self.options.id + 'Input',
placeholder: 'Find',
width: 256
})
.bindEvent('submit', findPlace)
)
)
.append(
self.$container = new Ox.Element('div')
.css({
width: '256px',
height: '160px'
})
)
.append(
self.$bottomBar = new Ox.Bar({
size: 16
})
.append(
self.$range = new Ox.Range({
arrows: true,
id: self.options.id + 'Range',
max: 22,
size: 256,
thumbSize: 32,
thumbValue: true
})
.bindEvent('change', changeZoom)
)
);
self.$input.$element.children('input[type=text]').css({
width: '230px',
paddingLeft: '2px',
MozBorderRadius: '0 8px 8px 0',
WebkitBorderRadius: '0 8px 8px 0'
});
self.$input.$element.children('input[type=image]').css({
MozBorderRadius: '0 8px 0 0',
WebkitBorderRadius: '0 8px 0 0'
});
self.$range.$element.children('input').css({
MozBorderRadius: 0,
WebkitBorderRadius: 0
});
that = new Ox.Picker({
element: self.$element,
elementHeight: 192,
elementWidth: 256,
id: self.options.id,
overlap: self.options.overlap,
value: self.options.value
}, self)
.bindEvent('show', showPicker);
that.$label.bind('click', clickLabel)
self.map = false;
function changeZoom(event, data) {
//Ox.print('changeZoom')
self.$map.zoom(data.value);
}
function clickLabel() {
var name = that.$label.html();
if (name) {
self.$input.options({
value: name
})
.triggerEvent('submit', {
value: name
});
}
}
function findPlace(event, data) {
//Ox.print('findPlace', data);
self.$map.find(data.value, function(place) {
place && that.$label.html(place.geoname);
})
}
function onSelect(event, data) {
that.$label.html(data.geoname);
}
function onZoom(event, data) {
self.$range.options({
value: data.value
});
}
function showPicker() {
if (!self.map) {
self.$map = new Ox.Map({
id: self.options.id + 'Map',
places: [self.options.value]
})
.css({
width: '256px',
height: '160px'
})
.bindEvent({
select: onSelect,
zoom: onZoom
})
.appendTo(self.$container);
self.map = true;
}
}
return that;
};

View file

@ -0,0 +1,4 @@
/**
Ox.Progressbar
*/

248
source/js/Ox.Range.js Normal file
View file

@ -0,0 +1,248 @@
Ox.Range = function(options, self) {
/**
options
arrows boolean if true, show arrows
arrowStep number step when clicking arrows
arrowSymbols array arrow symbols, like ['minus', 'plus']
max number maximum value
min number minimum value
orientation string 'horizontal' or 'vertical'
step number step between values
size number width or height, in px
thumbSize number minimum width or height of thumb, in px
thumbValue boolean if true, display value on thumb
trackGradient array colors
trackImages string or array one or multiple track background image URLs
trackStep number 0 (scroll here) or step when clicking track
value number initial value
valueNames array value names to display on thumb
*/
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
arrows: false,
arrowStep: 1,
arrowSymbols: ['left', 'right'],
max: 100,
min: 0,
orientation: 'horizontal',
step: 1,
size: 128,
thumbSize: 16,
thumbValue: false,
trackColors: [],
trackImages: [],
trackStep: 0,
value: 0,
valueNames: null,
})
.options($.extend(options, {
arrowStep: options.arrowStep ?
options.arrowStep : options.step,
trackImages: $.makeArray(options.trackImages || [])
}))
.addClass('OxRange')
.css({
width: self.options.size + 'px'
});
$.extend(self, {
trackColors: self.options.trackColors.length,
trackImages: self.options.trackImages.length,
values: (self.options.max - self.options.min + self.options.step) /
self.options.step
});
setSizes();
if (self.options.arrows) {
self.$arrows = [];
Ox.range(0, 2).forEach(function(i) {
self.$arrows[i] = new Ox.Button({
overlap: i == 0 ? 'right' : 'left',
title: self.options.arrowSymbols[i],
type: 'image'
})
.addClass('OxArrow')
.bindEvent({
mousedown: function(event, e) {
clickArrow(e, i, true);
},
mouserepeat: function(event, e) {
clickArrow(e, i, false);
}
})
.appendTo(that.$element);
});
}
self.$track = new Ox.Element()
.addClass('OxTrack')
.css($.extend({
width: (self.trackSize - 2) + 'px'
}, self.trackImages == 1 ? {
background: 'rgb(0, 0, 0)'
} : {}))
.bindEvent({
mousedown: clickTrack,
drag: dragTrack
})
.appendTo(that.$element);
self.trackColors && setTrackColors();
if (self.trackImages) {
self.$trackImages = $('<div>')
.css({
width: self.trackSize + 'px',
marginRight: (-self.trackSize - 1) + 'px'
})
.appendTo(self.$track.$element);
self.options.trackImages.forEach(function(v, i) {
//Ox.print(self.trackImageWidths[i])
$('<img>')
.attr({
src: v
})
.addClass(i == 0 ? 'OxFirstChild' : '')
.addClass(i == self.trackImages - 1 ? 'OxLastChild' : '')
.css({
width: self.trackImageWidths[i] + 'px'
})
.mousedown(function(e) {
e.preventDefault(); // prevent drag
})
.appendTo(self.$trackImages);
//left += self.trackImageWidths[i];
});
}
self.$thumb = Ox.Button({
id: self.options.id + 'Thumb',
title: self.options.thumbValue ? (self.options.valueNames ?
self.options.valueNames[self.options.value] :
self.options.value) : '',
width: self.thumbSize
})
.addClass('OxThumb')
/*
.css({
border: '1px solid rgb(255, 255, 255)',
background: 'rgba(0, 0, 0, 0)'
})
*/
.appendTo(self.$track);
setThumb();
function clickArrow(e, i, animate) {
// fixme: shift doesn't work, see menu scrolling
setValue(self.options.value + self.options.arrowStep * (i == 0 ? -1 : 1) * (e.shiftKey ? 2 : 1), animate);
}
function clickTrack(event, e) {
// fixme: thumb ends up a bit too far on the right
var isThumb = $(e.target).hasClass('OxThumb');
self.drag = {
left: self.$track.offset().left,
offset: isThumb ? e.clientX - self.$thumb.offset().left - 8 /*self.thumbSize / 2*/ : 0
};
setValue(getVal(e.clientX - self.drag.left - self.drag.offset), !isThumb);
}
function dragTrack(event, e) {
setValue(getVal(e.clientX - self.drag.left - self.drag.offset))
}
function getPx(val) {
var pxPerVal = (self.trackSize - self.thumbSize) /
(self.options.max - self.options.min);
return Math.ceil((val - self.options.min) * pxPerVal);
}
/*
function getTime(oldValue, newValue) {
return self.animationTime * Math.abs(oldValue - newValue) / (self.options.max - self.options.min);
}
*/
function getVal(px) {
var px = self.trackSize / self.values >= 16 ? px : px - 8,
valPerPx = (self.options.max - self.options.min) /
(self.trackSize - self.thumbSize);
return Ox.limit(self.options.min +
Math.floor(px * valPerPx / self.options.step) * self.options.step,
self.options.min, self.options.max);
}
function setSizes() {
self.trackSize = self.options.size - self.options.arrows * 32;
self.thumbSize = Math.max(self.trackSize / self.values, self.options.thumbSize);
self.trackImageWidths = self.trackImages == 1 ? [self.trackSize - 16] :
Ox.divideInt(self.trackSize - 2, self.trackImages);
self.trackColorsStart = self.thumbSize / 2 / self.options.size;
self.trackColorsStep = (self.options.size - self.thumbSize) /
(self.trackColors - 1) / self.options.size;
self.$track && self.$track.css({
width: (self.trackSize - 2) + 'px'
});
self.$thumb && self.$thumb.options({
width: self.thumbSize
});
}
function setThumb(animate) {
self.$thumb.stop().animate({
marginLeft: (getPx(self.options.value) - 1) + 'px',
//width: self.thumbSize + 'px'
}, animate ? 200 : 0, function() {
if (self.options.thumbValue) {
self.$thumb.options({
title: self.options.valueNames ?
self.options.valueNames[self.options.value] :
self.options.value
});
}
});
}
function setTrackColors() {
self.$track.css({
backgroundImage: $.browser.mozilla ?
('-moz-linear-gradient(left, ' +
self.options.trackColors[0] + ' 0%, ' + $.map(self.options.trackColors, function(v, i) {
return v + ' ' + ((self.trackColorsStart + self.trackColorsStep * i) * 100) + '%';
}).join(', ') + ', ' + self.options.trackColors[self.trackColors - 1] + ' 100%)') :
('-webkit-gradient(linear, left top, right top, color-stop(0, ' +
self.options.trackColors[0] + '), ' + $.map(self.options.trackColors, function(v, i) {
return 'color-stop(' + (self.trackColorsStart + self.trackColorsStep * i) + ', ' + v + ')';
}).join(', ') + ', color-stop(1, ' + self.options.trackColors[self.trackColors - 1] + '))')
});
}
function setValue(value, animate) {
var value = Ox.limit(value, self.options.min, self.options.max);
if (value != self.options.value) {
//time = getTime(self.options.value, value);
self.options.value = value;
setThumb(animate);
that.triggerEvent('change', {
value: value
});
}
}
self.onChange = function(key, value) {
if (key == 'size') {
setSizes();
} else if (key == 'trackColors') {
setTrackColors();
} else if (key == 'value') {
setThumb();
}
}
return that;
};

221
source/js/Ox.Request.js Normal file
View file

@ -0,0 +1,221 @@
Ox.Request = function(options) {
/***
Ox.Request
Basic request handler
Options
timeout
Methods
cancel() cancel request
clearCache() clear cache
options() get or set options
requests() return number of active requests
send() send request
***/
var cache = {},
//dfd = $.Deferred(),
pending = {},
requests = {},
self = {
options: $.extend({
timeout: 60000,
type: 'POST',
url: '/api/'
}, options)
};
return {
cancel: function() {
if (arguments.length == 0) {
// cancel all requests
requests = {};
} else if (Ox.isFunction(arguments[0])) {
// cancel with function
Ox.forEach(requests, function(req, id) {
if (arguments[0](req)) {
delete requests[id];
}
});
} else {
// cancel by id
delete requests[arguments[0]];
}
},
clearCache: function() {
cache = {};
},
options: function(options) {
return Ox.getset(self.options, options, $.noop(), this);
},
requests: function() {
return Ox.len(requests);
},
send: function(options) {
var options = $.extend({
age: -1,
callback: null,
id: Ox.uid(),
timeout: self.options.timeout,
type: self.options.type,
url: self.options.url
}, options),
req = JSON.stringify({
url: options.url,
data: options.data
});
if (pending[options.id]) {
setTimeout(function() {
Ox.Request.send(options);
}, 0);
} else {
requests[options.id] = {
url: options.url,
data: options.data
};
if (cache[req] && (options.age == -1 || options.age > Ox.getTime() - cache[req].time)) {
setTimeout(function() {
callback && callback(cache[req].data);
}, 0);
} else {
pending[options.id] = true;
$.ajax({
data: options.data,
dataType: 'json',
error: error,
success: success,
timeout: options.timeout,
type: options.type,
url: options.url
});
}
}
function callback(data) {
delete requests[options.id];
//Ox.len(requests) == 0 && $body.trigger('requestStop');
options.callback && options.callback(data);
}
function debug(request) {
var $iframe = $('<iframe>')
.css({ // fixme: should go into a class
width: 768,
height: 384
}),
$dialog = new Ox.Dialog({
title: 'Application Error',
buttons: [
new Ox.Button({
title: 'Close'
})
.bindEvent({
click: function() {
$dialog.close();
}
})
],
content: $iframe,
width: 800,
height: 400
})
.open(),
iframe = $iframe[0].contentDocument || $iframe[0].contentWindow.document;
iframe.open();
iframe.write(request.responseText);
iframe.close();
}
function error(request, status, error) {
var data;
if (arguments.length == 1) {
data = arguments[0]
} else {
try {
data = JSON.parse(request.responseText);
} catch (err) {
try {
data = {
status: {
code: request.status,
text: request.statusText
}
};
} catch (err) {
data = {
status: {
code: '500',
text: 'Unknown Error'
}
};
}
}
}
if (data.status.code < 500) {
callback(data);
} else {
var $dialog = new Ox.Dialog({
title: 'Application Error',
buttons: [
new Ox.Button({
id: 'details',
title: 'Details'
})
.bindEvent({
click: function() {
$dialog.close(function() {
debug(request);
});
}
}),
new Ox.Button({
id: 'close',
title: 'Close'
})
.bindEvent({
click: function() {
$dialog.close();
}
})
],
content: 'Sorry, we have encountered an application error while handling your request. To help us find out what went wrong, you may want to report this error to an administrator. Otherwise, please try again later.',
keys: {enter: 'close', escape: 'close'},
width: 400,
height: 200
})
.open();
// fixme: change this to Send / Don't Send
/*Ox.print({
request: request,
status: status,
error: error
});*/
}
pending[options.id] = false;
}
function success(data) {
pending[options.id] = false;
cache[req] = {
data: data,
time: Ox.getTime()
};
callback(data);
}
// return dfd.promise();
return options.id;
}
};
}();

143
source/js/Ox.Resizebar.js Normal file
View file

@ -0,0 +1,143 @@
/**
*/
Ox.Resizebar = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
collapsed: false,
collapsible: true,
edge: 'left',
elements: [],
orientation: 'horizontal',
parent: null,
resizable: true,
resize: [],
size: 0
})
.options(options || {}) // fixme: options function should be able to handle undefined, no need for || {}
.addClass('OxResizebar Ox' + Ox.toTitleCase(self.options.orientation))
/*
.attr({
draggable: 'true'
})
.bind('dragstart', function(e) {
// e.originalEvent.dataTransfer.setDragImage($('<div>')[0], 0, 0);
})
.bind('drag', function(e) {
Ox.print('dragging', e)
})
*/
.bindEvent({
anyclick: toggle,
dragstart: dragstart,
drag: drag,
dragend: dragend
})
.append($('<div>').addClass('OxSpace'))
.append($('<div>').addClass('OxLine'))
.append($('<div>').addClass('OxSpace'));
$.extend(self, {
clientXY: self.options.orientation == 'horizontal' ? 'clientY' : 'clientX',
dimensions: Ox.UI.DIMENSIONS[self.options.orientation], // fixme: should orientation be the opposite orientation here?
edges: Ox.UI.EDGES[self.options.orientation],
leftOrTop: self.options.edge == 'left' || self.options.edge == 'top'
});
function dragstart(event, e) {
if (self.options.resizable && !self.options.collapsed) {
Ox.print('DRAGSTART')
self.drag = {
startPos: e[self.clientXY],
startSize: self.options.size
}
} else { Ox.print('NO DRAGSTART r !c', self.options.resizable, !self.options.collapsed) }
}
function drag(event, e) {
if (self.options.resizable && !self.options.collapsed) {
var d = e[self.clientXY] - self.drag.startPos,
size = self.options.size;
self.options.size = Ox.limit(
self.drag.startSize + d * (self.leftOrTop ? 1 : -1),
self.options.resize[0],
self.options.resize[self.options.resize.length - 1]
);
Ox.forEach(self.options.resize, function(v) {
if (self.options.size >= v - 8 && self.options.size <= v + 8) {
self.options.size = v;
return false;
}
});
if (self.options.size != size) {
that.css(self.edges[self.leftOrTop ? 2 : 3], self.options.size + 'px');
// fixme: send {size: x}, not x
if (self.leftOrTop) {
self.options.elements[0]
.css(self.dimensions[1], self.options.size + 'px')
self.options.elements[1]
.css(self.edges[2], (self.options.size + 1) + 'px')
} else {
self.options.elements[0]
.css(self.edges[3], (self.options.size + 1) + 'px')
self.options.elements[1]
.css(self.dimensions[1], self.options.size + 'px')
}
triggerEvents('resize');
self.options.parent.updateSize(self.leftOrTop ? 0 : 1, self.options.size); // fixme: listen to event instead?
}
}
}
function dragend() {
if (self.options.resizable && !self.options.collapsed) {
self.options.size != self.drag.startSize && triggerEvents('resizeend');
}
}
function toggle() {
if (self.options.collapsible) {
// fixme: silly, pass a parameter
self.options.parent.toggle(
self.leftOrTop ? 0 :
self.options.parent.options('elements').length - 1
);
self.options.collapsed = !self.options.collapsed;
}
/*
//Ox.print('toggle');
if (Ox.isUndefined(self.options.position)) {
self.options.position = parseInt(self.options.parent.css(self.options.edge)) +
(self.options.collapsed ? self.options.size : 0);
}
var size = self.options.position -
(self.options.collapsed ? 0 : self.options.size),
animate = {};
//Ox.print('s.o.e', self.options.edge);
animate[self.options.edge] = size;
self.options.parent.animate(animate, 200, function() {
var i = (self.options.edge == 'left' || self.options.edge == 'top') ? 0 : 1;
self.options.collapsed = !self.options.collapsed;
Ox.Event.trigger(self.ids[i], 'toggle', self.options.collapsed);
Ox.Event.trigger(self.ids[1 - i], 'resize', self.options.elements[1 - i][self.dimensions[1]]());
});
*/
}
function triggerEvents(event) {
self.options.elements[0].triggerEvent(event,
self.leftOrTop ?
self.options.size :
self.options.elements[0][self.dimensions[1]]()
);
self.options.elements[1].triggerEvent(event,
self.leftOrTop ?
self.options.elements[1][self.dimensions[1]]() :
self.options.size
);
}
return that;
};

162
source/js/Ox.Select.js Normal file
View file

@ -0,0 +1,162 @@
Ox.Select = function(options, self) {
// fixme: selected item needs attribute "checked", not "selected" ... that's strange
var self = self || {},
that = new Ox.Element('div', self) // fixme: do we use 'div', or {}, or '', by default?
.defaults({
id: '',
items: [],
max: 1,
min: 1,
overlap: 'none', // can be none, left or right
selectable: true,
size: 'medium',
title: '',
type: 'text', // can be 'text' or 'image'
width: 'auto'
})
// fixme: make default selection restorable
// or allow for extra action items below options
.options(options)
.addClass(
'OxSelect Ox' + Ox.toTitleCase(self.options.size) +
(self.options.overlap == 'none' ? '' : ' OxOverlap' +
Ox.toTitleCase(self.options.overlap))
)
.css(self.options.width == 'auto' ? {} : {
width: self.options.width + 'px'
})
.bindEvent({
key_escape: loseFocus,
key_down: showMenu
});
Ox.print('Ox.Select', self.options)
$.extend(self, {
buttonId: self.options.id + 'Button',
groupId: self.options.id + 'Group',
menuId: self.options.id + 'Menu'
});
if (self.options.selectable) {
self.optionGroup = new Ox.OptionGroup(
self.options.items,
self.options.min,
self.options.max
);
self.options.items = self.optionGroup.init();
self.checked = self.optionGroup.checked();
}
if (self.options.type == 'text') {
self.$title = $('<div>')
.addClass('OxTitle')
.css({
width: (self.options.width - 22) + 'px'
})
.html(
self.options.title ? self.options.title :
self.options.items[self.checked[0]].title
)
.click(showMenu)
.appendTo(that.$element);
}
self.$button = new Ox.Button({
id: self.buttonId,
style: 'symbol',
title: 'select',
type: 'image'
})
.bindEvent('click', showMenu)
.appendTo(that);
self.$menu = new Ox.Menu({
element: self.$title || self.$button,
id: self.menuId,
items: [self.options.selectable ? {
group: self.groupId,
items: self.options.items,
max: self.options.max,
min: self.options.min
} : self.options.items],
side: 'bottom',
size: self.options.size
})
.bindEvent({
change: changeMenu,
click: clickMenu,
hide: hideMenu
});
self.options.type == 'image' && self.$menu.addClass('OxRight');
function clickMenu(event, data) {
that.triggerEvent('click', data);
}
function changeMenu(event, data) {
//Ox.print('clickMenu: ', self.options.id, data)
self.checked = self.optionGroup.checked();
self.$title && self.$title.html(
self.options.title ? self.options.title :
data.checked[0].title
);
that.triggerEvent('change', {
selected: data.checked
});
}
function hideMenu() {
//Ox.print('%% hideMenu that', that, 'self', self)
that.removeClass('OxSelected');
// self.$button.removeClass('OxSelected');
//Ox.print('%% hideMenu end')
}
function loseFocus() {
that.loseFocus();
}
function showMenu() {
that.gainFocus();
that.addClass('OxSelected');
self.$menu.showMenu();
}
self.onChange = function(key, value) {
};
that.selected = function() {
return $.map(/*self.checked*/self.optionGroup.checked(), function(v) {
return {
id: self.options.items[v].id,
title: self.options.items[v].title
};
});
};
that.selectItem = function(id) {
//Ox.print('selectItem', id, Ox.getObjectById(self.options.items, id).title)
self.options.type == 'text' && self.$title.html(
Ox.getObjectById(self.options.items, id).title[0] // fixme: title should not have become an array
);
self.$menu.checkItem(id);
self.checked = self.optionGroup.checked();
};
/*
that.width = function(val) {
// fixme: silly hack, and won't work for css() ... remove!
that.$element.width(val + 16);
that.$button.width(val);
//that.$symbol.width(val);
return that;
};
*/
return that;
};

View file

@ -0,0 +1,191 @@
Ox.SmallTimeline = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
duration: 0,
find: '',
matches: [],
points: [0, 0],
position: 0,
subtitles: [],
videoId: '',
width: 0
})
.options(options || {})
.addClass('OxTimelineSmall')
.mousedown(mousedown)
.mouseleave(mouseleave)
.mousemove(mousemove)
.bindEvent({
drag: function(event, e) {
mousedown(e);
}
});
$.extend(self, {
$images: [],
$markerPoint: [],
$subtitles: [],
$tooltip: new Ox.Tooltip({
animate: false
}).css({
textAlign: 'center'
}),
hasSubtitles: self.options.subtitles.length,
height: 16,
margin: 8
});
that.css({
width: (self.options.width + self.margin) + 'px',
height: (self.height + self.margin) + 'px'
});
self.$line = $('<img>')
.addClass('OxTimelineSmallImage')
.attr({
src: '/' + self.options.videoId + '/timelines/timeline.16.0.png'
})
.css({
position: 'absolute',
left: '4px',
top: '4px',
width: self.options.width,
height: '16px'
})
.appendTo(that.$element);
self.$markerPosition = $('<img>')
.addClass('OxMarkerPosition')
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarkerPlay.png'
})
.css({
position: 'absolute',
width: '9px',
height: '5px',
zIndex: 10
})
.appendTo(that.$element);
setPosition();
['in', 'out'].forEach(function(v, i) {
var titleCase = Ox.toTitleCase(v);
self.$markerPoint[i] = $('<img>')
.addClass('OxMarkerPoint' + titleCase)
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarker' + titleCase + '.png'
})
.appendTo(that.$element);
setMarkerPoint(i);
});
function getPosition(e) {
return e.offsetX / self.options.width * self.options.duration;
}
function getSubtitle(position) {
var subtitle = null;
Ox.forEach(self.options.subtitles, function(v) {
if (v['in'] <= position && v['out'] >= position) {
subtitle = v;
return false;
}
});
return subtitle;
}
function mousedown(e) {
var $target = $(e.target);
if (
$target.hasClass('OxTimelineSmallImage') ||
$target.hasClass('OxTimelineSmallSubtitles')
) {
self.options.position = getPosition(e);
setPosition();
that.triggerEvent('change', {
position: self.options.position
});
}
e.preventDefault();
}
function mouseleave(e) {
self.$tooltip.hide();
}
function mousemove(e) {
var $target = $(e.target),
position,
subtitle;
if (
$target.hasClass('OxTimelineSmallImage') ||
$target.hasClass('OxTimelineSmallSubtitles')
) {
position = getPosition(e),
subtitle = getSubtitle(position);
self.$tooltip.options({
title: subtitle ?
'<span class=\'OxBright\'>' +
Ox.highlight(subtitle.value, self.options.find).replace(/\n/g, '<br/>') + '</span><br/>' +
Ox.formatDuration(subtitle['in'], 3) + ' - ' + Ox.formatDuration(subtitle['out'], 3) :
Ox.formatDuration(position, 3)
})
.show(e.clientX, e.clientY);
} else {
self.$tooltip.hide();
}
}
function setMarker() {
self.$markerPosition
.css({
left: parseInt(
self.options.position / self.options.duration * self.options.width
) + 'px',
top: '2px',
});
}
function setMarkerPoint(i) {
var position = self.options.points[i];
self.$markerPoint[i]
.css({
left: (position % self.options.width) + 'px',
top: (parseInt(position / self.options.width) * (self.height + self.margin) + 16) + 'px',
});
}
function setPosition() {
self.options.position = Ox.limit(self.options.position, 0, self.options.duration);
setMarker();
}
function setWidth() {
self.$line.css({
width: self.options.width + 'px',
});
setMarker();
setMarkerPoint(0);
setMarkerPoint(1);
}
self.onChange = function(key, value) {
//Ox.print('onChange:', key, value)
if (key == 'points') {
//Ox.print('key', key, 'value', value)
setMarkerPoint(0);
setMarkerPoint(1);
} else if (key == 'position') {
setPosition();
} else if (key == 'width') {
setWidth();
}
};
return that;
};

435
source/js/Ox.SplitPanel.js Normal file
View file

@ -0,0 +1,435 @@
/**
options:
elements: [{ array of one, two or three elements
collapsible: false, collapsible or not (only for outer elements)
collapsed: false, collapsed or not (only for collapsible elements)
element: {}, OxElement (if any element is resizable or
collapsible, all OxElements must have an id)
resizable: false, resizable or not (only for outer elements)
resize: [], array of sizes (only for resizable elements,
first value is min, last value is max,
other values are 'snappy' points in between)
size: 0 size in px (one element must have no size)
}],
orientation: '' 'horizontal' or 'vertical'
events:
resize
toggle
*/
Ox.SplitPanel = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self) // fixme: Container
.defaults({
elements: [],
orientation: 'horizontal'
})
.options(options || {})
.addClass('OxSplitPanel');
$.extend(self, {
dimensions: Ox.UI.DIMENSIONS[self.options.orientation],
edges: Ox.UI.EDGES[self.options.orientation],
length: self.options.elements.length,
resizebarElements: [],
$resizebars: []
});
// create elements
that.$elements = [];
self.options.elements.forEach(function(v, i) {
self.options.elements[i] = $.extend({
collapsible: false,
collapsed: false,
resizable: false,
resize: [],
size: 'auto'
}, v);
that.$elements[i] = v.element
.css(self.edges[2], (parseInt(v.element.css(self.edges[2])) || 0) + 'px')
.css(self.edges[3], (parseInt(v.element.css(self.edges[3])) || 0) + 'px');
//alert(v.element.css(self.edges[3]))
});
// create resizebars
self.options.elements.forEach(function(v, i) {
//that.append(element)
//Ox.print('V: ', v, that.$elements[i])
var index = i == 0 ? 0 : 1;
that.$elements[i].appendTo(that.$element); // fixme: that.$content
if (v.collapsible || v.resizable) {
//Ox.print('v.size', v.size)
self.resizebarElements[index] = i < 2 ? [0, 1] : [1, 2];
self.$resizebars[index] = new Ox.Resizebar({
collapsible: v.collapsible,
edge: self.edges[index],
elements: [
that.$elements[self.resizebarElements[index][0]],
that.$elements[self.resizebarElements[index][1]]
],
id: v.element.options('id'),
orientation: self.options.orientation == 'horizontal' ? 'vertical' : 'horizontal',
parent: that, // fixme: that.$content
resizable: v.resizable,
resize: v.resize,
size: v.size
});
self.$resizebars[index][i == 0 ? 'insertAfter' : 'insertBefore'](that.$elements[i]);
}
});
self.options.elements.forEach(function(v, i) {
v.collapsed && that.css(
self.edges[i == 0 ? 0 : 1], -self.options.elements[i].size + 'px'
);
});
setSizes(true);
function getPositionById(id) {
var position = -1;
Ox.forEach(self.options.elements, function(element, i) {
if (element.element.options('id') == id) {
position = i;
return false;
}
});
//Ox.print('getPositionById', id, position);
return position;
}
function getSize(element) {
return element.size + (element.collapsible || element.resizable);
//return (element.size + (element.collapsible || element.resizable)) * !element.collapsed;
}
function getVisibleSize(element) {
return getSize(element) * !element.collapsed;
}
function setSizes(init) {
self.options.elements.forEach(function(v, i) {
// fixme: maybe we can add a conditional here, since init
// is about elements that are collapsed splitpanels
var edges = [
(init && parseInt(that.$elements[i].css(self.edges[0]))) || 0,
(init && parseInt(that.$elements[i].css(self.edges[1]))) || 0
];
v.size != 'auto' && that.$elements[i].css(self.dimensions[0], v.size + 'px');
if (i == 0) {
that.$elements[i].css(
self.edges[0], edges[0] + 'px'
);
that.$elements[i].css(
self.edges[1], (getSize(self.options.elements[1]) + (length == 3 ? getSize(self.options.elements[2]) : 0)) + 'px'
);
} else if (i == 1) {
that.$elements[i].css(
self.edges[0], self.options.elements[0].size == 'auto' ? 'auto' :
edges[0] + getSize(self.options.elements[0]) + 'px'
);
(self.options.elements[0].size != 'auto' || v.size != 'auto') && that.$elements[i].css(
self.edges[1], (self.length == 3 ? getSize(self.options.elements[2]) : 0) + 'px'
);
} else {
that.$elements[i].css(
self.edges[0], (self.options.elements[1].size == 'auto' || v.size == 'auto') ? 'auto' :
(getVisibleSize(self.options.elements[0]) + getVisibleSize(self.options.elements[1])) + 'px'
);
that.$elements[i].css(
self.edges[1], edges[1] + 'px'
);
}
if (v.collapsible || v.resizable) {
self.$resizebars[i == 0 ? 0 : 1].css(self.edges[i == 0 ? 0 : 1], v.size);
}
});
}
that.isCollapsed = function(id) {
var pos = Ox.isNumber(id) ? id : getPositionById(id);
return self.options.elements[pos].collapsed;
};
that.replaceElement = function(id, element) {
// one can pass pos instead of id
var pos = Ox.isNumber(id) ? id : getPositionById(id);
//Ox.print('replace', pos, element);
//Ox.print('element', self.options.elements[pos].element, element)
that.$elements[pos] = element
.css(self.edges[2], (parseInt(element.css(self.edges[2])) || 0) + 'px')
.css(self.edges[3], (parseInt(element.css(self.edges[3])) || 0) + 'px');
//alert(element.css(self.edges[3]))
self.options.elements[pos].element.replaceWith(element.$element.$element || element.$element);
self.options.elements[pos].element = element;
setSizes();
self.$resizebars.forEach(function($resizebar, i) {
$resizebar.options({
elements: [
that.$elements[self.resizebarElements[i][0]],
that.$elements[self.resizebarElements[i][1]]
]
});
});
//Ox.print(self.options.elements[pos])
return that;
};
that.replaceElements = function(elements) {
elements.forEach(function(element, i) {
if (Ox.isNumber(element.size)) {
that.size(i, element.size);
if (element.collapsible || element.resizable) {
self.$resizebars[i == 0 ? 0 : 1].options({
collapsible: element.collapsible,
resizable: element.resizable,
size: element.size
});
}
}
that.replace(i, element.element);
});
self.options.elements = elements;
self.$resizebars.forEach(function($resizebar, i) {
$resizebar.options({
elements: [
that.$elements[self.resizebarElements[i][0]],
that.$elements[self.resizebarElements[i][1]]
]
});
});
return that;
}
that.size = function(id, size) {
// one can pass pos instead of id
var pos = Ox.isNumber(id) ? id : getPositionById(id),
element = self.options.elements[pos];
if (arguments.length == 1) {
return element.element[self.dimensions[0]]() * !that.isCollapsed(pos);
} else {
element.size = size;
setSizes();
return that;
}
};
that.toggle = function(id) {
// one can pass pos instead of id
var pos = Ox.isNumber(id) ? id : getPositionById(id),
element = self.options.elements[pos],
value = parseInt(that.css(self.edges[pos == 0 ? 0 : 1])) +
element.element[self.dimensions[0]]() *
(element.collapsed ? 1 : -1),
animate = {};
animate[self.edges[pos == 0 ? 0 : 1]] = value;
that.animate(animate, 200, function() { // fixme: 250?
element.collapsed = !element.collapsed;
element.element.triggerEvent('toggle', {
'collapsed': element.collapsed
});
element = self.options.elements[pos == 0 ? 1 : pos - 1];
element.element.triggerEvent(
'resize',
element.element[self.dimensions[0]]()
);
});
};
that.updateSize = function(pos, size) {
// this is called from resizebar
var pos = pos == 0 ? 0 : self.options.elements.length - 1; // fixme: silly that 0 or 1 is passed, and not pos
self.options.elements[pos].size = size;
}
return that;
};
Ox.SplitPanel_ = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
elements: [],
orientation: 'horizontal'
})
.options(options)
.addClass(
'OxSplitPanel_ Ox' + Ox.toTitleCase(self.options.orientation)
);
Ox.extend(self, {
$separators: [],
clientXY: self.options.orientation == 'horizontal' ? 'clientX' : 'clientY',
dimensions: Ox.UI.DIMENSIONS[self.options.orientation],
edges: Ox.UI.EDGES[self.options.orientation]
});
self.options.elements.forEach(function(element, i) {
self.options.elements[i] = Ox.extend({
collapsible: false,
collapsed: false,
resizable: false,
resize: [],
size: 'auto'
}, element);
});
self.autoPercent = (100 - self.options.elements.reduce(function(val, element) {
return val + (Ox.endsWith(element.size, '%') ? parseFloat(element.size) : 0);
}, 0)) / self.options.elements.filter(function(element) {
return element.size == 'auto';
}).length + '%';
self.options.elements.forEach(function(element, i) {
var flex, index = i == 0 ? 0 : 1;
if (Ox.isNumber(element.size)) {
element.element.css(self.dimensions[0], element.size + 'px');
} else {
flex = (
element.size == 'auto' ? self.autoPercent : element.size
).replace('%', '');
element.element.css({
boxFlex: flex,
MozBoxFlex: flex,
WebkitBoxFlex: flex
});
}
element.element.appendTo(that);
if (element.collapsible || element.resizable) {
self.$separators.push(
Ox.Element()
.addClass('OxSeparator')
.bindEvent({
anyclick: function() {
that.toggle(i);
},
dragstart: function(event, e) {
dragstart(i, e);
},
drag: function(event, e) {
drag(i, e);
},
dragend: function(event, e) {
dragend(i, e);
},
})
.append($('<div>').addClass('OxSpace'))
.append($('<div>').addClass('OxLine'))
.append($('<div>').addClass('OxSpace'))
['insert' + (index ? 'Before' : 'After')](element.element)
);
}
});
function dragstart(pos, e) {
var element = self.options.elements[pos],
size = element.element[self.dimensions[0]]();
if (element.resizable && !element.collapsed) {
self.drag = {
size: size,
startPos: e[self.clientXY],
startSize: size
};
Ox.print('self.drag', self.drag)
}
}
function drag(pos, e) {
var data = {},
element = self.options.elements[pos],
index = pos == 0 ? 0 : 1;
if (element.resizable && !element.collapsed) {
var d = e[self.clientXY] - self.drag.startPos,
size = Ox.limit(
self.drag.startSize + d * (index ? -1 : 1),
element.resize[0],
element.resize[element.resize.length - 1]
);
Ox.forEach(element.resize, function(v) {
if (size >= v - 8 && size <= v + 8) {
size = v;
return false;
}
});
if (size != self.drag.size) {
self.drag.size = size;
data[self.dimensions[0]] = size;
element.element
.css(self.dimensions[0], size + 'px')
.triggerEvent('resize', data);
triggerEvents('resize', pos);
}
}
}
function dragend(pos, e) {
var data = {},
element = self.options.elements[pos];
if (element.resizable && !element.collapsed) {
data[self.dimensions[0]] = self.drag.size
element.element.triggerEvent('resizeend', data);
triggerEvents('resizeend', pos);
}
}
function triggerEvents(event, pos) {
var data = {};
self.options.elements.forEach(function(element, i) {
if (i != pos && element.size == 'auto') {
data[self.dimensions[0]] = element.element[self.dimensions[0]]();
element.element.triggerEvent(event, data);
}
});
}
that.replaceElement = function(pos, element) {
var $element = self.options.elements[pos].element,
size = self.options.elements[pos].size;
$element.replaceWith(self.options.elements[pos].element = element);
if (size == 'auto') {
$element.css(self.boxFlexCSS);
} else {
$element.css(self.dimensions[0], size + 'px')
}
return that;
};
that.size = function(pos, size) {
var element = self.options.elements[pos],
ret;
if (Ox.isUndefined(size)) {
ret = element.element[self.dimensions[0]]();
} else {
element.size = size;
element.element.css(self.dimensions[0], size + 'px')
ret = that;
}
return that;
}
that.toggle = function(pos) {
var css = {},
element = self.options.elements[pos],
flex,
index = pos == 0 ? 0 : 1,
size = element.element[self.dimensions[0]]();
if (element.collapsible) {
element.collapsed = !element.collapsed;
css['margin' + Ox.toTitleCase(self.edges[0][index])] =
element.collapsed ? -size : 0;
Ox.print('css', css);
that.animate(css, 250, function() {
element.element.triggerEvent('toggle', {collapsed: element.collapsed});
triggerEvents('resize', pos);
});
}
}
return that;
};

3
source/js/Ox.TabPanel.js Normal file
View file

@ -0,0 +1,3 @@
Ox.TabPanel = function(options, self) {
};

27
source/js/Ox.Tabbar.js Normal file
View file

@ -0,0 +1,27 @@
/**
*/
Ox.Tabbar = function(options, self) {
var self = self || {},
that = new Ox.Bar({
size: 20
}, self)
.defaults({
selected: 0,
tabs: []
})
.options(options || {})
.addClass('OxTabbar');
Ox.ButtonGroup({
buttons: self.options.tabs,
group: true,
selectable: true,
selected: self.options.selected,
size: 'medium',
style: 'tab',
}).appendTo(that);
return that;
};

719
source/js/Ox.TextList.js Normal file
View file

@ -0,0 +1,719 @@
Ox.TextList = function(options, self) {
// fixme: rename to TableList
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
columns: [],
columnsMovable: false,
columnsRemovable: false,
columnsResizable: false,
columnsVisible: false,
columnWidth: [40, 800],
id: '',
items: null, // function() {} {sort, range, keys, callback} or array
max: -1,
min: 0,
pageLength: 100,
scrollbarVisible: false,
selected: [],
sort: []
})
.options(options || {})
.addClass('OxTextList');
Ox.print('Ox.TextList self.options', self.options)
self.options.columns.forEach(function(v) { // fixme: can this go into a generic ox.js function?
// fixme: and can't these just remain undefined?
if (Ox.isUndefined(v.align)) {
v.align = 'left';
}
if (Ox.isUndefined(v.clickable)) {
v.clickable = false;
}
if (Ox.isUndefined(v.editable)) {
v.editable = false;
}
if (Ox.isUndefined(v.unique)) {
v.unique = false;
}
if (Ox.isUndefined(v.visible)) {
v.visible = false;
}
if (v.unique) {
self.unique = v.id;
}
});
$.extend(self, {
columnPositions: [],
defaultColumnWidths: $.map(self.options.columns, function(v) {
return v.defaultWidth || v.width;
}),
itemHeight: 16,
page: 0,
pageLength: 100,
scrollLeft: 0,
selectedColumn: getColumnIndexById(self.options.sort[0].key),
visibleColumns: $.map(self.options.columns, function(v) {
return v.visible ? v : null;
})
});
// fixme: there might be a better way than passing both visible and position
self.options.columns.forEach(function(v) {
if (!Ox.isUndefined(v.position)) {
self.visibleColumns[v.position] = v;
}
})
$.extend(self, {
columnWidths: $.map(self.visibleColumns, function(v, i) {
return v.width;
}),
pageHeight: self.options.pageLength * self.itemHeight
});
self.format = {};
self.options.columns.forEach(function(v, i) {
if (v.format) {
self.format[v.id] = v.format;
}
});
// Head
if (self.options.columnsVisible) {
that.$bar = new Ox.Bar({
orientation: 'horizontal',
size: 16
}).appendTo(that);
that.$head = new Ox.Container()
.addClass('OxHead')
.css({
right: self.options.scrollbarVisible ? Ox.UI.SCROLLBAR_SIZE + 'px' : 0
})
.appendTo(that.$bar);
that.$head.$content.addClass('OxTitles');
constructHead();
if (self.options.columnsRemovable) {
that.$select = new Ox.Select({
id: self.options.id + 'SelectColumns',
items: $.map(self.options.columns, function(v, i) {
return {
checked: v.visible,
disabled: v.removable === false,
id: v.id,
title: v.title
}
}),
max: -1,
min: 1,
type: 'image'
})
.bindEvent('change', changeColumns)
.appendTo(that.$bar.$element);
}
}
// Body
that.$body = new Ox.List({
construct: constructItem,
id: self.options.id,
items: self.options.items,
itemHeight: 16,
items: self.options.items,
itemWidth: getItemWidth(),
format: self.format, // fixme: not needed, happens in TextList
keys: $.map(self.visibleColumns, function(v) {
return v.id;
}),
max: self.options.max,
min: self.options.min,
pageLength: self.options.pageLength,
paste: self.options.paste,
orientation: 'vertical',
selected: self.options.selected,
sort: self.options.sort,
sortable: self.options.sortable,
type: 'text',
unique: self.unique
}, $.extend({}, self)) // pass event handler
.addClass('OxBody')
.css({
top: (self.options.columnsVisible ? 16 : 0) + 'px',
overflowY: (self.options.scrollbarVisible ? 'scroll' : 'hidden')
})
.scroll(function() {
var scrollLeft = $(this).scrollLeft();
if (scrollLeft != self.scrollLeft) {
self.scrollLeft = scrollLeft;
that.$head && that.$head.scrollLeft(scrollLeft);
}
})
.bindEvent({
edit: function(event, data) {
that.editCell(data.id, data.key);
},
select: function(event, data) {
self.options.selected = data.ids;
}
})
.appendTo(that);
that.$body.$content.css({
width: getItemWidth() + 'px'
});
//Ox.print('s.vC', self.visibleColumns)
function addColumn(id) {
//Ox.print('addColumn', id);
var column, ids,
index = 0;
Ox.forEach(self.options.columns, function(v) {
if (v.visible) {
index++;
} else if (v.id == id) {
column = v;
return false;
}
});
column.visible = true;
self.visibleColumns.splice(index, 0, column);
self.columnWidths.splice(index, 0, column.width);
that.$head.$content.empty();
constructHead();
that.$body.options({
keys: $.map(self.visibleColumns, function(v, i) {
return v.id;
})
});
that.$body.reloadPages();
}
function changeColumns(event, data) {
var add,
ids = [];
Ox.forEach(data.selected, function(column) {
var index = getColumnIndexById(column.id);
if (!self.options.columns[index].visible) {
addColumn(column.id);
add = true;
return false;
}
ids.push(column.id);
});
if (!add) {
Ox.forEach(self.visibleColumns, function(column) {
if (ids.indexOf(column.id) == -1) {
removeColumn(column.id);
return false;
}
});
}
triggerColumnChangeEvent();
}
function clickColumn(id) {
Ox.print('clickColumn', id);
var i = getColumnIndexById(id),
isSelected = self.options.sort[0].key == self.options.columns[i].id;
that.sortList(
self.options.columns[i].id, isSelected ?
(self.options.sort[0].operator == '+' ? '-' : '+') :
self.options.columns[i].operator
);
}
function constructHead() {
var offset = 0;
that.$titles = [];
self.columnOffsets = [];
self.visibleColumns.forEach(function(v, i) {
var $order, $resize, $left, $center, $right;
offset += self.columnWidths[i];
self.columnOffsets[i] = offset - self.columnWidths[i] / 2;
that.$titles[i] = new Ox.Element()
.addClass('OxTitle OxColumn' + Ox.toTitleCase(v.id))
.css({
width: (self.columnWidths[i] - 9) + 'px',
textAlign: v.align
})
.html(v.title)
.bindEvent({
anyclick: function(event, e) {
clickColumn(v.id);
},
dragstart: function(event, e) {
dragstartColumn(v.id, e);
},
drag: function(event, e) {
dragColumn(v.id, e);
},
dragend: function(event, e) {
dragendColumn(v.id, e);
}
})
.appendTo(that.$head.$content.$element);
$order = $('<div>')
.addClass('OxOrder')
.html(Ox.UI.symbols['triangle_' + (
v.operator == '+' ? 'up' : 'down'
)])
.click(function() {
$(this).prev().trigger('click')
})
.appendTo(that.$head.$content.$element);
$resize = new Ox.Element()
.addClass('OxResize')
.appendTo(that.$head.$content.$element);
if (self.options.columnsResizable) {
$resize.addClass('OxResizable')
.bindEvent({
doubleclick: function(event, e) {
resetColumn(v.id, e);
},
dragstart: function(event, e) {
dragstartResize(v.id, e);
},
drag: function(event, e) {
dragResize(v.id, e);
},
dragend: function(event, e) {
dragendResize(v.id, e);
}
});
}
$left = $('<div>').addClass('OxLeft').appendTo($resize.$element);
$center = $('<div>').addClass('OxCenter').appendTo($resize.$element);
$right = $('<div>').addClass('OxRight').appendTo($resize.$element);
});
that.$head.$content.css({
width: (Ox.sum(self.columnWidths) + 2) + 'px'
});
//Ox.print('s.sC', self.selectedColumn)
//Ox.print('s.cO', self.columnOffsets)
if (getColumnPositionById(self.options.columns[self.selectedColumn].id) > -1) { // fixme: save in var
toggleSelected(self.options.columns[self.selectedColumn].id);
that.$titles[getColumnPositionById(self.options.columns[self.selectedColumn].id)].css({
width: (self.options.columns[self.selectedColumn].width - 25) + 'px'
});
}
}
function constructItem(data) {
var $item = $('<div>')
.addClass('OxTarget')
.css({
width: getItemWidth() + 'px'
});
self.visibleColumns.forEach(function(v, i) {
var clickable = Ox.isBoolean(v.clickable) ? v.clickable : v.clickable(data),
editable = Ox.isBoolean(v.editable) ? v.editable : v.editable(data),
$cell = $('<div>')
.addClass(
'OxCell OxColumn' + Ox.toTitleCase(v.id) +
(clickable ? ' OxClickable' : '') +
(editable ? ' OxEditable' : '')
)
.css({
width: (self.columnWidths[i] - (self.options.columnsVisible ? 9 : 8)) + 'px',
borderRightWidth: (self.options.columnsVisible ? 1 : 0) + 'px',
textAlign: v.align
})
.html(v.id in data ? formatValue(data[v.id], v.format) : '')
.appendTo($item);
});
function formatValue(value, format) {
if (value === null) {
value = '';
} else if (format) {
value = Ox.isObject(format) ?
Ox['format' + Ox.toTitleCase(format.type)]
.apply(this, $.merge([value], format.args)) :
format(value);
} else if (Ox.isArray(value)) {
value = value.join(', ');
}
return value;
}
//Math.random() < 0.01 && Ox.print('item', data, $item);
return $item;
}
function dragstartColumn(id, e) {
self.drag = {
startX: e.clientX,
startPos: getColumnPositionById(id)
}
$.extend(self.drag, {
stopPos: self.drag.startPos,
offsets: $.map(self.visibleColumns, function(v, i) {
return self.columnOffsets[i] - self.columnOffsets[self.drag.startPos]
})
});
$('.OxColumn' + Ox.toTitleCase(id)).css({
opacity: 0.25
});
that.$titles[self.drag.startPos].addClass('OxDrag').css({ // fixme: why does the class not work?
cursor: 'move'
});
}
function dragColumn(id, e) {
var d = e.clientX - self.drag.startX,
pos = self.drag.stopPos;
Ox.forEach(self.drag.offsets, function(v, i) {
if (d < 0 && d < v) {
self.drag.stopPos = i;
return false;
} else if (d > 0 && d > v) {
self.drag.stopPos = i;
}
});
if (self.drag.stopPos != pos) {
moveColumn(id, self.drag.stopPos);
}
}
function dragendColumn(id, e) {
var column = self.visibleColumns.splice(self.drag.stopPos, 1)[0],
width = self.columnWidths.splice(self.drag.stopPos, 1)[0];
self.visibleColumns.splice(self.drag.stopPos, 0, column);
self.columnWidths.splice(self.drag.stopPos, 0, width);
that.$head.$content.empty();
constructHead();
$('.OxColumn' + Ox.toTitleCase(id)).css({
opacity: 1
});
that.$titles[self.drag.stopPos].removeClass('OxDrag').css({
cursor: 'pointer'
});
that.$body.clearCache();
triggerColumnChangeEvent();
}
function dragstartResize(id, e) {
var pos = getColumnPositionById(id);
self.drag = {
startX: e.clientX,
startWidth: self.columnWidths[pos]
};
}
function dragResize(id, e) {
var width = Ox.limit(
self.drag.startWidth - self.drag.startX + e.clientX,
self.options.columnWidth[0],
self.options.columnWidth[1]
);
resizeColumn(id, width);
}
function dragendResize(id, e) {
var pos = getColumnPositionById(id);
that.triggerEvent('columnresize', {
id: id,
width: self.columnWidths[pos]
});
}
function getCell(id, key) {
Ox.print('getCell', id, key)
var $item = getItem(id);
return $($item.find('.OxCell.OxColumn' + Ox.toTitleCase(key))[0]);
}
function getColumnIndexById(id) {
return Ox.getPositionById(self.options.columns, id);
}
function getColumnPositionById(id) {
return Ox.getPositionById(self.visibleColumns, id);
}
function getItem(id) {
//Ox.print('getItem', id)
var $item = null;
$.each(that.find('.OxItem'), function(i, v) {
$v = $(v);
if ($v.data('id') == id) {
$item = $v;
return false;
}
});
return $item;
}
function getItemWidth() {
return Math.max(
Ox.sum(self.columnWidths),
that.$element.width() -
(self.options.scrollbarVisible ? Ox.UI.SCROLLBAR_SIZE : 0)
);
//return Ox.sum(self.columnWidths)
}
function moveColumn(id, pos) {
// fixme: column head should be one element, not three
//Ox.print('moveColumn', id, pos)
var startPos = getColumnPositionById(id),
stopPos = pos,
startClassName = '.OxColumn' + Ox.toTitleCase(id),
stopClassName = '.OxColumn' + Ox.toTitleCase(self.visibleColumns[stopPos].id),
insert = startPos < stopPos ? 'insertAfter' : 'insertBefore'
$column = $('.OxTitle' + startClassName),
$order = $column.next(),
$resize = $order.next();
//Ox.print(startClassName, insert, stopClassName)
$column.detach()[insert](insert == 'insertAfter' ? $('.OxTitle' + stopClassName).next().next() : $('.OxTitle' + stopClassName));
$order.detach().insertAfter($column);
$resize.detach().insertAfter($order);
$.each(that.$body.find('.OxItem'), function(i, v) {
var $v = $(v);
$v.children(startClassName).detach()[insert]($v.children(stopClassName));
});
var column = self.visibleColumns.splice(startPos, 1)[0],
width = self.columnWidths.splice(startPos, 1)[0];
self.visibleColumns.splice(stopPos, 0, column);
self.columnWidths.splice(stopPos, 0, width);
}
function removeColumn(id) {
//Ox.print('removeColumn', id);
var className = '.OxColumn' + Ox.toTitleCase(id),
index = getColumnIndexById(id),
itemWidth,
position = getColumnPositionById(id),
$column = $('.OxTitle' + className),
$order = $column.next(),
$resize = $order.next();
self.options.columns[index].visible = false;
self.visibleColumns.splice(position, 1);
self.columnWidths.splice(position, 1);
that.$head.$content.empty();
constructHead();
itemWidth = getItemWidth();
$.each(that.$body.find('.OxItem'), function(i, v) {
var $v = $(v);
$v.children(className).remove();
$v.css({
width: itemWidth + 'px'
});
});
that.$body.$content.css({
width: itemWidth + 'px'
});
that.$body.options({
keys: $.map(self.visibleColumns, function(v, i) {
return v.id;
})
});
//that.$body.clearCache();
}
function resetColumn(id) {
var width = self.defaultColumnWidths[getColumnIndexById(id)];
resizeColumn(id, width);
that.triggerEvent('columnresize', {
id: id,
width: width
});
}
function resizeColumn(id, width) {
var i = getColumnIndexById(id),
pos = getColumnPositionById(id);
self.options.columns[i].width = width;
self.columnWidths[pos] = width;
if (self.options.columnsVisible) {
that.$head.$content.css({
width: (Ox.sum(self.columnWidths) + 2) + 'px'
});
that.$titles[pos].css({
width: (width - 9 - (i == self.selectedColumn ? 16 : 0)) + 'px'
});
}
that.find('.OxCell.OxColumn' + Ox.toTitleCase(self.options.columns[i].id)).css({
width: (width - (self.options.columnsVisible ? 9 : 8)) + 'px'
});
setWidth();
}
function setWidth() {
var width = getItemWidth();
that.$body.$content.find('.OxItem').css({ // fixme: can we avoid this lookup?
width: width + 'px'
});
that.$body.$content.css({
width: width + 'px' // fixme: check if scrollbar visible, and listen to resize/toggle event
});
}
function toggleSelected(id) {
var pos = getColumnPositionById(id);
if (pos > -1) {
updateOrder(id);
pos > 0 && that.$titles[pos].prev().children().eq(2).toggleClass('OxSelected');
that.$titles[pos].toggleClass('OxSelected');
that.$titles[pos].next().toggleClass('OxSelected');
that.$titles[pos].next().next().children().eq(0).toggleClass('OxSelected');
that.$titles[pos].css({
width: (
that.$titles[pos].width() + (that.$titles[pos].hasClass('OxSelected') ? -16 : 16)
) + 'px'
});
}
}
function triggerColumnChangeEvent() {
that.triggerEvent('columnchange', {
ids: $.map(self.visibleColumns, function(v, i) {
return v.id;
})
});
}
function updateOrder(id) {
var pos = getColumnPositionById(id);
//Ox.print(id, pos)
that.$titles[pos].next().html(Ox.UI.symbols[
'triangle_' + (self.options.sort[0].operator == '+' ? 'up' : 'down')
]);
}
self.onChange = function(key, value) {
if (key == 'items') {
//alert('request set!!')
that.$body.options(key, value);
} else if (key == 'paste') {
that.$body.options(key, value);
} else if (key == 'selected') {
that.$body.options(key, value);
}
};
// fixme: doesn't work, doesn't return that
that.closePreview = that.$body.closePreview;
that.editCell = function(id, key) {
Ox.print('editCell', id, key)
var $item = getItem(id),
$cell = getCell(id, key),
$input,
html = $cell.html(),
index = getColumnIndexById(key),
column = self.options.columns[index],
width = column.width - self.options.columnsVisible;
$cell.empty()
.addClass('OxEdit')
.css({
width: width + 'px'
});
$input = new Ox.Input({
autovalidate: column.input ? column.input.autovalidate : null,
style: 'square',
value: html,
width: width
})
.bind({
mousedown: function(e) {
// keep mousedown from reaching list
e.stopPropagation();
}
})
.bindEvent({
blur: submit,
})
.appendTo($cell);
//.focusInput();
setTimeout($input.focusInput, 0); // fixme: strange
function submit() {
var value = $input.value();
//$input.loseFocus().remove();
// fixme: leaky, inputs remain in focus stack
$cell.removeClass('OxEdit')
.css({
width: (width - 8) + 'px'
})
.html(value)
that.triggerEvent('submit', {
id: id,
key: key,
value: value
});
}
}
that.gainFocus = function() {
that.$body.gainFocus();
return that;
};
that.loseFocus = function() {
that.$body.loseFocus();
return that;
}
that.paste = function(data) {
that.$body.paste();
return that;
};
that.reloadList = function() {
that.$body.reloadList();
return that;
};
that.resizeColumn = function(id, width) {
resizeColumn(id, width);
return that;
}
that.size = function() {
setWidth();
that.$body.size();
}
that.sortList = function(key, operator) {
var isSelected = key == self.options.sort[0].key;
self.options.sort = [{key: key, operator: operator}];
if (self.options.columnsVisible) {
if (isSelected) {
updateOrder(self.options.columns[self.selectedColumn].id);
} else {
toggleSelected(self.options.columns[self.selectedColumn].id);
self.selectedColumn = getColumnIndexById(key);
toggleSelected(self.options.columns[self.selectedColumn].id);
}
}
that.$body.sortList(self.options.sort[0].key, self.options.sort[0].operator);
return that;
};
that.value = function(id, key, value) {
// fixme: make this accept id, {k: v, ...}
var $item = getItem(id),
//$cell = getCell(id, key),
column = self.options.columns[getColumnIndexById(key)];
if (arguments.length == 1) {
return that.$body.value(id);
} else if (arguments.length == 2) {
return that.$body.value(id, key);
} else {
that.$body.value(id, key, value);
/*
$cell && $cell.html(column.format ? column.format(value) : value);
if (column.unique) {
that.$body.setId($item.data('id'), value);
$item.data({id: value});
}
*/
return that;
}
}
return that;
};

65
source/js/Ox.Theme.js Normal file
View file

@ -0,0 +1,65 @@
// fixme: this should be Ox.Theme, and provide Ox.Theme.set(), Ox.Theme.load, etc.
/**
if name is given as argument, switch to this theme.
return current theme otherwise.
Ox.theme()
get theme
Ox.theme('foo')
set theme to 'foo'
*/
Ox.UI.ready(function() {
Ox.theme = function() {
var length = arguments.length,
classes = Ox.UI.$body.attr('class').split(' '),
arg, theme;
Ox.forEach(classes, function(v) {
if (Ox.startsWith(v, 'OxTheme')) {
theme = v.replace('OxTheme', '').toLowerCase();
if (length == 1) {
Ox.UI.$body.removeClass(v);
}
return false;
}
});
if (length == 1) {
arg = arguments[0]
Ox.UI.$body.addClass('OxTheme' + Ox.toTitleCase(arg));
if (theme) {
$('img').each(function() {
var $this = $(this);
if (!$this.attr('src')) return; // fixme: remove, should't be neccessary
$this.attr({
src: $this.attr('src').replace(
'/ox.ui.' + theme + '/', '/ox.ui.' + arg + '/'
)
});
});
$('input[type=image]').each(function() {
var $this = $(this);
$this.attr({
src: $this.attr('src').replace(
'/ox.ui.' + theme + '/', '/ox.ui.' + arg + '/'
)
});
});
$('.OxLoadingIcon').each(function() {
var $this = $(this);
$this.attr({
src: $this.attr('src').replace(
'/ox.ui.' + theme + '/', '/ox.ui.' + arg + '/'
)
});
})
}
}
return theme;
};
Ox.theme(Ox.UI.DEFAULT_THEME);
});

152
source/js/Ox.TimeInput.js Normal file
View file

@ -0,0 +1,152 @@
Ox.TimeInput = function(options, self) {
// fixme: seconds get set even if options.seconds is false
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
ampm: false,
seconds: false,
milliseconds: false,
value: Ox.formatDate(new Date(), '%T'),
})
.options(options || {});
if (self.options.milliseconds) {
self.options.seconds = true;
if (self.options.value.indexOf('.') == -1) {
self.options.value += '.000';
}
}
self.date = getDate();
self.values = getValues();
self.$input = {
hours: new Ox.Input({
autocomplete: $.map(self.options.ampm ? Ox.range(1, 13) : Ox.range(0, 24), function(v) {
return Ox.pad(v, 2);
}),
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'hours',
textAlign: 'right',
value: self.values.hours,
width: 32
}),
minutes: new Ox.Input({
autocomplete: $.map(Ox.range(0, 60), function(v) {
return Ox.pad(v, 2);
}),
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'minutes',
textAlign: 'right',
value: self.values.minutes,
width: 32
}),
seconds: new Ox.Input({
autocomplete: $.map(Ox.range(0, 60), function(v) {
return Ox.pad(v, 2);
}),
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'seconds',
textAlign: 'right',
value: self.values.seconds,
width: 32
}),
milliseconds: new Ox.Input({
autocomplete: $.map(Ox.range(0, 1000), function(v) {
return Ox.pad(v, 3);
}),
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'milliseconds',
textAlign: 'right',
value: self.values.milliseconds,
width: 40
}),
ampm: new Ox.Input({
autocomplete: ['AM', 'PM'],
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'ampm',
value: self.values.ampm,
width: 32
})
};
that = new Ox.InputGroup($.extend(self.options, {
inputs: $.merge($.merge($.merge([
self.$input.hours,
self.$input.minutes,
], self.options.seconds ? [
self.$input.seconds
] : []), self.options.milliseconds ? [
self.$input.milliseconds
] : []), self.options.ampm ? [
self.$input.ampm
] : []),
separators: $.merge($.merge($.merge([
{title: ':', width: 8},
], self.options.seconds ? [
{title: ':', width: 8}
] : []), self.options.milliseconds ? [
{title: '.', width: 8}
] : []), self.options.ampm ? [
{title: '', width: 8}
] : []),
//width: self.options.width || 128
}), self)
.bindEvent('change', setValue);
setValue();
function getDate() {
return new Date('1970/01/01 ' + (
self.options.milliseconds ?
self.options.value.substr(0, self.options.value.length - 4) :
self.options.value
));
}
function getValues() {
self.date = getDate();
return {
ampm: Ox.formatDate(self.date, '%p'),
hours: Ox.formatDate(self.date, self.options.ampm ? '%I' : '%H'),
milliseconds: self.options.milliseconds ? self.options.value.substr(-3) : '000',
minutes: Ox.formatDate(self.date, '%M'),
seconds: Ox.formatDate(self.date, '%S')
};
}
function setValue() {
self.options.value = Ox.formatDate(new Date('1970/01/01 ' + [
self.$input.hours.options('value'),
self.$input.minutes.options('value'),
self.options.seconds ? self.$input.seconds.options('value') : '00'
].join(':') + (self.options.ampm ? ' ' + self.$input.ampm.options('value') : '')),
(self.options.seconds? '%T' : '%H:%M')) +
(self.options.milliseconds ? '.' + self.$input.milliseconds.options('value') : '');
//Ox.print('SETVALUE', self.options.value);
}
function setValues() {
self.values = getValues();
Ox.forEach(self.$input, function(v, k) {
self.$input[k].options({
value: self.values[k]
});
});
}
self.onChange = function(key, value) {
if (key == 'value') {
setValues();
}
}
return that;
};

10
source/js/Ox.Toolbar.js Normal file
View file

@ -0,0 +1,10 @@
/**
fixme: no need for this
*/
Ox.Toolbar = function(options, self) {
var self = self || {},
that = new Ox.Bar({
size: Ox.UI.getBarSize(options.size)
}, self);
return that;
};

56
source/js/Ox.Tooltip.js Normal file
View file

@ -0,0 +1,56 @@
Ox.Tooltip = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
animate: true,
title: ''
})
.options(options || {})
.addClass('OxTooltip')
.html(self.options.title);
self.options.animate && that.css({
opacity: 0
});
self.onChange = function(key, value) {
if (key == 'title') {
that.html(value);
}
};
that.hide = function() {
if (self.options.animate) {
that.animate({
opacity: 0
}, 250, function() {
that.removeElement();
});
} else {
that.removeElement();
}
return that;
};
that.show = function(x, y) {
var left, top, width, height;
$('.OxTooltip').remove(); // fixme: don't use DOM
that.appendTo(Ox.UI.$body);
width = that.width();
height = that.height();
left = Ox.limit(x - width / 2, 0, Ox.UI.$document.width() - width);
top = y > Ox.UI.$document.height() - height - 16 ? y - 32 : y + 16;
that.css({
left: left + 'px',
top: top + 'px'
});
self.options.animate && that.animate({
opacity: 1
}, 250);
return that;
};
return that;
};

196
source/js/Ox.TreeList.js Normal file
View file

@ -0,0 +1,196 @@
Ox.TreeList = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
data: null,
items: [],
max: -1,
min: 0,
selected: [],
width: 256
})
.options(options || {});
if (self.options.data) {
self.options.items = [];
//Ox.print('d', self.options.data, 'i', self.options.items)
Ox.forEach(self.options.data, function(value, key) {
self.options.items.push(parseData(key, value));
});
//Ox.print('d', self.options.data, 'i', self.options.items)
}
that.$element = new Ox.List({
construct: constructItem,
itemHeight: 16,
items: parseItems(),
itemWidth: self.options.width,
max: self.options.max,
min: self.options.min,
unique: 'id',
}, $.extend({}, self))
.addClass('OxTextList OxTreeList')
.css({
width: self.options.width + 'px'
})
.click(clickItem)
.bindEvent({
toggle: toggleItems
});
function clickItem(e) {
var $target = $(e.target),
$item, id, item;
if ($target.hasClass('OxToggle')) {
$item = $target.parent().parent();
id = $item.data('id');
item = getItemById(id);
toggleItem(item, !item.expanded)
}
}
function constructItem(data) {
var $item = $('<div>'),
padding = (data.level + !data.items) * 16 - 8;
if (data.level || !data.items) {
$('<div>')
.addClass('OxCell OxTarget')
.css({
width: padding + 'px',
})
.appendTo($item);
}
if (data.items) {
$('<div>')
.addClass('OxCell')
.css({
width: '8px',
})
.append(
// fixme: need Ox.Icon()
$('<img>')
.addClass('OxToggle')
.attr({
src: Ox.UI.getImagePath(
'symbol' + (data.expanded ? 'Down' : 'Right') + '.svg'
)
})
.css({
width: '10px',
height: '10px',
padding: '3px'
})
)
.appendTo($item);
}
$('<div>')
.addClass('OxCell OxTarget')
.css({
width: (self.options.width - padding - 32 + !data.items * 16) + 'px'
})
.html(data.title)
.appendTo($item);
return $item;
}
function getItemById(id, items, level) {
var items = items || self.options.items,
level = level || 0,
ret = null;
Ox.forEach(items, function(item) {
if (item.id == id) {
ret = $.extend(item, {
level: level
});
return false;
}
if (item.items) {
ret = getItemById(id, item.items, level + 1);
if (ret) {
return false;
}
}
});
return ret;
}
function parseData(key, value) {
//Ox.print('parseData', key, value)
var ret = {
id: key,
title: key.toString().split('.').pop()
},
type = Ox.typeOf(value);
if (type == 'array' || type == 'object') {
ret.title += ': ' + Ox.toTitleCase(Ox.typeOf(value));
ret.items = Ox.map(Ox.sort(Ox.keys(value)), function(k) {
return parseData(key + '.' + k, value[k]);
});
} else {
ret.title += ': ' + (
type == 'function' ?
value.toString().split('{')[0] :
JSON.stringify(value)
)
}
return ret;
}
function parseItems(items, level) {
var items = items || self.options.items,
level = level || 0,
ret = [];
items.forEach(function(item, i) {
var item_ = $.extend({
level: level
}, item, item.items ? {
items: !!item.expanded ?
parseItems(item.items, level + 1) : []
} : {});
ret.push(item_);
item.items && $.merge(ret, item_.items);
});
return ret;
}
function toggleItem(item, expanded) {
var $img, $item, pos;
item.expanded = expanded;
$.each(that.$element.find('.OxItem'), function(i, v) {
var $item = $(v);
if ($item.data('id') == item.id) {
$img = $item.find('img');
pos = $item.data('position');
return false;
}
});
Ox.print('i.e', item.expanded)
$img.attr({
src: Ox.UI.getImagePath(
'symbol' + (item.expanded ? 'Down' : 'Right') + '.svg'
)
});
item.expanded ?
that.$element.addItems(pos + 1, parseItems(item.items, item.level + 1)) :
that.$element.removeItems(pos + 1, parseItems(item.items, item.level + 1).length);
}
function toggleItems(event, data) {
data.ids.forEach(function(id, i) {
var item = getItemById(id);
if (item.items && data.expanded != !!item.expanded) {
toggleItem(item, data.expanded);
}
});
}
self.onChange = function(key, value) {
if (key == 'data') {
}
};
return that;
};

4
source/js/Ox.URL.js Normal file
View file

@ -0,0 +1,4 @@
/***
Ox.URL
***/

View file

@ -0,0 +1,413 @@
Ox.VideoEditorPlayer = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
duration: 0,
find: '',
height: 0,
points: [0, 0],
position: 0,
posterFrame: 0,
size: 'small',
subtitles: [],
type: 'play',
url: '',
width: 0
})
.options(options || {})
.addClass('OxVideoPlayer')
.css({
height: (self.options.height + 16) + 'px',
width: self.options.width + 'px'
});
self.controlsHeight = 16;
if (self.options.type == 'play') {
self.$video = new Ox.VideoElement({
height: self.options.height,
paused: true,
points: self.options.points,
position: self.options.position,
url: self.options.url,
width: self.options.width
})
.bindEvent({
paused: paused,
playing: playing
})
.appendTo(that);
self.video = self.$video.$element[0];
} else {
self.$video = $('<img>')
.css({
height: self.options.height + 'px',
width: self.options.width + 'px'
})
.appendTo(that.$element)
}
self.$subtitle = $('<div>')
.addClass('OxSubtitle')
.appendTo(that.$element);
setSubtitleSize();
self.$markerFrame = $('<div>')
.addClass('OxMarkerFrame')
.append(
$('<div>')
.addClass('OxFrame')
.css({
width: Math.floor((self.options.width - self.options.height) / 2) + 'px',
height: self.options.height + 'px'
})
)
.append(
$('<div>')
.addClass('OxPoster')
.css({
width: (self.options.height - 2) + 'px',
height: (self.options.height - 2) + 'px'
})
)
.append(
$('<div>')
.addClass('OxFrame')
.css({
width: Math.ceil((self.options.width - self.options.height) / 2) + 'px',
height: self.options.height + 'px'
})
)
.hide()
.appendTo(that.$element);
self.$markerPoint = {};
['in', 'out'].forEach(function(point, i) {
self.$markerPoint[point] = {};
['top', 'bottom'].forEach(function(edge) {
var titleCase = Ox.toTitleCase(point) + Ox.toTitleCase(edge);
self.$markerPoint[point][edge] = $('<img>')
.addClass('OxMarkerPoint OxMarker' + titleCase)
.attr({
src: Ox.UI.PATH + 'png/ox.ui/videoMarker' + titleCase + '.png'
})
.hide()
.appendTo(that.$element);
if (self.options.points[i] == self.options.position) {
self.$markerPoint[point][edge].show();
}
});
});
self.$controls = new Ox.Bar({
size: self.controlsHeight
})
.css({
marginTop: '-2px'
})
.appendTo(that);
if (self.options.type == 'play') {
// fixme: $buttonPlay etc. ?
self.$playButton = new Ox.Button({
id: self.options.id + 'Play',
title: [
{id: 'play', title: 'play'},
{id: 'pause', title: 'pause'}
],
tooltip: ['Play', 'Pause'],
type: 'image'
})
.bindEvent('click', togglePlay)
.appendTo(self.$controls);
self.$playInToOutButton = new Ox.Button({
id: self.options.id + 'PlayInToOut',
title: 'PlayInToOut',
tooltip: 'Play In to Out',
type: 'image'
})
.bindEvent('click', function() {
that.playInToOut();
})
.appendTo(self.$controls);
self.$muteButton = new Ox.Button({
id: self.options.id + 'Mute',
title: [
{id: 'mute', title: 'mute'},
{id: 'unmute', title: 'unmute'}
],
tooltip: ['Mute', 'Unmute'],
type: 'image'
})
.bindEvent('click', toggleMute)
.appendTo(self.$controls);
self.$sizeButton = new Ox.Button({
id: self.options.id + 'Size',
title: self.options.size == 'small' ? [
{id: 'large', title: 'grow'},
{id: 'small', title: 'shrink'}
] : [
{id: 'small', title: 'shrink'},
{id: 'large', title: 'grow'}
],
tooltip: ['Larger', 'Smaller'],
type: 'image'
})
.bindEvent('click', toggleSize)
.appendTo(self.$controls);
} else {
self.$goToPointButton = new Ox.Button({
id: self.options.id + 'GoTo' + Ox.toTitleCase(self.options.type),
title: 'GoTo' + Ox.toTitleCase(self.options.type),
tooltip: 'Go to ' + Ox.toTitleCase(self.options.type) + ' Point',
type: 'image'
})
.bindEvent('click', goToPoint)
.appendTo(self.$controls);
self.$setPointButton = new Ox.Button({
id: self.options.id + 'Set' + Ox.toTitleCase(self.options.type),
title: 'Set' + Ox.toTitleCase(self.options.type),
tooltip: 'Set ' + Ox.toTitleCase(self.options.type) + ' Point',
type: 'image'
})
.bindEvent('click', setPoint)
.appendTo(self.$controls);
}
self.$positionInput = new Ox.TimeInput({
milliseconds: true,
seconds: true,
value: Ox.formatDuration(self.options.position, 3)
})
.css({
float: 'right',
})
.appendTo(self.$controls)
// fixme: strange positioning hack
self.$positionInput.css({
width: '98px'
});
$.browser.mozilla && self.$positionInput.css({
marginTop: '-19px'
});
// fixme: children doesnt work w/o $element
self.$positionInput.$element.children('.OxLabel').each(function(i, element) {
$(this).css({
width: '22px',
marginLeft: (i == 0 ? 8 : 0) + 'px',
background: 'rgb(32, 32, 32)'
});
});
self.$positionInput.$element.children('div.OxInput').each(function(i) {
var marginLeft = [-82, -58, -34, -10];
$(this).css({
marginLeft: marginLeft[i] + 'px'
});
});
if (self.options.type == 'play') {
self.$loadingIcon = new Ox.LoadingIcon()
.appendTo(that)
.start();
self.loadingInterval = setInterval(function() {
if (self.video.readyState) {
clearInterval(self.loadingInterval);
self.$loadingIcon.stop();
setPosition();
}
}, 50);
} else {
setPosition();
}
function getSubtitle() {
var subtitle = '';
Ox.forEach(self.options.subtitles, function(v) {
if (v['in'] <= self.options.position && v['out'] > self.options.position) {
subtitle = v.value;
return false;
}
});
return subtitle;
}
function goToPoint() {
that.triggerEvent('change', {
position: self.options.points[self.options.type == 'in' ? 0 : 1]
});
}
function paused(event, data) {
self.$playButton.toggleTitle();
}
function playing(event, data) {
self.options.position = data.position;
setMarkers();
setSubtitle();
self.$positionInput.options({
value: Ox.formatDuration(self.options.position, 3)
});
that.triggerEvent('playing', {
position: self.options.position
});
}
function setHeight() {
that.css({
height: (self.options.height + 16) + 'px'
});
self.options.type == 'play' ? self.$video.options({
height: self.options.height
}) : self.$video.css({
height: self.options.height + 'px'
});
}
function setMarkers() {
self.options.position == self.options.posterFrame ?
self.$markerFrame.show() : self.$markerFrame.hide();
Ox.forEach(self.$markerPoint, function(markers, point) {
Ox.forEach(markers, function(marker) {
self.options.position == self.options.points[point == 'in' ? 0 : 1] ?
marker.show() : marker.hide();
});
})
}
function setPoint() {
var data = {};
self.options.points[self.options.type == 'in' ? 0 : 1] = self.options.position;
setMarkers();
data[self.options.type] = self.options.position;
that.triggerEvent('set', data);
}
function setPosition() {
var position = Ox.limit(
self.options.position - (self.options.type == 'out' ? 0.01 : 0),
0, self.options.duration - 0.01
),
url;
if (self.options.type == 'play') {
self.$video.position(self.options.position);
} else {
self.$loadingIcon && self.$loadingIcon.stop();
url = self.options.url(position);
if (self.$video.attr('src') != url) {
self.$loadingIcon = new Ox.LoadingIcon()
.appendTo(that)
.start();
self.$video.attr({
src: url
})
.load(self.$loadingIcon.stop);
}
}
setMarkers();
setSubtitle();
self.$positionInput.options({
value: Ox.formatDuration(self.options.position, 3)
});
}
function setSubtitle() {
var subtitle = getSubtitle();
if (subtitle != self.subtitle) {
self.subtitle = subtitle;
self.$subtitle.html(Ox.highlight(self.subtitle, self.options.find).replace(/\n/g, '<br/>'));
}
}
function setSubtitleSize() {
self.$subtitle.css({
bottom: parseInt(self.controlsHeight + self.options.height / 16) + 'px',
width: self.options.width + 'px',
fontSize: parseInt(self.options.height / 20) + 'px',
WebkitTextStroke: (self.options.height / 1000) + 'px rgb(0, 0, 0)'
});
}
function setWidth() {
that.css({
width: self.options.width + 'px'
});
self.options.type == 'play' ? self.$video.options({
width: self.options.width
}) : self.$video.css({
width: self.options.width + 'px'
});
setSubtitleSize();
}
function toggleMute() {
self.$video.toggleMute();
}
function togglePlay() {
self.video.paused ? that.play() : that.pause();
}
function toggleSize(event, data) {
self.options.size = data.id
that.triggerEvent('togglesize', {
size: self.options.size
});
}
self.onChange = function(key, value) {
if (key == 'height') {
setHeight();
} else if (key == 'points') {
setMarkers();
} else if (key == 'position') {
setPosition();
} else if (key == 'posterFrame') {
setMarkers();
} else if (key == 'width') {
setWidth();
}
}
that.mute = function() {
self.$video.mute();
return that;
};
that.pause = function() {
self.$video.pause();
return that;
};
that.play = function() {
self.$video.play();
return that;
};
that.playInToOut = function() {
self.$video.paused() && self.$playButton.toggleTitle();
self.$video.playInToOut();
return that;
};
that.toggleMute = function() {
self.$muteButton.trigger('click');
return that;
}
that.togglePlay = function() {
self.$playButton.trigger('click');
return that;
}
that.unmute = function() {
self.$video.unmute();
return that;
};
return that;
};

View file

@ -0,0 +1,158 @@
Ox.VideoElement = function(options, self) {
var self = self || {},
that = new Ox.Element('video', self)
.defaults({
fps: 25,
height: 0,
loop: false,
muted: false,
paused: false,
playInToOut: false,
points: [0, 0],
position: 0,
poster: '',
url: '',
width: 0
})
.options(options || {})
.attr({
poster: self.options.poster,
preload: 'auto',
src: self.options.url
})
.css({
height: self.options.height + 'px',
width: self.options.width + 'px'
})
.bind({
ended: ended,
loadedmetadata: function() {
self.video.currentTime = self.options.position;
}
});
$.extend(self, {
millisecondsPerFrame: 1000 / self.options.fps,
video: that.$element[0]
});
function ended() {
that.pause()
.triggerEvent('paused', {
position: self.options.position
});
}
function playing() {
var event = 'playing';
self.options.position = Math.round(self.video.currentTime * self.options.fps) / self.options.fps;
if (self.options.playInToOut && self.options.position >= self.options.points[1]) {
event = 'paused';
that.position(self.options.points[1]).pause();
}
that.triggerEvent(event, {
position: self.options.position
});
}
self.onChange = function(key, value) {
if (key == 'height') {
that.size(self.options.width, value);
} else if (key == 'muted') {
that[value ? 'mute' : 'unmute']();
} else if (key == 'paused') {
that[value ? 'pause' : 'play']();
} else if (key == 'points') {
that.points(value);
} else if (key == 'width') {
that.size(value, self.options.height);
}
};
that.mute = function() {
self.options.muted = true;
self.video.muted = true;
return that;
};
that.muted = function() {
return self.options.muted;
}
that.pause = function() {
self.options.paused = true;
self.options.playInToOut = false;
self.video.pause();
clearInterval(self.playInterval);
return that;
};
that.paused = function() {
return self.options.paused;
}
that.play = function() {
self.options.paused = false;
self.video.play();
self.playInterval = setInterval(playing, self.millisecondsPerFrame);
return that;
};
that.playInToOut = function() {
self.options.playInToOut = true;
that.position(self.options.points[0]);
self.options.paused && that.play();
return that;
};
that.points = function(points) {
self.options.points = points;
}
that.position = function(pos) {
if (arguments.length == 0) {
return self.video.currentTime;
} else {
self.options.position = pos;
self.video.currentTime = self.options.position;
return that;
}
};
that.size = function(width, height) {
// fixme: why options? use css!
if (arguments.length == 0) {
return {
width: self.options.width,
height: self.options.height
};
} else {
self.options.width = width;
self.options.height = height;
that.css({
width: width + 'px',
height: height + 'px'
});
return that;
}
};
that.toggleMute = function() {
self.video.muted = !self.video.muted;
return that;
}
that.togglePlay = function() {
self.options.paused = !self.options.paused;
that[self.options.paused ? 'pause' : 'play']();
}
that.unmute = function() {
self.video.muted = false;
return that;
};
return that;
};

View file

@ -0,0 +1,421 @@
Ox.VideoPanelPlayer = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
annotationsSize: 256,
duration: 0,
height: 0,
loop: false,
muted: false,
paused: false,
playInToOut: false,
points: [0, 0],
position: 0,
poster: '',
showAnnotations: true,
showControls: true,
subtitles: [],
videoHeight: 0,
videoSize: 'fit',
videoWidth: 0,
videoURL: '',
width: 0
})
.options(options || {})
.css({
height: self.options.height + 'px',
width: self.options.width + 'px'
})
.bindEvent({
resize: resizeElement,
key_shift_a: function() {
that.toggleAnnotations();
},
key_shift_c: function() {
that.toggleControls();
},
key_shift_s: function() {
that.toggleSize();
},
key_space: function() {
that.togglePlay();
}
});
$.extend(self, {
fullscreen: false,
videoCSS: getVideoCSS()
});
//alert(JSON.stringify([self.playerHeight, self.playerWidth, self.videoCSS]))
self.$player = new Ox.Element()
.css({
overflowX: 'hidden',
overflowY: 'hidden'
})
.bind({
mousedown: that.gainFocus
})
.bindEvent({
resize: resizeVideo
});
self.$video = new Ox.VideoElement({
height: self.videoCSS.height,
paused: true,
points: self.options.points,
position: self.options.position,
url: self.options.videoURL,
width: self.videoCSS.width
})
.css(self.videoCSS)
.bindEvent({
paused: paused,
playing: playing
})
.appendTo(self.$player);
self.$controls = new Ox.Element()
.bindEvent({
toggle: toggleControls
});
self.$buttons = new Ox.Element()
.css({
float: 'left',
width: '16px',
margin: '4px'
})
.appendTo(self.$controls);
self.$button = {
play: new Ox.Button({
id: 'play',
title: [
{id: 'play', title: 'play'},
{id: 'pause', title: 'pause'}
],
tooltip: ['Play', 'Pause'],
type: 'image'
})
.bindEvent({
click: self.$video.togglePlay
}),
mute: new Ox.Button({
id: 'mute',
title: [
{id: 'mute', title: 'mute'},
{id: 'unmute', title: 'unmute'}
],
tooltip: ['Mute', 'Unmute'],
type: 'image'
})
.bindEvent({
click: self.$video.toggleMute
}),
size: new Ox.Button({
id: 'size',
title: self.options.videoSize == 'fit' ? [
{id: 'fill', title: 'fill'},
{id: 'fit', title: 'fit'}
] : [
{id: 'fit', title: 'fit'},
{id: 'fill', title: 'fill'}
],
tooltip: self.options.videoSize == 'fit' ? [
'Fill Screen', 'Fit to Screen'
] : [
'Fit to Screen', 'Fill Screen'
],
type: 'image'
})
.bindEvent({
click: toggleSize
}),
fullscreen: new Ox.Button({
id: 'size',
title: [
{id: 'grow', title: 'grow'},
{id: 'shrink', title: 'shrink'}
],
tooltip: [
'Enter Fullscreen', 'Exit Fullscreen'
],
type: 'image'
})
.bindEvent({
click: toggleFullscreen
})
}
var i = 0;
Ox.forEach(self.$button, function($button) {
$button.css({
position: 'absolute',
left: '8px',
top: (8 + i++ * 24) + 'px'
})
.appendTo(self.$buttons);
});
self.$timelines = new Ox.Element()
.css({
float: 'left',
margin: '4px'
})
.appendTo(self.$controls);
self.$timeline = {
large: new Ox.LargeTimeline({
duration: self.options.duration,
position: self.options.position,
subtitles: self.options.subtitles,
videoId: self.options.videoId,
width: getTimelineWidth()
})
.css({
top: '4px'
})
.bindEvent({
change: changeLargeTimeline
}),
small: new Ox.SmallTimeline({
duration: self.options.duration,
position: self.options.position,
subtitles: self.options.subtitles,
videoId: self.options.videoId,
width: getTimelineWidth()
})
.css({
top: '76px'
})
.bindEvent({
change: changeSmallTimeline
})
};
Ox.forEach(self.$timeline, function($timeline) {
$timeline.appendTo(self.$timelines);
});
self.$panel = new Ox.SplitPanel({
elements: [
{
element: self.$player
},
{
collapsed: !self.options.showControls,
collapsible: true,
element: self.$controls,
size: 104
}
],
orientation: 'vertical'
})
.bindEvent({
resize: resizePanel
});
self.$annotations = new Ox.Element()
.bindEvent({
resize: resizeAnnotations,
resizeend: resizeendAnnotations,
toggle: toggleAnnotations
});
that.$element = new Ox.SplitPanel({
elements: [
{
element: self.$panel
},
{
collapsed: !self.options.showAnnotations,
collapsible: true,
element: self.$annotations,
resizable: true,
resize: [192, 256, 320, 384],
size: self.options.annotationsSize
}
],
orientation: 'horizontal'
});
function changeLargeTimeline(event, data) {
self.options.position = data.position;
self.$video.position(self.options.position);
self.$timeline.small.options({
position: self.options.position
});
}
function changeSmallTimeline(event, data) {
self.options.position = data.position;
self.$video.position(self.options.position);
self.$timeline.large.options({
position: self.options.position
});
}
function getPlayerHeight() {
return self.options.height -
self.options.showControls * 104 - 1;
}
function getPlayerWidth() {
return self.options.width -
(self.options.showAnnotations && !self.fullscreen) *
self.options.annotationsSize - 1;
}
function getTimelineWidth() {
return self.options.width -
(self.options.showAnnotations && !self.fullscreen) *
self.options.annotationsSize - 40
}
function getVideoCSS() {
var width = getPlayerWidth(),
height = getPlayerHeight(),
ratio = width / height,
videoRatio = self.options.videoWidth / self.options.videoHeight,
isWide = ratio < videoRatio;
return self.options.videoSize == 'fit' ? {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
width: (isWide ? width : Math.round(height * videoRatio)) + 'px',
height: (isWide ? Math.round(width / videoRatio) : height) + 'px',
margin: 'auto'
} : {
width: (isWide ? Math.round(height * videoRatio) : width) + 'px',
height: (isWide ? height : Math.round(width / videoRatio)) + 'px',
margin: [
isWide ? '0' : Math.floor((height - width / videoRatio) / 2) + 'px',
isWide ? Math.ceil((width - height * videoRatio) / 2) + 'px' : '0',
isWide ? '0' : Math.ceil((height - width / videoRatio) / 2) + 'px',
isWide ? Math.floor((width - height * videoRatio) / 2) + 'px' : '0'
].join(' ')
};
}
function paused() {
}
function playing(event, data) {
self.options.position = data.position;
self.$timeline.large.options({
position: self.options.position
});
self.$timeline.small.options({
position: self.options.position
});
}
function resizeAnnotations(event, data) {
self.options.annotationsSize = data;
resizeVideoAndControls();
}
function resizeendAnnotations(event, data) {
self.options.annotationsSize = data;
that.triggerEvent('change', {
annotationsSize: self.options.annotationsSize
});
}
function resizeControls() {
self.$timeline.large.options({
width: getTimelineWidth()
});
self.$timeline.small.options({
width: getTimelineWidth()
});
}
function resizeElement(event, data) {
// called on browser toggle
self.options.height = data;
resizeVideo();
}
function resizePanel(event, data) {
// called on annotations toggle
resizeVideoAndControls();
}
function resizeVideoAndControls() {
resizeVideo();
resizeControls();
}
function resizeVideo() {
self.videoCSS = getVideoCSS();
self.$video.css(self.videoCSS);
};
function toggleAnnotations(event, data) {
self.options.showAnnotations = !data.collapsed;
that.triggerEvent('change', {
showAnnotations: self.options.showAnnotations
});
}
function toggleControls(event, data) {
self.options.showControls = !data.collapsed;
that.triggerEvent('change', {
showControls: self.options.showControls
});
}
function toggleFullscreen() {
self.fullscreen = !self.fullscreen;
self.options.showAnnotations && that.$element.toggle(1);
self.fullscreen && self.options.showControls && self.$panel.toggle(1);
that.triggerEvent((self.fullscreen ? 'enter' : 'exit') + 'fullscreen', {});
}
function toggleSize() {
self.options.videoSize = self.options.videoSize == 'fit' ? 'fill' : 'fit';
resizeVideo();
that.triggerEvent('change', {
videoSize: self.options.videoSize
});
}
self.onChange = function(key, value) {
if (key == 'height') {
resizeVideo();
} else if (key == 'position') {
self.$video.position(value);
} else if (key == 'width') {
resizeVideoAndControls();
}
}
that.toggleAnnotations = function() {
that.$element.toggle(1);
//that.toggleAnnotations(null, !self.options.showAnnotations);
};
that.toggleControls = function() {
self.$panel.toggle(1);
//that.toggleControls(null, !self.options.showControls);
};
that.toggleMute = function() {
self.$button.mute.trigger('click');
};
that.togglePlay = function() {
self.$button.play.trigger('click');
};
that.toggleSize = function() {
self.$button.size.trigger('click');
}
return that;
}

588
source/js/Ox.VideoPlayer.js Normal file
View file

@ -0,0 +1,588 @@
Ox.VideoEditor = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
.defaults({
annotationsSize: 0,
cuts: [],
duration: 0,
find: '',
frameURL: function() {},
fps: 25, // fixme: doesn't get handed through to player
height: 0,
largeTimeline: true,
layers: [],
matches: [],
points: [0, 0],
position: 0,
posterFrame: 0,
showAnnotations: false,
subtitles: [],
videoHeight: 0,
videoId: '',
videoWidth: 0,
videoSize: 'small',
videoURL: '',
width: 0
})
.options(options || {})
.mousedown(function() {
that.gainFocus();
})
.bindEvent({
key_shift_0: function() {
movePositionBy(-self.options.position);
},
key_alt_left: function() {
},
key_alt_right: function() {
},
key_alt_shift_left: function() {
},
key_alt_shift_right: function() {
},
key_backslash: function() {
select('subtitle');
},
key_closebracket: function() {
movePositionTo('subtitle', 1);
},
key_comma: function() {
movePositionTo('cut', -1);
},
key_dot: function() {
movePositionTo('cut', 1);
},
key_down: function() {
movePositionBy(self.sizes.timeline[0].width);
},
key_i: function() {
setPoint('in');
},
key_left: function() {
movePositionBy(-1);
},
key_m: toggleMute,
key_o: function() {
setPoint('out');
},
key_openbracket: function() {
movePositionTo('subtitle', -1);
},
key_p: playInToOut,
key_right: function() {
movePositionBy(1);
},
key_s: function() {
// toggleSize
},
key_shift_comma: function() {
movePositionTo('match', -1)
},
key_shift_dot: function() {
movePositionTo('match', 1)
},
key_shift_down: function() {
movePositionBy(self.options.duration);
},
key_shift_left: function() {
movePositionBy(-0.04);
//movePositionBy(-60);
},
key_shift_i: function() {
goToPoint('in');
},
key_shift_o: function() {
goToPoint('out');
},
key_shift_right: function() {
movePositionBy(0.04);
//movePositionBy(60);
},
key_shift_up: function() {
movePositionBy(-self.options.duration);
},
key_slash: function() {
select('cut');
},
key_space: togglePlay,
key_up: function() {
movePositionBy(-self.sizes.timeline[0].width);
}
});
$.extend(self, {
$player: [],
$timeline: [],
controlsHeight: 16,
margin: 8,
videoRatio: self.options.videoWidth / self.options.videoHeight
});
self.$editor = new Ox.Element()
.addClass('OxVideoEditor')
.click(function() {
that.gainFocus()
});
self.sizes = getSizes();
['play', 'in', 'out'].forEach(function(type, i) {
self.$player[i] = new Ox.VideoEditorPlayer({
duration: self.options.duration,
find: self.options.find,
height: self.sizes.player[i].height,
id: 'player' + Ox.toTitleCase(type),
points: self.options.points,
position: type == 'play' ? self.options.position : self.options.points[type == 'in' ? 0 : 1],
posterFrame: self.options.posterFrame,
subtitles: self.options.subtitles,
type: type,
url: type == 'play' ? self.options.videoURL : self.options.frameURL,
width: self.sizes.player[i].width
})
.css({
left: self.sizes.player[i].left + 'px',
top: self.sizes.player[i].top + 'px'
})
.bindEvent(type == 'play' ? {
playing: changePlayer,
togglesize: toggleSize
} : {
change: function() {
goToPoint(type);
},
set: function() {
setPoint(type);
}
})
.appendTo(self.$editor);
});
self.$timeline[0] = new Ox.LargeTimeline({
cuts: self.options.cuts,
duration: self.options.duration,
find: self.options.find,
id: 'timelineLarge',
matches: self.options.matches,
points: self.options.points,
position: self.options.position,
subtitles: self.options.subtitles,
videoId: self.options.videoId,
width: self.sizes.timeline[0].width
})
.css({
left: self.sizes.timeline[0].left + 'px',
top: self.sizes.timeline[0].top + 'px'
})
.bindEvent('change', changeTimelineLarge)
.bindEvent('changeEnd', changeTimelineLarge)
.appendTo(self.$editor);
self.$timeline[1] = new Ox.BlockTimeline({
cuts: self.options.cuts,
duration: self.options.duration,
find: self.options.find,
id: 'timelineSmall',
matches: self.options.matches,
points: self.options.points,
position: self.options.position,
subtitles: self.options.subtitles,
videoId: self.options.videoId,
width: self.sizes.timeline[1].width
})
.css({
left: self.sizes.timeline[1].left + 'px',
top: self.sizes.timeline[1].top + 'px'
})
.bindEvent('change', changeTimelineSmall)
.appendTo(self.$editor);
self.$annotations = new Ox.Element()
.css({
overflowY: 'auto'
})
.bindEvent({
resize: resizeAnnotations,
toggle: toggleAnnotations
});
self.$annotationPanel = [];
self.options.layers.forEach(function(layer, i) {
self.$annotationPanel[i] = new Ox.AnnotationPanel(
$.extend({
width: self.options.annotationSize
}, layer)
)
.bindEvent({
add: function(event, data) {
data.layer = layer.id;
data['in'] = self.options.points[0];
data.out = self.options.points[1];
that.triggerEvent('addAnnotation', data);
},
'delete': function(event, data) {
data.layer = layer.id;
that.triggerEvent('removeAnnotations', data);
},
select: function(event, data) {
self.options.layers.forEach(function(l, j) { // fixme: l? j?
if(l.id != layer.id) {
self.$annotationPanel[j].deselectItems();
}
});
selectAnnotation(event, data);
},
submit: updateAnnotation
});
self.$annotationPanel[i]
.appendTo(self.$annotations);
});
that.$element = new Ox.SplitPanel({
elements: [
{
element: self.$editor
},
{
collapsed: !self.options.showAnnotations,
collapsible: true,
element: self.$annotations,
resizable: true,
resize: [192, 256, 320, 384],
size: self.options.annotationsSize
}
],
orientation: 'horizontal'
});
function changePlayer(event, data) {
self.options.position = data.position;
self.$timeline[0].options({
position: data.position
});
self.$timeline[1].options({
position: data.position
});
}
function changeTimelineLarge(event, data) {
self.options.position = data.position;
self.$player[0].options({
position: data.position
});
self.$timeline[1].options({
position: data.position
});
}
function changeTimelineSmall(event, data) {
self.options.position = data.position;
self.$player[0].options({
position: data.position
});
self.$timeline[0].options({
position: data.position
});
}
function getNextPosition(type, direction) {
var found = false,
position = 0,
positions;
if (type == 'cut') {
positions = self.options.cuts;
} else if (type == 'match') {
positions = $.map(self.options.matches, function(v, i) {
return self.options.subtitles[v]['in'];
});
} else if (type == 'subtitle') {
positions = $.map(self.options.subtitles, function(v, i) {
return v['in'];
});
}
direction == -1 && positions.reverse();
Ox.forEach(positions, function(v) {
if (direction == 1 ? v > self.options.position : v < self.options.position) {
position = v;
found = true;
return false;
}
});
direction == -1 && positions.reverse();
if (!found) {
position = positions[direction == 1 ? 0 : positions.length - 1];
}
return position;
}
function getPoints(type) {
var found = false,
points,
positions = [];
if (type == 'cut') {
positions = self.options.cuts;
} else if (type == 'match') {
// ...
} else if (type == 'subtitle') {
self.options.subtitles.forEach(function(v, i) {
positions.push(v['in']);
positions.push(v.out);
});
}
positions.indexOf(0) == -1 && positions.unshift(0);
positions.indexOf(self.options.duration) == -1 &&
positions.push(self.options.duration);
Ox.forEach(positions, function(v, i) {
if (v > self.options.position) {
points = [positions[i - 1], positions[i]];
found = true;
return false;
}
});
return points;
}
function getSizes(scrollbarIsVisible) {
//Ox.print('getSizes', scrollbarIsVisible)
var scrollbarWidth = Ox.UI.SCROLLBAR_SIZE,
contentWidth = self.options.width -
(self.options.showAnnotations * self.options.annotationsSize) - 1 -
(scrollbarIsVisible ? scrollbarWidth : 0),
height,
lines,
size = {
player: [],
timeline: []
},
width, widths;
if (self.options.videoSize == 'small') {
width = 0;
widths = Ox.divideInt(contentWidth - 4 * self.margin, 3);
[1, 0, 2].forEach(function(v, i) {
size.player[v] = {
left: (i + 0.5) * self.margin + width,
top: self.margin / 2,
width: widths[i],
height: Math.round(widths[1] / self.videoRatio)
}
width += widths[i];
});
} else {
size.player[0] = {
left: self.margin / 2,
top: self.margin / 2,
width: Math.round((contentWidth - 3 * self.margin + (self.controlsHeight + self.margin) / 2 * self.videoRatio) * 2/3),
}
size.player[0].height = Math.round(size.player[0].width / self.videoRatio);
size.player[1] = {
left: size.player[0].left + size.player[0].width + self.margin,
top: size.player[0].top,
width: contentWidth - 3 * self.margin - size.player[0].width
}
size.player[1].height = Math.ceil(size.player[1].width / self.videoRatio)
size.player[2] = {
left: size.player[1].left,
top: size.player[0].top + size.player[1].height + self.controlsHeight + self.margin,
width: size.player[1].width,
height: size.player[0].height - size.player[1].height - self.controlsHeight - self.margin
}
}
size.timeline[0] = {
left: self.margin / 2,
top: size.player[0].height + self.controlsHeight + 1.5 * self.margin,
width: contentWidth - 2 * self.margin,
height: 64
}
size.timeline[1] = {
left: size.timeline[0].left,
top: size.timeline[0].top + size.timeline[0].height + self.margin,
width: size.timeline[0].width
}
lines = Math.ceil(self.options.duration / size.timeline[1].width);
height = getHeight();
self.$editor.css({
overflowY: (scrollbarIsVisible && height <= self.options.height) ? 'scroll' : 'auto'
});
return (!scrollbarIsVisible && height > self.options.height) ? getSizes(true) : size;
function getHeight() {
return size.player[0].height + self.controlsHeight +
size.timeline[0].height + lines * 16 +
(lines + 3) * self.margin;
}
}
function goToPoint(point) {
self.options.position = self.options.points[point == 'in' ? 0 : 1];
setPosition();
that.triggerEvent('change', {
position: self.options.position
});
}
function movePositionBy(sec) {
self.options.position = Ox.limit(self.options.position + sec, 0, self.options.duration);
setPosition();
that.triggerEvent('change', {
position: self.options.position
});
}
function movePositionTo(type, direction) {
self.options.position = getNextPosition(type, direction);
setPosition();
that.triggerEvent('change', {
position: self.options.position
});
}
function playInToOut() {
self.$player[0].playInToOut();
}
function resizeAnnotations(event, data) {
self.options.annotationsSize = data;
setSizes();
}
function resizeEditor(event, data) {
var width = data - 2 * margin + 100;
resizeVideoPlayers(width);
$timelineLarge.options({
width: width
});
$timelineSmall.options({
width: width
});
}
function resizePlayers() {
self.$player.forEach(function(v, i) {
v.options({
width: size[i].width,
height: size[i].height
})
.css({
left: size[i].left + 'px',
top: size[i].top + 'px',
});
});
}
function selectAnnotation(event, data) {
self.options.position = data['in']
self.options.points = [data['in'], data.out];
setPosition();
setPoints();
}
function updateAnnotation(event, data) {
data['in'] = self.options.points[0];
data.out = self.options.points[1];
that.triggerEvent('updateAnnotation', data);
}
function select(type) {
self.options.points = getPoints(type);
setPoints();
}
function setPoint(point) {
self.options.points[point == 'in' ? 0 : 1] = self.options.position;
if (self.options.points[1] < self.options.points[0]) {
self.options.points[point == 'in' ? 1 : 0] = self.options.position;
}
setPoints();
}
function setPoints() {
self.$player.forEach(function(v, i) {
v.options($.extend({
points: self.options.points
}, i ? {
position: self.options.points[i - 1]
} : {}));
});
self.$timeline.forEach(function(v) {
v.options({
points: self.options.points
});
});
}
function setPosition() {
self.$player[0].options({
position: self.options.position
});
self.$timeline.forEach(function(v) {
v.options({
position: self.options.position
});
});
}
function setSizes() {
self.sizes = getSizes();
self.$player.forEach(function(v, i) {
v.options({
height: self.sizes.player[i].height,
width: self.sizes.player[i].width
})
.css({
left: self.sizes.player[i].left + 'px',
top: self.sizes.player[i].top + 'px'
});
});
self.$timeline.forEach(function(v, i) {
v.options({
width: self.sizes.timeline[i].width
})
.css({
left: self.sizes.timeline[i].left + 'px',
top: self.sizes.timeline[i].top + 'px'
});
});
}
function toggleAnnotations(event, data) {
self.options.showAnnotations = !data.collapsed;
setSizes();
}
function toggleMute() {
self.$player[0].toggleMute();
}
function togglePlay() {
self.$player[0].togglePlay();
}
function toggleSize(event, data) {
self.options.videoSize = data.size
setSizes();
that.triggerEvent('togglesize', {
size: self.options.videoSize
});
}
self.onChange = function(key, value) {
if (key == 'width' || key == 'height') {
//Ox.print('XXXX setSizes', key, value, self.options.width, self.options.height)
setSizes();
} else if (key == 'position') {
self.$player[0].position(value);
}
};
that.addAnnotation = function(layer, item) {
var i = Ox.getPositionById(self.options.layers, layer);
self.$annotationPanel[i].addItem(item);
}
that.removeAnnotations = function(layer, ids) {
var i = Ox.getPositionById(self.options.layers, layer);
self.$annotationPanel[i].removeItems(ids);
}
return that;
};

53
source/js/Ox.Window.js Normal file
View file

@ -0,0 +1,53 @@
Ox.Window = function(options, self) {
self = self || {},
that = new Ox.Element('div', self)
.defaults({
draggable: true,
fullscreenable: true, // fixme: silly name
height: 225,
resizeable: true,
scaleable: true,
width: 400
})
.options(options || {})
self.center = function() {
};
self.drag = function() {
};
self.fullscreen = function() {
};
self.onChange = function() {
};
self.reset = function() {
};
self.resize = function() {
};
self.scale = function() {
};
that.close = function() {
};
that.open = function() {
};
return that;
};

Some files were not shown because too many files have changed in this diff Show more