diff --git a/build.xml b/build.xml index 5da7777..689e028 100644 --- a/build.xml +++ b/build.xml @@ -11,6 +11,10 @@ + + + + diff --git a/build/multigraph-min.js b/build/multigraph-min.js new file mode 100644 index 0000000..e72d079 --- /dev/null +++ b/build/multigraph-min.js @@ -0,0 +1 @@ +if(!Array.prototype.indexOf){Array.prototype.indexOf=function(c){if(this==null){throw new TypeError()}var d=Object(this);var a=d.length>>>0;if(a===0){return -1}var e=0;if(arguments.length>0){e=Number(arguments[1]);if(e!=e){e=0}else{if(e!=0&&e!=Infinity&&e!=-Infinity){e=(e>0||-1)*Math.floor(Math.abs(e))}}}if(e>=a){return -1}var b=e>=0?e:Math.max(a-Math.abs(e),0);for(;be});b.addValidator("isLessThan",function(e){this.message=this.param+" should be less than "+e;return this.param-1){this.message=this.param+" should be a "+f;return typeof(this.param)===f}else{if(f==="integer"){if(this.param.toString!==undefined){this.message=this.param.toString()+" should be an integer"}else{this.message="parameter should be an integer"}return(typeof(this.param)==="number")&&(parseInt(this.param,10)===this.param)}else{if(typeof(f)==="string"){throw new Error("Validator: isA accepts a string which is one of "+e)}else{throw new Error("Validator: isA only accepts a string for a primitive types for the time being")}}}});a.isAn=a.isA;b.addValidator("isOneOf",function(e){this.message=this.param+" should be one of the set: "+e;return e.indexOf(this.param)>-1});c.Validator=b});window.jermaine.util.namespace("window.jermaine",function(b){var a={};var c=function(g){var j=[],n=this,o="invalid setter call for "+g,k,l,m,f,d,p=false,e,q=window.jermaine.AttrList,h=window.jermaine.Validator;e=function(i){for(m=0;m=this.size()){throw new Error("AttrList: replace method index parameter out of bounds")}if(!(e.validator())(k)){throw new Error(e.errorMessage())}f[j]=k;return this};g.at=function(j){if(j<0||j>=this.size()){throw new Error("AttrList: Index out of bounds")}return f[j]};g.get=g.at;g.size=function(){return f.length};h[c]=function(){return g}}}}b.prototype=new window.jermaine.Attr(name);a.AttrList=b});window.jermaine.util.namespace("window.jermaine",function(a){var b=function(c,d){if(!c||typeof(c)!=="string"){throw new Error("Method: constructor requires a name parameter which must be a string")}else{if(!d||typeof(d)!=="function"){throw new Error("Method: second parameter must be a function")}}this.addTo=function(e){if(!e||typeof(e)!=="object"){throw new Error("Method: addTo method requires an object parameter")}e[c]=d}};a.Method=b});window.jermaine.util.namespace("window.jermaine",function(a){function b(u){var h=this,q={},i={},p,f=true,d=[],n=[],r=[],c=a.Method,s=a.Attr,l=a.AttrList,g,v,k,j,t=function(){},o=function(){},e=function(){if(f){k()}return o.apply(this,arguments)};if(arguments.length>1){u=arguments[arguments.length-1]}if(u&&typeof(u)==="function"){e=new b();u.call(e);return e}else{if(u){throw new Error("Model: specification parameter must be a function")}}var m=function(y,x){var A=y==="Attr"?s:l,w=y==="Attr"?"hasA":"hasMany",z;f=true;if(typeof(x)==="string"){z=new A(x);i[x]=z;return z}else{throw new Error("Model: "+w+" parameter must be a string")}};g=function(y,x){var w;if(typeof(x)!=="string"){throw new Error("Model: expected string argument to "+y+" method, but recieved "+x)}w=y==="attribute"?i[x]:q[x];if(w===undefined){throw new Error("Model: "+y+" "+x+" does not exist!")}return w};v=function(y){var x,z=[],w=y==="attributes"?i:q;for(x in w){if(w.hasOwnProperty(x)){z.push(x)}}return z};k=function(x){var A=this,y,w,z;e.validate();o=function(){var C,D,B;if(!(this instanceof e)){throw new Error("Model: instances must be created using the new operator")}B=function(H,G){var F=G==="attributes"?i:q,E;for(E in F){if(F.hasOwnProperty(E)){if(F===i&&j){F[E].isImmutable()}F[E].addTo(H)}}};B(this,"attributes");B(this,"methods");this.toString=p;if(arguments.length>0){if(arguments.lengthd.length+n.length){throw new Error("Too many arguments to constructor. Expected "+d.length+" required arguments and "+n.length+" optional arguments")}else{for(C=0;C-1){throw new Error("Model: invalid model specification to "+x[y]+" being both an attribute and method")}}if(j){for(y=0;y=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement){while(b.length){c.createElement(b.pop())}}return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a)){return}var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h){for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement){bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close()}b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b)){p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)})}else{if(!c&&p.type(b)==="object"){for(e in b){ci(a+"["+e+"]",b[e],c,d)}}else{d(a,b)}}}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c)){for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a){return this}if(a.nodeType){return this.context=this[0]=a,this.length=1,this}if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1]){return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a)}g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2]){return d.find(a)}this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return !c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,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(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0){return}d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return !isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a)){return !1}try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf")){return !1}}catch(c){return !1}var d;for(d in a){}return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a){return !1}return !0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return !a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string"){return null}b=p.trim(b);if(a.JSON&&a.JSON.parse){return a.JSON.parse(b)}if(w.test(b.replace(y,"@").replace(z,"]").replace(x,""))){return(new Function("return "+b))()}p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string"){return null}try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a){if(c.apply(a[e],d)===!1){break}}}else{for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j){for(;h-1){i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return !i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return !j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return !!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length){return{}}f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent){for(k in {submit:!0,change:!0,focusin:!0}){j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l}}return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i){return}c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
t
",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a)){return}var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b){return}l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function"){e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c)}return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a)){return}var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i]){return}if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a){return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]}},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a)){return this.each(function(b){p(this).addClass(a.call(this,b,this.className))})}if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0){d=d.replace(" "+c[f]+" "," ")}}e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++]){h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}}else{if(c==="undefined"||c==="boolean"){this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""}}})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0){return !0}}return !1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f){return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get" in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d)}return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1){return}e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set" in c)||c.set(this,f,"value")===b){this.value=f}})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return !b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0){return null}c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2){return}if(e&&p.isFunction(p.fn[c])){return p(a)[c](d)}if(typeof a.getAttribute=="undefined"){return p.prop(a,c,d)}h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set" in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get" in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a))){return}d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s]){return}c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h){h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0)}return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1){return}q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode){q.push([k,r]),l=k}l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l)}j.length&&u.push({elem:f,matches:j})}}}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string"){return c}if(k!==1&&k!==9){return[]}i=g(b);if(!i&&!d){if(e=P.exec(a)){if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode){return c}if(f.id===j){return c.push(f),c}}else{if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j){return c.push(f),c}}}else{if(e[2]){return w.apply(c,x.call(b.getElementsByTagName(a),0)),c}if((j=e[3])&&_&&b.getElementsByClassName){return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}}}}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--){c[e=f[g]]&&(c[e]=!(d[e]=c[e]))}})})}function bg(a,b,c){if(a===b){return c}var d=a.nextSibling;while(d){if(d===b){return -1}d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k){return b?0:k.slice(0)}h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h))){d&&(h=h.slice(d[0].length)),i.push(f=[])}c=!1;if(d=N.exec(h)){f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ")}for(g in e.filter){(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d)}if(!c){break}}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e]){if(f||b.nodeType===1){return a(b,c,d)}}}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e]){if(f||b.nodeType===1){if((i=b[o])===k){return b.sizset}if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset){return b}}else{b[o]=k;if(a(b,d,h)){return b.sizset=!0,b}b.sizset=!1}}}}else{while(b=b[e]){if(f||b.nodeType===1){if(a(b,d,h)){return b}}}}}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--){if(!a[e](b,c,d)){return !1}}return !0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return !g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++){if(p(n,i,j)){k.push(n);break}}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++){p(x,q,i,j)}if(h){if(s>0){while(u--){!x[u]&&!q[u]&&(q[u]=v.call(k))}}q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b){return c}a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type]){break}if(l=e.find[k]){if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a){return w.apply(c,x.call(d,0)),c}break}}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return !1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++){c.push(b)}return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string"){return a.textContent}for(a=a.firstChild;a;a=a.nextSibling){c+=f(a)}}else{if(e===3||e===4){return a.nodeValue}}}else{for(;b=a[d];d++){c+=f(b)}}return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode){if(b===a){return !0}}return !1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n){return b.getElementsByTagName(a)}}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++){d.nodeType===1&&e.push(d)}return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n){return b.getElementsByName(name)}},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c){return b.getElementsByClassName(a)}}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0])){return null}if(a[3]){a[2]=a[3]}else{if(b=a[4]){O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b}}return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return !0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0){return !0}if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling){if(b.nodeType===1){e++;if(a===b){break}}}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling){if(c.nodeType===1){return !1}}if(a==="first"){return !0}c=b;case"last":while(c=c.nextSibling){if(c.nodeType===1){return !1}}return !0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--){e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--){if(f=g[h]){a[h]=!(b[h]=f)}}}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return !e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4){return !1}a=a.nextSibling}return !0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;){a.push(d)}return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--){i[j]=l+i[j].join("")}m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n){try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c))){try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11){return i}}catch(j){}}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string"){return p(a).filter(function(){for(b=0,c=h.length;b0){for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d))){f.nodeType===1&&e.push(f),f=f[c]}return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling){a.nodeType===1&&a!==b&&c.push(a)}return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
","
"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a)){return this.each(function(b){p(this).wrapAll(a.call(this,b))})}if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1){a=a.firstChild}return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0])){return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)})}if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0])){return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)})}if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++){if(!a||p.filter(a,[c]).length){!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c)}}return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild){a.removeChild(a.firstChild)}}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b){return c.nodeType===1?c.innerHTML.replace(bm,""):b}if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j)){return this.each(function(){p(this).domManip(a,c,d)})}if(p.isFunction(j)){return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)})}if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d)}return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f){e[f]&&bE(d[f],e[f])}}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f){bD(d[f],e[f])}}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined"){b=e}for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h){continue}if(typeof h=="string"){if(!br.test(h)){h=b.createTextNode(h)}else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--){l=l.lastChild}if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g){p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked){for(f=0;(h=t[f])!=null;f++){p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG)}}if(c){q=function(a){if(!a.type||bx.test(a.type)){return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)}};for(f=0;(h=t[f])!=null;f++){if(!p.nodeName(h,"script")||!q(h)){c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}}}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++){if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events){for(f in c.events){k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle)}}i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style){return}var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b){return h&&"get" in h&&(f=h.get(a,!1,e))!==b?f:j[c]}g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d)){return}g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set" in h)||(d=h.set(a,d,e))!==b){try{j[c]=d}catch(k){}}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get" in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b){f[e]=a.style[e],a.style[e]=b[e]}d=c.call(a);for(e in b){a.style[e]=f[e]}return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c){return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)}},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?0.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter){return}}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b){return bH(a,"marginRight")}})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return !p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++){f[a+bV[d]+b]=e[d]||e[d-2]||e[0]}return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a)){p.each(a,function(){f(this.name,this.value)})}else{for(d in a){ci(d,a[d],c,f)}}return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu){return cu.apply(this,arguments)}if(!this.length){return this}var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2){return}v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304){l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t)}else{t=y;if(!y||a){y="error",a<0&&(a=0)}}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e)){f[c[1].toLowerCase()]=c[2]}}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2){for(b in a){r[b]=[r[b],a[b]]}}else{b=a[x.status],x.always(b)}}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2){return x}j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers){x.setRequestHeader(k,l.headers[k])}if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in {success:1,error:1,complete:1}){x[k](l[k])}g=cA(cw,l,c,x);if(!g){y(-1,"No Transport")}else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2){y(-1,B)}else{throw B}}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m){return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState)){c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")}},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI){cI[a](0,1)}}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return !this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials" in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields){for(h in c.xhrFields){i[h]=c.xhrFields[h]}}c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e){i.setRequestHeader(h,e[h])}}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e){i.readyState!==4&&i.abort()}else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do{i=i||".5",h=h/i,p.style(e.elem,a,h+d)}while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using" in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0]){return}var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static"){a=a.offsetParent}return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b){return g?c in g?g[c]:g.document.documentElement[e]:a[e]}g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);(function(a){a.ajaxthrottle=function(k){var i,e=a.extend({numRequestsPerTimePeriod:0,timePeriod:0,maxConcurrent:1},k),d=function(){return(new Date()).getTime()},j=[],g=[],c=[],b=function(l){if(e.timePeriod>=0){while((g.length>0)&&(g[0].time+e.timePeriod-l<=0)){g.shift()}if(g.length>0){return g[0].time+e.timePeriod-l}}return 0},f=function(l){a.each(j,function(m){if(j[m]===l){j.splice(m,1);return false}return true})},h=function(){var n=d(),m,o,l;if(c.length<=0){return}m=b(n);if((e.numRequestsPerTimePeriod>0)&&(e.timePeriod>0)&&(m>0)&&(g.length>=e.numRequestsPerTimePeriod)){if(i!==undefined){clearTimeout(i)}i=setTimeout(function(){i=undefined;h()},m);return}if((e.maxConcurrent>0)&&(j.length>=e.maxConcurrent)){return}o=c.shift();o.time=d();g.push(o);j.push(o);a.ajax.apply(a,o.arguments).done(function(){o.deferred.resolve.apply(o.deferred,arguments)}).fail(function(){o.deferred.reject.apply(o.deferred,arguments)}).always(function(){f(o);h()})};return{ajax:function(){var l=a.Deferred();c.push({arguments:arguments,deferred:l});h();return l.promise()}}}}(jQuery));(function(e){var f={fullscreen:false,scale:false,defaultEventHandling:true,preopen:function(){},postopen:function(){},preclose:function(){},postclose:function(){},preresize:function(){},postresize:function(){}};var b={open:function(){var m=this.clone(true),l=this.data("lightbox"),g,j;l.contents=m;l.preopen.call(this);m=l.contents;var i=m.data("lightbox");l.overlay=e("
").css({position:"fixed",left:"0px",top:"0px",height:"100%","min-height":"100%",width:"100%","z-index":"9999","background-color":"black",opacity:"0.5"}).appendTo("body");l.box=e("
").css({position:"fixed","z-index":"9999"}).appendTo("body");l.box.append(m);if(l.fullscreen===true){g=window.innerWidth;j=window.innerHeight}else{g=m.width();j=m.height();if(l.scale===true){var k=d(g,j);g=parseInt(g*k,10);j=parseInt(j*k,10)}}a(l.box,g,j);c(l.box,g,j);a(m,g,j);c(m,g,j);m.css("position","fixed").css("z-index",9999);l.box.append(e('close').css({position:"absolute",right:"-9px",top:"-8px",width:"44px",height:"44px","z-index":"10000"}).click(function(){m.lightbox("close")}));i.contentWidth=g;i.contentHeight=j;i.opened=true;i.resizeHandler=function(){m.lightbox("resize")};e(window).on("resize",i.resizeHandler);e(window).on("orientationchange",i.resizeHandler);l.postopen.call(this);return this},close:function(){var g=this.data("lightbox");g.preclose.call(this);e(window).off("resize",g.resizeHandler);e(window).off("orientationchange",g.resizeHandler);g.opened=false;g.overlay.remove();g.overlay=undefined;g.postclose.call(this);g.box.remove();return this},resize:function(){var k=this.data("lightbox"),g,i;k.preresize.call(this);if(k.fullscreen===true){g=window.innerWidth;i=window.innerHeight}else{g=k.contentWidth;i=k.contentHeight;if(k.scale===true){var j=d(g,i);g=parseInt(g*j,10);i=parseInt(i*j,10)}}a(k.box,g,i);c(k.box,g,i);a(k.contents,g,i);c(k.contents,g,i);k.contentWidth=g;k.contentHeight=i;k.postresize.call(this);return this},toggle:function(){if(this.data("lightbox").opened===true){this.lightbox("close")}else{this.lightbox("open")}return this},init:function(g){return this.each(function(){var j=e(this),i=j.data("lightbox");if(!i){var h=e.extend(f,g,{opened:false});j.data("lightbox",h)}if(j.data("lightbox").defaultEventHandling===true){j.on("touchstart",function(o){var l=o.timeStamp,n=j.data("lightbox").lastTouch||l,m=l-n,k=o.originalEvent.touches.length;j.data("lightbox").lastTouch=l;if(!m||m>500||k>1){return}o.preventDefault();j.lightbox("toggle")})}return this})}};e.fn.lightbox=function(g){if(b[g]){return b[g].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof g==="object"||!g){return b.init.apply(this,arguments)}else{e.error("Method "+g+" does not exist on jQuery.lightbox");return null}}};var d=function(k,j){var g=(k>0)?window.innerWidth/k:1,h=(j>0)?window.innerHeight/j:1,i=Math.min(g,h);return i};var a=function(i,h,g){i.css("width",h+"px").css("height",g+"px")};var c=function(i,h,g){var k=(window.innerWidth-h)/2,j=(window.innerHeight-g)/2;if(k<0){k=0}if(j<0){j=0}i.css("left",k+"px").css("top",j+"px")}}(jQuery));(function(d){var b=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks){for(var a=b.length;a;){d.event.fixHooks[b[--a]]=d.event.mouseHooks}}d.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var e=b.length;e;){this.addEventListener(b[--e],c,false)}}else{this.onmousewheel=c}},teardown:function(){if(this.removeEventListener){for(var e=b.length;e;){this.removeEventListener(b[--e],c,false)}}else{this.onmousewheel=null}}};d.fn.extend({mousewheel:function(e){return e?this.bind("mousewheel",e):this.trigger("mousewheel")},unmousewheel:function(e){return this.unbind("mousewheel",e)}});function c(j){var h=j||window.event,g=[].slice.call(arguments,1),k=0,i=true,f=0,e=0;j=d.event.fix(h);j.type="mousewheel";if(h.wheelDelta){k=h.wheelDelta/120}if(h.detail){k=-h.detail/3}e=k;if(h.axis!==undefined&&h.axis===h.HORIZONTAL_AXIS){e=0;f=-1*k}if(h.wheelDeltaY!==undefined){e=h.wheelDeltaY/120}if(h.wheelDeltaX!==undefined){f=-1*h.wheelDeltaX/120}g.unshift(j,k,f,e);return(d.event.dispatch||d.event.handle).apply(this,g)}})(jQuery);window.jermaine.util.namespace("window.multigraph",function(a){window.multigraph.jQuery=jQuery.noConflict()});(function(b){var a={on:function(c){if(c===undefined){return b(this).data("busy_spinner").on}else{return this.each(function(){if(c){b(this).data("busy_spinner").on=true;b(this).data("busy_spinner").level=1;b(this).show()}else{b(this).data("busy_spinner").on=false;b(this).data("busy_spinner").level=0;b(this).hide()}return this})}},level:function(c){if(c===undefined){return b(this).data("busy_spinner").level}else{return this.each(function(){if(b(this).data("busy_spinner").level+c>=0){b(this).data("busy_spinner").level=b(this).data("busy_spinner").level+c;if(b(this).data("busy_spinner").level===1){b(this).busy_spinner("on",true)}else{if(b(this).data("busy_spinner").level===0){b(this).busy_spinner("on",false)}}}return this})}},init:function(c){return this.each(function(){var f=b(this),e=f.data("busy_spinner"),d=b.extend({on:false},c);if(!e){f.data("busy_spinner",{on:d.on,level:0});if(d.on){b(this).show()}else{b(this).hide()}b(this).css({width:32,height:32}).append(b('ajax loading'))}return this})}};b.fn.busy_spinner=function(c){if(a[c]){return a[c].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof c==="object"||!c){return a.init.apply(this,arguments)}else{b.error("Method "+c+" does not exist on jQuery.busy_spinner");return null}}}}(jQuery));(function(d){var c=('
');var e=('');var b=('
    ');var a={init:function(f){return this.each(function(){var k=d(this),j=k.data("errorDisplay"),h=d.extend({fontColor:"#ff0000",backgroundColor:"#ffffff",displayTime:1000,indicatorColor:"#ff0000"},f);if(!j){k.append(c);k.find(".errorDisplay").width(k.width()-6);var i=d(e).appendTo(d("body"));var g=d(b);d(i).find(".errorDisplayXButton").click(function(l){l.preventDefault();d(i).find(".errorDisplayOptions").hide();d(i).hide();k.find(".errorDisplayRetriever").css("background-color",h.indicatorColor).show()});k.data("errorDisplay",{detailDisplay:i,detailDisplayList:g,fontColor:h.fontColor,backgroundColor:h.backgroundColor,displayTime:h.displayTime,indicatorColor:h.indicatorColor});k.find(".errorDisplayXButton").click(function(l){l.preventDefault();k.find(".errorDisplayOptions").hide();k.find(".errorDisplay").slideUp(h.displayTime,function(){k.find(".errorDisplayRetriever").show()})});k.find(".errorDisplayDetailsButton").click(function(l){l.preventDefault();k.find(".errorDisplay").off();k.find(".errorDisplay").hide();k.find(".errorDisplayRetriever").hide();d(i).find(".errorDisplayFullMessageArea").empty().append(d(g));d(i).find(".errorDisplayOptions").show();d(i).show()})}return this})},displayError:function(h,f,g){return this.each(function(){var k=d(this),j=k.data("errorDisplay"),i=d.extend({fontColor:j.fontColor,backgroundColor:j.backgroundColor,displayTime:j.displayTime,indicatorColor:j.indicatorColor},g);k.find(".errorDisplayRetriever").hide();k.find(".errorDisplayOptions").hide();k.find(".errorDisplayShortMessage").css("color",i.fontColor);k.find(".errorDisplay").css("background-color",i.backgroundColor);k.find(".errorDisplayOptions").css("background-color",i.backgroundColor);k.find(".errorDisplayShortMessage").text(f);k.find(".errorDisplay").show();k.find(".errorDisplayRetriever").css("background-color",i.indicatorColor);if(i.displayTime!=-1){k.find(".errorDisplay").slideUp(i.displayTime,function(){k.find(".errorDisplayRetriever").show()})}else{k.find(".errorDisplayOptions").show();k.find(".errorDisplay").show()}d(j.detailDisplayList).append(d("
  • "+h+"
  • ").css("color",i.fontColor));k.find(".errorDisplayRetriever").hover(function(l){l.preventDefault();k.find(".errorDisplayOptions").hide();k.find(".errorDisplayShortMessage").text(f).css("color",i.fontColor);k.find(".errorDisplay").slideDown(function(){k.find(".errorDisplayOptions").show();k.find(".errorDisplay").mouseleave(function(m){m.preventDefault();k.find(".errorDisplayOptions").hide();k.find(".errorDisplay").slideUp(i.displayTime,function(){k.find(".errorDisplayRetriever").show()})})});k.find(".errorDisplayRetriever").hide()})})}};d.fn.errorDisplay=function(f){if(a[f]){return a[f].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof f==="object"||!f){return a.init.apply(this,arguments)}else{d.error("Method "+f+" does not exist on jQuery.errorDisplay");return null}}}}(jQuery));jQuery("head").append(jQuery(""));if(!window.multigraph){window.multigraph={}}window.multigraph.util=jermaine.util;var sprintf=(function(){function a(d){return Object.prototype.toString.call(d).slice(8,-1).toLowerCase()}function b(e,f){for(var d=[];f>0;d[--f]=e){}return d.join("")}var c=function(){if(!c.cache.hasOwnProperty(arguments[0])){c.cache[arguments[0]]=c.parse(arguments[0])}return c.format.call(null,c.cache[arguments[0]],arguments)};c.format=function(m,l){var q=1,o=m.length,g="",r,d=[],h,f,j,e,n,p;for(h=0;h=0?"+"+r:r);n=j[4]?j[4]=="0"?"0":j[4].charAt(1):" ";p=j[6]-String(r).length;e=j[6]?b(n,p):"";d.push(j[5]?r+e:e+r)}}}return d.join("")};c.cache={};c.parse=function(d){var g=d,h=[],j=[],i=0;while(g){if((h=/^[^\x25]+/.exec(g))!==null){j.push(h[0])}else{if((h=/^\x25{2}/.exec(g))!==null){j.push("%")}else{if((h=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(g))!==null){if(h[2]){i|=1;var k=[],f=h[2],e=[];if((e=/^([a-z_][a-z_\d]*)/i.exec(f))!==null){k.push(e[1]);while((f=f.substring(e[0].length))!==""){if((e=/^\.([a-z_][a-z_\d]*)/i.exec(f))!==null){k.push(e[1])}else{if((e=/^\[(\d+)\]/.exec(f))!==null){k.push(e[1])}else{throw ("[sprintf] invalid format string")}}}}else{throw ("[sprintf] invalid format string")}h[2]=k}else{i|=2}if(i===3){throw ("[sprintf] mixing positional and named placeholders is not (yet) supported")}j.push(h)}else{throw ("[sprintf] invalid format string")}}}g=g.substring(h[0].length)}return j};return c})();var vsprintf=function(b,a){a.unshift(b);return sprintf.apply(null,a)};(function(){var b=0;var c=["ms","moz","webkit","o"];for(var a=0;a-1){d.attribute(b[c]).defaultsTo(e[b[c]])}}}return d};a.getDefaultValuesFromXSD=function(){return{window:{border:2,margin:function(){return new window.multigraph.math.Insets(2,2,2,2)},padding:function(){return new window.multigraph.math.Insets(5,5,5,5)},bordercolor:function(){return new window.multigraph.math.RGBColor.parse("0x000000")}},legend:{icon:{height:30,width:40,border:1},visible:null,base:function(){return new window.multigraph.math.Point(1,1)},anchor:function(){return new window.multigraph.math.Point(1,1)},position:function(){return new window.multigraph.math.Point(0,0)},frame:"plot",color:function(){return new window.multigraph.math.RGBColor.parse("0xffffff")},bordercolor:function(){return new window.multigraph.math.RGBColor.parse("0x000000")},opacity:1,border:1,rows:undefined,columns:undefined,cornerradius:0,padding:0},background:{img:{src:undefined,anchor:function(){return new window.multigraph.math.Point(-1,-1)},base:function(){return new window.multigraph.math.Point(-1,-1)},position:function(){return new window.multigraph.math.Point(0,0)},frame:"padding"},color:"0xffffff"},plotarea:{margin:function(){return new window.multigraph.math.Insets(10,38,35,35)},border:0,color:null,bordercolor:function(){return new window.multigraph.math.RGBColor.parse("0xeeeeee")}},title:{text:undefined,frame:"padding",border:0,color:function(){return new window.multigraph.math.RGBColor.parse("0xffffff")},bordercolor:function(){return new window.multigraph.math.RGBColor.parse("0x000000")},opacity:1,padding:0,cornerradius:15,anchor:function(){return new window.multigraph.math.Point(0,1)},base:function(){return new window.multigraph.math.Point(0,1)},position:function(){return new window.multigraph.math.Point(0,0)}},horizontalaxis:{title:{content:undefined,anchor:undefined,base:0,position:undefined,"position-horizontal-top":function(){return new window.multigraph.math.Point(0,15)},"position-horizontal-bottom":function(){return new window.multigraph.math.Point(0,-18)},"position-vertical-right":function(){return new window.multigraph.math.Point(33,0)},"position-vertical-left":function(){return new window.multigraph.math.Point(-25,0)},"anchor-horizontal-top":function(){return new window.multigraph.math.Point(0,-1)},"anchor-horizontal-bottom":function(){return new window.multigraph.math.Point(0,1)},"anchor-vertical-right":function(){return new window.multigraph.math.Point(-1,0)},"anchor-vertical-left":function(){return new window.multigraph.math.Point(1,0)},angle:0},labels:{label:{format:undefined,position:undefined,anchor:undefined,"position-horizontal-top":function(){return new window.multigraph.math.Point(0,5)},"position-horizontal-bottom":function(){return new window.multigraph.math.Point(0,-5)},"position-vertical-right":function(){return new window.multigraph.math.Point(5,0)},"position-vertical-left":function(){return new window.multigraph.math.Point(-8,0)},"anchor-horizontal-top":function(){return new window.multigraph.math.Point(0,-1)},"anchor-horizontal-bottom":function(){return new window.multigraph.math.Point(0,1)},"anchor-vertical-right":function(){return new window.multigraph.math.Point(-1,0)},"anchor-vertical-left":function(){return new window.multigraph.math.Point(1,0)},angle:0,spacing:undefined,densityfactor:1,color:function(){return new window.multigraph.math.RGBColor.parse("0x000000")},visible:true},"start-number":function(){return new window.multigraph.core.NumberValue(0)},"start-datetime":function(){return new window.multigraph.core.DatetimeValue(0)},angle:0,position:function(){return new window.multigraph.math.Point(0,0)},anchor:function(){return new window.multigraph.math.Point(0,0)},color:function(){return new window.multigraph.math.RGBColor.parse("0x000000")},visible:true,defaultNumberSpacing:"10000 5000 2000 1000 500 200 100 50 20 10 5 2 1 0.1 0.01 0.001",defaultDatetimeSpacing:"1000Y 500Y 200Y 100Y 50Y 20Y 10Y 5Y 2Y 1Y 6M 3M 2M 1M 7D 3D 2D 1D 12H 6H 3H 2H 1H","function":undefined,densityfactor:undefined},grid:{color:function(){return new window.multigraph.math.RGBColor.parse("0xeeeeee")},visible:false},pan:{allowed:true,min:null,max:null},zoom:{allowed:true,min:undefined,max:undefined,anchor:null},binding:{id:undefined,min:undefined,max:undefined},id:undefined,type:"number",length:function(){return new window.multigraph.math.Displacement(1,0)},position:function(){return new window.multigraph.math.Point(0,0)},pregap:0,postgap:0,anchor:-1,base:function(){return new window.multigraph.math.Point(-1,-1)},min:"auto",minoffset:0,minposition:function(){return new window.multigraph.math.Displacement(-1,0)},max:"auto",maxoffset:0,maxposition:function(){return new window.multigraph.math.Displacement(1,0)},positionbase:undefined,color:function(){return new window.multigraph.math.RGBColor(0,0,0)},tickmin:-3,tickmax:3,tickcolor:null,highlightstyle:"axis",linewidth:1,orientation:undefined},verticalaxis:{title:{content:undefined,anchor:function(){return new window.multigraph.math.Point(0,-20)},position:function(){return new window.multigraph.math.Point(0,1)},angle:"0"},labels:{label:{format:undefined,start:undefined,angle:undefined,position:undefined,anchor:undefined,spacing:undefined,densityfactor:undefined},format:"%1d",visible:"true",start:"0",angle:"0.0",position:"0 0",anchor:"0 0","function":undefined,densityfactor:undefined},grid:{visible:"false"},pan:{allowed:"yes",min:undefined,max:undefined},zoom:{allowed:"yes",min:undefined,max:undefined,anchor:"none"},binding:{id:undefined,min:undefined,max:undefined},id:undefined,type:"number",position:"0 0",pregap:"0",postgap:"0",anchor:"-1",base:"-1 1",min:"auto",minoffset:"0",minposition:"-1",max:"auto",maxoffset:"0",maxposition:"1",positionbase:undefined,tickmin:"-3",tickmax:"3",highlightstyle:"axis",linewidth:"1",orientation:undefined},plot:{legend:{visible:true,label:undefined},horizontalaxis:{variable:{ref:undefined,factor:undefined},constant:{value:undefined},ref:undefined},verticalaxis:{variable:{ref:undefined,factor:undefined},constant:{value:undefined},ref:undefined},filter:{option:{name:undefined,value:undefined},type:undefined},renderer:{option:{name:undefined,value:undefined,min:undefined,max:undefined},type:function(){return window.multigraph.core.Renderer.Type.parse("line")}},datatips:{variable:{format:undefined},format:undefined,bgalpha:"1.0",border:1,pad:2}},throttle:{pattern:"",requests:0,period:0,concurrent:0},data:{variables:{variable:{id:undefined,column:undefined,type:"number",missingvalue:undefined,missingop:undefined},missingvalue:"-9000",missingop:"eq"},values:{content:undefined},csv:{location:undefined},service:{location:undefined}}}}});window.multigraph.util.namespace("window.multigraph.utilityFunctions",function(a){a.parseAttribute=function(d,c,b){if(d!==undefined){c(b(d));return true}return false};a.parseString=function(b){return b};a.parseInteger=function(b){return parseInt(b,10)};a.parseDataValue=function(b){return function(c){return window.multigraph.core.DataValue.parse(b,c)}};a.parseDataMeasure=function(b){return function(c){return window.multigraph.core.DataMeasure.parse(b,c)}};a.parseBoolean=function(b){switch(b.toLowerCase()){case"true":case"yes":return true;case"false":case"no":return false;default:return b}}});window.multigraph.util.namespace("window.multigraph.utilityFunctions",function(a){a.validateNumberRange=function(b,d,c){return typeof(b)==="number"&&b>=d&&b<=c};a.typeOf=function(c){var b=typeof c;if(b==="object"){if(c){if(Object.prototype.toString.call(c)==="[object Array]"){b="array"}}else{b="null"}}return b}});window.multigraph.util.namespace("window.multigraph.core",function(b){var c={};c.NUMBER="number";c.DATETIME="datetime";c.UNKNOWN="unknown";c.types=function(){return[c.NUMBER,c.DATETIME,c.UNKNOWN]};c.parseType=function(d){if(d.toLowerCase()===c.NUMBER){return c.NUMBER}if(d.toLowerCase()===c.DATETIME){return c.DATETIME}throw new Error("unknown DataValue type: "+d)};c.serializeType=function(d){return d};c.isInstance=function(d){return(d&&(typeof(d.getRealValue)==="function")&&(typeof(d.compareTo)==="function"))};c.isInstanceOrNull=function(d){return((d===null)||c.isInstance(d))};c.create=function(d,e){if(d===c.NUMBER){return new b.NumberValue(e)}else{if(d===c.DATETIME){return new b.DatetimeValue(e)}}throw new Error("attempt to parse an unknown DataValue type")};c.parse=function(e,d){if(e===c.NUMBER){return b.NumberValue.parse(d)}else{if(e===c.DATETIME){return b.DatetimeValue.parse(d)}}throw new Error("attempt to parse an unknown DataValue type")};c.LT="lt";c.LE="le";c.EQ="eq";c.GE="ge";c.GT="gt";c.NE="ne";var a={};a[c.LT]=function(d){return this.compareTo(d)<0};a[c.LE]=function(d){return this.compareTo(d)<=0};a[c.EQ]=function(d){return this.compareTo(d)===0};a[c.GE]=function(d){return this.compareTo(d)>=0};a[c.GT]=function(d){return this.compareTo(d)>0};a[c.NE]=function(d){return this.compareTo(d)!==0};c.mixinComparators=function(d){d[c.LT]=a[c.LT];d[c.LE]=a[c.LE];d[c.EQ]=a[c.EQ];d[c.GE]=a[c.GE];d[c.GT]=a[c.GT];d[c.NE]=a[c.NE]};c.comparators=function(){return[c.LT,c.LE,c.EQ,c.GE,c.GT,c.NE]};c.parseComparator=function(d){if(typeof(d)==="string"){switch(d.toLowerCase()){case"lt":return c.LT;case"le":return c.LE;case"eq":return c.EQ;case"ge":return c.GE;case"gt":return c.GT;case"ne":return c.NE}}throw new Error(d+" should be one of 'lt', 'le', 'eq', 'ge', 'gt', 'ne'.")};b.DataValue=c});window.multigraph.util.namespace("window.multigraph.core",function(b){var a={};a.isInstance=function(c){return(c&&(typeof(c.getRealValue)==="function")&&(!c.compareTo))};a.parse=function(d,c){if(d===b.DataValue.NUMBER){return b.NumberMeasure.parse(c)}else{if(d===b.DataValue.DATETIME){return b.DatetimeMeasure.parse(c)}}throw new Error("attempt to parse an unknown DataMeasure type")};b.DataMeasure=a});window.multigraph.util.namespace("window.multigraph.core",function(a){var b={};b.isInstance=function(c){return(c&&(typeof(c.format)==="function")&&(typeof(c.getMaxLength)==="function"))};b.create=function(c,d){if(c===a.DataValue.NUMBER){return new a.NumberFormatter(d)}else{if(c===a.DataValue.DATETIME){return new a.DatetimeFormatter(d)}}throw new Error("attempt to create an unknown DataFormatter type")};a.DataFormatter=b});window.multigraph.util.namespace("window.multigraph.math",function(a){a.Box=new window.jermaine.Model("Box",function(){this.hasA("width").isA("number");this.hasA("height").isA("number");this.isBuiltWith("width","height")})});window.multigraph.util.namespace("window.multigraph.math",function(a){a.Displacement=new window.jermaine.Model("Displacement",function(){this.hasA("a").validatesWith(function(b){return window.multigraph.utilityFunctions.validateNumberRange(b,-1,1)});this.hasA("b").isA("integer").defaultsTo(0);this.isBuiltWith("a","%b");this.respondsTo("calculateLength",function(b){return this.a()*b+this.b()});this.respondsTo("calculateCoordinate",function(b){return(this.a()+1)*b/2+this.b()})});a.Displacement.regExp=/^([\+\-]?[0-9\.]+)([+\-])([0-9\.+\-]+)$/;a.Displacement.parse=function(h){var g=a.Displacement.regExp.exec(h),i,f,c,e;if(h===undefined){i=new a.Displacement(1)}else{if(g!==null){f=parseFloat(g[1]);c=parseFloat(g[3]);switch(g[2]){case"+":e=1;break;case"-":e=-1;break;default:e=0;break}i=new a.Displacement(f,e*c)}else{f=parseFloat(h);i=new a.Displacement(f)}}return i}});window.multigraph.util.namespace("window.multigraph.math",function(b){var a=function(c){var e={};var d=function(f){if(e[f]!==undefined){throw new Error("attempt to redefine "+c+" Enum with key '"+f+"'")}this.enumType=c;this.key=f;e[f]=this};d.parse=function(f){return e[f]};d.prototype.toString=function(){return this.key};d.isInstance=function(f){return(f!==undefined&&f!==null&&f.enumType===c)};return d};b.Enum=a});window.multigraph.util.namespace("window.multigraph.math",function(a){a.Insets=new window.jermaine.Model("Insets",function(){this.hasA("top").isA("number");this.hasA("left").isA("number");this.hasA("bottom").isA("number");this.hasA("right").isA("number");this.respondsTo("set",function(e,d,b,c){this.top(e);this.left(d);this.bottom(b);this.right(c)});this.isBuiltWith("top","left","bottom","right")})});window.multigraph.util.namespace("window.multigraph.math",function(a){a.Point=new window.jermaine.Model("Point",function(){this.hasA("x").isA("number");this.hasA("y").isA("number");this.isBuiltWith("x","y");this.respondsTo("eq",function(b){return((this.x()===b.x())&&(this.y()===b.y()))})});a.Point.regExp=/^\s*([0-9\-\+\.eE]+)(,|\s+|\s*,\s+|\s+,\s*)([0-9\-\+\.eE]+)\s*$/;a.Point.parse=function(c){var b=a.Point.regExp.exec(c),d;if(!b||(b.length!==4)){throw new Error("cannot parse string '"+c+"' as a Point")}return new a.Point(parseFloat(b[1]),parseFloat(b[3]))}});window.multigraph.util.namespace("window.multigraph.math",function(a){a.RGBColor=new window.jermaine.Model("RGBColor",function(){this.hasA("r").validatesWith(function(c){return window.multigraph.utilityFunctions.validateNumberRange(c,0,1)});this.hasA("g").validatesWith(function(c){return window.multigraph.utilityFunctions.validateNumberRange(c,0,1)});this.hasA("b").validatesWith(function(c){return window.multigraph.utilityFunctions.validateNumberRange(c,0,1)});var b=function(c){c=parseInt(c*255,10).toString(16);if(c.length===1){c="0"+c}return c};this.respondsTo("getHexString",function(c){if(!c){c="0x"}return c+b(this.r())+b(this.g())+b(this.b())});this.respondsTo("toRGBA",function(c){if(c===undefined){c=1}if(typeof(c)!=="number"){throw new Error("RGBColor.toRGBA: The argument, if present, must be a number")}return"rgba("+(255*this.r())+", "+(255*this.g())+", "+(255*this.b())+", "+c+")"});this.respondsTo("eq",function(c){return((this.r()===c.r())&&(this.g()===c.g())&&(this.b()===c.b()))});this.isBuiltWith("r","g","b")});a.RGBColor.colorNameIsDeprecated=function(b){switch(b){case"grey":return"0xeeeeee";case"skyblue":return"0x87ceeb";case"khaki":return"0xf0e68c";case"orange":return"0xffa500";case"salmon":return"0xfa8072";case"olive":return"0x9acd32";case"sienna":return"0xa0522d";case"pink":return"0xffb5c5";case"violet":return"0xee82ee"}return false};a.RGBColor.parse=function(c){var h,e,b,g,f,d;if(c===undefined){return undefined}else{if(typeof(c)==="string"){f=c.toLowerCase();switch(f){case"black":h=0;e=0;b=0;break;case"red":h=1;e=0;b=0;break;case"green":h=0;e=1;b=0;break;case"blue":h=0;e=0;b=1;break;case"yellow":h=1;e=1;b=0;break;case"magenta":h=1;e=0;b=1;break;case"cyan":h=0;e=1;b=1;break;case"white":h=1;e=1;b=1;break;case"grey":g=parseInt("ee",16)/255;h=g;e=g;b=g;break;case"skyblue":h=parseInt("87",16)/255;e=parseInt("ce",16)/255;b=parseInt("eb",16)/255;break;case"khaki":h=parseInt("f0",16)/255;e=parseInt("e6",16)/255;b=parseInt("8c",16)/255;break;case"orange":h=parseInt("ff",16)/255;e=parseInt("a5",16)/255;b=parseInt("00",16)/255;break;case"salmon":h=parseInt("fa",16)/255;e=parseInt("80",16)/255;b=parseInt("72",16)/255;break;case"olive":h=parseInt("9a",16)/255;e=parseInt("cd",16)/255;b=parseInt("32",16)/255;break;case"sienna":h=parseInt("a0",16)/255;e=parseInt("52",16)/255;b=parseInt("2d",16)/255;break;case"pink":h=parseInt("ff",16)/255;e=parseInt("b5",16)/255;b=parseInt("c5",16)/255;break;case"violet":h=parseInt("ee",16)/255;e=parseInt("82",16)/255;b=parseInt("ee",16)/255;break;default:f=f.replace(/(0(x|X)|#)/,"");if(f.search(new RegExp(/([^0-9a-f])/))!==-1){throw new Error("'"+c+"' is not a valid color")}if(f.length===6){h=parseInt(f.substring(0,2),16)/255;e=parseInt(f.substring(2,4),16)/255;b=parseInt(f.substring(4,6),16)/255}else{if(f.length===3){h=parseInt(f.charAt(0),16)/15;e=parseInt(f.charAt(1),16)/15;b=parseInt(f.charAt(2),16)/15}else{throw new Error("'"+c+"' is not a valid color")}}break}d=new a.RGBColor(h,e,b);return d}}throw new Error("'"+c+"' is not a valid color")}});window.multigraph.util.namespace("window.multigraph.math",function(a){a.util={interp:function(b,d,c,f,e){return f+((e-f)*(b-d))/(c-d)},safe_interp:function(b,d,c,f,e){if(d===c){return(f+e)/2}return a.util.interp(b,d,c,f,e)},l2dist:function(e,g,d,f){var c=e-d;var b=g-f;return Math.sqrt(c*c+b*b)}}});window.multigraph.util.namespace("window.multigraph.core",function(e){var f,g,d,c=window.multigraph.utilityFunctions,h=c.getDefaultValuesFromXSD(),b=c.getKeys(h.plot.renderer),a=new window.multigraph.math.Enum("RendererType");g=new window.jermaine.Model("Renderer",function(){this.hasA("type").validatesWith(a.isInstance);this.hasA("plot").validatesWith(function(j){return j instanceof e.Plot});this.hasA("numberOfVariables").isA("number");this.respondsTo("setUpMissing",function(){var k=this.plot(),j;if(!k){console.log("Warning: renderer.setUpMissing() called for renderer that has no plot ref");return}if(k instanceof e.ConstantPlot){this.isMissing=function(l){return false};return}if(!k.data()){console.log("Warning: renderer.setUpMissing() called for renderer whose plot has no data ref");return}j=k.data();this.isMissing=function(m){var l;for(l=1;l=0;--k){var m=o.at(k);if(((m.min()===undefined)||(n===undefined)||m.min().le(n))&&((m.max()===undefined)||(n===undefined)||m.max().gt(n))){return m.value()}}});this.respondsTo("begin",function(){});this.respondsTo("dataPoint",function(j){});this.respondsTo("end",function(){})});f=[];g.addType=function(i){f.push(i)};g.create=function(k){var j,l;for(j=0;j0){for(b=e.length-1;b>=0;--b){c.splice(e[b],1)}}})})});window.multigraph.util.namespace("window.multigraph.core",function(c){var b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.data.variables.variable),d=new window.jermaine.Model("DataVariable",function(){this.hasA("id").isA("string");this.hasA("column").isA("integer");this.hasA("type").isOneOf(c.DataValue.types()).defaultsTo(c.DataValue.NUMBER);this.hasA("data").validatesWith(function(f){return f instanceof window.multigraph.core.Data});this.hasA("missingvalue").validatesWith(c.DataValue.isInstance);this.hasA("missingop").isOneOf(c.DataValue.comparators());this.isBuiltWith("id","%column","%type");b.insertDefaults(this,e.data.variables.variable,a)});c.DataVariable=d});window.multigraph.util.namespace("window.multigraph.core",function(b){var a=new window.jermaine.Model(function(){var d=b.DataVariable;this.isA(b.EventEmitter);var c=function(h,j,g){var e=-1,f;for(f=0;f=0){e=this.columns().at(f)}if(e===undefined){throw new Error("Data: no column with the label "+g)}return e.column()});this.respondsTo("columnIdToDataVariable",function(g){if(typeof(g)!=="string"){throw new Error("Data: columnIdToDataVariable requires a string parameter")}var f=this.columns(),e=c("id",g,f)!==-1?f.at(c("id",g,f)):undefined;if(e===undefined){throw new Error("Data: no column with the label "+g)}return e});this.respondsTo("getColumnId",function(f){if(typeof(f)!=="number"){throw new Error("Data: getColumnId method expects an integer")}var e=c("column",f,this.columns());if(e===-1){throw new Error("Data: column "+f+" does not exist")}return this.columns().at(e).id()});this.respondsTo("getColumns",function(){var e=[],g=this.columns(),f;for(f=0;f=this.columns().size()){throw new Error("metadata.isMissing(): index out of range")}f=this.columns().at(e);if(!f.missingvalue()||!f.missingop()){return false}return g[f.missingop()](f.missingvalue())})});b.Data=a});window.multigraph.util.namespace("window.multigraph.core",function(b){var a;a=new window.jermaine.Model("Plot",function(){this.hasA("legend").validatesWith(function(c){return c instanceof b.PlotLegend});this.hasA("horizontalaxis").validatesWith(function(c){return c instanceof b.Axis});this.hasA("verticalaxis").validatesWith(function(c){return c instanceof b.Axis});this.hasA("renderer").validatesWith(function(c){return c instanceof b.Renderer})});b.Plot=a});window.multigraph.util.namespace("window.multigraph.core",function(a){a.ArrayData=window.jermaine.Model(function(){var b=this;this.isA(a.Data);this.hasAn("array");this.hasA("stringArray");this.isBuiltWith("columns","stringArray",function(){this.init();this.addListener("listenerAdded",function(c){if(c.targetType==="dataReady"){var d=this.array();c.listener(d[0][0],d[d.length-1][0])}})});this.respondsTo("getIterator",function(d,f,c,e){return b.getArrayDataIterator(this,d,f,c,e)});this.respondsTo("getBounds",function(d){var g=this.array(),f=g[0][d],c=f,e;for(e=1;ec){c=g[e][d]}}return[f,c]});b.getArrayDataIterator=function(g,m,e,q,h){var l,f,c,n,p,r,o=g.array();h=h||0;if(Object.prototype.toString.apply(m)!=="[object Array]"){throw new Error("ArrayData: getIterator method requires that the first parameter be an array of strings")}else{for(l=0;lo.length-1){n=o.length-1}r=[];for(f=0;fn){return null}for(k=0;kn){if(i===0){k=false}else{j=o;i--}}else{if(on){if(i===0){break}else{if(q>i){q=i;j=o;i--}else{i=q;o=j;break}}}else{if(oi){break}else{if(i===m){break}else{q=i;j=o;i++}}}else{if(o===n){break}}}}}g=l.at(i);this.currentLabeler(g);this.currentLabelerIndex(i);this.currentLabelDensity(o)});this.respondsTo("toRealValue",function(g){if(typeof(g)==="number"){return g}else{if(d.DataValue.isInstance(g)){return g.getRealValue()}else{throw new Error("unknown value type for axis value "+g)}}});this.respondsTo("toDataValue",function(g){if(typeof(g)==="number"){return d.DataValue.create(this.type(),g)}else{if(d.DataValue.isInstance(g)){return g}else{throw new Error("unknown value type for axis value "+g)}}});this.respondsTo("setDataRangeNoBind",function(i,g,h){var k=this.toDataValue(i),j=this.toDataValue(g);this.dataMin(k);this.dataMax(j);if(h===undefined){h=true}this.emit({type:"dataRangeSet",min:k,max:j})});this.respondsTo("setDataRange",function(i,g,h){if(this.binding()){this.binding().setDataRange(this,i,g,h)}else{this.setDataRangeNoBind(i,g,h)}});this.respondsTo("doPan",function(h,l){var k=this.pan(),n=k.min(),i=k.max(),j,g,m;if(!k.allowed()){return}j=l/this.axisToDataRatio();g=this.dataMin().getRealValue()-j;m=this.dataMax().getRealValue()-j;if(n&&gi.getRealValue()){g-=(m-i.getRealValue());m=i.getRealValue()}this.setDataRange(d.DataValue.create(this.type(),g),d.DataValue.create(this.type(),m))});this.respondsTo("doZoom",function(o,l){var u=this.zoom(),t=this.pan(),r=this.type(),w=this.dataMin(),j=this.dataMax(),n=t.min(),v=t.max(),k=u.min(),s=u.max(),g=d.DataValue,i,q,h,p,m;if(!u.allowed()){return}i=this.axisValueToDataValue(o).getRealValue();if(g.isInstance(u.anchor())){i=u.anchor().getRealValue()}q=10*Math.abs(l/(this.pixelLength()-this.maxoffset()-this.minoffset()));if(l<=0){h=g.create(r,(w.getRealValue()-i)*(1+q)+i);p=g.create(r,(j.getRealValue()-i)*(1+q)+i)}else{h=g.create(r,(w.getRealValue()-i)*(1-q)+i);p=g.create(r,(j.getRealValue()-i)*(1-q)+i)}if(n&&h.lt(n)){h=n}if(v&&p.gt(v)){p=v}if((w.le(j)&&h.lt(p))||(w.ge(j)&&h.gt(p))){if(s&&(p.gt(h.add(s)))){m=(p.getRealValue()-h.getRealValue()-s.getRealValue())/2;p=p.addRealValue(-m);h=h.addRealValue(m)}else{if(k&&(p.lt(h.add(k)))){m=(k.getRealValue()-(p.getRealValue()-h.getRealValue()))/2;p=p.addRealValue(m);h=h.addRealValue(-m)}}this.setDataRange(h,p)}});this.respondsTo("distanceToPoint",function(g,n){var h=(this.orientation()===c.HORIZONTAL)?n:g,m=(this.orientation()===c.HORIZONTAL)?g:n,k=this.parallelOffset(),j=this.perpOffset(),l=this.pixelLength(),i=window.multigraph.math.util.l2dist;if(mk+l){return i(m,h,k+l,j)}return Math.abs(h-j)});b.insertDefaults(this,f.horizontalaxis,a)});c.HORIZONTAL=new e("horizontal");c.VERTICAL=new e("vertical");c.Orientation=e;d.Axis=c});window.multigraph.util.namespace("window.multigraph.core",function(a){a.AxisBinding=new window.jermaine.Model("AxisBinding",function(){var b=this;b.instances={};this.hasA("id").isA("string");this.hasA("axes");this.isBuiltWith("id",function(){b.instances[this.id()]=this;this.axes([])});this.respondsTo("addAxis",function(f,e,c,d){if(f.binding()){f.binding().removeAxis(f)}f.binding(this);e=f.toRealValue(e);c=f.toRealValue(c);this.axes().push({axis:f,multigraph:d,factor:1/(c-e),offset:-e/(c-e),min:e,max:c})});this.respondsTo("removeAxis",function(d){var e=this.axes(),c;for(c=0;cj.height()/2){k(h(o["position-horizontal-top"]))}else{k(h(o["position-horizontal-bottom"]))}}else{if(g>j.width()/2){k(h(o["position-vertical-right"]))}else{k(h(o["position-vertical-left"]))}}}if(i()===undefined){if(l){if(g>j.height()/2){i(h(o["anchor-horizontal-top"]))}else{i(h(o["anchor-horizontal-bottom"]))}}else{if(g>j.width()/2){i(h(o["anchor-vertical-right"]))}else{i(h(o["anchor-vertical-left"]))}}}n.angle=this.angle();this.content().initializeGeometry(n);return this});this.respondsTo("render",function(){});b.insertDefaults(this,e.horizontalaxis.title,a)});c.AxisTitle=d});window.multigraph.util.namespace("window.multigraph.core",function(d){var a,c=window.multigraph.utilityFunctions,e=c.getDefaultValuesFromXSD(),b=c.getKeys(e.background);a=new window.jermaine.Model("Background",function(){this.hasA("color").validatesWith(function(f){return f instanceof window.multigraph.math.RGBColor}).defaultsTo(window.multigraph.math.RGBColor.parse(e.background.color));this.hasA("img").validatesWith(function(f){return f instanceof d.Img})});d.Background=a});window.multigraph.util.namespace("window.multigraph.core",function(c){var b=window.multigraph.utilityFunctions,d=b.getDefaultValuesFromXSD(),a=b.getKeys(d.plot);c.ConstantPlot=new window.jermaine.Model("ConstantPlot",function(){this.isA(c.Plot);this.hasA("constantValue").validatesWith(c.DataValue.isInstance);this.isBuiltWith("constantValue");b.insertDefaults(this,d.plot,a);this.respondsTo("render",function(i,e){var f=this.horizontalaxis(),h=this.renderer(),g=this.constantValue();if(!f.hasDataMin()||!f.hasDataMax()){return}h.setUpMissing();h.begin(e);h.dataPoint([f.dataMin(),g]);h.dataPoint([f.dataMax(),g]);h.end()})})});window.multigraph.util.namespace("window.multigraph.core",function(b){var a=window.jermaine.Model(function(){var c=b.ArrayData;this.isA(c);this.hasA("filename").isA("string");this.hasA("messageHandler");this.hasA("ajaxthrottle");this.hasA("dataIsReady").isA("boolean").defaultsTo(false);this.respondsTo("getIterator",function(e,g,d,f){if(this.dataIsReady()){return c.getArrayDataIterator(this,e,g,d,f)}else{return{next:function(){},hasNext:function(){return false}}}});this.respondsTo("_displayError",function(d){if(this.messageHandler()){this.messageHandler().error(d)}else{throw d}});this.isBuiltWith("columns","filename","%messageHandler","%ajaxthrottle",function(){var d=this,e=this.ajaxthrottle();if(e===undefined){e=window.multigraph.jQuery}this.adapter(c);this.init();if(d.filename()!==undefined){d.emit({type:"ajaxEvent",action:"start"});e.ajax({url:d.filename(),success:function(g){var f=d.adapter().textToStringArray(d.getColumns(),g);d.stringArray(f);d.ajaxNormalize();d.dataIsReady(true);d.emit({type:"dataReady"})},error:function(g,i,h){var f=h;if(g.statusCode().status===404){f="File not found: '"+d.filename()+'"'}else{if(i){f=i+": "+f}}d._displayError(new Error(f))},complete:function(f,g){d.emit({type:"ajaxEvent",action:"complete"})}})}})});b.CSVData=a});window.multigraph.util.namespace("window.multigraph.core",function(c){var d,b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.plot);d=new window.jermaine.Model("DataPlot",function(){this.isA(c.Plot);this.hasMany("variable").validateWith(function(f){return f instanceof c.DataVariable||f===null});this.hasA("filter").validatesWith(function(f){return f instanceof c.Filter});this.hasA("datatips").validatesWith(function(f){return f instanceof c.Datatips});this.hasA("data").validatesWith(function(f){return f instanceof c.Data});b.insertDefaults(this,e.plot,a);this.respondsTo("render",function(o,p){var g=this.data();if(!g){return}var f=this.horizontalaxis(),q=this.verticalaxis();if(!f.hasDataMin()||!f.hasDataMax()){return}var n=this.variable(),j=[],h;for(h=0;hj.getUTCDate()){++h}else{if(e.getUTCDate()===j.getUTCDate()&&e.getUTCHours()>j.getUTCHours()){++h}else{if(e.getUTCDate()===j.getUTCDate()&&e.getUTCHours()===j.getUTCHours()&&e.getUTCMinutes()>j.getUTCMinutes()){++h}else{if(e.getUTCDate()===j.getUTCDate()&&e.getUTCHours()===j.getUTCHours()&&e.getUTCMinutes()===j.getUTCMinutes()&&e.getUTCSeconds()>j.getUTCSeconds()){++h}else{if(e.getUTCDate()===j.getUTCDate()&&e.getUTCHours()===j.getUTCHours()&&e.getUTCMinutes()===j.getUTCMinutes()&&e.getUTCSeconds()===j.getUTCSeconds()&&e.getUTCMilliseconds()>j.getUTCMilliseconds()){++h}}}}}}return k.add(a.parse((h*f)+"M"))};a.prototype.firstSpacingLocationAtOrAfter=function(d,e){switch(this.unit){case a.MONTH:return a.findTickmarkWithMonthSpacing(d,e,this.measure);case a.YEAR:return a.findTickmarkWithMonthSpacing(d,e,this.measure*12);default:return a.findTickmarkWithMillisecondSpacing(d.getRealValue(),e.getRealValue(),this.getRealValue())}};a.prototype.lastSpacingLocationAtOrBefore=function(e,g){var d=this.firstSpacingLocationAtOrAfter(e,g);if(d.eq(e)){return d}var f=d.add(this.negative());return f};a.prototype.toString=function(){return this.measure.toString()+this.unit.toString()};a.MILLISECOND=new c("ms");a.SECOND=new c("s");a.MINUTE=new c("m");a.HOUR=new c("H");a.DAY=new c("D");a.WEEK=new c("W");a.MONTH=new c("M");a.YEAR=new c("Y");b.DatetimeMeasure=a});window.multigraph.util.namespace("window.multigraph.core",function(a){var b=function(c){if(typeof(c)!=="number"){throw new Error("DatetimeValue requires its parameter to be a number")}this.value=new Date(c)};b.prototype.getRealValue=function(){return this.value.getTime()};b.prototype.type=a.DataValue.DATETIME;b.prototype.clone=function(){return new b(this.getRealValue())};b.parse=function(e){var i=0,j=0,h=1,f=0,c=0,g=0,d=0;if(typeof(e)==="string"){e=e.replace(/[\.\-\:\s]/g,"");if(e.length===4){i=parseInt(e,10)}else{if(e.length===6){i=parseInt(e.substring(0,4),10);j=parseInt(e.substring(4,6),10)-1}else{if(e.length===8){i=parseInt(e.substring(0,4),10);j=parseInt(e.substring(4,6),10)-1;h=parseInt(e.substring(6,8),10)}else{if(e.length===10){i=parseInt(e.substring(0,4),10);j=parseInt(e.substring(4,6),10)-1;h=parseInt(e.substring(6,8),10);f=parseInt(e.substring(8,10),10)}else{if(e.length===12){i=parseInt(e.substring(0,4),10);j=parseInt(e.substring(4,6),10)-1;h=parseInt(e.substring(6,8),10);f=parseInt(e.substring(8,10),10);c=parseInt(e.substring(10,12),10)}else{if(e.length===14){i=parseInt(e.substring(0,4),10);j=parseInt(e.substring(4,6),10)-1;h=parseInt(e.substring(6,8),10);f=parseInt(e.substring(8,10),10);c=parseInt(e.substring(10,12),10);g=parseInt(e.substring(12,14),10)}else{if(e.length===15||e.length===16||e.length===17){i=parseInt(e.substring(0,4),10);j=parseInt(e.substring(4,6),10)-1;h=parseInt(e.substring(6,8),10);f=parseInt(e.substring(8,10),10);c=parseInt(e.substring(10,12),10);g=parseInt(e.substring(12,14),10);d=parseInt(e.substring(14,17),10)}else{if(e==="0"){i=1970}else{throw new Error("Incorrect input format for Datetime Value's parse method")}}}}}}}}}else{throw new Error("Datetime Value's parse method requires its parameter to be a string")}return new b(Date.UTC(i,j,h,f,c,g,d))};b.prototype.toString=function(){var h,i,g,e,c,f,d;h=sprintf("%04s",this.value.getUTCFullYear().toString());i=sprintf("%02s",(this.value.getUTCMonth()+1).toString());g=sprintf("%02s",this.value.getUTCDate().toString());e=sprintf("%02s",this.value.getUTCHours().toString());c=sprintf("%02s",this.value.getUTCMinutes().toString());f=sprintf("%02s",this.value.getUTCSeconds().toString());d="."+sprintf("%03s",this.value.getUTCMilliseconds().toString());if(d===".000"){d=""}return h+i+g+e+c+f+d};b.prototype.compareTo=function(c){if(this.getRealValue()c.getRealValue()){return 1}}return 0};b.prototype.addRealValue=function(c){return new b(this.value.getTime()+c)};b.prototype.add=function(d){var c=new b(this.getRealValue());switch(d.unit){case a.DatetimeMeasure.MILLISECOND:c.value.setUTCMilliseconds(c.value.getUTCMilliseconds()+d.measure);break;case a.DatetimeMeasure.SECOND:c.value.setUTCSeconds(c.value.getUTCSeconds()+d.measure);break;case a.DatetimeMeasure.MINUTE:c.value.setUTCMinutes(c.value.getUTCMinutes()+d.measure);break;case a.DatetimeMeasure.HOUR:c.value.setUTCHours(c.value.getUTCHours()+d.measure);break;case a.DatetimeMeasure.DAY:c.value.setUTCDate(c.value.getUTCDate()+d.measure);break;case a.DatetimeMeasure.WEEK:c.value.setUTCDate(c.value.getUTCDate()+d.measure*7);break;case a.DatetimeMeasure.MONTH:c.value.setUTCMonth(c.value.getUTCMonth()+d.measure);break;case a.DatetimeMeasure.YEAR:c.value.setUTCFullYear(c.value.getUTCFullYear()+d.measure);break}return c};a.DataValue.mixinComparators(b.prototype);a.DatetimeValue=b});window.multigraph.util.namespace("window.multigraph.core",function(d){var c,b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.plot.filter);c=new window.jermaine.Model("Filter",function(){this.hasMany("options").validatesWith(function(f){return f instanceof d.FilterOption});this.hasA("type").validatesWith(function(f){return typeof(f)==="string"});b.insertDefaults(this,e.plot.filter,a)});d.Filter=c});window.multigraph.util.namespace("window.multigraph.core",function(d){var c=window.multigraph.utilityFunctions,e=c.getDefaultValuesFromXSD(),b=c.getKeys(e.plot.filter.option),a=new window.jermaine.Model("FilterOption",function(){this.hasA("name").validatesWith(function(f){return typeof(f)==="string"});this.hasA("value").validatesWith(function(f){return typeof(f)==="string"});c.insertDefaults(this,e.plot.filter.option,b)});d.FilterOption=a});window.multigraph.util.namespace("window.multigraph.core",function(e){var d=window.multigraph.math.Box;var c=window.multigraph.utilityFunctions,f=c.getDefaultValuesFromXSD(),b=c.getKeys(f),a=new window.jermaine.Model("Graph",function(){this.hasA("window").validatesWith(function(g){return g instanceof e.Window});this.hasA("plotarea").validatesWith(function(g){return g instanceof e.Plotarea});this.hasA("legend").validatesWith(function(g){return g instanceof e.Legend});this.hasA("background").validatesWith(function(g){return g instanceof e.Background});this.hasA("title").validatesWith(function(g){return g instanceof e.Title});this.hasMany("axes").validateWith(function(g){return g instanceof e.Axis});this.hasMany("plots").validateWith(function(g){return g instanceof e.Plot});this.hasMany("data").validateWith(function(g){return g instanceof e.Data});this.hasA("windowBox").validatesWith(function(g){return g instanceof d});this.hasA("paddingBox").validatesWith(function(g){return g instanceof d});this.hasA("plotBox").validatesWith(function(g){return g instanceof d});this.hasA("multigraph").validatesWith(function(g){return g instanceof window.multigraph.core.Multigraph});this.hasA("x0").isA("number");this.hasA("y0").isA("number");this.isBuiltWith(function(){this.window(new e.Window());this.plotarea(new e.Plotarea());this.background(new e.Background())});this.respondsTo("postParse",function(){var h,j=this,g=function(i){if(i.action==="start"){if(j.multigraph()){j.multigraph().busySpinnerLevel(1)}}else{if(i.action==="complete"){if(j.multigraph()){j.multigraph().busySpinnerLevel(-1)}}}};for(h=0;hi.height()/2){this.position(h(k["position-horizontal-top"]))}else{this.position(h(k["position-horizontal-bottom"]))}}else{if(j.perpOffset()>i.width()/2){this.position(h(k["position-vertical-right"]))}else{this.position(h(k["position-vertical-left"]))}}}if(this.anchor()===undefined){if(j.orientation()===a.HORIZONTAL){if(j.perpOffset()>i.height()/2){this.anchor(h(k["anchor-horizontal-top"]))}else{this.anchor(h(k["anchor-horizontal-bottom"]))}}else{if(j.perpOffset()>i.width()/2){this.anchor(h(k["anchor-vertical-right"]))}else{this.anchor(h(k["anchor-vertical-left"]))}}}});this.respondsTo("isEqualExceptForSpacing",function(i){return((this.axis()===i.axis())&&(this.formatter().getFormatString()===i.formatter().getFormatString())&&(this.start().eq(i.start()))&&(this.angle()===i.angle())&&(this.position().eq(i.position()))&&(this.anchor().eq(i.anchor()))&&(this.densityfactor()===i.densityfactor()))});this.hasA("iteratorNextValue").validatesWith(e.DataValue.isInstanceOrNull).defaultsTo(null);this.hasA("iteratorMinValue").validatesWith(e.DataValue.isInstance);this.hasA("iteratorMaxValue").validatesWith(e.DataValue.isInstance);this.respondsTo("prepare",function(i,j){this.iteratorMinValue(i);this.iteratorMaxValue(j);this.iteratorNextValue(this.spacing().firstSpacingLocationAtOrAfter(i,this.start()))});this.respondsTo("hasNext",function(){var i=this.iteratorNextValue();if(i===null||i===undefined){return false}return i.le(this.iteratorMaxValue())});this.respondsTo("peekNext",function(){var i=this.iteratorNextValue(),j=this.iteratorMaxValue();if(i===null||i===undefined){return undefined}if(j!==undefined&&i.gt(j)){return undefined}return i});this.respondsTo("next",function(){var i=this.iteratorNextValue(),j=this.iteratorMaxValue();if(i===null||i===undefined){return undefined}if(j!==undefined&&i.gt(j)){return undefined}this.iteratorNextValue(i.add(this.spacing()));return i});this.respondsTo("getLabelDensity",function(o){var j=this.axis(),m=this.spacing().getRealValue()*j.axisToDataRatio(),q=j.dataMin().getRealValue(),p=j.dataMax().getRealValue(),l=q+0.51234567*(p-q),n=f.create(j.type(),l),i=this.formatter().format(n);var k=((j.orientation()===a.HORIZONTAL)?this.measureStringWidth(o,i):this.measureStringHeight(o,i));return k/(m*this.densityfactor())});this.respondsTo("measureStringWidth",function(i,j){return j.length*30});this.respondsTo("measureStringHeight",function(i,j){return j.length*30});this.respondsTo("renderLabel",function(i,j){});c.insertDefaults(this,g.horizontalaxis.labels.label,b)});e.Labeler=d});window.multigraph.util.namespace("window.multigraph.core",function(d){var c,b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.legend);c=new window.jermaine.Model("Legend",function(){this.hasA("visible").validatesWith(function(f){return typeof f==="boolean"||f===null});this.hasA("base").validatesWith(function(f){return f instanceof window.multigraph.math.Point});this.hasAn("anchor").validatesWith(function(f){return f instanceof window.multigraph.math.Point});this.hasA("position").validatesWith(function(f){return f instanceof window.multigraph.math.Point});this.hasA("frame").validatesWith(function(f){return f==="plot"||f==="padding"});this.hasA("color").validatesWith(function(f){return f instanceof window.multigraph.math.RGBColor});this.hasA("bordercolor").validatesWith(function(f){return f instanceof window.multigraph.math.RGBColor});this.hasA("opacity").validatesWith(function(f){return b.validateNumberRange(f,0,1)});this.hasA("border").isA("integer");this.hasA("rows").isA("integer").isGreaterThan(0);this.hasA("columns").isA("integer").isGreaterThan(0);this.hasA("cornerradius").isA("integer");this.hasA("padding").isA("integer");this.hasAn("icon").validatesWith(function(f){return f instanceof d.Icon});this.isBuiltWith(function(){this.icon(new d.Icon())});this.hasMany("plots").validateWith(function(f){return f instanceof d.Plot});this.hasA("iconOffset").isAn("integer").defaultsTo(5);this.hasA("labelOffset").isAn("integer").defaultsTo(5);this.hasA("labelEnding").isAn("integer").defaultsTo(15);this.hasA("width").isA("number");this.hasA("height").isA("number");this.hasA("x").isA("number");this.hasA("y").isA("number");this.hasA("blockWidth").isA("number");this.hasA("blockHeight").isA("number");this.hasA("maxLabelWidth").isA("number");this.hasA("maxLabelHeight").isA("number");this.respondsTo("determineVisibility",function(){switch(this.visible()){case true:return true;case false:return false;case null:if(this.plots().size()>1){return true}else{return false}}});this.respondsTo("initializeGeometry",function(o,p){var k=this.anchor(),f=this.base(),l=this.position(),g=this.iconOffset(),h=[],m=[],n,j;if(this.determineVisibility()===false){return this}for(j=0;j=p.size()){break}n=this.border()+((this.rows()-f-1)*this.blockHeight());j=n+this.iconOffset();h=j;for(k=0;k=p.size()){break}o=this.border()+(k*this.blockWidth());l=o+this.iconOffset();i=l+m.width()+this.labelOffset();p.at(g).renderer().renderLegendIcon(q,l,j,m,this.opacity());if(m.border()>0){m.renderBorder(q,l,j,this.opacity())}this.renderLabel(p.at(g).legend().label(),q,i,h);g++}}this.end(q);return this});b.insertDefaults(this,e.legend,a)});d.Legend=c});window.multigraph.util.namespace("window.multigraph.core",function(a){var b=new window.jermaine.Model("Mixin",function(){this.hasMany("mixinfuncs");this.hasA("applied").isA("boolean").defaultsTo(false);this.respondsTo("add",function(c){this.mixinfuncs().add(c)});this.respondsTo("apply",function(){if(!this.applied()){var c;for(c=0;c0){b(g).width(d.width)}if(d.height!==undefined&&d.height>0){b(g).height(d.height)}e={};if(typeof(d.error)==="function"){e.error=d.error}if(typeof(d.warning)==="function"){e.warning=d.warning}if(!e.error||!e.warning){f=c.createDefaultMessageHandlers(g);if(!e.error){e.error=f.error}if(!e.warning){e.warning=f.warning}}d.messageHandler=e;if(d.muglString!==undefined){if(d.driver==="canvas"){return c.createCanvasGraphFromString(d)}else{if(d.driver==="raphael"){return c.createRaphaelGraphFromString(d)}else{d.messageHanlder.error(new Error("invalid graphic driver '"+d.driver+"' specified to Multigraph.createGraph"));return undefined}}}if(d.driver==="canvas"){return c.createCanvasGraph(d)}else{if(d.driver==="raphael"){return c.createRaphaelGraph(d)}else{d.messageHanlder.error(new Error("invalid graphic driver '"+d.driver+"' specified to Multigraph.createGraph"));return undefined}}};window.multigraph.create=c.createGraph;c.createDefaultMessageHandlers=function(d){b(d).css("position","relative");b(d).errorDisplay({});return{error:function(g){var f=(g.stack&&typeof(g.stack)==="string")?g.stack.replace(/\n/g,"
  • "):g.message;b(d).errorDisplay("displayError",f,g.message,{fontColor:"#000000",backgroundColor:"#ff0000",indicatorColor:"#ff0000"})},warning:function(f){var g="Warning: "+((typeof(f)==="string")?f:f.message),e=(typeof(f)!=="string"&&f.stack&&typeof(f.stack)==="string")?f.stack.replace(/\n/g,"
  • "):g;b(d).errorDisplay("displayError",e,g,{fontColor:"#000000",backgroundColor:"#e06a1b",indicatorColor:"#e06a1b"})}}};a.Multigraph=c});window.multigraph.util.namespace("window.multigraph.core",function(b){var a=function(d){var c;if(typeof(d)!=="string"){throw new Error("format must be a string")}this.formatString=d;c=sprintf(d,0);this.length=c.length};a.prototype.format=function(c){return sprintf(this.formatString,c.getRealValue())};a.prototype.getMaxLength=function(){return this.length};a.prototype.getFormatString=function(){return this.formatString};b.NumberFormatter=a});window.multigraph.util.namespace("window.multigraph.core",function(a){var c=1e-12;var b=function(d){this.measure=d};b.prototype.getRealValue=function(){return this.measure};b.prototype.toString=function(){return this.measure.toString()};b.prototype.firstSpacingLocationAtOrAfter=function(j,l){var i,k,d,e=l.value,g=j.value,h=Math.abs(this.measure);i=(g-e)/h;k=Math.floor(i);d=k+1;if((i-kc.value){return 1}}return 0};a.prototype.addRealValue=function(c){return new a(this.value+c)};a.prototype.add=function(c){return new a(this.value+c.measure)};a.prototype.type=b.DataValue.NUMBER;a.prototype.clone=function(){return new a(this.value)};a.parse=function(c){return new a(parseFloat(c))};b.DataValue.mixinComparators(a.prototype);b.NumberValue=a});window.multigraph.util.namespace("window.multigraph.core",function(d){var b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.horizontalaxis.pan),c;c=new window.jermaine.Model("Pan",function(){this.hasA("allowed").isA("boolean");this.hasA("min").validatesWith(d.DataValue.isInstanceOrNull);this.hasA("max").validatesWith(d.DataValue.isInstanceOrNull);b.insertDefaults(this,e.horizontalaxis.pan,a)});d.Pan=c});window.multigraph.util.namespace("window.multigraph.core",function(a){a.PeriodicArrayData=window.jermaine.Model(function(){var c=this,b={next:function(){},hasNext:function(){return false}};this.isA(a.ArrayData);this.hasA("period").validatesWith(a.DataMeasure.isInstance);this.isBuiltWith("columns","stringArray","period",function(){this.init();this.addListener("listenerAdded",function(d){var e=this.array();if(d.targetType==="dataReady"){d.listener(e[0][0],e[e.length-1][0])}})});this.respondsTo("getIterator",function(e,g,d,f){return c.getArrayDataIterator(this,e,g,d,f)});c.getArrayDataIterator=function(y,d,o,s,q){var l=a.DataValue,t={},z=[],v=0,u,r,e,g,f=y.array();q=q||0;if(Object.prototype.toString.apply(d)!=="[object Array]"){throw new Error("ArrayData: getIterator method requires that the first parameter be an array of strings")}else{for(u=0;u=f.length){e=0;w=w.add(y.period());n=w.getRealValue()-x.getRealValue()}h=a.DataValue.create(f[e][0].type,f[e][0].getRealValue()+n);if(h.gt(s)){e=-1}return k},hasNext:function(){return(e>=0)}}}})});window.multigraph.util.namespace("window.multigraph.core",function(d){var b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.plot.legend),c=new window.jermaine.Model("PlotLegend",function(){this.hasA("visible").isA("boolean");this.hasA("label").validatesWith(function(f){return f instanceof d.Text});b.insertDefaults(this,e.plot.legend,a)});d.PlotLegend=c});window.multigraph.util.namespace("window.multigraph.core",function(d){var c=window.multigraph.utilityFunctions,e=c.getDefaultValuesFromXSD(),b=c.getKeys(e.plotarea),a=new window.jermaine.Model("Plotarea",function(){this.hasA("margin").validatesWith(function(f){return f instanceof window.multigraph.math.Insets});this.hasA("border").isA("integer");this.hasA("color").validatesWith(function(f){return f===null||f instanceof window.multigraph.math.RGBColor});this.hasA("bordercolor").validatesWith(function(f){return f instanceof window.multigraph.math.RGBColor});c.insertDefaults(this,e.plotarea,b)});d.Plotarea=a});window.multigraph.util.namespace("window.multigraph.core",function(a){var b;b=new window.jermaine.Model("BandRenderer",function(){this.isA(a.Renderer);this.hasA("numberOfVariables").defaultsTo(3)});b.GRAY=parseInt("80",16)/255;a.Renderer.declareOptions(b,"BandRendererOptions",[{name:"linecolor",type:a.Renderer.RGBColorOption,"default":new window.multigraph.math.RGBColor(0,0,0)},{name:"linewidth",type:a.Renderer.NumberOption,"default":1},{name:"line1color",type:a.Renderer.RGBColorOption,"default":null},{name:"line1width",type:a.Renderer.NumberOption,"default":-1},{name:"line2color",type:a.Renderer.RGBColorOption,"default":null},{name:"line2width",type:a.Renderer.NumberOption,"default":-1},{name:"fillcolor",type:a.Renderer.RGBColorOption,"default":new window.multigraph.math.RGBColor(b.GRAY,b.GRAY,b.GRAY)},{name:"fillopacity",type:a.Renderer.NumberOption,"default":1}]);a.Renderer.BAND=new a.Renderer.Type("band");a.Renderer.addType({type:a.Renderer.Type.parse("band"),model:b});a.BandRenderer=b});window.multigraph.util.namespace("window.multigraph.core",function(b){var c,d=window.multigraph.utilityFunctions.getDefaultValuesFromXSD(),a=window.multigraph.utilityFunctions.getKeys(d.plot.renderer);c=new window.jermaine.Model("BarRenderer",function(){this.isA(b.Renderer);this.hasA("numberOfVariables").defaultsTo(2)});b.Renderer.declareOptions(c,"BarRendererOptions",[{name:"barwidth",type:b.Renderer.HorizontalDataMeasureOption,"default":new b.DataMeasure.parse("number",0)},{name:"baroffset",type:b.Renderer.NumberOption,"default":0},{name:"barbase",type:b.Renderer.VerticalDataValueOption,"default":null},{name:"fillcolor",type:b.Renderer.RGBColorOption,"default":new window.multigraph.math.RGBColor(0,0,0)},{name:"fillopacity",type:b.Renderer.NumberOption,"default":1},{name:"linecolor",type:b.Renderer.RGBColorOption,"default":new window.multigraph.math.RGBColor(0,0,0)},{name:"hidelines",type:b.Renderer.NumberOption,"default":2}]);b.Renderer.BAR=new b.Renderer.Type("bar");b.Renderer.addType({type:b.Renderer.Type.parse("bar"),model:c});b.BarRenderer=c});window.multigraph.util.namespace("window.multigraph.core",function(c){var a,d=window.multigraph.utilityFunctions.getDefaultValuesFromXSD(),b=window.multigraph.utilityFunctions.getKeys(d.plot.renderer);a=new window.jermaine.Model("FillRenderer",function(){this.isA(c.Renderer);this.hasA("numberOfVariables").defaultsTo(2)});a.GRAY=parseInt("80",16)/255;c.Renderer.declareOptions(a,"FillRendererOptions",[{name:"linecolor",type:c.Renderer.RGBColorOption,"default":new window.multigraph.math.RGBColor(0,0,0)},{name:"linewidth",type:c.Renderer.NumberOption,"default":1},{name:"fillcolor",type:c.Renderer.RGBColorOption,"default":new window.multigraph.math.RGBColor(a.GRAY,a.GRAY,a.GRAY)},{name:"downfillcolor",type:c.Renderer.RGBColorOption,"default":null},{name:"fillopacity",type:c.Renderer.NumberOption,"default":1},{name:"fillbase",type:c.Renderer.VerticalDataValueOption,"default":null}]);c.Renderer.FILL=new c.Renderer.Type("fill");c.Renderer.addType({type:c.Renderer.Type.parse("fill"),model:a});c.FillRenderer=a});window.multigraph.util.namespace("window.multigraph.core",function(c){var b,d=window.multigraph.utilityFunctions.getDefaultValuesFromXSD(),a=window.multigraph.utilityFunctions.getKeys(d.plot.renderer);b=new window.jermaine.Model("PointlineRenderer",function(){this.isA(c.Renderer);this.hasA("numberOfVariables").defaultsTo(2)});b.CIRCLE="circle";b.SQUARE="square";b.TRIANGLE="triangle";b.DIAMOND="diamond";b.STAR="star";b.PLUS="plus";b.X="x";b.shapes=[b.CIRCLE,b.SQUARE,b.TRIANGLE,b.DIAMOND,b.STAR,b.PLUS,b.X];b.isShape=function(e){var f;for(f=0;fc){c=f}}return c*15});this.respondsTo("measureStringHeight",function(b){if(this.string()===undefined){throw new Error("measureStringHeight requires the string attr to be set.")}var c=this.string().match(/\n/g);return(c!==null?(c.length+1):1)*12})})});window.multigraph.util.namespace("window.multigraph.core",function(a){a.Warning=function(b){this.message=b};a.Warning.prototype=new Error()});window.multigraph.util.namespace("window.multigraph.core",function(a){a.WebServiceData=window.jermaine.Model(function(){this.isA(a.Data);this.hasA("serviceaddress").isA("string");this.hasA("serviceaddresspattern").isA("string");this.hasA("format").isA("string");this.hasA("formatter").validatesWith(a.DataFormatter.isInstance);this.hasA("messageHandler");this.hasA("ajaxthrottle");this.isBuiltWith("columns","serviceaddress","%messageHandler","%ajaxthrottle",function(){this.init();if(this.columns().size()>0){var b=this.columns().at(0).type();if(this.format()===undefined){this.format(b===a.DataValue.NUMBER?"%f":"%Y%M%D%H%i%s")}this.formatter(a.DataFormatter.create(b,this.format()))}if(this.ajaxthrottle()===undefined){this.ajaxthrottle(window.multigraph.jQuery)}});this.respondsTo("_displayError",function(b){if(this.messageHandler()){this.messageHandler().error(b)}else{throw b}});this.respondsTo("getBounds",function(b){return[0,10]});this.hasA("arraydata").defaultsTo(null).validatesWith(function(b){return b instanceof a.ArrayData||b===null});this.hasA("cacheHead").defaultsTo(null).validatesWith(function(b){return b===null||b instanceof a.WebServiceDataCacheNode});this.hasA("cacheTail").defaultsTo(null).validatesWith(function(b){return b===null||b instanceof a.WebServiceDataCacheNode});this.respondsTo("dataHead",function(){var b=this.cacheHead();if(b===null){return null}if(b.hasData()){return b}return b.dataNext()});this.respondsTo("dataTail",function(){var b=this.cacheTail();if(b===null){return null}if(b.hasData()){return b}return b.dataPrev()});this.respondsTo("insertCacheNode",function(d){var c=this.cacheHead(),b=this.cacheTail();if(c===null){this.cacheHead(d);this.cacheTail(d)}else{if(d.coveredMin().lt(c.coveredMin())){d.next(c);c.prev(d);this.cacheHead(d)}else{d.prev(b);b.next(d);this.cacheTail(d)}}});this.respondsTo("constructRequestURL",function(d,b){var e=this.serviceaddress(),c=this.formatter();if(e===undefined){throw new Error("WebServiceData.constructRequestURL: undefined service address")}if(c===undefined){throw new Error("WebServiceData.constructRequestURL: undefined formatter for column 0")}if(this.serviceaddresspattern()===undefined){if((e.indexOf("$min")<0)&&(e.indexOf("$max")<0)){this.serviceaddresspattern(e+"$min,$max")}else{this.serviceaddresspattern(e)}}return(this.serviceaddresspattern().replace("$min",c.format(d)).replace("$max",c.format(b)))});this.hasA("coveredMin").defaultsTo(null).validatesWith(function(b){return b===null||a.DataValue.isInstance(b)});this.hasA("coveredMax").defaultsTo(null).validatesWith(function(b){return b===null||a.DataValue.isInstance(b)});this.respondsTo("insureCoveredRange",function(){var d=this.cacheHead(),c=this.cacheTail(),b=this.coveredMin(),e=this.coveredMax();if(b===null||e===null){return}if(d===null||c===null){this.requestSingleRange(b,e)}else{if(b.lt(d.coveredMin())){this.requestSingleRange(b,d.coveredMin())}if(e.gt(c.coveredMax())){this.requestSingleRange(c.coveredMax(),e)}}});this.respondsTo("requestSingleRange",function(c,b){var f,e,d=this;f=new a.WebServiceDataCacheNode(c,b);this.insertCacheNode(f);e=this.constructRequestURL(c,b);this.emit({type:"ajaxEvent",action:"start"});this.ajaxthrottle().ajax({url:e,dataType:"text",success:function(g){if(g.indexOf("")>0){g=window.multigraph.parser.jquery.stringToJQueryXMLObj(g).find("values").text()}f.parseData(d.getColumns(),g);d.emit({type:"ajaxEvent",action:"success"});d.emit({type:"dataReady"})},error:function(h,j,i){var g=i;if(h.statusCode().status===404){g="URL not found: '"+e+'"'}else{if(j){g=j+": "+g}}d._displayError(new Error(g))},complete:function(g,h){d.emit({type:"ajaxEvent",action:"complete"})}})});this.respondsTo("getIterator",function(j,e,l,f){var c,k,d,m,h,g,q,o,p;if(e.gt(l)){g=e;e=l;l=g}if(this.coveredMin()===null||e.lt(this.coveredMin())){this.coveredMin(e.clone())}if(this.coveredMax()===null||l.gt(this.coveredMax())){this.coveredMax(l.clone())}if(!this.paused()){this.insureCoveredRange()}if(this.dataHead()===null){return{next:function(){},hasNext:function(){return false}}}p=[];for(h=0;h=q.data().length){m=q.dataNext();if(m!==null){q=m;o=0}else{o=q.data().length-1;break}}++d}}return new a.WebServiceDataIterator(p,c,k,q,o)});this.hasA("paused").isA("boolean").defaultsTo(false);this.respondsTo("pause",function(){this.paused(true)});this.respondsTo("resume",function(){this.paused(false);this.emit({type:"dataReady",min:this.coveredMin(),max:this.coveredMax()})})})});window.multigraph.util.namespace("window.multigraph.core",function(a){a.WebServiceDataCacheNode=window.jermaine.Model(function(){this.hasA("data").defaultsTo(null).validatesWith(function(d){var b=window.multigraph.util.namespace("window.multigraph.utilityFunctions");if(d===null){return true}if(b.typeOf(d)!=="array"){this.message="WebServiceDataCacheNode's data attribute is not an Array";return false}if(d.length>0){var e=d[0],c;if(b.typeOf(e)!=="array"){this.message="WebServiceDataCacheNode's data attribute is not an Array of Arrays";return false}for(c=0;cg){return null}for(e=0;e=f.data().length){this.currentNode(f.dataNext());this.currentIndex(0)}return j}})})});window.multigraph.util.namespace("window.multigraph.core",function(d){var b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.window),c=new window.jermaine.Model("Window",function(){this.hasA("width").isA("integer");this.hasA("height").isA("integer");this.hasA("border").isA("integer");this.hasA("margin").validatesWith(function(f){return f instanceof window.multigraph.math.Insets});this.hasA("padding").validatesWith(function(f){return f instanceof window.multigraph.math.Insets});this.hasA("bordercolor").validatesWith(function(f){return f instanceof window.multigraph.math.RGBColor});b.insertDefaults(this,e.window,a)});d.Window=c});window.multigraph.util.namespace("window.multigraph.core",function(d){var b=window.multigraph.utilityFunctions,e=b.getDefaultValuesFromXSD(),a=b.getKeys(e.horizontalaxis.zoom),c=new window.jermaine.Model("Zoom",function(){this.hasA("allowed").isA("boolean");this.hasA("min").validatesWith(function(f){return d.DataMeasure.isInstance(f)});this.hasA("max").validatesWith(function(f){return d.DataMeasure.isInstance(f)});this.hasA("anchor").validatesWith(function(f){return d.DataValue.isInstance(f)||f===null});b.insertDefaults(this,e.horizontalaxis.zoom,a)});d.Zoom=c});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin=new window.multigraph.core.Mixin()});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,d){var c=function(n,g){var q=[],o,f=n.find("labels"),j=n.find("label"),p=g.labelers(),m=b.core.Labeler,l=b.jQuery,k;o=l.trim(f.attr("spacing"));if(o!==""){q=o.split(/\s+/)}if(q.length>0){for(k=0;k0){var h=m[d](f,g,undefined,null);l.each(j,function(i,r){o=l.trim(l(r).attr("spacing"));q=[];if(o!==""){q=o.split(/\s+/)}for(k=0;k0){g.title(A.AxisTitle[d](m,g))}else{g.title(new A.AxisTitle(g))}m=k.find("grid");if(m.length>0){g.grid(A.Grid[d](m))}m=k.find("pan");if(m.length>0){g.pan(A.Pan[d](m,g.type()))}m=k.find("zoom");if(m.length>0){g.zoom(A.Zoom[d](m,g.type()))}if(k.find("labels").length>0){c(k,g)}m=k.find("binding");if(m.length>0){var f=m.attr("id"),p=m.attr("min"),t=m.attr("max"),B=q.parse(g.type(),p),r=q.parse(g.type(),t);if(typeof(f)!=="string"||f.length<=0){throw new Error("invalid axis binding id: '"+f+"'")}if(!q.isInstance(B)){throw new Error("invalid axis binding min: '"+p+"'")}if(!q.isInstance(r)){throw new Error("invalid axis binding max: '"+t+"'")}A.AxisBinding.findByIdOrCreateNew(f).addAxis(g,B,r,l)}}return g}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.AxisTitle[c]=function(e,g){var j=new b.core.AxisTitle(g),d=false,f=b.math.Point.parse,i,h=function(m,l,k){if(b.utilityFunctions.parseAttribute(m,l,k)){}};if(e){i=e.text();if(i!==""){j.content(new b.core.Text(i));d=true}h(e.attr("anchor"),j.anchor,f);h(e.attr("base"),j.base,parseFloat);h(e.attr("position"),j.position,f);h(e.attr("angle"),j.angle,parseFloat)}if(d===true){return j}return undefined}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Background[c]=function(e,d){var f=new b.core.Background(),g;if(e){b.utilityFunctions.parseAttribute(e.attr("color"),f.color,b.math.RGBColor.parse);g=e.find("img");if(g.length>0){f.img(b.core.Img[c](g,d))}}return f}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){window.multigraph.core.Data[c]=function(f,j,e){var y=b.core,p=y.ArrayData,h=b.jQuery,g,i,s,u=[],B,n,r=p;if(f){n=h(f).attr("adapter");if(n!==undefined&&n!==""){r=window.multigraph.adapters[n];if(r===undefined){throw new Error("Missing data adapater: "+r)}}g=f.find("variables");i=g.attr("missingvalue");s=g.attr("missingop");var k=g.find(">variable");if(k.length>0){h.each(k,function(C,D){u.push(y.DataVariable[c](h(D)))})}var o=false,x,m=h(f.find(">repeat"));if(m.length>0){var v=h(m).attr("period");if(v===undefined||v===""){e.warning(" tag requires a 'period' attribute; data treated as non-repeating")}else{x=y.DataMeasure.parse(u[0].type(),v);o=true}}var A=h(f.find(">values"));if(A.length>0){A=A[0];var z=r.textToStringArray(u,h(A).text());if(o){B=new y.PeriodicArrayData(u,z,x)}else{B=new p(u,z)}}var l=h(f.find(">csv"));if(l.length>0){l=l[0];var t=h(l).attr("location");B=new y.CSVData(u,j?j.rebaseUrl(t):t,e,j?j.getAjaxThrottle(t):undefined)}var q=h(f.find(">service"));if(q.length>0){q=h(q[0]);var d=q.attr("location");B=new y.WebServiceData(u,j?j.rebaseUrl(d):d,e,j?j.getAjaxThrottle(d):undefined);var w=q.attr("format");if(w){B.format(w)}}}if(B){if(i!==undefined){B.defaultMissingvalue(i)}if(s!==undefined){B.defaultMissingop(s)}B.adapter(r)}return B}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.DataVariable[c]=function(g,h){var f,e=b.utilityFunctions,j=e.parseAttribute,i=b.core.DataValue,d;if(g&&g.attr("id")){f=new b.core.DataVariable(g.attr("id"));j(g.attr("column"),f.column,e.parseInteger);j(g.attr("type"),f.type,i.parseType);j(g.attr("missingvalue"),f.missingvalue,e.parseDataValue(f.type()));j(g.attr("missingop"),f.missingop,i.parseComparator)}return f}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Datatips[c]=function(j){var h=new b.core.Datatips(),i=b.jQuery,l=b.math.RGBColor.parse,d=b.utilityFunctions,f=d.parseAttribute,g=d.parseInteger,k=d.parseString,e;if(j){e=j.find("variable");if(e.length>0){i.each(e,function(m,n){h.variables().add(b.core.DatatipsVariable[c](i(n)))})}f(j.attr("format"),h.format,k);f(j.attr("bgcolor"),h.bgcolor,l);f(j.attr("bgalpha"),h.bgalpha,k);f(j.attr("border"),h.border,g);f(j.attr("bordercolor"),h.bordercolor,l);f(j.attr("pad"),h.pad,g)}return h}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.DatatipsVariable[c]=function(f){var e=new b.core.DatatipsVariable(),d=b.utilityFunctions;if(f){d.parseAttribute(f.attr("format"),e.format,d.parseString)}return e}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Filter[c]=function(e){var f=new b.core.Filter(),g=b.jQuery,d=b.utilityFunctions,h;if(e){h=e.find("option");if(h.length>0){g.each(h,function(j,k){f.options().add(b.core.FilterOption[c](g(k)))})}d.parseAttribute(e.attr("type"),f.type,d.parseString)}return f}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.FilterOption[c]=function(d){var e=new b.core.FilterOption();if(d){e.name(d.attr("name"));e.value(d.attr("value")===""?undefined:d.attr("value"))}return e}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,e){var d=b.jQuery;var c=function(h,k){var j=d(h),g=j[0].attributes,i=j.children(),f=b.math.RGBColor.colorNameIsDeprecated,l;if(h.nodeName==="option"){if(/color/.test(j.attr("name"))){l=f(j.attr("value"));if(l){k.warning('Warning: color string "'+j.attr("value")+'" is deprecated; use "'+l+'" instead')}}}if(g){d.each(g,function(){if(/color/.test(this.name)){l=f(this.value);if(l){k.warning('Warning: color string "'+this.value+'" is deprecated; use "'+l+'" instead')}}})}if(i){i.each(function(){c(this,k)})}};b.core.Graph[e]=function(j,f,m){var h=b.core,n=new h.Graph(),l=h.Axis,i=b.utilityFunctions.getDefaultValuesFromXSD(),g;n.multigraph(f);if(j){try{c(j,m)}catch(k){}g=j.find(">window");if(g.length>0){n.window(h.Window[e](g))}g=j.find(">legend");if(g.length>0){n.legend(h.Legend[e](g))}else{n.legend(h.Legend[e]())}g=j.find(">background");if(g.length>0){n.background(h.Background[e](g,n.multigraph()))}g=j.find(">plotarea");if(g.length>0){n.plotarea(h.Plotarea[e](g))}g=j.find(">title");if(g.length>0){n.title(h.Title[e](g,n))}d.each(j.find(">horizontalaxis"),function(o,p){n.axes().add(l[e](d(p),l.HORIZONTAL,m,n.multigraph()))});d.each(j.find(">verticalaxis"),function(o,p){n.axes().add(l[e](d(p),l.VERTICAL,m,n.multigraph()))});d.each(j.find(">throttle"),function(o,r){var q=d(r).attr("pattern")?d(r).attr("pattern"):i.throttle.pattern,t=d(r).attr("requests")?d(r).attr("requests"):i.throttle.requests,s=d(r).attr("period")?d(r).attr("period"):i.throttle.period,p=d(r).attr("concurrent")?d(r).attr("concurrent"):i.throttle.concurrent;f.addAjaxThrottle(q,t,s,p)});d.each(j.find(">data"),function(o,p){n.data().add(h.Data[e](d(p),n.multigraph(),m))});d.each(j.find(">plot"),function(o,p){n.plots().add(h.Plot[e](d(p),n,m))});n.postParse()}return n}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Title[c]=function(h,l){var j,g=b.math.Point.parse,i=b.math.RGBColor.parse,d=b.utilityFunctions,e=d.parseAttribute,f=d.parseInteger;if(h){var k=h.text();if(k!==""){j=new b.core.Title(new b.core.Text(k),l)}else{return undefined}e(h.attr("frame"),j.frame,function(m){return m.toLowerCase()});e(h.attr("border"),j.border,f);e(h.attr("color"),j.color,i);e(h.attr("bordercolor"),j.bordercolor,i);e(h.attr("opacity"),j.opacity,parseFloat);e(h.attr("padding"),j.padding,f);e(h.attr("cornerradius"),j.cornerradius,f);e(h.attr("anchor"),j.anchor,g);e(h.attr("base"),j.base,g);e(h.attr("position"),j.position,g)}return j}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Grid[c]=function(f){var g=new b.core.Grid(),e=b.utilityFunctions,h=e.parseAttribute,d;if(f){h(f.attr("color"),g.color,b.math.RGBColor.parse);d=f.attr("visible");if(d!==undefined){g.visible(e.parseBoolean(d))}else{g.visible(true)}}return g}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Icon[c]=function(f){var g=new b.core.Icon(),e=b.utilityFunctions,h=e.parseAttribute,d=e.parseInteger;if(f){h(f.attr("height"),g.height,d);h(f.attr("width"),g.width,d);h(f.attr("border"),g.border,d)}return g}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Img[c]=function(f,e){var d,i=b.utilityFunctions.parseAttribute,g=b.math.Point.parse;if(f&&f.attr("src")!==undefined){var h=f.attr("src");if(!h){throw new Error('img elment requires a "src" attribute value')}if(e){h=e.rebaseUrl(h)}d=new b.core.Img(h);i(f.attr("anchor"),d.anchor,g);i(f.attr("base"),d.base,g);i(f.attr("position"),d.position,g);i(f.attr("frame"),d.frame,function(j){return j.toLowerCase()})}return d}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Labeler[c]=function(h,e,f,j){var k,l=b.math,d=b.utilityFunctions,g=l.Point.parse;var i=function(p,o,n,q){if(!d.parseAttribute(p,o,n)&&f!==undefined){o(f[q]())}};var m=function(n){return function(o){return window.multigraph.core.DataFormatter.create(n,o)}};if(h){k=new b.core.Labeler(e);if(j!==null){if(j===undefined){j=h.attr("spacing")}i(j,k.spacing,d.parseDataMeasure(e.type()),"spacing")}i(h.attr("format"),k.formatter,m(e.type()),"formatter");i(h.attr("start"),k.start,d.parseDataValue(e.type()),"start");i(h.attr("angle"),k.angle,parseFloat,"angle");i(h.attr("position"),k.position,g,"position");i(h.attr("anchor"),k.anchor,g,"anchor");i(h.attr("densityfactor"),k.densityfactor,parseFloat,"densityfactor");i(h.attr("color"),k.color,l.RGBColor.parse,"color");i(h.attr("visible"),k.visible,d.parseBoolean,"visible")}return k}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Legend[c]=function(f){var h=new b.core.Legend(),e=b.utilityFunctions,k=e.parseAttribute,d=e.parseInteger,g=b.math.Point.parse,i=b.math.RGBColor.parse,j;if(f){k(f.attr("visible"),h.visible,e.parseBoolean);k(f.attr("base"),h.base,g);k(f.attr("anchor"),h.anchor,g);k(f.attr("position"),h.position,g);k(f.attr("frame"),h.frame,e.parseString);k(f.attr("color"),h.color,i);k(f.attr("bordercolor"),h.bordercolor,i);k(f.attr("opacity"),h.opacity,parseFloat);k(f.attr("border"),h.border,d);k(f.attr("rows"),h.rows,d);k(f.attr("columns"),h.columns,d);k(f.attr("cornerradius"),h.cornerradius,d);k(f.attr("padding"),h.padding,d);j=f.find("icon");if(j.length>0){h.icon(b.core.Icon[c](j))}}return h}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Multigraph[c]=function(g,i,h){var f=new b.core.Multigraph(),e=f.graphs(),d=b.core.Graph,j=b.jQuery,k;f.mugl(i);if(g){k=g.find(">graph");if(k.length>0){j.each(k,function(l,m){e.add(d[c](j(m),f,h))})}else{if(k.length===0&&g.children().length>0){e.add(d[c](g,f,h))}}}return f}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Pan[c]=function(f,g){var h=new b.core.Pan(),d=b.utilityFunctions,i=d.parseAttribute,e=d.parseDataValue;if(f){i(f.attr("allowed"),h.allowed,d.parseBoolean);i(f.attr("min"),h.min,e(g));i(f.attr("max"),h.max,e(g))}return h}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.stringToJQueryXMLObj=function(c){var d=window.multigraph.jQuery;if(typeof(c)!=="string"){return d(c)}var b=d.parseXML(c);return d(d(b).children()[0])}});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Plot[c]=function(k,p,o){var h=b.jQuery,f=b.core,i=f.DataPlot,j=f.PlotLegend,n,e,q,g,m,d;if(k){d=k.find(">verticalaxis");if(d.length===1&&d.attr("ref")!==undefined){if(p){q=p.axisById(d.attr("ref"));if(q===undefined){throw new Error("Plot Vertical Axis Error: The graph does not contain an axis with an id of '"+d.attr("ref")+"'")}}}d=k.find("verticalaxis constant");if(d.length>0){var l=d.attr("value");if(l===undefined){throw new Error("Constant Plot Error: A 'value' attribute is needed to define a Constant Plot")}n=new f.ConstantPlot(f.DataValue.parse(q.type(),l))}else{n=new i()}n.verticalaxis(q);d=k.find(">horizontalaxis");if(d.length===1&&d.attr("ref")!==undefined){if(p){e=p.axisById(d.attr("ref"));if(e!==undefined){n.horizontalaxis(e)}else{throw new Error("Plot Horizontal Axis Error: The graph does not contain an axis with an id of '"+d.attr("ref")+"'")}}}if(n instanceof i){if(k.find("horizontalaxis variable").length===0){n.variable().add(null)}d=k.find("horizontalaxis variable, verticalaxis variable");if(d.length>0){if(p){h.each(d,function(r,s){m=h(s).attr("ref");g=p.variableById(m);if(g!==undefined){n.data(g.data());n.variable().add(g)}else{throw new Error("Plot Variable Error: No Data tag contains a variable with an id of '"+m+"'")}})}}}d=k.find("legend");if(d.length>0){n.legend(j[c](d,n))}else{n.legend(j[c](undefined,n))}d=k.find("renderer");if(d.length>0){n.renderer(f.Renderer[c](d,n,o))}d=k.find("filter");if(d.length>0){n.filter(f.Filter[c](d))}d=k.find("datatips");if(d.length>0){n.datatips(f.Datatips[c](d))}}return n}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.PlotLegend[c]=function(e,h){var f=new b.core.PlotLegend(),d=b.utilityFunctions,j=d.parseAttribute,g=b.core.Text,i;if(e){j(e.attr("visible"),f.visible,d.parseBoolean);j(e.attr("label"),f.label,function(k){return new g(k)})}if(f.label()===undefined){if(typeof(h.variable)==="function"&&h.variable().size()>=2){f.label(new g(h.variable().at(1).id()))}else{f.label(new g("plot"))}}return f}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Plotarea[c]=function(f){var j=new b.core.Plotarea(),g=j.margin(),e=b.utilityFunctions,i=e.parseAttribute,d=e.parseInteger,h=b.math.RGBColor.parse;if(f){i(f.attr("marginbottom"),g.bottom,d);i(f.attr("marginleft"),g.left,d);i(f.attr("margintop"),g.top,d);i(f.attr("marginright"),g.right,d);i(f.attr("border"),j.border,d);i(f.attr("color"),j.color,h);i(f.attr("bordercolor"),j.bordercolor,h)}return j}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Renderer[c]=function(h,i,l){var k,j,d,g=b.jQuery,e=b.core,f=e.Renderer;if(h&&h.attr("type")!==undefined){k=f.Type.parse(h.attr("type"));if(!f.Type.isInstance(k)){throw new Error("unknown renderer type '"+h.attr("type")+"'")}j=f.create(k);j.plot(i);if(h.find("option").length>0){(function(s,q,r,u){var p,o=q.find("option[name=missingvalue]"),t=q.find("option[name=missingop]");if(o.length>0||t.length>0){var n=r.data().columns(),m;for(p=0;p0&&(m.missingvalue()===undefined)){m.missingvalue(e.NumberValue.parse(o.attr("value")))}if(t.length>0&&(m.missingop()===undefined)){m.missingop(e.DataValue.parseComparator(t.attr("value")))}}}}if(o.length>0){u.warning("Renderer option 'missingvalue' is deprecated; use 'missingvalue' attribute of 'data'/'variable'; instead");o.remove()}if(t.length>0){u.warning("Renderer option 'missingop' is deprecated; use 'missingvalue' attribute of 'data'/'variable'; instead");t.remove()}}(j,h,i,l));g.each(h.find(">option"),function(m,n){try{j.setOptionFromString(g(n).attr("name"),g(n).attr("value"),g(n).attr("min"),g(n).attr("max"))}catch(n){if(n instanceof e.Warning){l.warning(n)}else{throw n}}})}}return j}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Window[c]=function(h){var e=new b.core.Window(),g=b.utilityFunctions,i=g.parseAttribute,f=g.parseInteger,d;if(h){i(h.attr("width"),e.width,f);i(h.attr("height"),e.height,f);i(h.attr("border"),e.border,f);d=h.attr("margin");if(d!==undefined){(function(j){e.margin().set(j,j,j,j)}(parseInt(d,10)))}d=h.attr("padding");if(d!==undefined){(function(j){e.padding().set(j,j,j,j)}(parseInt(d,10)))}i(h.attr("bordercolor"),e.bordercolor,b.math.RGBColor.parse)}return e}})});window.multigraph.util.namespace("window.multigraph.parser.jquery",function(a){a.mixin.add(function(b,c){b.core.Zoom[c]=function(h,i){var f=b.core,j=new f.Zoom(),g=b.utilityFunctions,k=g.parseAttribute,e=g.parseDataMeasure,d;if(h){k(h.attr("allowed"),j.allowed,g.parseBoolean);k(h.attr("min"),j.min,e(i));k(h.attr("max"),j.max,e(i));d=h.attr("anchor");if(d!==undefined){if(d.toLowerCase()==="none"){j.anchor(null)}else{j.anchor(f.DataValue.parse(i,d))}}}return j}})});window.multigraph.util.namespace("window.multigraph.normalizer",function(a){a.mixin=new window.multigraph.core.Mixin()});window.multigraph.util.namespace("window.multigraph.normalizer",function(a){a.mixin.add(function(b){b.Axis.respondsTo("normalize",function(f){var e,g,d;if(this.title()&&this.title().content()===undefined){this.title().content(new b.Text(this.id()))}if(this.labelers().size()===0){var j=(window.multigraph.utilityFunctions.getDefaultValuesFromXSD()).horizontalaxis.labels,c=this.type()===b.DataValue.NUMBER?j.defaultNumberSpacing:j.defaultDatetimeSpacing,h=c.split(/\s+/);for(e=0;e0){for(k=0;kk){for(j=0;jk){throw new Error("Data Variable Error: Attempting to specify column '"+m[j].column()+"' for a variable, while there are only "+k+" data columns available")}}}};var d=function(o,k,n){var m=f.DataValue,j,l;k=m.parseComparator(k);for(l=0;l0){k.pop()}for(j=0;j0){if(j[0].length0){c+=n}n++}else{if(d.orientation()===h){c="y";if(f>0){c+=f}f++}}if(d.id()===undefined){d.id(c)}}for(k=0;k0?1:0),10))}else{if(k()===undefined){k(parseInt(c.size()/h()+((c.size()%h())>0?1:0),10))}}return this})})});window.multigraph.util.namespace("window.multigraph.normalizer",function(a){a.mixin.add(function(b){b.Multigraph.respondsTo("normalize",function(){var c;for(c=0;cMath.abs(o)){j(g)}else{j(i)}h(this.findNearestAxis(m,l,j()));if(h()===null){j((j()===g)?i:g);h(this.findNearestAxis(m,l,j()))}this.dragStarted(true)}if(n){if(j()===g){h().doZoom(m,p)}else{h().doZoom(l,o)}}else{if(j()===g){h().doPan(m,p)}else{h().doPan(l,o)}}f.redraw()}catch(k){d(k)}})})});window.multigraph.util.namespace("window.multigraph.events.jquery.mouse",function(a){a.mixin=new window.multigraph.core.Mixin()});window.multigraph.util.namespace("window.multigraph.events.jquery.mouse",function(a){a.mixin.add(function(d,c){var b=d.core.Graph;b.hasA("mouseWheelTimer").defaultsTo(null);b.respondsTo("doWheelZoom",function(h,f,m,l){var j=this;try{this.pauseAllData();var i=this.findNearestAxis(f,m);if(i.orientation()===d.core.Axis.HORIZONTAL){i.doZoom(f,4*l)}else{i.doZoom(m,4*l)}h.redraw();var g=this.mouseWheelTimer;if(g()!==null){clearTimeout(g());g(null)}g(setTimeout(function(){j.resumeAllData()},500))}catch(k){c(k)}})})});window.multigraph.util.namespace("window.multigraph.events.jquery.mouse",function(a){a.mixin.add(function(b){var c=window.multigraph.util.namespace("window.multigraph.math");b.core.Multigraph.respondsTo("registerMouseEvents",function(h){var g,f,i=false,k=false,e=this,d=window.multigraph.jQuery(h);var j=function(l){return new c.Point((l.pageX-d.offset().left)-e.graphs().at(0).x0(),d.height()-(l.pageY-d.offset().top)-e.graphs().at(0).y0())};d.mousedown(function(l){l.preventDefault();f=g=j(l);i=true;k=false});d.mouseup(function(l){i=false;e.graphs().at(0).doDragDone()});d.mousemove(function(n){var o=j(n);if(i){var m=o.x()-f.x(),l=o.y()-f.y();if(e.graphs().size()>0){if(!k){e.graphs().at(0).doDragReset()}e.graphs().at(0).doDrag(e,g.x(),g.y(),m,l,n.shiftKey)}k=true}f=o});d.mousewheel(function(l,n){var m=j(l);if(e.graphs().size()>0){e.graphs().at(0).doWheelZoom(e,m.x(),m.y(),n)}l.preventDefault()});d.mouseenter(function(l){f=j(l);i=false;e.graphs().at(0).doDragDone()});d.mouseleave(function(l){i=false;e.graphs().at(0).doDragDone()})})})});(function(c){var a=window.multigraph.util.namespace("window.multigraph.core");var b={multigraph:function(){return this.data("multigraph").multigraph},done:function(d){return this.each(function(){return c(this).data("multigraph").multigraph.done(d)})},init:function(d){return this.each(function(){var f=c(this),e=f.data("multigraph");d.div=this;if(!e){f.data("multigraph",{multigraph:a.Multigraph.createGraph(d)})}return this})}};c.fn.multigraph=function(d){if(b[d]){return b[d].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof d==="object"||!d){return b.init.apply(this,arguments)}else{c.error("Method "+d+" does not exist on jQuery.multigraph");return null}}};c(document).ready(function(){c("div.multigraph").each(function(){var f=c(this).attr("data-width"),d=c(this).attr("data-height"),h=c(this).attr("data-src"),g=c(this).attr("data-driver"),e;if(f!==undefined){c(this).css("width",f+"px")}if(d!==undefined){c(this).css("height",d+"px")}e={div:this,mugl:h,driver:g};c(this).multigraph(e);c(this).lightbox({scale:true,postopen:function(){var i=this.data("lightbox");i.originalDiv=this;this.data("multigraph").multigraph.done(function(k){k.div(i.contents);k.initializeSurface();k.resizeSurface(i.contentWidth,i.contentHeight);k.width(i.contentWidth).height(i.contentHeight);k.busySpinner().remove();k.busySpinner(c('
    ').appendTo(c(k.div())).busy_spinner());k.render()});var j=window.setTimeout(function(){i.contents.lightbox("resize");window.clearTimeout(j)},50)},postclose:function(){var i=this.data("lightbox");this.data("multigraph").multigraph.done(function(j){j.div(i.originalDiv).width(c(j.div()).width()).height(c(j.div()).height()).busySpinner(c('
    ').appendTo(c(j.div())).busy_spinner());j.initializeSurface();j.render()})},postresize:function(){var i=this.data("lightbox");this.data("multigraph").multigraph.done(function(j){j.resizeSurface(i.contentWidth,i.contentHeight);j.width(i.contentWidth).height(i.contentHeight);j.render()})}})})})}(window.multigraph.jQuery));window.multigraph.util.namespace("window.multigraph.events.jquery.touch",function(a){a.mixin=new window.multigraph.core.Mixin()});window.multigraph.util.namespace("window.multigraph.events.jquery.touch",function(a){a.mixin.add(function(c,b){c.core.Graph.respondsTo("doFirstPinchZoom",function(d,m,l,q,p,o,n){var g=this.dragAxis,i=this.dragOrientation,k=c.core.Axis,f=k.HORIZONTAL,h=k.VERTICAL;try{if(!this.dragStarted()){if(o>n){i(f)}else{i(h)}g(this.findNearestAxis(m,l,i()));if(g()===null){i((i()===f)?h:f);g(this.findNearestAxis(m,l,i()))}this.dragStarted(true)}if(i()===f){g().doZoom(m,q)}else{g().doZoom(l,p)}d.redraw()}catch(j){b(j)}})})});window.multigraph.util.namespace("window.multigraph.events.jquery.touch",function(a){a.mixin.add(function(b){var c=window.multigraph.util.namespace("window.multigraph.math");b.core.Multigraph.respondsTo("registerTouchEvents",function(v){var r=false,f=false,m=false,d=false,j={},t,w,u,h,k=this,e=window.multigraph.jQuery(v);var g=function(x){return new c.Point((x.pageX-e.offset().left)-k.graphs().at(0).x0(),e.height()-(x.pageY-e.offset().top)-k.graphs().at(0).y0())};var n=function(x){var y=x.originalEvent;y.preventDefault();if(y.touches.length===1){h=g(y.touches[0])}w=g(y.touches[0]);if(y.touches.length===1){f=true}else{f=false}if(y.touches.length===2){m=true;d=false;u=g(y.touches[1])}else{m=false;d=false}r=false;k.graphs().at(0).doDragDone()};var o=function(x){var y=x.originalEvent;y.preventDefault();if(y.touches.length===1&&f===true){i(y)}if(y.touches.length===2&&m===true){l(y)}};var p=function(x){var y=x.originalEvent;y.preventDefault();if(y.touches.length===1){f=true}else{f=false}if(y.touches.length===2){m=true;d=false}else{m=false;d=false}r=false;k.graphs().at(0).doDragDone()};var q=function(x){x.originalEvent.preventDefault();f=false;m=false;d=false;r=false;k.graphs().at(0).doDragDone()};var i=function(A){var z=g(A.touches[0]),y=z.x()-w.x(),x=z.y()-w.y();if(k.graphs().size()>0){if(!r){k.graphs().at(0).doDragReset()}k.graphs().at(0).doDrag(k,h.x(),h.y(),y,x,false)}r=true;w=z};var l=function(z){var C=g(z.touches[0]),A=g(z.touches[1]),D=(C.x()+A.x())/2,B=(C.y()+A.y())/2,F=s(C.x(),A.x())-s(w.x(),u.x()),E=s(C.y(),A.y())-s(w.y(),u.y());if(k.graphs().size()>0){if(!r){k.graphs().at(0).doDragReset()}if(d===true){k.graphs().at(0).doDrag(k,D,B,F,E,true)}}r=true;var y=((C.x()-w.x())+(A.x()-u.x()))/2,x=((C.y()-w.y())+(A.y()-u.y()))/2;if(d===true){k.graphs().at(0).doDrag(k,D,B,y,x,false)}if(d===false){if(j.base===undefined){j.base={};j.base.x=D;j.base.y=B}if(j.zoomDeltas===undefined){j.zoomDeltas={dx:0,dy:0,totalx:0,totaly:0}}if(j.panDeltas===undefined){j.panDeltas={dx:0,dy:0}}j.zoomDeltas.dx+=F;j.zoomDeltas.dy+=E;j.panDeltas.dx+=y;j.panDeltas.dy+=x;j.zoomDeltas.totalx+=Math.abs(F);j.zoomDeltas.totaly+=Math.abs(E);if(t===undefined){t=setTimeout(function(){var K=j.base.x,J=j.base.y,I=j.zoomDeltas.dx,H=j.zoomDeltas.dy,G=j.panDeltas.dx,L=j.panDeltas.dy;k.graphs().at(0).doDragReset();k.graphs().at(0).doFirstPinchZoom(k,K,J,I,H,j.zoomDeltas.totalx,j.zoomDeltas.totaly);k.graphs().at(0).doDrag(k,K,J,G,L,false);j={};d=true;clearTimeout(t);t=undefined},60)}}w=C;u=A};var s=function(y,x){return Math.abs(y-x)};e.on("touchstart",n);e.on("touchmove",o);e.on("touchend",p);e.on("touchleave",q)})})});(function(i){var e="0.3.4",j="hasOwnProperty",b=/[\.\/]/,a="*",g=function(){},f=function(m,l){return m-l},d,h,k={n:{}},c=function(m,C){var v=k,s=h,w=Array.prototype.slice.call(arguments,2),y=c.listeners(m),x=0,u=false,p,o=[],t={},q=[],n=d,A=[];d=m;h=0;for(var r=0,B=y.length;r';aH=aE.firstChild;aH.style.behavior="url(#default#VML)";if(!(aH&&typeof aH.adj=="object")){return(aR.type=aX)}aE=null}aR.svg=!(aR.vml=aR.type=="VML");aR._Paper=bF;aR.fn=a4=bF.prototype=aR.prototype;aR._id=0;aR._oid=0;aR.is=function(d,b){b=bK.call(b);if(b=="finite"){return !av[ak](+d)}if(b=="array"){return d instanceof Array}return(b=="null"&&d===null)||(b==typeof d&&d!==null)||(b=="object"&&d===Object(d))||(b=="array"&&Array.isArray&&Array.isArray(d))||a1.call(d).slice(8,-1).toLowerCase()==b};function X(g){if(Object(g)!==g){return g}var d=new g.constructor;for(var b in g){if(g[ak](b)){d[b]=X(g[b])}}return d}aR.angle=function(E,S,g,R,d,i){if(d==null){var b=E-g,bL=S-R;if(!b&&!bL){return 0}return(180+au.atan2(-bL,-b)*180/aV+360)%360}else{return aR.angle(E,S,d,i)-aR.angle(g,R,d,i)}};aR.rad=function(b){return b%360*aV/180};aR.deg=function(b){return b*180/aV%360};aR.snapTo=function(d,E,b){b=aR.is(b,"finite")?b:10;if(aR.is(d,bd)){var g=d.length;while(g--){if(aw(d[g]-E)<=b){return d[g]}}}else{d=+d;var R=E%d;if(Rd-b){return E-R+d}}return E};var h=aR.createUUID=(function(b,d){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(b,d).toUpperCase()}})(/[xy]/g,function(g){var d=au.random()*16|0,b=g=="x"?d:(d&3|8);return b.toString(16)});aR.setWindow=function(b){eve("raphael.setWindow",aR,aA.win,b);aA.win=b;aA.doc=aA.win.document;if(aR._engine.initWin){aR._engine.initWin(aA.win)}};var bf=function(g){if(aR.vml){var b=/^\s+|\s+$/g;var R;try{var S=new ActiveXObject("htmlfile");S.write("");S.close();R=S.body}catch(bL){R=createPopup().document.body}var d=R.createTextRange();bf=aG(function(i){try{R.style.color=bH(i).replace(b,aX);var bM=d.queryCommandValue("ForeColor");bM=((bM&255)<<16)|(bM&65280)|((bM&16711680)>>>16);return"#"+("000000"+bM.toString(16)).slice(-6)}catch(bN){return"none"}})}else{var E=aA.doc.createElement("i");E.title="Rapha\xebl Colour Picker";E.style.display="none";aA.doc.body.appendChild(E);bf=aG(function(i){E.style.color=i;return aA.doc.defaultView.getComputedStyle(E,aX).getPropertyValue("color")})}return bf(g)},aI=function(){return"hsb("+[this.h,this.s,this.b]+")"},M=function(){return"hsl("+[this.h,this.s,this.l]+")"},x=function(){return this.hex},aY=function(R,E,d){if(E==null&&aR.is(R,"object")&&"r" in R&&"g" in R&&"b" in R){d=R.b;E=R.g;R=R.r}if(E==null&&aR.is(R,aj)){var i=aR.getRGB(R);R=i.r;E=i.g;d=i.b}if(R>1||E>1||d>1){R/=255;E/=255;d/=255}return[R,E,d]},a2=function(R,E,d,S){R*=255;E*=255;d*=255;var i={r:R,g:E,b:d,hex:aR.rgb(R,E,d),toString:x};aR.is(S,"finite")&&(i.opacity=S);return i};aR.color=function(b){var d;if(aR.is(b,"object")&&"h" in b&&"s" in b&&"b" in b){d=aR.hsb2rgb(b);b.r=d.r;b.g=d.g;b.b=d.b;b.hex=d.hex}else{if(aR.is(b,"object")&&"h" in b&&"s" in b&&"l" in b){d=aR.hsl2rgb(b);b.r=d.r;b.g=d.g;b.b=d.b;b.hex=d.hex}else{if(aR.is(b,"string")){b=aR.getRGB(b)}if(aR.is(b,"object")&&"r" in b&&"g" in b&&"b" in b){d=aR.rgb2hsl(b);b.h=d.h;b.s=d.s;b.l=d.l;d=aR.rgb2hsb(b);b.v=d.b}else{b={hex:"none"};b.r=b.g=b.b=b.h=b.s=b.v=b.l=-1}}}b.toString=x;return b};aR.hsb2rgb=function(S,bN,bL,i){if(this.is(S,"object")&&"h" in S&&"s" in S&&"b" in S){bL=S.b;bN=S.s;S=S.h;i=S.o}S*=360;var E,bM,d,g,b;S=(S%360)/60;b=bL*bN;g=b*(1-aw(S%2-1));E=bM=d=bL-b;S=~~S;E+=[b,g,0,0,g,b][S];bM+=[g,b,b,g,0,0][S];d+=[0,0,g,b,b,g][S];return a2(E,bM,d,i)};aR.hsl2rgb=function(bL,bN,E,i){if(this.is(bL,"object")&&"h" in bL&&"s" in bL&&"l" in bL){E=bL.l;bN=bL.s;bL=bL.h}if(bL>1||bN>1||E>1){bL/=360;bN/=100;E/=100}bL*=360;var S,bM,d,g,b;bL=(bL%360)/60;b=2*bN*(E<0.5?E:1-E);g=b*(1-aw(bL%2-1));S=bM=d=E-b/2;bL=~~bL;S+=[b,g,0,0,g,b][bL];bM+=[g,b,b,g,0,0][bL];d+=[0,0,g,b,b,g][bL];return a2(S,bM,d,i)};aR.rgb2hsb=function(bM,bL,d){d=aY(bM,bL,d);bM=d[0];bL=d[1];d=d[2];var R,E,i,bN;i=m(bM,bL,d);bN=i-bm(bM,bL,d);R=(bN==0?null:i==bM?(bL-d)/bN:i==bL?(d-bM)/bN+2:(bM-bL)/bN+4);R=((R+360)%6)*60/360;E=bN==0?0:bN/i;return{h:R,s:E,b:i,toString:aI}};aR.rgb2hsl=function(d,bL,bO){bO=aY(d,bL,bO);d=bO[0];bL=bO[1];bO=bO[2];var bP,R,bN,bM,E,i;bM=m(d,bL,bO);E=bm(d,bL,bO);i=bM-E;bP=(i==0?null:bM==d?(bL-bO)/i:bM==bL?(bO-d)/i+2:(d-bL)/i+4);bP=((bP+360)%6)*60/360;bN=(bM+E)/2;R=(i==0?0:bN<0.5?i/(2*bN):i/(2-2*bN));return{h:bP,s:R,l:bN,toString:M}};aR._path2string=function(){return this.join(",").replace(bg,"$1")};function bk(E,g){for(var b=0,d=E.length;b=1000&&delete R[bL.shift()];bL.push(S);R[S]=i[bG](d,E);return b?b(R[S]):R[S]}return g}var bv=aR._preload=function(g,d){var b=aA.doc.createElement("img");b.style.cssText="position:absolute;left:-9999em;top:-9999em";b.onload=function(){d.call(this);this.onload=null;aA.doc.body.removeChild(this)};b.onerror=function(){aA.doc.body.removeChild(this)};aA.doc.body.appendChild(b);b.src=g};function aq(){return this.hex}aR.getRGB=aG(function(b){if(!b||!!((b=bH(b)).indexOf("-")+1)){return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:aq}}if(b=="none"){return{r:-1,g:-1,b:-1,hex:"none",toString:aq}}!(n[ak](b.toLowerCase().substring(0,2))||b.charAt()=="#")&&(b=bf(b));var E,d,g,S,i,bM,bL,R=b.match(A);if(R){if(R[2]){S=U(R[2].substring(5),16);g=U(R[2].substring(3,5),16);d=U(R[2].substring(1,3),16)}if(R[3]){S=U((bM=R[3].charAt(3))+bM,16);g=U((bM=R[3].charAt(2))+bM,16);d=U((bM=R[3].charAt(1))+bM,16)}if(R[4]){bL=R[4][F](bi);d=an(bL[0]);bL[0].slice(-1)=="%"&&(d*=2.55);g=an(bL[1]);bL[1].slice(-1)=="%"&&(g*=2.55);S=an(bL[2]);bL[2].slice(-1)=="%"&&(S*=2.55);R[1].toLowerCase().slice(0,4)=="rgba"&&(i=an(bL[3]));bL[3]&&bL[3].slice(-1)=="%"&&(i/=100)}if(R[5]){bL=R[5][F](bi);d=an(bL[0]);bL[0].slice(-1)=="%"&&(d*=2.55);g=an(bL[1]);bL[1].slice(-1)=="%"&&(g*=2.55);S=an(bL[2]);bL[2].slice(-1)=="%"&&(S*=2.55);(bL[0].slice(-3)=="deg"||bL[0].slice(-1)=="\xb0")&&(d/=360);R[1].toLowerCase().slice(0,4)=="hsba"&&(i=an(bL[3]));bL[3]&&bL[3].slice(-1)=="%"&&(i/=100);return aR.hsb2rgb(d,g,S,i)}if(R[6]){bL=R[6][F](bi);d=an(bL[0]);bL[0].slice(-1)=="%"&&(d*=2.55);g=an(bL[1]);bL[1].slice(-1)=="%"&&(g*=2.55);S=an(bL[2]);bL[2].slice(-1)=="%"&&(S*=2.55);(bL[0].slice(-3)=="deg"||bL[0].slice(-1)=="\xb0")&&(d/=360);R[1].toLowerCase().slice(0,4)=="hsla"&&(i=an(bL[3]));bL[3]&&bL[3].slice(-1)=="%"&&(i/=100);return aR.hsl2rgb(d,g,S,i)}R={r:d,g:g,b:S,toString:aq};R.hex="#"+(16777216|S|(g<<8)|(d<<16)).toString(16).slice(1);aR.is(i,"finite")&&(R.opacity=i);return R}return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:aq}},aR);aR.hsb=aG(function(i,g,d){return aR.hsb2rgb(i,g,d).hex});aR.hsl=aG(function(g,d,b){return aR.hsl2rgb(g,d,b).hex});aR.rgb=aG(function(E,i,d){return"#"+(16777216|d|(i<<8)|(E<<16)).toString(16).slice(1)});aR.getColor=function(d){var g=this.getColor.start=this.getColor.start||{h:0,s:1,b:d||0.75},b=this.hsb2rgb(g.h,g.s,g.b);g.h+=0.075;if(g.h>1){g.h=0;g.s-=0.2;g.s<=0&&(this.getColor.start={h:0,s:1,b:g.b})}return b.hex};aR.getColor.reset=function(){delete this.start};function bb(E,bL){var S=[];for(var g=0,b=E.length;b-2*!bL>g;g+=2){var R=[{x:+E[g-2],y:+E[g-1]},{x:+E[g],y:+E[g+1]},{x:+E[g+2],y:+E[g+3]},{x:+E[g+4],y:+E[g+5]}];if(bL){if(!g){R[0]={x:+E[b-2],y:+E[b-1]}}else{if(b-4==g){R[3]={x:+E[0],y:+E[1]}}else{if(b-2==g){R[2]={x:+E[0],y:+E[1]};R[3]={x:+E[2],y:+E[3]}}}}}else{if(b-4==g){R[3]=R[2]}else{if(!g){R[0]={x:+E[g],y:+E[g+1]}}}}S.push(["C",(-R[0].x+6*R[1].x+R[2].x)/6,(-R[0].y+6*R[1].y+R[2].y)/6,(R[1].x+6*R[2].x-R[3].x)/6,(R[1].y+6*R[2].y-R[3].y)/6,R[2].x,R[2].y])}return S}aR.parsePathString=function(b){if(!b){return null}var g=Y(b);if(g.arr){return aZ(g.arr)}var i={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},d=[];if(aR.is(b,bd)&&aR.is(b[0],bd)){d=aZ(b)}if(!d.length){bH(b).replace(a0,function(R,E,bM){var bL=[],S=E.toLowerCase();bM.replace(aP,function(bO,bN){bN&&bL.push(+bN)});if(S=="m"&&bL.length>2){d.push([E][bE](bL.splice(0,2)));S="l";E=E=="m"?"l":"L"}if(S=="r"){d.push([E][bE](bL))}else{while(bL.length>=i[S]){d.push([E][bE](bL.splice(0,i[S])));if(!i[S]){break}}}})}d.toString=aR._path2string;g.arr=aZ(d);return d};aR.parseTransformString=aG(function(d){if(!d){return null}var g={r:3,s:4,t:2,m:6},b=[];if(aR.is(d,bd)&&aR.is(d[0],bd)){b=aZ(d)}if(!b.length){bH(d).replace(ai,function(E,i,bL){var S=[],R=bK.call(i);bL.replace(aP,function(bN,bM){bM&&S.push(+bM)});b.push([i][bE](S))})}b.toString=aR._path2string;return b});var Y=function(d){var b=Y.ps=Y.ps||{};if(b[d]){b[d].sleep=100}else{b[d]={sleep:100}}setTimeout(function(){for(var g in b){if(b[ak](g)&&g!=d){b[g].sleep--;!b[g].sleep&&delete b[g]}}});return b[d]};aR.findDotsAtSegment=function(d,b,b2,b0,S,E,bN,bL,bV){var bS=1-bV,bX=bp(bS,3),bY=bp(bS,2),bP=bV*bV,bM=bP*bV,bR=bX*d+bY*3*bV*b2+bS*3*bV*bV*S+bM*bN,bO=bX*b+bY*3*bV*b0+bS*3*bV*bV*E+bM*bL,bW=d+2*bV*(b2-d)+bP*(S-2*b2+d),bU=b+2*bV*(b0-b)+bP*(E-2*b0+b),b1=b2+2*bV*(S-b2)+bP*(bN-2*S+b2),bZ=b0+2*bV*(E-b0)+bP*(bL-2*E+b0),bT=bS*d+bV*b2,bQ=bS*b+bV*b0,i=bS*S+bV*bN,g=bS*E+bV*bL,R=(90-au.atan2(bW-b1,bU-bZ)*180/aV);(bW>b1||bU=d.x&&b<=d.x2&&g>=d.y&&g<=d.y2};aR.isBBoxIntersect=function(g,d){var b=aR.isPointInsideBBox;return b(d,g.x,g.y)||b(d,g.x2,g.y)||b(d,g.x,g.y2)||b(d,g.x2,g.y2)||b(g,d.x,d.y)||b(g,d.x2,d.y)||b(g,d.x,d.y2)||b(g,d.x2,d.y2)||(g.xd.x||d.xg.x)&&(g.yd.y||d.yg.y)};function bj(b,S,R,E,i){var g=-3*S+9*R-9*E+3*i,d=b*g+6*S-12*R+6*E;return b*d-3*S+3*R}function q(bW,R,bV,g,bU,d,bR,b,bO){if(bO==null){bO=1}bO=bO>1?1:bO<0?0:bO;var bP=bO/2,bQ=12,bL=[-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],bT=[0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],E=0;for(var bS=0;bSS){i/=2;R+=(Em(b,bS)||m(bQ,bO)m(bN,bM)){return}var bL=(i*bO-bQ*g)*(b-bS)-(i-g)*(b*bM-bN*bS),S=(i*bO-bQ*g)*(bN-bM)-(bQ-bO)*(b*bM-bN*bS),E=(i-g)*(bN-bM)-(bQ-bO)*(b-bS);if(!E){return}var bR=bL/E,bP=S/E,R=+bR.toFixed(2),d=+bP.toFixed(2);if(R<+bm(i,g).toFixed(2)||R>+m(i,g).toFixed(2)||R<+bm(b,bS).toFixed(2)||R>+m(b,bS).toFixed(2)||d<+bm(bQ,bO).toFixed(2)||d>+m(bQ,bO).toFixed(2)||d<+bm(bN,bM).toFixed(2)||d>+m(bN,bM).toFixed(2)){return}return{x:bR,y:bP}}function ay(d,b){return af(d,b)}function t(d,b){return af(d,b,1)}function af(b2,b1,b0){var E=aR.bezierBBox(b2),d=aR.bezierBBox(b1);if(!aR.isBBoxIntersect(E,d)){return b0?0:[]}var bV=q.apply(0,b2),bU=q.apply(0,b1),bM=~~(bV/5),bL=~~(bU/5),bS=[],bR=[],g={},b3=b0?0:[];for(var bX=0;bX=0&&bO<=1&&bN>=0&&bN<=1){if(b0){b3++}else{b3.push({x:R.x,y:R.y,t1:bO,t2:bN})}}}}}return b3}aR.pathIntersection=function(d,b){return D(d,b)};aR.pathIntersectionNumber=function(d,b){return D(d,b,1)};function D(g,b,bW){g=aR._path2curve(g);b=aR._path2curve(b);var bU,S,bT,E,bR,bL,d,bO,b0,bZ,b1=bW?0:[];for(var bS=0,bM=g.length;bS1){ch=au.sqrt(ch);b1=ch*b1;bZ=ch*bZ}var g=b1*b1,ca=bZ*bZ,cc=(bN==E?-1:1)*au.sqrt(aw((g*ca-g*b6*b6-ca*b7*b7)/(g*b6*b6+ca*b7*b7))),bW=cc*b1*b6/bZ+(bS+bR)/2,bV=cc*-bZ*b7/b1+(cn+cm)/2,bM=au.asin(((cn-bV)/bZ).toFixed(9)),bL=au.asin(((cm-bV)/bZ).toFixed(9));bM=bSbL){bM=bM-aV*2}if(!E&&bL>bM){bL=bL-aV*2}}else{bM=bU[0];bL=bU[1];bW=bU[2];bV=bU[3]}var bQ=bL-bM;if(aw(bQ)>bY){var bX=bL,b0=bR,bO=cm;bL=bM+bY*(E&&bL>bM?1:-1);bR=bW+b1*au.cos(bL);cm=bV+bZ*au.sin(bL);b5=ae(bR,cm,b1,bZ,bT,0,E,b0,bO,[bL,bX,bW,bV])}bQ=bL-bM;var S=au.cos(bM),cl=au.sin(bM),R=au.cos(bL),ck=au.sin(bL),b8=au.tan(bQ/4),cb=4/3*b1*b8,b9=4/3*bZ*b8,ci=[bS,cn],cg=[bS+cb*cl,cn-b9*S],cf=[bR+cb*ck,cm-b9*R],cd=[bR,cm];cg[0]=2*ci[0]-cg[0];cg[1]=2*ci[1]-cg[1];if(bU){return[cg,cf,cd][bE](b5)}else{b5=[cg,cf,cd][bE](b5).join()[F](",");var b3=[];for(var ce=0,b4=b5.length;ce"1e12"&&(bL=0.5);aw(S)>"1e12"&&(S=0.5);if(bL>0&&bL<1){g=ag(i,d,R,E,bU,bT,bQ,bN,bL);bR.push(g.x);bO.push(g.y)}if(S>0&&S<1){g=ag(i,d,R,E,bU,bT,bQ,bN,S);bR.push(g.x);bO.push(g.y)}bS=(bT-2*E+d)-(bN-2*bT+E);bP=2*(E-d)-2*(bT-E);bM=d-E;bL=(-bP+au.sqrt(bP*bP-4*bS*bM))/2/bS;S=(-bP-au.sqrt(bP*bP-4*bS*bM))/2/bS;aw(bL)>"1e12"&&(bL=0.5);aw(S)>"1e12"&&(S=0.5);if(bL>0&&bL<1){g=ag(i,d,R,E,bU,bT,bQ,bN,bL);bR.push(g.x);bO.push(g.y)}if(S>0&&S<1){g=ag(i,d,R,E,bU,bT,bQ,bN,S);bR.push(g.x);bO.push(g.y)}return{min:{x:bm[bG](0,bR),y:bm[bG](0,bO)},max:{x:m[bG](0,bR),y:m[bG](0,bO)}}}),W=aR._path2curve=aG(function(bU,bP){var bN=!bP&&Y(bU);if(!bP&&bN.curve){return aZ(bN.curve)}var E=w(bU),bQ=bP&&w(bP),bR={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},d={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},S=function(bV,bW){var i,bX;if(!bV){return["C",bW.x,bW.y,bW.x,bW.y,bW.x,bW.y]}!(bV[0] in {T:1,Q:1})&&(bW.qx=bW.qy=null);switch(bV[0]){case"M":bW.X=bV[1];bW.Y=bV[2];break;case"A":bV=["C"][bE](ae[bG](0,[bW.x,bW.y][bE](bV.slice(1))));break;case"S":i=bW.x+(bW.x-(bW.bx||bW.x));bX=bW.y+(bW.y-(bW.by||bW.y));bV=["C",i,bX][bE](bV.slice(1));break;case"T":bW.qx=bW.x+(bW.x-(bW.qx||bW.x));bW.qy=bW.y+(bW.y-(bW.qy||bW.y));bV=["C"][bE](bn(bW.x,bW.y,bW.qx,bW.qy,bV[1],bV[2]));break;case"Q":bW.qx=bV[1];bW.qy=bV[2];bV=["C"][bE](bn(bW.x,bW.y,bV[1],bV[2],bV[3],bV[4]));break;case"L":bV=["C"][bE](bI(bW.x,bW.y,bV[1],bV[2]));break;case"H":bV=["C"][bE](bI(bW.x,bW.y,bV[1],bW.y));break;case"V":bV=["C"][bE](bI(bW.x,bW.y,bW.x,bV[1]));break;case"Z":bV=["C"][bE](bI(bW.x,bW.y,bW.X,bW.Y));break}return bV},b=function(bV,bW){if(bV[bW].length>7){bV[bW].shift();var bX=bV[bW];while(bX.length){bV.splice(bW++,0,["C"][bE](bX.splice(0,6)))}bV.splice(bW,1);bS=m(E.length,bQ&&bQ.length||0)}},g=function(bZ,bY,bW,bV,bX){if(bZ&&bY&&bZ[bX][0]=="M"&&bY[bX][0]!="M"){bY.splice(bX,0,["M",bV.x,bV.y]);bW.bx=0;bW.by=0;bW.x=bZ[bX][1];bW.y=bZ[bX][2];bS=m(E.length,bQ&&bQ.length||0)}};for(var bM=0,bS=m(E.length,bQ&&bQ.length||0);bMR){if(d&&!bS.start){bQ=k(bP,bO,g[1],g[2],g[3],g[4],g[5],g[6],R-bN);E+=["C"+bQ.start.x,bQ.start.y,bQ.m.x,bQ.m.y,bQ.x,bQ.y];if(S){return E}bS.start=E;E=["M"+bQ.x,bQ.y+"C"+bQ.n.x,bQ.n.y,bQ.end.x,bQ.end.y,g[5],g[6]].join();bN+=bL;bP=+g[5];bO=+g[6];continue}if(!b&&!d){bQ=k(bP,bO,g[1],g[2],g[3],g[4],g[5],g[6],R-bN);return{x:bQ.x,y:bQ.y,alpha:bQ.alpha}}}bN+=bL;bP=+g[5];bO=+g[6]}E+=g.shift()+g}bS.end=E;bQ=b?bN:d?bS:aR.findDotsAtSegment(bP,bO,g[0],g[1],g[2],g[3],g[4],g[5],1);bQ.alpha&&(bQ={x:bQ.x,y:bQ.y,alpha:bQ.alpha});return bQ}};var aS=a6(1),J=a6(),ad=a6(0,1);aR.getTotalLength=aS;aR.getPointAtLength=J;aR.getSubpath=function(d,i,g){if(this.getTotalLength(d)-g<0.000001){return ad(d,i).end}var b=ad(d,g,1);return i?ad(b,i).end:b};bh.getTotalLength=function(){if(this.type!="path"){return}if(this.node.getTotalLength){return this.node.getTotalLength()}return aS(this.attrs.path)};bh.getPointAtLength=function(b){if(this.type!="path"){return}return J(this.attrs.path,b)};bh.getSubpath=function(d,b){if(this.type!="path"){return}return aR.getSubpath(this.attrs.path,d,b)};var o=aR.easing_formulas={linear:function(b){return b},"<":function(b){return bp(b,1.7)},">":function(b){return bp(b,0.48)},"<>":function(bL){var i=0.48-bL/1.04,g=au.sqrt(0.1734+i*i),b=g-i,S=bp(aw(b),1/3)*(b<0?-1:1),R=-g-i,E=bp(aw(R),1/3)*(R<0?-1:1),d=S+E+0.5;return(1-d)*3*d*d+d*d*d},backIn:function(d){var b=1.70158;return d*d*((b+1)*d-b)},backOut:function(d){d=d-1;var b=1.70158;return d*d*((b+1)*d+b)+1},elastic:function(b){if(b==!!b){return b}return bp(2,-10*b)*au.sin((b-0.075)*(2*aV)/0.3)+1},bounce:function(i){var d=7.5625,g=2.75,b;if(i<(1/g)){b=d*i*i}else{if(i<(2/g)){i-=(1.5/g);b=d*i*i+0.75}else{if(i<(2.5/g)){i-=(2.25/g);b=d*i*i+0.9375}else{i-=(2.625/g);b=d*i*i+0.984375}}}return b}};o.easeIn=o["ease-in"]=o["<"];o.easeOut=o["ease-out"]=o[">"];o.easeInOut=o["ease-in-out"]=o["<>"];o["back-in"]=o.backIn;o["back-out"]=o.backOut;var ab=[],aN=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b){setTimeout(b,16)},bC=function(){var bL=+new Date,bT=0;for(;bT1&&!bZ.next){for(b1 in d){if(d[ak](b1)){bX[b1]=bZ.totalOrigin[b1]}}bZ.el.attr(bX);aM(bZ.anim,bZ.el,bZ.anim.percents[0],null,bZ.totalOrigin,bZ.repeat-1)}if(bZ.next&&!bZ.stop){aM(bZ.anim,bZ.el,bZ.next,null,bZ.totalOrigin,bZ.repeat)}}}aR.svg&&S&&S.paper&&S.paper.safari();ab.length&&aN(bC)},H=function(b){return b>255?255:b<0?0:b};bh.animateWith=function(d,E,g,b,bL,bQ){var S=this;if(S.removed){bQ&&bQ.call(S);return S}var bO=g instanceof bA?g:aR.animation(g,b,bL,bQ),bN,bM;aM(bO,S,bO.percents[0],null,S.attr());for(var R=0,bP=ab.length;RbY){return bY}while(bZbU){bZ=bW}else{bY=bW}bW=(bY-bZ)/2+bZ}return bW}return g(bR,1/(200*bL))}bh.onAnimation=function(b){b?eve.on("raphael.anim.frame."+this.id,b):eve.unbind("raphael.anim.frame."+this.id);return this};function bA(E,g){var d=[],i={};this.ms=g;this.times=1;if(E){for(var b in E){if(E[ak](b)){i[an(b)]=E[b];d.push(an(b))}}d.sort(u)}this.anim=i;this.top=d[d.length-1];this.percents=d}bA.prototype.delay=function(d){var b=new bA(this.anim,this.ms);b.times=this.times;b.del=+d||0;return b};bA.prototype.repeat=function(d){var b=new bA(this.anim,this.ms);b.del=this.del;b.times=au.floor(m(d,0))||1;return b};function aM(b3,g,b,b1,bL,bP){b=an(b);var ca,S,bO,cb=[],bV,bU,R,bX=b3.ms,b2={},E={},bR={};if(b1){for(b6=0,bQ=ab.length;b6b1*b3.top){b=b3.percents[b6];bU=b3.percents[b6-1]||0;bX=bX/b3.top*(b-bU);bV=b3.percents[b6+1];ca=b3.anim[b];break}else{if(b1){g.attr(b3.anim[b3.percents[b6]])}}}if(!ca){return}if(!S){for(var bZ in ca){if(ca[ak](bZ)){if(ar[ak](bZ)||g.paper.customAttributes[ak](bZ)){b2[bZ]=g.attr(bZ);(b2[bZ]==null)&&(b2[bZ]=r[bZ]);E[bZ]=ca[bZ];switch(ar[bZ]){case aL:bR[bZ]=(E[bZ]-b2[bZ])/bX;break;case"colour":b2[bZ]=aR.getRGB(b2[bZ]);var b0=aR.getRGB(E[bZ]);bR[bZ]={r:(b0.r-b2[bZ].r)/bX,g:(b0.g-b2[bZ].g)/bX,b:(b0.b-b2[bZ].b)/bX};break;case"path":var bM=W(b2[bZ],E[bZ]),bT=bM[1];b2[bZ]=bM[0];bR[bZ]=[];for(b6=0,bQ=b2[bZ].length;b60.5)*2-1);h(K-0.5,2)+h(I-0.5,2)>0.25&&(I=f.sqrt(0.25-h(K-0.5,2))*U+0.5)&&I!=0.5&&(I=I.toFixed(5)-0.00001*U)}return r});Q=Q.split(/\s*\-\s*/);if(O=="linear"){var J=Q.shift();J=-n(J);if(isNaN(J)){return null}var H=[0,0,f.cos(l.rad(J)),f.sin(l.rad(J))],P=1/(C(s(H[2]),s(H[3]))||1);H[2]*=P;H[3]*=P;if(H[2]<0){H[0]=-H[2];H[2]=0}if(H[3]<0){H[1]=-H[3];H[3]=0}}var N=l._parseDots(Q);if(!N){return null}E=E.replace(/[\(\)\s,\xb0#]/g,"_");if(M.gradient&&E!=M.gradient.id){D.defs.removeChild(M.gradient);delete M.gradient}if(!M.gradient){F=i(O+"Gradient",{id:E});M.gradient=F;i(F,O=="radial"?{fx:K,fy:I}:{x1:H[0],y1:H[1],x2:H[2],y2:H[3],gradientTransform:M.matrix.invert()});D.defs.appendChild(F);for(var L=0,R=N.length;L1?G.opacity/100:G.opacity});case"stroke":G=l.getRGB(Q);S.setAttribute(R,G.hex);R=="stroke"&&G[d]("opacity")&&i(S,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity});if(R=="stroke"&&O._.arrows){"startString" in O._.arrows&&c(O,O._.arrows.startString);"endString" in O._.arrows&&c(O,O._.arrows.endString,1)}break;case"gradient":(O.type=="circle"||O.type=="ellipse"||B(Q).charAt()!="r")&&a(O,Q);break;case"opacity":if(P.gradient&&!P[d]("stroke-opacity")){i(S,{"stroke-opacity":Q>1?Q/100:Q})}case"fill-opacity":if(P.gradient){D=l._g.doc.getElementById(S.getAttribute("fill").replace(/^url\(#|\)$/g,r));if(D){J=D.getElementsByTagName("stop");i(J[J.length-1],{"stop-opacity":Q})}break}default:R=="font-size"&&(Q=q(Q,10)+"px");var K=R.replace(/(\-.)/g,function(X){return X.substring(1).toUpperCase()});S.style[K]=Q;O._.dirty=1;S.setAttribute(R,Q);break}}}p(O,W);S.style.visibility=M},A=1.2,p=function(D,H){if(D.type!="text"||!(H[d]("text")||H[d]("font")||H[d]("font-size")||H[d]("x")||H[d]("y"))){return}var M=D.attrs,F=D.node,O=F.firstChild?q(l._g.doc.defaultView.getComputedStyle(F.firstChild,r).getPropertyValue("font-size"),10):10;if(H[d]("text")){M.text=H.text;while(F.firstChild){F.removeChild(F.firstChild)}var G=B(H.text).split("\n"),E=[],K;for(var I=0,N=G.length;I"));var U=ag.getBoundingClientRect();aq.W=an.w=(U.right-U.left)/ab;aq.H=an.h=(U.bottom-U.top)/ab;aq.X=an.x;aq.Y=an.y+aq.H/2;("x" in aj||"y" in aj)&&(aq.path.v=l.format("m{0},{1}l{2},{1}",B(an.x*b),B(an.y*b),B(an.x*b)+1));var T=["x","y","text","font","font-family","font-weight","font-style","font-size"];for(var ai=0,ak=T.length;ai0.25&&(W=h.sqrt(0.25-L(Y-0.5,2))*((W>0.5)*2-1)+0.5);Q=Y+k+W}return q});R=R.split(/\s*\-\s*/);if(P=="linear"){var J=R.shift();J=-n(J);if(isNaN(J)){return null}}var O=l._parseDots(R);if(!O){return null}E=E.shape||E.node;if(O.length){E.removeChild(U);U.on=true;U.method="none";U.color=O[0].color;U.color2=O[O.length-1].color;var V=[];for(var K=0,T=O.length;K')}}catch(E){G=function(L){return J.createElement("<"+L+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}};l._engine.initWin(l._g.win);l._engine.create=function(){var K=l._getContainer.apply(0,arguments),E=K.container,Q=K.height,R,J=K.width,P=K.x,O=K.y;if(!E){throw new Error("VML container not found.")}var M=new l._Paper,N=M.canvas=l._g.doc.createElement("div"),L=N.style;P=P||0;O=O||0;J=J||512;Q=Q||342;M.width=J;M.height=Q;J==+J&&(J+="px");Q==+Q&&(Q+="px");M.coordsize=b*1000+k+b*1000;M.coordorigin="0 0";M.span=l._g.doc.createElement("span");M.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";N.appendChild(M.span);L.cssText=l.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",J,Q);if(E==1){l._g.doc.body.appendChild(N);L.left=P+"px";L.top=O+"px";L.position="absolute"}else{if(E.firstChild){E.insertBefore(N,E.firstChild)}else{E.appendChild(N)}}M.renderfix=function(){};return M};l.prototype.clear=function(){l.eve("raphael.clear",this);this.canvas.innerHTML=q;this.span=l._g.doc.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas.appendChild(this.span);this.bottom=this.top=null};l.prototype.remove=function(){l.eve("raphael.remove",this);this.canvas.parentNode.removeChild(this.canvas);for(var E in this){this[E]=typeof this[E]=="function"?l._removedFactory(E):null}return true};var y=l.st;for(var g in m){if(m[e](g)&&!y[e](g)){y[g]=(function(E){return function(){var J=arguments;return this.forEach(function(K){K[E].apply(K,J)})}})(g)}}}(window.Raphael);window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin=new window.multigraph.core.Mixin();a.mixin.add(function(b){window.multigraph.driver="raphael"})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(c){var b=c.Axis;b.hasAn("axisElem");b.hasAn("gridElem");b.hasAn("tickmarkElem");var e=function(j,p){var h=j.currentLabeler(),m=j.perpOffset(),i=j.orientation(),l=p.plotBox(),q="",k,n,o;if(i===b.HORIZONTAL){k=l.height()-m}else{k=l.width()-m}while(h.hasNext()){o=h.next();n=j.dataValueToAxisValue(o);if(i===b.HORIZONTAL){q=q+"M"+n+","+m+"L"+n+","+k}else{q=q+"M"+m+","+n+"L"+k+","+n}}return q};var d=function(h){if(h.orientation()===b.HORIZONTAL){return"M "+h.parallelOffset()+", "+h.perpOffset()+" l "+h.pixelLength()+", 0"}else{return"M "+h.perpOffset()+", "+h.parallelOffset()+" l 0, "+h.pixelLength()}};var f=function(h,j){var i=h.perpOffset();if(h.orientation()===c.Axis.HORIZONTAL){return"M"+j+","+(i+h.tickmax())+"L"+j+","+(i+h.tickmin())}else{return"M"+(i+h.tickmin())+","+j+"L"+(i+h.tickmax())+","+j}};var g=function(h,j){var i=h.currentLabeler();h.prepareRender(j);if(h.currentLabeler()!==i&&i!==undefined){h.currentLabeler().elems(i.elems());i.elems([])}};b.respondsTo("renderGrid",function(i,k,l){var j=k.text(100,100,"foo");g(this,j);if(this.hasDataMin()&&this.hasDataMax()){if(this.grid().visible()){if(this.labelers().size()>0&&this.currentLabelDensity()<=1.5){this.currentLabeler().prepare(this.dataMin(),this.dataMax());var h=k.path(e(this,i)).attr({"stroke-width":1,stroke:this.grid().color().getHexString("#")});this.gridElem(h);l.push(h)}}}j.remove()});b.respondsTo("redrawGrid",function(h,j){var i=j.text(100,100,"foo");g(this,i);if(this.hasDataMin()&&this.hasDataMax()){if(this.grid().visible()){if(this.labelers().size()>0&&this.currentLabelDensity()<=1.5){this.currentLabeler().prepare(this.dataMin(),this.dataMax());this.gridElem().attr("path",e(this,h))}}}i.remove()});b.respondsTo("render",function(w,l,s){var u=l.text(100,100,"foo"),h=this.currentLabeler(),k=this.tickcolor(),n="";var m=l.path(d(this)).attr("stroke",this.color().getHexString("#"));this.axisElem(m);s.push(m);if(this.hasDataMin()&&this.hasDataMax()){if(h){var t,r;h.prepare(this.dataMin(),this.dataMax());if(h.elems().length>0){var p,o;for(p=0,o=h.elems().length;p0){var o=i.rect(k/2,k/2,r+(2*p)+k,l+(2*p)+k).transform(f).attr({stroke:this.bordercolor().toRGBA(),"stroke-width":k});this.borderElem(o);s.push(o)}var e=i.rect(k,k,r+(2*p),l+(2*p)).transform(f).attr({stroke:"none",fill:this.color().toRGBA(this.opacity())});this.backgroundElem(e);s.push(e);var v=new n(m.x()+k+p+r/2,m.y()+k+p+l/2),j=t.drawText(i,q,g,v,0).attr({"font-size":this.fontSize()});this.textElem(j);s.push(j);return this});c.respondsTo("redraw",function(){var j=b(this),h=this.previousBase();if(j.x()===h.x()&&j.y()===h.y()){return this}var k=this.textElem(),g=j.x()-h.x(),f=j.y()-h.y(),e=k.attr("x"),l=k.attr("y"),i="...t"+g+" "+f;k.attr({x:e+g,y:l-f});if(this.borderElem()){this.borderElem().transform(i)}this.backgroundElem().transform(i);this.previousBase(j);return this})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(b){b.Icon.respondsTo("renderBorder",function(d,c,f,e){d.set.push(d.paper.rect(c,f,this.width(),this.height()).attr({stroke:"rgba(0, 0, 0, 1)"}))})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(b){var d=b.Img;var c=function(j,p){var n=window.multigraph.math.util.interp,o=p.window(),i=p.plotarea(),f=j.base(),e=n(j.anchor().x(),-1,1,0,j.image().width),r=n(j.anchor().y(),1,-1,0,j.image().height),h=o.margin().left()+o.border(),q=o.margin().top()+o.border(),g=h+o.padding().left()+i.margin().left()+i.border(),m=q+o.padding().top()+i.margin().top()+i.border(),l,k;if(j.frame()===d.PLOT){l=g+n(f.x(),-1,1,0,p.plotBox().width());k=m+n(f.y(),1,-1,0,p.plotBox().height())}else{l=h+n(f.x(),-1,1,0,p.paddingBox().width());k=q+n(f.y(),1,-1,0,p.paddingBox().height())}return{x:l+j.position().x()-e,y:k+j.position().y()-r}};d.hasA("image").defaultsTo(function(){return new Image()});d.hasA("fetched").defaultsTo(false);d.hasAn("elem");d.respondsTo("render",function(l,f,k,e,m){var h=this.image(),j=this;if(this.fetched()){var i=c(this,l),g=f.image(this.src(),i.x,i.y,h.width,h.height);this.elem(g);k.push(g)}else{h.onload=function(){j.fetched(true);l.render(f,e,m)};h.src=this.src()}});d.respondsTo("redraw",function(f){if(this.fetched()){var e=c(this,f);this.elem().attr({x:e.x,y:e.y})}})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(d){var b=d.Labeler;b.hasAn("elems").defaultsTo(function(){return[]});var f=function(i,h,g,j){return"t"+i.x()+","+i.y()+"s1,-1t"+g.x()+","+(-g.y())+"r"+(-j)+"t"+(-h.x())+","+h.y()};var c=function(h,j){var g=h.dataValueToAxisValue(j),i=h.perpOffset();if(h.orientation()===d.Axis.HORIZONTAL){return{x:function(){return g},y:function(){return i}}}else{return{x:function(){return i},y:function(){return g}}}};var e=function(o,p,h,l,m,j,k){var n=new window.multigraph.math.Point(0.5*o.origWidth()*l.x(),0.5*o.origHeight()*l.y()),g=f(h,n,m,j);var i=p.paper.text(0,0,o.string()).transform(g).attr("fill",k.getHexString("#"));p.set.push(i);return i};b.respondsTo("measureStringWidth",function(h,g){if(window.Raphael.svg){return(new d.Text(g)).initializeGeometry({elem:h,angle:this.angle()}).rotatedWidth()}else{h.attr("text",g);return h.W}});b.respondsTo("measureStringHeight",function(h,g){if(window.Raphael.svg){return(new d.Text(g)).initializeGeometry({elem:h,angle:this.angle()}).rotatedHeight()}else{h.attr("text",g);return h.H}});b.respondsTo("renderLabel",function(o,m){var k=this.anchor(),j=this.angle(),l=new d.Text(this.formatter().format(m)),g=c(this.axis(),m),n,h,i;l.initializeGeometry({elem:o.textElem,angle:this.angle()});n=new window.multigraph.math.Point(0.5*l.origWidth()*k.x(),0.5*l.origHeight()*k.y());i=l.drawText(o.paper,n,g,this.position(),this.angle()).attr("fill",this.color().getHexString("#"));this.elems().push({elem:i,base:g});o.set.push(i)});b.respondsTo("redraw",function(h,t,k){var l=this.axis(),E=this.elems(),G=[],w=[],B,F,r,z,A,v;var g,D,C,q,o;for(A=0;A0){B=E.pop().elem;B.transform("").attr({text:g.string(),x:0,y:0})}else{B=t.text(0,0,g.string()).attr("fill",this.color().getHexString("#"))}g.initializeGeometry({elem:B,angle:this.angle()});var s=0.5*g.origWidth()*this.anchor().x(),p=0.5*g.origHeight()*this.anchor().y(),n={x:function(){return s},y:function(){return p}},u=g.computeTransform(n,F,this.position(),this.angle());B.transform(h.transformString()+u);G.push({elem:B,base:F})}var m=E.length;for(A=0;A=e.size()){break}for(i=0;i=e.size()){break}e.at(h).renderer().redrawLegendIcon();h++}}return this})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(b){var d=window.multigraph.jQuery;b.mixin.add(function(e){var f=e.Multigraph;f.hasA("paper");f.hasA("$div");f.hasA("width").isA("number");f.hasA("height").isA("number");f.hasA("baseX").isA("number");f.hasA("baseY").isA("number");f.hasA("mouseLastX").isA("number");f.hasA("mouseLastY").isA("number");e.Multigraph.respondsTo("redraw",function(){var g=this;window.requestAnimationFrame(function(){var m=g.paper().text(-8000,-8000,"foo"),h=g.graphs(),l,k;for(l=0;l
  • ').appendTo(this.$div()).busy_spinner());this.render()});e.Multigraph.respondsTo("render",function(){this.paper().clear();var h=this.paper().text(-8000,-8000,"foo"),g;this.initializeGeometry(this.width(),this.height(),{elem:h});for(g=0;g0){e["fill-opacity"]=0;e["stroke-opacity"]=1;e.stroke=this.bordercolor().getHexString("#");e["stroke-width"]=d}else{e.stroke="none"}h=g.rect(f.x0()-d/2,f.y0()-d/2,f.plotBox().width()+d,f.plotBox().height()+d).attr(e);h.insertAfter(i);this.elem(h);i.push(h)});b.respondsTo("redraw",function(h){var e=this.border(),d=h.plotBox(),f=d.width()+e,i=d.height()+e,g=this.elem();if(g.attr("width")!==f){g.attr("width",f)}if(g.attr("height")!==i){g.attr("height",i)}})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(c){var d=c.BandRenderer;d.hasA("fillElem");d.hasA("line1Elem");d.hasA("line2Elem");d.hasA("state");d.respondsTo("begin",function(f){var g={paper:f.paper,set:f.set,run:[],fillPath:"",line1Path:"",line2Path:"",linecolor:this.getOptionValue("linecolor"),line1color:this.getOptionValue("line1color"),line2color:this.getOptionValue("line2color"),linewidth:this.getOptionValue("linewidth"),line1width:this.getOptionValue("line1width"),line2width:this.getOptionValue("line2width"),fillcolor:this.getOptionValue("fillcolor"),fillopacity:this.getOptionValue("fillopacity")};this.state(g)});d.respondsTo("beginRedraw",function(){var f=this.state();f.run=[];f.fillPath="";f.line1Path="";f.line2Path=""});d.respondsTo("dataPoint",function(f){var g=this.state();if(this.isMissing(f)){if(g.run.length>0){b(g);g.run=[]}}else{g.run.push(this.transformPoint(f))}});d.respondsTo("end",function(){var k=this.state(),l=k.paper,m=k.set,i,h;if(k.run.length>0){b(k)}var g=l.path(k.fillPath).attr({fill:k.fillcolor.toRGBA(k.fillopacity),stroke:"none"});this.fillElem(g);m.push(g);i=(k.line1width>=0)?k.line1width:k.linewidth;if(k.line1Path!==""&&i>0){h=(k.line1color!==null)?k.line1color:k.linecolor;var f=l.path(k.line1Path).attr({"stroke-width":i,stroke:h.getHexString("#")});this.line1Elem(f);m.push(f)}i=(k.line2width>=0)?k.line2width:k.linewidth;if(k.line2Path!==""&&i>0){h=(k.line2color!==null)?k.line2color:k.linecolor;var j=l.path(k.line2Path).attr({"stroke-width":i,stroke:h.getHexString("#")});this.line2Elem(j);m.push(j)}});d.respondsTo("endRedraw",function(){var g=this.state(),f;if(g.run.length>0){b(g)}this.fillElem().attr("path",g.fillPath);if(this.line1Elem()){this.line1Elem().attr("path",g.line1Path)}if(this.line2Elem()){this.line2Elem().attr("path",g.line2Path)}});var e=function(j,h,k,g,l){var f;g=(g>=0)?g:l;if(g>0){j=j+"M"+h[0][0]+","+h[0][k];for(f=1;f=0;--h){g=g+"L"+k[h][0]+","+k[h][2]}g=g+"Z";f=e(f,k,1,j.line1width,j.linewidth);l=e(l,k,2,j.line2width,j.linewidth);j.fillPath=g;j.line1Path=f;j.line2Path=l};d.respondsTo("renderLegendIcon",function(p,m,k,l){var f=this.state(),g=p.paper,o=p.set,h=l.width(),j=l.height(),n,i,q,r="M"+0+","+(2*j/8)+"L"+0+","+(6*j/8)+"L"+h+","+(7*j/8)+"L"+h+","+(3*j/8)+"L"+0+","+(2*j/8);if(h<10||j<10){n=f.fillcolor.toRGBA()}else{n="#FFFFFF"}o.push(g.rect(m,k,h,j).attr({fill:n,stroke:n}));i=(f.line2width>=0)?f.line2width:f.linewidth;q=(f.line2color!==null)?f.line2color:f.linecolor;o.push(g.path(r).attr({"stroke-width":i,stroke:q.toRGBA(),fill:f.fillcolor.toRGBA(f.fillopacity)}).transform("t"+m+","+k))});d.respondsTo("redrawLegendIcon",function(){})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(b){var d=b.BarRenderer;d.hasMany("barElems");d.hasAn("outlineElem");d.hasAn("iconGraphicElem");d.hasA("settings");d.respondsTo("begin",function(f){var h={paper:f.paper,set:f.set,paths:{},barwidth:this.getOptionValue("barwidth"),baroffset:this.getOptionValue("baroffset"),barbase:this.getOptionValue("barbase"),fillcolor:this.getOptionValue("fillcolor"),linecolor:this.getOptionValue("linecolor"),hidelines:this.getOptionValue("hidelines"),barGroups:[],currentBarGroup:null,prevCorner:null,pixelEdgeTolerance:1};h.barpixelwidth=h.barwidth.getRealValue()*this.plot().horizontalaxis().axisToDataRatio();h.barpixelbase=(h.barbase!==null)?this.plot().verticalaxis().dataValueToAxisValue(h.barbase):0;var g;for(g=0;gj.hidelines){if(j.prevCorner===null){j.currentBarGroup=[[i,k[1]]]}else{if(Math.abs(i-j.prevCorner[0])<=j.pixelEdgeTolerance){j.currentBarGroup.push([i,k[1]])}else{j.currentBarGroup.push(j.prevCorner);j.barGroups.push(j.currentBarGroup);j.currentBarGroup=[[i,k[1]]]}}j.prevCorner=[f,k[1]]}});var c=function(l){var f="",k=l.barpixelbase,m,h,g,o;for(h=0;h20||n>20){g=l/6}else{if(l>10||n>10){g=l/4}else{g=l/4}}if(l>20&&n>20){t=t+e(q+(l/4)-(g/2),o,g,n/2)+e(q+l-(l/4)-(g/2),o,g,n/3)}t=t+e(q+(l/2)-(g/2),o,g,n-(n/4));var f=h.path(t).attr(m);this.iconGraphicElem(f);r.push(f)});d.respondsTo("redrawLegendIcon",function(){var f=this.settings(),g;if(f.barpixelwidth0){h=h+"M"+g[0]+","+g[1]}}else{e=e+"L"+g[0]+","+g[1];if(f.linewidth>0){h=h+"L"+g[0]+","+g[1]}}f.fillpath=e;f.path=h;f.previouspoint=g});b.respondsTo("end",function(){var e=this.settings(),g=e.paper,h=e.set;if(e.previouspoint!==null){e.fillpath=e.fillpath+"L"+e.previouspoint[0]+","+e.fillpixelbase}var d=g.path(e.fillpath).attr({fill:e.fillcolor.toRGBA(e.fillopacity),stroke:"none"});this.fillElem(d);h.push(d);if(e.linewidth>0){var f=g.path(e.path).attr({stroke:e.linecolor.getHexString("#"),"stroke-width":e.linewidth});this.lineElem(f);h.push(f)}});b.respondsTo("endRedraw",function(){var d=this.settings();if(d.previouspoint!==null){d.fillpath=d.fillpath+"L"+d.previouspoint[0]+","+d.fillpixelbase}this.fillElem().attr("path",d.fillpath);if(this.lineElem()){this.lineElem().attr("path",d.path)}});b.respondsTo("renderLegendIcon",function(m,k,i,j){var f=this.settings(),e=m.paper,l=m.set,g=j.width(),h=j.height(),d={},n="M0,0";d.stroke="rgba(255, 255, 255, 1)";if(g<10||h<10){d.fill=f.fillcolor.toRGBA(f.fillopacity)}else{d.fill="rgba(255, 255, 255, 1)"}l.push(e.rect(k,i,g,h).attr(d));if(g>10||h>10){if(g>20||h>20){n=n+"L"+(g/6)+","+(h/2)+"L"+(g/3)+","+(h/4)}n=n+"L"+(g/2)+","+(h-h/4);if(g>20||h>20){n=n+"L"+(g-g/3)+","+(h/4)+"L"+(g-g/6)+","+(h/2)}}n=n+"L"+g+",0";l.push(e.path(n).attr({stroke:f.linecolor.toRGBA(f.fillopacity),"stroke-width":f.linewidth,fill:f.fillcolor.toRGBA(f.fillopacity)}).transform("t"+k+","+i))});b.respondsTo("redrawLegendIcon",function(){})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(d){var c=d.PointlineRenderer;c.hasA("lineElem");c.hasA("pointsElem");c.hasA("settings");c.respondsTo("begin",function(g){var h={paper:g.paper,set:g.set,path:"",points:[],first:true,pointshape:this.getOptionValue("pointshape"),pointcolor:this.getOptionValue("pointcolor"),pointopacity:this.getOptionValue("pointopacity"),pointsize:this.getOptionValue("pointsize"),pointoutlinewidth:this.getOptionValue("pointoutlinewidth"),pointoutlinecolor:this.getOptionValue("pointoutlinecolor"),linecolor:this.getOptionValue("linecolor"),linewidth:this.getOptionValue("linewidth")};if(this.type()===d.Renderer.LINE){h.pointsize=0}if(this.type()===d.Renderer.POINT){h.linewidth=0}this.settings(h)});c.respondsTo("beginRedraw",function(){var g=this.settings();g.path="";g.points=[];g.first=true});c.respondsTo("dataPoint",function(g){var h=this.settings();if(this.isMissing(g)){h.first=true;return}var i=this.transformPoint(g);if(h.linewidth>0){if(h.first){h.path=h.path+"M"+i[0]+","+i[1];h.first=false}else{h.path=h.path+"L"+i[0]+","+i[1]}}if(h.pointsize>0){h.points.push(i)}});c.respondsTo("end",function(){var g=this.settings(),j=g.paper,k=g.set;if(g.linewidth>0){var i=j.path(g.path).attr({stroke:g.linecolor.getHexString("#"),"stroke-width":g.linewidth});this.lineElem(i);k.push(i)}if(g.pointsize>0){var h=j.path(f(g)).attr(b(g));this.pointsElem(h);k.push(h)}});c.respondsTo("endRedraw",function(){var g=this.settings();if(this.lineElem()){this.lineElem().attr("path",g.path)}if(this.pointsElem()){this.pointsElem().attr("path",f(g))}});var f=function(l){var k=l.points,m=l.pointshape,g=l.pointsize,h="",j;for(j=0;j0){var p="M"+m+","+(k+j/2)+"L"+(m+i)+","+(k+j/2);n.push(g.path(p).attr({stroke:h.linecolor.toRGBA(),"stroke-width":h.linewidth}))}if(h.pointsize>0){n.push(g.path(e(h.pointshape,h.pointsize,[(m+i/2),(k+j/2)])).attr(b(h)))}});c.respondsTo("redrawLegendIcon",function(){})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(c){var b=c.RangeBarRenderer;b.hasAn("elem");b.hasAn("iconGraphicElem");b.hasA("state");b.respondsTo("begin",function(e){var f={paper:e.paper,set:e.set,path:"",barwidth:this.getOptionValue("barwidth"),baroffset:this.getOptionValue("baroffset"),fillcolor:this.getOptionValue("fillcolor"),fillopacity:this.getOptionValue("fillopacity"),linecolor:this.getOptionValue("linecolor"),linewidth:this.getOptionValue("linewidth"),hidelines:this.getOptionValue("hidelines")};f.barpixelwidth=f.barwidth.getRealValue()*this.plot().horizontalaxis().axisToDataRatio();f.barpixeloffset=f.barpixelwidth*f.baroffset;this.state(f)});b.respondsTo("beginRedraw",function(){var e=this.state();e.path="";e.barpixelwidth=e.barwidth.getRealValue()*this.plot().horizontalaxis().axisToDataRatio();e.barpixeloffset=e.barpixelwidth*e.baroffset});b.respondsTo("dataPoint",function(f){if(this.isMissing(f)){return}var h=this.state(),i=this.transformPoint(f),g=i[0]-h.barpixeloffset,e=g+h.barpixelwidth;h.path=h.path+"M"+g+","+i[1]+"L"+g+","+i[2]+"L"+e+","+i[2]+"L"+e+","+i[1]+"Z"});b.respondsTo("end",function(){var f=this.state(),g=f.path,h={"fill-opacity":f.fillopacity,fill:f.fillcolor.getHexString("#"),stroke:"none"};if(f.linewidth>0&&f.barpixelwidth>f.hidelines){h.stroke=f.linecolor.getHexString("#");h["stroke-width"]=f.linewidth}var e=f.paper.path(g).attr(h);this.elem(e);f.set.push(e)});b.respondsTo("endRedraw",function(){var e=this.state(),f={path:e.path};if(e.linewidth>0&&e.barpixelwidth>e.hidelines){f.stroke=e.linecolor.getHexString("#");f["stroke-width"]=e.linewidth}else{f.stroke="none";f["stroke-width"]=1}this.elem().attr(f)});var d=function(f,h,g,e){return"M"+f+","+h+"L"+f+","+(h+e)+"L"+(f+g)+","+(h+e)+"L"+(f+g)+","+h+"Z"};b.respondsTo("renderLegendIcon",function(p,m,k,l){var f=this.state(),h=p.paper,n=p.set,i=l.width(),j=l.height(),q="";n.push(h.rect(m,k,i,j).attr({stroke:"#FFFFFF",fill:"#FFFFFF"}));var o={fill:f.fillcolor.toRGBA(f.fillopacity),"stroke-width":f.linewidth};if(f.barpixelwidth<10){o.stroke=f.fillcolor.toRGBA(f.fillopacity)}else{o.stroke=f.linecolor.getHexString("#")}var g;if(i>20||j>20){g=i/6}else{if(i>10||j>10){g=i/4}else{g=i/4}}if(i>20&&j>20){q=q+d(m+i/4-g/2,k+j/8,g,j/2)+d(m+i-i/4-g/2,k+j/4,g,j/3)}q=q+d(m+i/2-g/2,k,g,j-j/4);var e=h.path(q).attr(o);this.iconGraphicElem(e);n.push(e);return this});b.respondsTo("redrawLegendIcon",function(){var e=this.state(),f;if(e.barpixelwidth<10){f=e.fillcolor.toRGBA(e.fillopacity)}else{f=e.linecolor.getHexString("#")}this.iconGraphicElem().attr("stroke",f)})})});window.multigraph.util.namespace("window.multigraph.graphics.raphael",function(a){a.mixin.add(function(b){var c=b.Text;c.respondsTo("initializeGeometry",function(p){var f=p.elem,n,q,o,k,h,e,r,m;if(p.fontSize!==undefined){e=f.attr("font-size");f.attr("font-size",p.fontSize)}m=f.attr("text");f.attr("text",this.string());r=f.transform();f.transform("");h=f.getBBox();n=h.width;q=h.height;if(p.angle!==undefined){var g=p.angle/180*Math.PI,d=Math.abs(Math.sin(g)),l=Math.abs(Math.cos(g));o=l*n+d*q;k=d*n+l*q}else{o=n;k=q}if(p.fontSize!==undefined){f.attr("font-size",e)}f.attr("text",m);var j;for(j=0;j0&&this.currentLabelDensity()<=1.5){var h=this.currentLabeler(),g=this.perpOffset(),e=i.plotBox();h.prepare(this.dataMin(),this.dataMax());f.beginPath();while(h.hasNext()){var d=h.next(),c=this.dataValueToAxisValue(d);if(this.orientation()===b.Axis.HORIZONTAL){f.moveTo(c,g);f.lineTo(c,e.height()-g)}else{f.moveTo(g,c);f.lineTo(e.width()-g,c)}}f.strokeStyle=this.grid().color().getHexString("#");f.stroke()}}}});b.Axis.respondsTo("render",function(o,f){var g=this.parallelOffset(),i=this.perpOffset(),j=this.pixelLength(),e=this.currentLabeler(),k=(this.orientation()===b.Axis.HORIZONTAL);if(this.linewidth()>0){f.beginPath();if(k){f.moveTo(g,i);f.lineTo(g+j,i)}else{f.moveTo(i,g);f.lineTo(i,g+j)}f.strokeStyle=this.color().getHexString("#");f.stroke()}if(this.hasDataMin()&&this.hasDataMax()){if(e&&e.visible()){var n=this.tickwidth(),c=this.tickmin(),h=this.tickmax(),d=this.tickcolor();f.beginPath();f.fillStyle="#000000";e.prepare(this.dataMin(),this.dataMax());while(e.hasNext()){var m=e.next(),l=this.dataValueToAxisValue(m);if(n>0){if(d!==undefined&&d!==null){f.strokeStyle=d.getHexString("#")}if(k){f.moveTo(l,i+h);f.lineTo(l,i+c)}else{f.moveTo(i+c,l);f.lineTo(i+h,l)}if(d!==undefined&&d!==null){f.restore()}}e.renderLabel(f,m)}f.stroke()}}if(this.title()){this.title().render(f)}})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){b.AxisTitle.respondsTo("render",function(d){var j=window.multigraph.math.Point,e=this.axis(),l=this.content(),f=this.anchor(),i=e.perpOffset(),g=l.origHeight(),n=l.origWidth(),m=new j(0.5*n*(f.x()+1),0.5*g*(f.y()+1)),c=(this.base()+1)*(e.pixelLength()/2)+e.minoffset()+e.parallelOffset(),k;if(e.orientation()===b.Axis.HORIZONTAL){k=new j(c,i)}else{k=new j(i,c)}d.save();d.fillStyle="rgba(0, 0, 0, 1)";l.drawText(d,m,k,this.position(),this.angle());d.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){b.Background.respondsTo("render",function(g,e,f,c){var h=g.window().margin().left()+g.window().border(),d=this.img();e.save();e.fillStyle=this.color().getHexString("#");e.fillRect(h,h,f-2*h,c-2*h);e.restore();if(d&&d.src()!==undefined){d.render(g,e,f,c)}})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(c){var b=c.Graph;b.respondsTo("render",function(f,g,d){var e;this.window().render(f,g,d);this.background().render(this,f,g,d);f.transform(1,0,0,1,this.x0(),this.y0());this.plotarea().render(this,f);for(e=0;e0){d.strokeStyle=this.bordercolor().toRGBA();d.lineWidth=p;d.strokeRect(p/2,p/2,l+(2*n)+p,r+(2*n)+p)}d.fillStyle=f;d.fillRect(p,p,l+(2*n),r+(2*n));d.restore();d.save();var e=new s(t.x()+p+n,t.y()+p+n);d.font=this.fontSize()+" sans-serif";d.fillStyle="rgba(0, 0, 0, 1)";u.drawText(d,i,o,e,0);d.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){b.Icon.respondsTo("renderBorder",function(d,c,e){d.save();d.strokeStyle="rgba(0, 0, 0, 1)";d.strokeRect(c,e,this.width(),this.height());d.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){var c=window.multigraph.core.Img;c.hasA("image").defaultsTo(function(){return new Image()});c.hasA("fetched").defaultsTo(false);c.respondsTo("render",function(d,e,r,o){if(this.fetched()){var h=window.multigraph.math.util.interp,p=this.image(),f=d.window(),w=d.plotarea(),g=this.base(),m=h(this.anchor().x(),-1,1,0,p.width),l=h(this.anchor().y(),1,-1,0,p.height),v=f.margin().left()+f.border(),u=f.margin().top()+f.border(),n=v+f.padding().left()+w.margin().left()+w.border(),q=u+f.padding().top()+w.margin().top()+w.border(),t,s,k,j;if(this.frame()===c.PLOT){t=n+h(g.x(),-1,1,0,d.plotBox().width());s=q+h(g.y(),1,-1,0,d.plotBox().height())}else{t=v+h(g.x(),-1,1,0,d.paddingBox().width());s=u+h(g.y(),1,-1,0,d.paddingBox().height())}k=t+this.position().x()-m;j=s+this.position().y()-l;e.save();e.transform(1,0,0,-1,0,o);e.drawImage(p,k,j,p.width,p.height);e.restore()}else{var i=this;this.image().onload=function(){i.fetched(true);e.save();e.setTransform(1,0,0,-1,0,o);d.render(e,r,o);e.restore()};this.image().src=this.src()}})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(c){var b=c.Labeler;b.respondsTo("measureStringWidth",function(e,d){return(new c.Text(d)).initializeGeometry({context:e,angle:this.angle()}).rotatedWidth()});b.respondsTo("measureStringHeight",function(e,d){return(new c.Text(d)).initializeGeometry({context:e,angle:this.angle()}).rotatedHeight()});b.respondsTo("renderLabel",function(e,m){var i=window.multigraph.math.Point,f=this.axis(),n=this.anchor(),g=this.angle(),h=f.perpOffset(),k=f.dataValueToAxisValue(m),j=new c.Text(this.formatter().format(m)),l,d;j.initializeGeometry({context:e,angle:g});l=new i(0.5*j.origWidth()*(n.x()+1),0.5*j.origHeight()*(n.y()+1));if(f.orientation()===c.Axis.HORIZONTAL){d=new i(k,h)}else{d=new i(h,k)}e.save();e.fillStyle=this.color().getHexString("#");j.drawText(e,l,d,this.position(),g);e.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(c){var b=c.Legend;b.respondsTo("begin",function(d){d.save();d.transform(1,0,0,1,this.x(),this.y())});b.respondsTo("end",function(d){d.restore()});b.respondsTo("renderLegend",function(e){var d=this.border();e.save();if(d>0){e.strokeStyle=this.bordercolor().toRGBA();e.strokeRect(d/2,d/2,this.width()-d/2,this.height()-d/2)}e.fillStyle=this.color().toRGBA(this.opacity());e.fillRect(d,d,this.width()-(2*d),this.height()-(2*d));e.restore()});b.respondsTo("renderLabel",function(e,f,d,g){f.save();f.fillStyle="rgba(0, 0, 0, 1)";f.transform(1,0,0,-1,0,g+this.maxLabelHeight()/2-e.origHeight()/2);f.fillText(e.string(),d,0);f.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(b){var d=window.multigraph.jQuery;b.mixin.add(function(e){var f=e.Multigraph;f.hasA("canvas");f.hasA("context");f.hasA("width").isA("number");f.hasA("height").isA("number");f.respondsTo("redraw",function(){var g=this;window.requestAnimationFrame(function(){g.render()})});f.respondsTo("init",function(){var g=d(this.div());this.width(g.width());this.height(g.height());if(this.width()>0&&this.height()>0){d('').appendTo(g);this.initializeSurface();this.busySpinner(d('
    ').appendTo(g).busy_spinner())}this.render()});f.respondsTo("render",function(){var j=this.context(),k=this.width(),g=this.height(),h;j.setTransform(1,0,0,1,0,0);j.transform(1,0,0,-1,0,g);j.clearRect(0,0,k,g);this.initializeGeometry(k,g,{context:j});for(h=0;h0){e.save();e.lineWidth=d;e.strokeStyle=this.bordercolor().getHexString("#");e.strokeRect(-d/2,-d/2,c.width()+d,c.height()+d);e.restore()}})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){var c=b.BandRenderer;c.hasA("state");c.respondsTo("begin",function(e){var f={context:e,run:[],linecolor:this.getOptionValue("linecolor"),line1color:this.getOptionValue("line1color"),line2color:this.getOptionValue("line2color"),linewidth:this.getOptionValue("linewidth"),line1width:this.getOptionValue("line1width"),line2width:this.getOptionValue("line2width"),fillcolor:this.getOptionValue("fillcolor"),fillopacity:this.getOptionValue("fillopacity")};this.state(f)});c.respondsTo("dataPoint",function(e){var f=this.state();if(this.isMissing(e)){if(f.run.length>0){this.renderRun();f.run=[]}}else{var g=this.transformPoint(e);f.run.push(g)}});c.respondsTo("end",function(){var e=this.state();if(e.run.length>0){this.renderRun()}});var d=function(g,k,l,e,j,h,m){var f;h=(h>=0)?h:m;if(h>0){e=(e!==null)?e:j;g.save();g.strokeStyle=e.getHexString("#");g.lineWidth=h;g.beginPath();g.moveTo(k[0][0],k[0][l]);for(f=1;f=0;--e){f.lineTo(h[e][0],h[e][2])}f.fill();f.restore();d(f,h,1,g.line1color,g.linecolor,g.line1width,g.linewidth);d(f,h,2,g.line2color,g.linecolor,g.line2width,g.linewidth)});c.respondsTo("renderLegendIcon",function(f,e,k,g){var h=this.state(),i=g.width(),j=g.height();f.save();f.transform(1,0,0,1,e,k);f.save();if(i<10||j<10){f.fillStyle=h.fillcolor.toRGBA()}else{f.fillStyle="#FFFFFF"}f.fillRect(0,0,i,j);f.restore();f.strokeStyle=(h.line2color!==null)?h.line2color:h.linecolor;f.lineWidth=(h.line2width>=0)?h.line2width:h.linewidth;f.fillStyle=h.fillcolor.toRGBA(h.fillopacity);f.beginPath();f.moveTo(0,2*j/8);f.lineTo(0,6*j/8);f.lineTo(i,7*j/8);f.lineTo(i,3*j/8);f.lineTo(0,2*j/8);f.fill();f.stroke();f.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){var c=b.BarRenderer;c.hasA("settings");c.respondsTo("begin",function(d){var e={context:d,barpixelwidth:this.getOptionValue("barwidth").getRealValue()*this.plot().horizontalaxis().axisToDataRatio(),baroffset:this.getOptionValue("baroffset"),barpixelbase:(this.getOptionValue("barbase")!==null)?this.plot().verticalaxis().dataValueToAxisValue(this.getOptionValue("barbase")):0,fillcolor:this.getOptionValue("fillcolor"),linecolor:this.getOptionValue("linecolor"),hidelines:this.getOptionValue("hidelines"),barGroups:[],currentBarGroup:null,prevCorner:null,pixelEdgeTolerance:1};this.settings(e)});c.respondsTo("dataPoint",function(e){if(this.isMissing(e)){return}var h=this.settings(),g=h.context,i=this.transformPoint(e),f=i[0]+h.baroffset,d=i[0]+h.baroffset+h.barpixelwidth;g.save();g.fillStyle=this.getOptionValue("fillcolor",e[1]).getHexString("#");g.fillRect(f,h.barpixelbase,h.barpixelwidth,i[1]-h.barpixelbase);g.restore();if(h.barpixelwidth>h.hidelines){if(h.prevCorner===null){h.currentBarGroup=[[f,i[1]]]}else{if(Math.abs(f-h.prevCorner[0])<=h.pixelEdgeTolerance){h.currentBarGroup.push([f,i[1]])}else{h.currentBarGroup.push(h.prevCorner);h.barGroups.push(h.currentBarGroup);h.currentBarGroup=[[f,i[1]]]}}h.prevCorner=[d,i[1]]}});c.respondsTo("end",function(){var g=this.settings(),e=g.context,m=g.barpixelbase,q=Math.max,k=Math.min,d,o,l,h,f;if(g.prevCorner!==null&&g.currentBarGroup!==null){g.currentBarGroup.push(g.prevCorner);g.barGroups.push(g.currentBarGroup)}e.save();e.strokeStyle=g.linecolor.getHexString("#");e.beginPath();for(l=0;l20||j>20){e=h/6}else{if(h>10||j>10){e=h/4}else{e=h/4}}if(h>20&&j>20){d.fillRect((h/4)-(e/2),0,e,j/2);d.strokeRect((h/4)-(e/2),0,e,j/2);d.fillRect(h-(h/4)-(e/2),0,e,j/3);d.strokeRect(h-(h/4)-(e/2),0,e,j/3)}d.fillRect((h/2)-(e/2),0,e,j-(j/4));d.strokeRect((h/2)-(e/2),0,e,j-(j/4));d.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(b){var a=window.multigraph.math.util;b.mixin.add(function(d){var c=d.FillRenderer;c.hasA("state");c.respondsTo("begin",function(e){var f={context:e,run:[],previouspoint:null,linecolor:this.getOptionValue("linecolor"),linewidth:this.getOptionValue("linewidth"),fillcolor:this.getOptionValue("fillcolor"),downfillcolor:this.getOptionValue("downfillcolor"),fillopacity:this.getOptionValue("fillopacity"),fillbase:this.getOptionValue("fillbase"),currentfillcolor:null};if(f.downfillcolor===null){f.downfillcolor=f.fillcolor}if(f.fillbase!==null){f.fillpixelbase=this.plot().verticalaxis().dataValueToAxisValue(f.fillbase)}else{f.fillpixelbase=0}this.state(f);e.save();e.fillStyle=f.fillcolor.getHexString("#")});c.respondsTo("dataPoint",function(h){var j=this.state(),g=j.fillpixelbase,i,f,k;if(this.isMissing(h)){if(j.previouspoint!==null){j.run.push([j.previouspoint[0],g]);this.renderRun();j.run=[];j.previouspoint=null}return}k=this.transformPoint(h);if(k[1]>=g){i=j.fillcolor}else{i=j.downfillcolor}if(j.run.length===0){j.run.push([k[0],g])}else{if(!i.eq(j.currentfillcolor)){var e=a.safe_interp(g,j.previouspoint[1],k[1],j.previouspoint[0],k[0]);j.run.push([e,g]);j.run.push([e,g]);this.renderRun();j.run=[];j.run.push([e,g]);j.run.push([e,g])}}j.run.push(k);j.previouspoint=k;j.currentfillcolor=i});c.respondsTo("end",function(){var f=this.state(),e=f.context;if(f.run.length>0){f.run.push([f.run[f.run.length-1][0],f.fillpixelbase]);this.renderRun()}e.restore()});c.respondsTo("renderRun",function(){var g=this.state(),f=g.context,e;f.save();f.globalAlpha=g.fillopacity;f.fillStyle=g.currentfillcolor.getHexString("#");f.beginPath();f.moveTo(g.run[0][0],g.run[0][1]);for(e=1;e10||j>10){if(i>20||j>20){f.lineTo(i/6,j/2);f.lineTo(i/3,j/4)}f.lineTo(i/2,j-j/4);if(i>20||j>20){f.lineTo(i-i/3,j/4);f.lineTo(i-i/6,j/2)}}f.lineTo(i,0);f.stroke();f.fill();f.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(c){var b=c.PointlineRenderer;b.hasA("settings");b.respondsTo("begin",function(d){var e={context:d,points:[],first:true,pointshape:this.getOptionValue("pointshape"),pointcolor:this.getOptionValue("pointcolor"),pointopacity:this.getOptionValue("pointopacity"),pointsize:this.getOptionValue("pointsize"),pointoutlinewidth:this.getOptionValue("pointoutlinewidth"),pointoutlinecolor:this.getOptionValue("pointoutlinecolor"),linecolor:this.getOptionValue("linecolor"),linewidth:this.getOptionValue("linewidth")};if(this.type()===c.Renderer.LINE){e.pointsize=0}if(this.type()===c.Renderer.POINT){e.linewidth=0}this.settings(e);if(e.linewidth>0){d.save();d.beginPath();d.lineWidth=e.linewidth;d.strokeStyle=e.linecolor.getHexString("#")}});b.respondsTo("dataPoint",function(d){var f=this.settings(),e=f.context,g;if(this.isMissing(d)){f.first=true;return}g=this.transformPoint(d);if(f.linewidth>0){if(f.first){e.moveTo(g[0],g[1]);f.first=false}else{e.lineTo(g[0],g[1])}}if(f.pointsize>0){f.points.push(g)}});b.respondsTo("end",function(){var e=this.settings(),d=e.context;if(e.linewidth>0){d.stroke();d.restore()}if(e.pointsize>0){this.drawPoints()}});b.respondsTo("drawPoints",function(h){var g=this.settings(),e=g.context,f=g.points,j=g.pointshape,d;e.save();e.beginPath();if((j===b.PLUS)||(j===b.X)){e.strokeStyle=g.pointcolor.getHexString("#");e.lineWidth=g.pointoutlinewidth}else{e.fillStyle=g.pointcolor.toRGBA(g.pointopacity);e.strokeStyle=g.pointoutlinecolor.getHexString("#");e.lineWidth=g.pointoutlinewidth}for(d=0;d0){e.strokeStyle=f.linecolor.toRGBA();e.lineWidth=f.linewidth;e.beginPath();e.moveTo(d,k+i/2);e.lineTo(d+h,k+i/2);e.stroke()}if(f.pointsize>0){e.beginPath();if((j===b.PLUS)||(j===b.X)){e.strokeStyle=f.pointcolor.toRGBA();e.lineWidth=f.pointoutlinewidth}else{e.fillStyle=f.pointcolor.toRGBA(f.pointopacity);e.strokeStyle=f.pointoutlinecolor.toRGBA();e.lineWidth=f.pointoutlinewidth}this.drawPoint(e,f,[(d+h/2),(k+i/2)]);if(!((j===b.PLUS)||(j===b.X))){e.fill()}e.stroke()}e.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(c){var b=c.RangeBarRenderer;b.hasA("state");b.respondsTo("begin",function(d){var e={context:d,run:[],barpixelwidth:this.getOptionValue("barwidth").getRealValue()*this.plot().horizontalaxis().axisToDataRatio(),barpixeloffset:0,baroffset:this.getOptionValue("baroffset"),fillcolor:this.getOptionValue("fillcolor"),fillopacity:this.getOptionValue("fillopacity"),linecolor:this.getOptionValue("linecolor"),linewidth:this.getOptionValue("linewidth"),hidelines:this.getOptionValue("hidelines")};e.barpixeloffset=e.barpixelwidth*e.baroffset;this.state(e);d.save();d.beginPath()});b.respondsTo("dataPoint",function(e){if(this.isMissing(e)){return}var h=this.state(),g=h.context,i=this.transformPoint(e),f=i[0]-h.barpixeloffset,d=f+h.barpixelwidth;g.moveTo(f,i[1]);g.lineTo(f,i[2]);g.lineTo(d,i[2]);g.lineTo(d,i[1]);g.lineTo(f,i[1])});b.respondsTo("end",function(){var e=this.state(),d=e.context;d.globalAlpha=e.fillopacity;d.fillStyle=e.fillcolor.getHexString("#");d.fill();if(e.linewidth>0&&e.barpixelwidth>e.hidelines){d.strokeStyle=e.linecolor.getHexString("#");d.lineWidth=e.linewidth;d.stroke()}d.restore()});b.respondsTo("renderLegendIcon",function(e,d,k,f){var g=this.state(),h=f.width(),j=f.height(),i;e.save();e.transform(1,0,0,1,d,k);e.save();e.strokeStyle="#FFFFFF";e.fillStyle="#FFFFFF";e.fillRect(0,0,h,j);e.restore();e.fillStyle=g.fillcolor.toRGBA(g.fillopacity);e.lineWidth=g.linewidth;if(g.barpixelwidth<10){e.strokeStyle=g.fillcolor.toRGBA(g.fillopacity)}else{e.strokeStyle=g.linecolor.getHexString("#")}if(h>20||j>20){i=h/6}else{if(h>10||j>10){i=h/4}else{i=h/4}}if(h>20&&j>20){e.fillRect(h/4-i/2,j/8,i,j/2);e.strokeRect(h/4-i/2,j/8,i,j/2);e.fillRect(h-h/4-i/2,j/4,i,j/3);e.strokeRect(h-h/4-i/2,j/4,i,j/3)}e.fillRect(h/2-i/2,0,i,j-j/4);e.strokeRect(h/2-i/2,0,i,j-j/4);e.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){var c=b.Text;c.respondsTo("initializeGeometry",function(d){var i,h,g,e;d.context.save();if(d.fontSize!==undefined){d.context.font=d.fontSize+" sans-serif"}i=this.measureStringWidth(d.context);h=this.measureStringHeight(d.context);d.context.restore();if(d.angle!==undefined){var f=d.angle/180*Math.PI;g=Math.abs(Math.cos(f))*i+Math.abs(Math.sin(f))*h;e=Math.abs(Math.sin(f))*i+Math.abs(Math.cos(f))*h}else{g=i;e=h}this.origWidth(i);this.origHeight(h);this.rotatedWidth(g);this.rotatedHeight(e);return this});c.respondsTo("measureStringWidth",function(d){if(this.string()===undefined){throw new Error("measureStringWidth requires the string attr to be set.")}var e=d.measureText(this.string());return e.width});c.respondsTo("measureStringHeight",function(d){if(this.string()===undefined){throw new Error("measureStringHeight requires the string attr to be set.")}var e=d.measureText("M"),f=this.string().match(/\n/g);return(f!==null?(f.length+1):1)*e.width});c.respondsTo("setTransform",function(f,e,g,d,h){f.transform(1,0,0,-1,0,2*g.y());f.transform(1,0,0,1,g.x(),g.y());f.transform(1,0,0,1,d.x(),-d.y());f.rotate(-h*Math.PI/180);f.transform(1,0,0,1,-e.x(),e.y())});c.respondsTo("drawText",function(f,e,g,d,h){f.save();this.setTransform(f,e,g,d,h);f.fillText(this.string(),0,0);f.restore()})})});window.multigraph.util.namespace("window.multigraph.graphics.canvas",function(a){a.mixin.add(function(b){b.Window.respondsTo("render",function(e,f,d){var c=this.margin().left();e.save();e.fillStyle=this.bordercolor().getHexString("#");e.fillRect(c,c,f-2*c,d-2*c);e.restore()})})}); \ No newline at end of file diff --git a/build/multigraph.js b/build/multigraph.js new file mode 100644 index 0000000..faddaf5 --- /dev/null +++ b/build/multigraph.js @@ -0,0 +1,22154 @@ +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { + "use strict"; + if (this == null) { + throw new TypeError(); + } + var t = Object(this); + var len = t.length >>> 0; + if (len === 0) { + return -1; + } + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n != n) { // shortcut for verifying if it's NaN + n = 0; + } else if (n != 0 && n != Infinity && n != -Infinity) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + if (n >= len) { + return -1; + } + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + } +} +/*global describe, it, beforeEach, expect, xit, jasmine */ + +(function (ns) { + "use strict"; + + var namespace = function (ns, aliases, func) { + var nsRegExp = /^([a-zA-Z]+)(\.[a-zA-Z]*)*$/, + nsArray, + currentNS, + i; + + //check to assure ns is a properly formatted namespace string + if (ns.match(nsRegExp) === null || ns === "window") { + throw new Error("namespace: " + ns + " is a malformed namespace string"); + } + + //check to assure that if alias is defined that func is defined + if (aliases !== undefined && func === undefined) { + if (typeof (aliases) === "function") { + func = aliases; + aliases = undefined; + } else if (typeof (aliases) === "object") { + throw new Error("namespace: if second argument exists, final function argument must exist"); + } else if (typeof (aliases) !== "object") { + throw new Error("namespace: second argument must be an object of aliased local namespaces"); + } + } else if (typeof (aliases) !== "object" && typeof (func) === "function") { + throw new Error("namespace: second argument must be an object of aliased local namespaces"); + } + + //parse namespace string + nsArray = ns.split("."); + + //set the root namespace to window (if it's not explictly stated) + if (nsArray[0] === "window") { + currentNS = window; + } else { + currentNS = (window[nsArray[0]] === undefined) ? window[nsArray[0]] = {} : window[nsArray[0]]; + } + + //confirm func is actually a function + if (func !== undefined && typeof (func) !== "function") { + throw new Error("namespace: last parameter must be a function that accepts a namespace parameter"); + } + + //build namespace + for (i = 1; i < nsArray.length; i = i + 1) { + if (currentNS[nsArray[i]] === undefined) { + currentNS[nsArray[i]] = {}; + } + currentNS = currentNS[nsArray[i]]; + } + + //namespaces.push(currentNS); + //namespace = currentNS; + + //if the function was defined, but no aliases run it on the current namespace + if (aliases === undefined && func) { + func(currentNS); + } else if (func) { + for (i in aliases) { + if (aliases.hasOwnProperty(i)) { + aliases[i] = namespace(aliases[i]); + } + } + func.call(aliases, currentNS); + } + + //return namespace + return currentNS; + }; + + return namespace(ns, function (exports) { + exports.namespace = namespace; + }); +}("window.jermaine.util")); +window.jermaine.util.namespace("window.jermaine", function (ns) { + "use strict"; + var that = this, + Validator, + validators = {}; + + Validator = function (spec) { + var validatorFunction = function (arg) { + var result, + resultObject = {}, + errorMessage; + result = spec.call(resultObject, arg); + if (!result) { + errorMessage = resultObject.message || "validator failed with parameter " + arg; + throw new Error(errorMessage); + } + return result; + }; + return validatorFunction; + }; + + Validator.addValidator = function (name, v) { + if (name === undefined || typeof(name) !== "string") { + throw new Error("addValidator requires a name to be specified as the first parameter"); + } + + if (v === undefined || typeof(v) !== "function") { + throw new Error("addValidator requires a function as the second parameter"); + } + + if (validators[name] === undefined) { + validators[name] = function (expected) { + return new Validator(function (val) { + var resultObject = {"actual":val, "param":val}, + result = v.call(resultObject, expected); + this.message = resultObject.message; + return result; + }); + }; + } else { + throw new Error("Validator '" + name +"' already defined"); + } + }; + + Validator.getValidator = function (name) { + var result; + + if (name === undefined) { + throw new Error("Validator: getValidator method requires a string parameter"); + } else if (typeof (name) !== "string") { + throw new Error("Validator: parameter to getValidator method must be a string"); + } + + result = validators[name]; + + if (result === undefined) { + throw new Error("Validator: '" + name + "' does not exist"); + } + + return result; + }; + + + Validator.validators = function () { + var prop, + result = []; + for (prop in validators) { + if (validators.hasOwnProperty(prop)) { + result.push(prop); + } + } + + return result; + }; + + Validator.addValidator("isGreaterThan", function (val) { + this.message = this.param + " should be greater than " + val; + return this.param > val; + }); + + Validator.addValidator("isLessThan", function (val) { + this.message = this.param + " should be less than " + val; + return this.param < val; + }); + + Validator.addValidator("isA", function (val) { + var types = ["string", "number", "boolean", "function", "object"]; + if (typeof(val) === "string" && types.indexOf(val) > -1) { + this.message = this.param + " should be a " + val; + return typeof(this.param) === val; + } else if (val === 'integer') { + // special case for 'integer'; since javascript has no integer type, + // just check for number type and check that it's numerically an int + if (this.param.toString !== undefined) { + this.message = this.param.toString() + " should be an integer"; + } else { + this.message = "parameter should be an integer"; + } + return (typeof(this.param) === 'number') && (parseInt(this.param,10) === this.param); + } else if (typeof(val) === "string") { + throw new Error("Validator: isA accepts a string which is one of " + types); + } else { + throw new Error("Validator: isA only accepts a string for a primitive types for the time being"); + } + }); + + validators["isAn"] = validators["isA"]; + + Validator.addValidator("isOneOf", function (val) { + this.message = this.param + " should be one of the set: " + val; + return val.indexOf(this.param) > -1; + }); + + ns.Validator = Validator; +}); +/* + + what about isNotGreaterThan()?, isNotLessThan()? Or, better still: a general 'not' operator, as in jasmine? + + use of deprecated errorsWith in implementation of clone()? +*/ + +window.jermaine.util.namespace("window.jermaine", function (ns) { + "use strict"; + + var staticValidators = {}; + + var Attr = function (name) { + var validators = [], + that = this, + errorMessage = "invalid setter call for " + name, + defaultValueOrFunction, + getDefaultValue, + i, + prop, + addValidator, + immutable = false, + validator, + AttrList = window.jermaine.AttrList, + Validator = window.jermaine.Validator; + + + /* This is the validator that combines all the specified validators */ + validator = function (thingBeingValidated) { + for (i = 0; i < validators.length; ++i) { + validators[i](thingBeingValidated); + } + return true; + }; + + getDefaultValue = function() { + return (typeof(defaultValueOrFunction) === 'function') ? defaultValueOrFunction() : defaultValueOrFunction; + }; + + if (name === undefined || typeof(name) !== 'string') { + throw new Error("Attr: constructor requires a name parameter which must be a string"); + } + + this.validatesWith = function (v) { + if (typeof(v) === 'function') { + validators.push(new Validator(v)); + return this; + } else { + throw new Error("Attr: validator must be a function"); + } + }; + + this.defaultsTo = function (value) { + defaultValueOrFunction = value; + return this; + }; + + this.isImmutable = function () { + immutable = true; + return this; + }; + + this.isMutable = function () { + immutable = false; + return this; + }; + + this.clone = function () { + var result = (this instanceof AttrList)?new AttrList(name):new Attr(name), + i; + + for (i = 0; i < validators.length; ++i) { + result.validatesWith(validators[i]); + } + + result.defaultsTo(defaultValueOrFunction); + if (immutable) { + result.isImmutable(); + } + + return result; + }; + + //syntactic sugar + this.and = this; + this.which = this; + this.eachOfWhich = this; + + this.validator = function () { + return validator; + }; + + this.addTo = function (obj) { + var attribute, + defaultValue; + + if (!obj || typeof(obj) !== 'object') { + throw new Error("Attr: addAttr method requires an object parameter"); + } + + defaultValue = getDefaultValue(); + + if (defaultValue !== undefined && validator(defaultValue)) { + attribute = defaultValue; + } else if (defaultValue !== undefined && !validator(defaultValue)) { + throw new Error("Attr: Default value of " + defaultValue + " does not pass validation for " + name); + } + + obj[name] = function (newValue) { + if (newValue !== undefined) { + //setter + if (immutable && attribute !== undefined) { + throw new Error("cannot set the immutable property " + name + " after it has been set"); + } else + if (!validator(newValue)) { + throw new Error(errorMessage); + } else { + attribute = newValue; + } + return obj; + } else { + //getter + return attribute; + } + }; + }; + + //add a single validator object to the attribute + addValidator = function (name) { + that[name] = function (param) { + validators.push(Validator.getValidator(name)(param)); + return that; + }; + }; + + //add the validators to the attribute + for (i = 0; i < Validator.validators().length; ++i) { + addValidator(Validator.validators()[i]); + } + }; + + ns.Attr = Attr; +}); +window.jermaine.util.namespace("window.jermaine", function (ns) { + "use strict"; + + function AttrList(name) { + var that = this; + + //this is where the inheritance happens now + ns.Attr.call(this, name); + + var delegate = function (obj, func) { + return function () { return obj[func].apply(obj, arguments); }; + }; + + //syntactic sugar to keep things grammatically correct + this.validateWith = this.validatesWith; + + //disable defaultsTo and isImmutable until we figure out how to make it make sense + this.defaultsTo = function () { + //no op + }; + + this.isImmutable = function () { + //no op + }; + + this.isMutable = function () { + //no op + }; + + this.addTo = function (obj) { + var prop, + arr = [], + actualList = {}; + if(!obj || typeof(obj) !== 'object') { + throw new Error("AttrList: addTo method requires an object parameter"); + } else { + actualList.pop = delegate(arr, "pop"); + + actualList.add = function (obj) { + if ((that.validator())(obj)) { + arr.push(obj); + return this; + } else { + throw new Error(that.errorMessage()); + } + }; + + actualList.replace = function (index, obj) { + if ((typeof(index) !== 'number') || (parseInt(index, 10) !== index)) { + throw new Error("AttrList: replace method requires index parameter to be an integer"); + } + + if (index < 0 || index >= this.size()) { + throw new Error("AttrList: replace method index parameter out of bounds"); + } + + if (!(that.validator())(obj)) { + throw new Error(that.errorMessage()); + } + + arr[index] = obj; + return this; + }; + + actualList.at = function (index) { + if (index < 0 || index >= this.size()) { + throw new Error("AttrList: Index out of bounds"); + } + return arr[index]; + }; + + //to keep things more java-y + actualList.get = actualList.at; + + actualList.size = function () { + return arr.length; + }; + + obj[name] = function () { + return actualList; + }; + } + }; + } + + //this needs to stay if we're going to use instanceof + //but note we override all of the methods via delegation + //so it's not doing anything except for making an AttrList + //an instance of Attr + AttrList.prototype = new window.jermaine.Attr(name); + + ns.AttrList = AttrList; +}); +window.jermaine.util.namespace("window.jermaine", function (ns) { + "use strict"; + + var Method = function (name, method) { + if (!name || typeof(name) !== "string") { + throw new Error("Method: constructor requires a name parameter which must be a string"); + } else if (!method || typeof(method) !== "function") { + throw new Error("Method: second parameter must be a function"); + } + + this.addTo = function (obj) { + if (!obj || typeof(obj) !== 'object') { + throw new Error("Method: addTo method requires an object parameter"); + } + + obj[name] = method; + }; + }; + ns.Method = Method; +}); +window.jermaine.util.namespace("window.jermaine", function (ns) { + "use strict"; + function Model(specification) { + var that = this, + methods = {}, + attributes = {}, + pattern, + modified = true, + requiredConstructorArgs = [], + optionalConstructorArgs = [], + parents = [], + Method = ns.Method, + Attr = ns.Attr, + AttrList = ns.AttrList, + property, + listProperties, + create, + isImmutable, + initializer = function () {}, + constructor = function () {}, + model = function () { + if (modified) { + create(); + } + return constructor.apply(this, arguments); + }; + + //temporary fix so API stays the same + if (arguments.length > 1) { + specification = arguments[arguments.length-1]; + } + + //handle specification function + if (specification && typeof(specification) === "function") { + model = new Model(); + specification.call(model); + return model; + } else if (specification) { + throw new Error("Model: specification parameter must be a function"); + } + + /********** BEGIN PRIVATE METHODS ****************/ + /* private method that abstracts hasA/hasMany */ + var hasAProperty = function (type, name) { + var Property = type==="Attr"?Attr:AttrList, + methodName = type==="Attr"?"hasA":"hasMany", + attribute; + + modified = true; + + if (typeof(name) === 'string') { + attribute = new Property(name); + attributes[name] = attribute; + return attribute; + } else { + throw new Error("Model: " + methodName + " parameter must be a string"); + } + }; + + /* private method that abstracts attribute/method */ + property = function (type, name) { + var result; + + if (typeof(name) !== "string") { + throw new Error("Model: expected string argument to " + type + " method, but recieved " + name); + } + + result = type==="attribute" ? attributes[name] : methods[name]; + + if (result === undefined) { + throw new Error("Model: " + type + " " + name + " does not exist!"); + } + + return result; + }; + + /* private method that abstracts attributes/methods */ + listProperties = function (type) { + var i, + list = [], + properties = type==="attributes"?attributes:methods; + + for (i in properties) { + if (properties.hasOwnProperty(i)) { + list.push(i); + } + } + + return list; + }; + + /* private function that creates the constructor */ + create = function (name) { + var that = this, + i, j, + err; + + //validate the model first + model.validate(); + + constructor = function () { + var i, + attribute, + addProperties; + + + if (!(this instanceof model)) { + throw new Error("Model: instances must be created using the new operator"); + } + + //utility function that adds methods and attributes + addProperties = function (obj, type) { + var properties = type==="attributes" ? attributes : methods, + i; + for (i in properties) { + if (properties.hasOwnProperty(i)) { + //if the object is immutable, all attributes should be immutable + if(properties === attributes && isImmutable) { + properties[i].isImmutable(); + } + properties[i].addTo(obj); + } + } + }; + + + //add attributes + addProperties(this, "attributes"); + addProperties(this, "methods"); + + this.toString = pattern; + + //use constructor args to build object + if(arguments.length > 0) { + if (arguments.length < requiredConstructorArgs.length) { + //construct and throw error + err = "Constructor requires "; + for(i = 0; i < requiredConstructorArgs.length; ++i) { + err += requiredConstructorArgs[i]; + err += i===requiredConstructorArgs.length-1?"":", "; + } + err += " to be specified"; + throw new Error(err); + } if (arguments.length > requiredConstructorArgs.length + optionalConstructorArgs.length) { + throw new Error("Too many arguments to constructor. Expected " + requiredConstructorArgs.length + " required arguments and " + + optionalConstructorArgs.length + " optional arguments"); + } + else { + for (i = 0; i < arguments.length; ++i) { + attribute = i < requiredConstructorArgs.length? + requiredConstructorArgs[i]: + optionalConstructorArgs[i-requiredConstructorArgs.length]; + + + if (model.attribute(attribute) instanceof AttrList) { + //make sure that arguments[i] is an array + if (Object.prototype.toString.call(arguments[i]) !== "[object Array]") { + throw new Error("Model: Constructor requires 'names' attribute to be set with an Array"); + } else { + //iterate over the array adding the elements + for (j = 0; j < arguments[i].length; ++j) { + this[attribute]().add(arguments[i][j]); + } + } + } else { + //go ahead and set it like normal + this[attribute](arguments[i]); + } + } + } + } + initializer.call(this); + }; + return constructor; + }; + /*********** END PRIVATE METHODS **************/ + + + /*********** BEGIN PUBLIC API *****************/ + model.hasA = function (attr) { + return hasAProperty("Attr", attr); + }; + + model.hasAn = model.hasA; + model.hasSome = model.hasA; + + model.hasMany = function (attrs) { + return hasAProperty("AttrList", attrs); + }; + + model.isA = function (parent) { + var i, + parentAttributes, + parentMethods, + isAModel; + + modified = true; + + //checks to make sure a potentialModel has all attributes of a model + isAModel = function (potentialModel) { + var i, + M = new Model(); + for (i in M) { + if (M.hasOwnProperty(i) && typeof(potentialModel[i]) !== typeof(M[i])) { + return false; + } + } + return true; + }; + + //confirm parent is a model via duck-typing + if (typeof (parent) !== "function" || !isAModel(parent)) { + throw new Error("Model: parameter sent to isA function must be a Model"); + } + + //only allow single inheritance for now + if (parents.length === 0) { + parents.push(parent); + } else { + throw new Error("Model: Model only supports single inheritance at this time"); + } + + //add attributes and methods to current model + parentAttributes = parents[0].attributes(); + for (i = 0; i < parentAttributes.length; ++i) { + if (attributes[parentAttributes[i]] === undefined) { + attributes[parentAttributes[i]] = parents[0].attribute(parentAttributes[i]).clone(); + //subclass attributes are mutable by default + attributes[parentAttributes[i]].isMutable(); + } + } + + parentMethods = parents[0].methods(); + for (i = 0; i < parentMethods.length; ++i) { + if (methods[parentMethods[i]] === undefined) { + methods[parentMethods[i]] = parents[0].method(parentMethods[i]); + } + } + + for (i = 0; i < parents.length; i++) { + model.prototype = new parents[i](); + } + }; + + model.isAn = model.isA; + + model.parent = function () { + return parents[0].apply(this, arguments); + }; + + model.attribute = function (attr) { + return property("attribute", attr); + }; + + model.attributes = function () { + return listProperties("attributes"); + }; + + model.method = function (m) { + return property("method", m); + }; + + model.methods = function () { + return listProperties("methods"); + }; + + model.isBuiltWith = function () { + var optionalParamFlag = false, + i; + + modified = true; + requiredConstructorArgs = []; + optionalConstructorArgs = []; + + for (i = 0; i < arguments.length; ++i) { + if (typeof(arguments[i]) === "string" && arguments[i].charAt(0) !== '%') { + //in required parms + if (optionalParamFlag) { + //throw error + throw new Error("Model: isBuiltWith requires parameters preceded with a % to be the final parameters before the optional function"); + } else { + //insert into required array + requiredConstructorArgs.push(arguments[i]); + } + } else if(typeof(arguments[i]) === "string" && arguments[i].charAt(0) === '%') { + //in optional parms + optionalParamFlag = true; + //insert into optional array + optionalConstructorArgs.push(arguments[i].slice(1)); + } else if(typeof(arguments[i]) === "function" && i === arguments.length - 1) { + //init function + initializer = arguments[i]; + } else { + throw new Error("Model: isBuiltWith parameters must be strings except for a function as the optional final parameter"); + } + } + }; + + model.isImmutable = function () { + isImmutable = true; + }; + + model.looksLike = function (p) { + modified = true; + pattern = p; + }; + + model.respondsTo = function (methodName, methodBody) { + var m = new Method(methodName, methodBody); + modified = true; + methods[methodName] = m; + }; + + model.validate = function () { + var i, + attributes = this.attributes(), + methods = this.methods(); + + //check to make sure that isBuiltWith has actual attributes + for (i = 0; i < requiredConstructorArgs.length; ++i) { + try { + this.attribute(requiredConstructorArgs[i]); + } catch (e) { + throw new Error(requiredConstructorArgs[i] + ", specified in the isBuiltWith method, is not an attribute"); + } + } + + for (i = 0; i < optionalConstructorArgs.length; ++i) { + try { + this.attribute(optionalConstructorArgs[i]); + } catch (e) { + throw new Error(optionalConstructorArgs[i] + ", specified in the isBuiltWith method, is not an attribute"); + } + } + + //check for method/attribute collisions + for (i = 0; i < attributes.length; i++) { + if (methods.indexOf(attributes[i]) > -1) { + throw new Error("Model: invalid model specification to " + attributes[i] + " being both an attribute and method"); + } + } + + //check to make sure that all attributes are requiredConstructorArgs if the object is immutable + if (isImmutable) { + for (i = 0; i < attributes.length; i++) { + if (requiredConstructorArgs.indexOf(attributes[i]) < 0) { + throw new Error("immutable objects must have all attributes required in a call to isBuiltWith"); + } + } + } + + //set modifiedSinceLastValidation to false + modified = false; + }; + /************** END PUBLIC API ****************/ + + + + //here we are returning our model object + //which is a function with a bunch of methods that + //manipulate how the function behaves + return model; + } + + ns.Model = Model; +}); +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,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(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
    ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); +/** + * ajaxthrottle.js + * + * Usage: + * + * var t = $.ajaxthrottle({ + * numRequestsPerTimePeriod : N, + * timePeriod : P, + * maxConcurrent : M + * }); + * + * t.ajax(args); + * + * This is just like calling $.ajax(args), except that requests are throttled + * so that no more than N are initiated in any time period of P milliseconds, + * and no more than M concurrent (outstanding at the same time) requests are allowed. + * If N or P is 0, there is no time period based constraint, and if M is 0, there + * is no constraint on the number of concurrent requests. + * + * Mark Phillips + * Thu Dec 20 11:04:19 2012 + */ +(function($) { + $.ajaxthrottle = function(options) { + + var timeout, + + settings = $.extend({ + numRequestsPerTimePeriod : 0, + timePeriod : 0, + maxConcurrent : 1 + }, options), + + time = function() { + return (new Date()).getTime(); + }, + + // Array of outstanding requests; these are requests that have + // been initiated with a call to $.ajax() but that have not + // completed yet. Each entry in this array is an object of the form + // { + // arguments: the original arguments list passed to .ajax() + // time: the time this request was passed to $.ajax() + // deferred: the jQuery deferred object for this request + // } + outstanding_reqs = [], + + // Array of initiated requests; each entry in this array + // is an object just like the ones in the outstanding_reqs + // array above, but this array keeps track of all + // requests, regardless of whether they have completed. + // This list is used to keep track of how many requests + // have been initiated in settings.timePeriod. Requests + // that are older than settings.timePeriod milliseconds + // get removed from this list when it is purged. + initiated_reqs = [], + + // Array of requests waiting to be initiated + waiting_reqs = [], + + // Purge the initiated reqs list so that it doesn't contain any + // reqs from more than settings.timePeriod ms ago. Return the + // amount of time that needs to be waited until the oldest remaining + // (after purging) req in the list will be settings.timePeriod ms old. + // Do all of this relative to the passed in 'now' value. + purge_initiated_reqs = function(now) { + if (settings.timePeriod >= 0) { + while ((initiated_reqs.length > 0) + && + (initiated_reqs[0].time + settings.timePeriod - now <= 0)) { + initiated_reqs.shift(); + } + if (initiated_reqs.length > 0) { + return initiated_reqs[0].time + settings.timePeriod - now; + } + } + return 0; + }, + + // remove a req from the outstanding_reqs list + remove_outstanding_req = function(obj) { + $.each(outstanding_reqs, function(i) { + if (outstanding_reqs[i] === obj) { + outstanding_reqs.splice(i,1); + return false; + } + return true; + }); + }, + + // Initiate the next request on the waiting list, unless we need to wait + // till some time has passed or some outstanding requests have completed. + process_waiting = function() { + var now = time(), + delay, req, deferred; + + if (waiting_reqs.length <= 0) { + return; + } + + delay = purge_initiated_reqs(now); + + // If we have a timePeriod constraint, and the max number of allowed + // requests have gone out in that time period, arrange to wait for + // 'delay' ms + if ((settings.numRequestsPerTimePeriod > 0) && (settings.timePeriod > 0) + && + (delay > 0) + && + (initiated_reqs.length >= settings.numRequestsPerTimePeriod)) { + // clear any existing timeout first, because this one will + // require waiting till after it would finish anyway + if (timeout !== undefined) { + clearTimeout(timeout); + } + timeout = setTimeout(function() { + timeout = undefined; + process_waiting(); + }, delay); + return; + } + + // If the max number of allowed requests is outstanding, do nothing; + // process_waiting() will get called again when a request completes. + if ((settings.maxConcurrent > 0) + && + (outstanding_reqs.length >= settings.maxConcurrent)) { + return; + } + + // If we make it to here, then it's OK to initiate the next + // request in the waiting list + req = waiting_reqs.shift(); + req.time = time(); + initiated_reqs.push(req); + outstanding_reqs.push(req); + $.ajax.apply($,req.arguments).done(function() { + req.deferred.resolve.apply(req.deferred, arguments); + }).fail(function() { + req.deferred.reject.apply(req.deferred, arguments); + }).always(function() { + remove_outstanding_req(req); + process_waiting(); + }); + + } + ; + + return { + ajax : function() { + var deferred = $.Deferred(); + waiting_reqs.push({ arguments : arguments, deferred : deferred }); + process_waiting(); + return deferred.promise(); + } + }; + }; +}(jQuery)); +(function ($) { + var defaults = { + fullscreen : false, + scale : false, + defaultEventHandling : true, + preopen : function () {}, + postopen : function () {}, + preclose : function () {}, + postclose : function () {}, + preresize : function () {}, + postresize : function () {} + }; + + var methods = { + open : function () { + var clone = this.clone(true), + data = this.data("lightbox"), + w, h; + + data.contents = clone; + data.preopen.call(this); + clone = data.contents; // data.contents might have been altered by data.preopen + var cloneData = clone.data("lightbox"); + + data.overlay = $("
    ") + .css({ + "position" : "fixed", + "left" : "0px", + "top" : "0px", + "height" : "100%", + "min-height" : "100%", + "width" : "100%", + "z-index" : "9999", + "background-color" : "black", + "opacity" : "0.5" + }) + .appendTo("body"); + + data.box = $("
    ") + .css({ + "position" : "fixed", + "z-index" : "9999" + }) + .appendTo("body"); + + + data.box.append(clone); + + if (data.fullscreen === true) { + w = window.innerWidth; + h = window.innerHeight; + } else { + w = clone.width(); + h = clone.height(); + if (data.scale === true) { + var r = computeRatio(w, h); + w = parseInt(w * r, 10); + h = parseInt(h * r, 10); + } + } + + scaleElement(data.box, w, h); + positionElement(data.box, w, h); + + scaleElement(clone, w, h); + positionElement(clone, w, h); + clone.css("position", "fixed") + .css("z-index", 9999); + + data.box.append( + $("\"close\"/") + .css({ + "position" : "absolute", + "right" : "-9px", + "top" : "-8px", + "width" : "44px", + "height" : "44px", + "z-index" : "10000" + }) + .click(function () { + clone.lightbox("close"); + }) + ); + + cloneData.contentWidth = w; + cloneData.contentHeight = h; + cloneData.opened = true; + cloneData.resizeHandler = function () { + clone.lightbox("resize"); + }; + + $(window).on("resize", cloneData.resizeHandler); + $(window).on("orientationchange", cloneData.resizeHandler); + + data.postopen.call(this); + + return this; + }, + + close : function () { + var data = this.data("lightbox"); + + data.preclose.call(this); + + $(window).off("resize", data.resizeHandler); + $(window).off("orientationchange", data.resizeHandler); + + data.opened = false; + data.overlay.remove(); + data.overlay = undefined; + + data.postclose.call(this); + + data.box.remove(); + return this; + }, + + resize : function () { + var data = this.data("lightbox"), + w, h; + + data.preresize.call(this); + + if (data.fullscreen === true) { + w = window.innerWidth; + h = window.innerHeight; + } else { + w = data.contentWidth; + h = data.contentHeight; + if (data.scale === true) { + var r = computeRatio(w, h); + w = parseInt(w * r, 10); + h = parseInt(h * r, 10); + } + } + + scaleElement(data.box, w, h); + positionElement(data.box, w, h); + + scaleElement(data.contents, w, h); + positionElement(data.contents, w, h); + + data.contentWidth = w; + data.contentHeight = h; + + data.postresize.call(this); + + return this; + }, + + toggle : function () { + if (this.data("lightbox").opened === true) { + this.lightbox("close"); + } else { + this.lightbox("open"); + } + return this; + }, + + init : function (options) { + return this.each(function() { + var $this = $(this), + data = $this.data("lightbox"); + if ( !data ) { + var settings = $.extend(defaults, options, { opened : false }); + $this.data("lightbox", settings); + } + + if ($this.data("lightbox").defaultEventHandling === true) { + // modified from ecmanaut's answer at + // http://stackoverflow.com/questions/3103842/safari-ipad-prevent-zoom-on-double-tap + $this.on("touchstart", function (e) { + var t2 = e.timeStamp, + t1 = $this.data("lightbox").lastTouch || t2, + dt = t2 - t1, + fingers = e.originalEvent.touches.length; + $this.data("lightbox").lastTouch = t2; + if (!dt || dt > 500 || fingers > 1) { + return; + } + e.preventDefault(); // double tap - prevent the zoom + $this.lightbox("toggle"); + }); + } + + return this; + }); + } + }; + + $.fn.lightbox = function (method) { + if ( methods[method] ) { + return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === "object" || !method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( "Method " + method + " does not exist on jQuery.lightbox" ); + return null; + } + }; + + var computeRatio = function (originalWidth, originalHeight) { + var wr = (originalWidth > 0) ? window.innerWidth / originalWidth : 1, + hr = (originalHeight > 0) ? window.innerHeight / originalHeight : 1, + r = Math.min(wr, hr); + return r; + }; + + var scaleElement = function (elem, width, height) { + elem.css("width", width + "px") + .css("height", height + "px"); + }; + + var positionElement = function (elem, width, height) { + var left = (window.innerWidth - width) / 2, + top = (window.innerHeight - height) / 2; + if (left < 0) { + left = 0; + } + if (top < 0) { + top = 0; + } + + elem.css("left", left + "px") + .css("top", top + "px"); + }; + +}(jQuery)); +/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) + * Licensed under the MIT License (LICENSE.txt). + * + * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. + * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. + * Thanks to: Seamus Leahy for adding deltaX and deltaY + * + * Version: 3.0.6 + * + * Requires: 1.2.2+ + */ + +(function($) { + +var types = ['DOMMouseScroll', 'mousewheel']; + +if ($.event.fixHooks) { + for ( var i=types.length; i; ) { + $.event.fixHooks[ types[--i] ] = $.event.mouseHooks; + } +} + +$.event.special.mousewheel = { + setup: function() { + if ( this.addEventListener ) { + for ( var i=types.length; i; ) { + this.addEventListener( types[--i], handler, false ); + } + } else { + this.onmousewheel = handler; + } + }, + + teardown: function() { + if ( this.removeEventListener ) { + for ( var i=types.length; i; ) { + this.removeEventListener( types[--i], handler, false ); + } + } else { + this.onmousewheel = null; + } + } +}; + +$.fn.extend({ + mousewheel: function(fn) { + return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); + }, + + unmousewheel: function(fn) { + return this.unbind("mousewheel", fn); + } +}); + + +function handler(event) { + var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; + event = $.event.fix(orgEvent); + event.type = "mousewheel"; + + // Old school scrollwheel delta + if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; } + if ( orgEvent.detail ) { delta = -orgEvent.detail/3; } + + // New school multidimensional scroll (touchpads) deltas + deltaY = delta; + + // Gecko + if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { + deltaY = 0; + deltaX = -1*delta; + } + + // Webkit + if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; } + if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; } + + // Add event and delta to the front of the arguments + args.unshift(event, delta, deltaX, deltaY); + + return ($.event.dispatch || $.event.handle).apply(this, args); +} + +})(jQuery); +window.jermaine.util.namespace("window.multigraph", function (ns) { + "use strict"; + window.multigraph.jQuery = jQuery.noConflict(); +}); +(function ($) { + "use strict"; + + var methods = { + on : function(on) { + if (on === undefined) { + return $(this).data('busy_spinner').on; + } else { + return this.each(function() { + if (on) { + $(this).data('busy_spinner').on = true; + $(this).data('busy_spinner').level = 1; + $(this).show(); + } else { + $(this).data('busy_spinner').on = false; + $(this).data('busy_spinner').level = 0; + $(this).hide(); + } + return this; + }); + } + }, + + level : function(delta) { + if (delta === undefined) { + return $(this).data('busy_spinner').level; + } else { + return this.each(function() { + if ($(this).data('busy_spinner').level + delta >= 0) { + $(this).data('busy_spinner').level = $(this).data('busy_spinner').level + delta; + if ($(this).data('busy_spinner').level === 1) { + $(this).busy_spinner('on', true); + } else if ($(this).data('busy_spinner').level === 0) { + $(this).busy_spinner('on', false); + } + } + return this; + }); + } + }, + + init : function(options) { + return this.each(function() { + var $this = $(this), + data = $this.data('busy_spinner'), + settings = $.extend({ + on : false + }, options); + if ( ! data ) { + $this.data('busy_spinner', { + on : settings.on, + level : 0 + }); + if (settings.on) { + $(this).show(); + } else { + $(this).hide(); + } + $(this).css({ + width : 32, + height : 32 + }).append($('ajax loading')); + } + + return this; + }); + } + }; + + $.fn.busy_spinner = function( method ) { + if ( methods[method] ) { + return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.busy_spinner' ); + return null; + } + }; + +}(jQuery)); +(function ($) { + "use strict"; + + var errorDisplayHtml = ( + '' + + '
    ' + + '' + + '' + + '' + + '' + + '' + + '
    ' + + '' + ); + + var detailDisplayHtml = ( + '' + + '
    ' + + '' + + '' + + '' + + '' + + '
    ' + ); + + var detailDisplayListHtml = ( + '' + + '
      ' + + '
    ' + ); + + var methods = { + init : function(options) { + return this.each(function() { + var $this = $(this), + data = $this.data('errorDisplay'), + settings = $.extend({ + 'fontColor' : '#ff0000', + 'backgroundColor' : '#ffffff', + 'displayTime' : 1000, + 'indicatorColor' : '#ff0000' + }, options); + + if ( ! data ) { + + $this.append(errorDisplayHtml); + $this.find('.errorDisplay').width($this.width()-6); + + var detailDisplay = $(detailDisplayHtml).appendTo($("body")); + var detailDisplayList = $(detailDisplayListHtml); + + $(detailDisplay).find('.errorDisplayXButton').click(function(event) { + event.preventDefault(); + $(detailDisplay).find('.errorDisplayOptions').hide(); + $(detailDisplay).hide(); + $this.find('.errorDisplayRetriever').css('background-color', settings.indicatorColor).show(); + }); + + $this.data('errorDisplay', { + 'detailDisplay' : detailDisplay, + 'detailDisplayList' : detailDisplayList, + 'fontColor' : settings.fontColor, + 'backgroundColor' : settings.backgroundColor, + 'displayTime' : settings.displayTime, + 'indicatorColor' : settings.indicatorColor + }); + + + $this.find('.errorDisplayXButton').click(function(event) { + event.preventDefault(); + $this.find('.errorDisplayOptions').hide(); + $this.find('.errorDisplay').slideUp(settings.displayTime, function(){ + $this.find('.errorDisplayRetriever').show(); + }); + }); + + + $this.find('.errorDisplayDetailsButton').click(function(event) { + event.preventDefault(); + $this.find('.errorDisplay').off(); //stops mouseleaveevent when details button is clicked + $this.find('.errorDisplay').hide(); + $this.find('.errorDisplayRetriever').hide(); + $(detailDisplay).find('.errorDisplayFullMessageArea').empty().append($(detailDisplayList)); + $(detailDisplay).find('.errorDisplayOptions').show(); + $(detailDisplay).show(); + }); + + } + return this; + }); + }, // init() method + + displayError : function(fullMessage, shortMessage, options) { + return this.each(function() { + var $this = $(this), + data = $this.data('errorDisplay'), + settings = $.extend({ + 'fontColor' : data.fontColor, + 'backgroundColor' : data.backgroundColor, + 'displayTime' : data.displayTime, + 'indicatorColor' : data.indicatorColor + }, options); + $this.find('.errorDisplayRetriever').hide(); + $this.find('.errorDisplayOptions').hide(); + $this.find('.errorDisplayShortMessage').css('color', settings.fontColor); + $this.find('.errorDisplay').css('background-color', settings.backgroundColor); + $this.find('.errorDisplayOptions').css('background-color', settings.backgroundColor); + $this.find('.errorDisplayShortMessage').text(shortMessage); + $this.find('.errorDisplay').show(); + $this.find('.errorDisplayRetriever').css('background-color', settings.indicatorColor); + + if(settings.displayTime != -1){ + $this.find('.errorDisplay').slideUp(settings.displayTime, function(){ + $this.find('.errorDisplayRetriever').show(); + }); + } + + else{ + $this.find('.errorDisplayOptions').show(); + $this.find('.errorDisplay').show(); + } + + $(data.detailDisplayList).append($('
  • '+fullMessage+'
  • ').css('color', settings.fontColor)); + + $this.find('.errorDisplayRetriever').hover(function(event) { + event.preventDefault(); + $this.find('.errorDisplayOptions').hide(); + $this.find('.errorDisplayShortMessage').text(shortMessage).css('color', settings.fontColor); + $this.find('.errorDisplay').slideDown(function(){ + $this.find('.errorDisplayOptions').show(); + $this.find('.errorDisplay').mouseleave(function(event){ + event.preventDefault(); + $this.find('.errorDisplayOptions').hide(); + $this.find('.errorDisplay').slideUp(settings.displayTime, function(){ + $this.find('.errorDisplayRetriever').show(); + }); + }); + }); + $this.find('.errorDisplayRetriever').hide(); + }); + }); + + } // displayError() method + + + }; + + $.fn.errorDisplay = function( method ) { + if ( methods[method] ) { + return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.errorDisplay' ); + return null; + } + }; + +}(jQuery)); +jQuery('head').append(jQuery('')); +if (!window.multigraph) { + window.multigraph = {}; +} + +window.multigraph.util = jermaine.util; +/** +sprintf() for JavaScript 0.7-beta1 +http://www.diveintojavascript.com/projects/javascript-sprintf + +Copyright (c) Alexandru Marasteanu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of sprintf() for JavaScript nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Changelog: +2010.09.06 - 0.7-beta1 + - features: vsprintf, support for named placeholders + - enhancements: format cache, reduced global namespace pollution + +2010.05.22 - 0.6: + - reverted to 0.4 and fixed the bug regarding the sign of the number 0 + Note: + Thanks to Raphael Pigulla (http://www.n3rd.org/) + who warned me about a bug in 0.5, I discovered that the last update was + a regress. I appologize for that. + +2010.05.09 - 0.5: + - bug fix: 0 is now preceeded with a + sign + - bug fix: the sign was not at the right position on padded results (Kamal Abdali) + - switched from GPL to BSD license + +2007.10.21 - 0.4: + - unit test and patch (David Baird) + +2007.09.17 - 0.3: + - bug fix: no longer throws exception on empty paramenters (Hans Pufal) + +2007.09.11 - 0.2: + - feature: added argument swapping + +2007.04.03 - 0.1: + - initial release +**/ + +var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + function str_repeat(input, multiplier) { + for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} + return output.join(''); + } + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw('[sprintf] invalid format string'); + } + } + } + else { + throw('[sprintf] invalid format string'); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw('[sprintf] invalid format string'); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; +})(); + +var vsprintf = function(fmt, argv) { + argv.unshift(fmt); + return sprintf.apply(null, argv); +}; +(function() { + "use strict"; + + var lastTime = 0; + var vendors = ['ms', 'moz', 'webkit', 'o']; + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; + } + + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }; + } + + if (!window.cancelAnimationFrame) { + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; + } +}()); +window.multigraph.util.namespace("window.multigraph.utilityFunctions", function (ns) { + "use strict"; + + ns.getKeys = function (obj) { + var keys = [], + key; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + keys.push(key); + } + } + return keys; + }; + + ns.insertDefaults = function (elem, defaults, attributes) { + var i; + for (i = 0; i < attributes.length; i++) { + if (defaults[attributes[i]] !== undefined && (typeof(defaults[attributes[i]]) !== "object" || defaults[attributes[i]] === null)) { + if (elem.attributes().indexOf(attributes[i]) > -1) { + elem.attribute(attributes[i]).defaultsTo(defaults[attributes[i]]); + } + } + } + return elem; + }; + + ns.getDefaultValuesFromXSD = function () { + + return { + "window": { +// "width": undefined, +// "height": undefined, + "border": 2, + "margin" : function () { return new window.multigraph.math.Insets(/*top*/2, /*left*/2, /*bottom*/2, /*right*/2); }, + "padding": function () { return new window.multigraph.math.Insets(/*top*/5, /*left*/5, /*bottom*/5, /*right*/5); }, + "bordercolor": function () { return new window.multigraph.math.RGBColor.parse("0x000000"); } + }, + "legend": { + "icon" : { + "height": 30, + "width": 40, + "border": 1 + }, + "visible": null, + "base": function () { return new window.multigraph.math.Point(1,1); }, + "anchor": function () { return new window.multigraph.math.Point(1,1); }, + "position": function () { return new window.multigraph.math.Point(0,0); }, + "frame": "plot", + "color": function () { return new window.multigraph.math.RGBColor.parse("0xffffff"); }, + "bordercolor": function () { return new window.multigraph.math.RGBColor.parse("0x000000"); }, + "opacity": 1.0, + "border": 1, + "rows": undefined, + "columns": undefined, + "cornerradius": 0, + "padding": 0 + }, + "background": { + "img": { + "src": undefined, + "anchor": function () { return new window.multigraph.math.Point(-1,-1); }, + "base": function () { return new window.multigraph.math.Point(-1,-1); }, + "position": function () { return new window.multigraph.math.Point(0,0); }, + "frame": "padding" + }, + "color": "0xffffff" + }, + "plotarea": { + "margin" : function () { return new window.multigraph.math.Insets(/*top*/10 , /*left*/38, /*bottom*/35, /*right*/35); }, + "border": 0, + "color" : null, + "bordercolor": function () { return new window.multigraph.math.RGBColor.parse("0xeeeeee"); } + }, + "title": { + "text" : undefined, + "frame" : "padding", + "border" : 0, + "color" : function () { return new window.multigraph.math.RGBColor.parse("0xffffff"); }, + "bordercolor" : function () { return new window.multigraph.math.RGBColor.parse("0x000000"); }, + "opacity" : 1.0, + "padding" : 0, + "cornerradius" : 15, + "anchor" : function () { return new window.multigraph.math.Point(0,1); }, + "base" : function () { return new window.multigraph.math.Point(0,1); }, + "position" : function () { return new window.multigraph.math.Point(0,0); } + }, + "horizontalaxis": { + "title": { + "content": undefined, +// "fontname": "default", +// "fontsize": "12", +// "fontcolor": "0x000000", + "anchor": undefined, + "base" : 0, + "position": undefined, + + "position-horizontal-top" : function () { return new window.multigraph.math.Point(0, 15); }, + "position-horizontal-bottom" : function () { return new window.multigraph.math.Point(0, -18); }, + "position-vertical-right" : function () { return new window.multigraph.math.Point(33, 0); }, + "position-vertical-left" : function () { return new window.multigraph.math.Point(-25, 0); }, + + "anchor-horizontal-top" : function () { return new window.multigraph.math.Point(0, -1); }, + "anchor-horizontal-bottom" : function () { return new window.multigraph.math.Point(0, 1); }, + "anchor-vertical-right" : function () { return new window.multigraph.math.Point(-1, 0); }, + "anchor-vertical-left" : function () { return new window.multigraph.math.Point(1, 0); }, + + "angle": 0 + }, + "labels": { + "label": { + "format": undefined, + // NOTE: the Labeler object's default values for position and anchor should be undefined. + // If those attributes are not specified in the MUGL, the Labeler's + // initializeGeometry() method sets them to one of the context-dependent values + // below. + "position": undefined, + "anchor": undefined, + + "position-horizontal-top" : function () { return new window.multigraph.math.Point(0, 5); }, + "position-horizontal-bottom" : function () { return new window.multigraph.math.Point(0, -5); }, + "position-vertical-right" : function () { return new window.multigraph.math.Point(5, 0); }, + "position-vertical-left" : function () { return new window.multigraph.math.Point(-8, 0); }, + + "anchor-horizontal-top" : function () { return new window.multigraph.math.Point(0, -1); }, + "anchor-horizontal-bottom" : function () { return new window.multigraph.math.Point(0, 1); }, + "anchor-vertical-right" : function () { return new window.multigraph.math.Point(-1, 0); }, + "anchor-vertical-left" : function () { return new window.multigraph.math.Point(1, 0); }, + + "angle": 0.0, + "spacing": undefined, + "densityfactor": 1.0, + "color" : function () { return new window.multigraph.math.RGBColor.parse("0x000000"); }, + "visible" : true +// "fontname": undefined, +// "fontsize": undefined, +// "fontcolor": undefined + }, +// "fontname": "default", +// "fontsize": "12", +// "fontcolor": "0x000000", +// "format": "%1d", +// "visible": "true", + "start-number": function () { return new window.multigraph.core.NumberValue(0); }, + "start-datetime": function () { return new window.multigraph.core.DatetimeValue(0); }, + "angle": 0.0, + "position": function () { return new window.multigraph.math.Point(0,0); }, + "anchor": function () { return new window.multigraph.math.Point(0,0); }, + "color" : function () { return new window.multigraph.math.RGBColor.parse("0x000000"); }, + "visible" : true, + "defaultNumberSpacing": "10000 5000 2000 1000 500 200 100 50 20 10 5 2 1 0.1 0.01 0.001", + "defaultDatetimeSpacing": "1000Y 500Y 200Y 100Y 50Y 20Y 10Y 5Y 2Y 1Y 6M 3M 2M 1M 7D 3D 2D 1D 12H 6H 3H 2H 1H", + "function": undefined, + "densityfactor": undefined + }, + "grid": { + "color": function () { return new window.multigraph.math.RGBColor.parse("0xeeeeee"); }, + "visible": false + }, + "pan": { + "allowed": true, + "min": null, + "max": null + }, + "zoom": { + "allowed": true, + "min": undefined, + "max": undefined, + "anchor": null + }, + "binding": { + "id": undefined, + "min": undefined, + "max": undefined + }, + "id": undefined, + "type": "number", +// "length": 1.0, + "length" : function () { return new window.multigraph.math.Displacement(1,0); }, + "position": function () { return new window.multigraph.math.Point(0,0); }, + "pregap": 0, + "postgap": 0, + "anchor": -1, + "base": function () { return new window.multigraph.math.Point(-1,-1); }, + "min": "auto", + "minoffset": 0, + //"minposition": -1, + "minposition": function () { return new window.multigraph.math.Displacement(-1,0); }, + "max": "auto", + "maxoffset": 0, + //"maxposition": 1, + "maxposition": function () { return new window.multigraph.math.Displacement(1,0); }, + "positionbase": undefined, +// "color": "0x000000", + "color": function () { return new window.multigraph.math.RGBColor(0,0,0); }, + "tickmin": -3, + "tickmax": 3, + "tickcolor": null, + "highlightstyle": "axis", + "linewidth": 1, + "orientation": undefined + }, + "verticalaxis": { + "title": { + "content": undefined, +// "fontname": "default", +// "fontsize": "12", +// "fontcolor": "0x000000", + "anchor": function () { return new window.multigraph.math.Point(0,-20); }, + "position": function () { return new window.multigraph.math.Point(0,1); }, + "angle": "0" + }, + "labels": { + "label": { + "format": undefined, + "start": undefined, + "angle": undefined, + "position": undefined, + "anchor": undefined, + "spacing": undefined, + "densityfactor": undefined +// "fontname": undefined, +// "fontsize": undefined, +// "fontcolor": undefined + }, +// "fontname": "default", +// "fontsize": "12", +// "fontcolor": "0x000000", + "format": "%1d", + "visible": "true", + "start": "0", + "angle": "0.0", + "position": "0 0", + "anchor": "0 0", +// "spacing": "10000 5000 2000 1000 500 200 100 50 20 10 5 2 1 0.1 0.01 0.001", +// "defaultDatetimeSpacing": "1000Y 500Y 200Y 100Y 50Y 20Y 10Y 5Y 2Y 1Y 6M 3M 2M 1M 7D 3D 2D 1D 12H 6H 3H 2H 1H", + "function": undefined, + "densityfactor": undefined + }, + "grid": { +// "color": "0xeeeeee", + "visible": "false" + }, + "pan": { + "allowed": "yes", + "min": undefined, + "max": undefined + }, + "zoom": { + "allowed": "yes", + "min": undefined, + "max": undefined, + "anchor": "none" + }, + "binding": { + "id": undefined, + "min": undefined, + "max": undefined + }, + "id": undefined, + "type": "number", +// "length": "1.0", + "position": "0 0", + "pregap": "0", + "postgap": "0", + "anchor": "-1", + "base": "-1 1", + "min": "auto", + "minoffset": "0", + "minposition": "-1", + "max": "auto", + "maxoffset": "0", + "maxposition": "1", + "positionbase": undefined, +// "color": "0x000000", + "tickmin": "-3", + "tickmax": "3", + "highlightstyle": "axis", + "linewidth": "1", + "orientation": undefined + }, + "plot": { + "legend": { + "visible": true, + "label": undefined + }, + "horizontalaxis": { + "variable": { + "ref": undefined, + "factor": undefined + }, + "constant": { + "value": undefined + }, + "ref": undefined + }, + "verticalaxis": { + "variable": { + "ref": undefined, + "factor": undefined + }, + "constant": { + "value": undefined + }, + "ref": undefined + }, + "filter": { + "option": { + "name": undefined, + "value": undefined + }, + "type": undefined + }, + "renderer":{ + "option": { + "name": undefined, + "value": undefined, + "min": undefined, + "max": undefined + }, + "type": function () { return window.multigraph.core.Renderer.Type.parse("line"); } + }, + "datatips":{ + "variable": { + "format": undefined + }, +// "visible": "false", + "format": undefined, +// "bgcolor": "0xeeeeee", + "bgalpha": "1.0", + "border": 1, +// "bordercolor": "0x000000", + "pad": 2 + } + }, + "throttle": { + "pattern" : "", + "requests" : 0, + "period" : 0, + "concurrent" : 0 + }, + "data": { + "variables": { + "variable": { + "id": undefined, + "column": undefined, + "type": "number", + "missingvalue": undefined, + "missingop": undefined + }, + "missingvalue": "-9000", + "missingop": "eq" + }, + "values": { + "content": undefined + }, + "csv": { + "location": undefined + }, + "service": { + "location": undefined + } + } + }; + + }; +}); +window.multigraph.util.namespace("window.multigraph.utilityFunctions", function (ns) { + "use strict"; + + /** + * The Utility Functions module provides utility functions which correspond to general concepts. + * + * @module multigraph + * @submodule utilityfunctions + * @main utilityfunctions + */ + + /** + * Functions which provide abstractions for the parser. + * + * @class ParsingFunctions + * @for ParsingFunctions + * @static + */ + + /** + * Abstract function for parsing and setting jermaine attributes which do not require + * extremely complicated logic to determine their values. Any attributes which require + * complex logic to determine their proper values should be explicitly set in the parser. + * + * @method parseAttribute + * @param {String} value + * @param {Function} attribute + * @param {Function} preprocessor + * @static + * @return {Boolean} + */ + ns.parseAttribute = function (value, attribute, preprocessor) { + if (value !== undefined) { + attribute(preprocessor(value)); + return true; + } + return false; + }; + + /** + * Parses String attributes. + * + * @method parseString + * @param {String} value + * @static + * @return {String} + */ + ns.parseString = function (value) { + return value; + }; + + /** + * Parses a string argument with a radix of 10 and returns an integer. + * + * @method parseInteger + * @param {String} value + * @static + * @return {Integer} + */ + ns.parseInteger = function (value) { + return parseInt(value, 10); + }; + + /** + * Returns a curried function that parses a value into a DataValue of the specified type. + * + * @method parseDataValue + * @param {String} type + * @static + * @return {Function} + */ + ns.parseDataValue = function (type) { + return function (value) { + return window.multigraph.core.DataValue.parse(type, value); + }; + }; + + /** + * Returns a curried function that parses a value into a DataMeasure of the specified type. + * + * @method parseDataMeasure + * @param {String} type + * @static + * @return {Function} + */ + ns.parseDataMeasure = function (type) { + return function (value) { + return window.multigraph.core.DataMeasure.parse(type, value); + }; + }; + + /** + * Parses the allowed Boolean Strings and returns the appropriate value. If the parameter + * is not one of the allowed values then the parameter is returned as an error might not + * need to be thrown immediately. + * + * @method parseBoolean + * @param {String} param + * @static + * @return {Boolean} + */ + ns.parseBoolean = function (param) { + switch (param.toLowerCase()) { + case "true": + case "yes": + return true; + case "false": + case "no": + return false; + default: + return param; + } + }; + +}); +window.multigraph.util.namespace("window.multigraph.utilityFunctions", function (ns) { + "use strict"; + + ns.validateNumberRange = function (number, lowerBound, upperBound) { + return typeof(number) === "number" && number >= lowerBound && number <= upperBound; + }; + + // This function, from http://javascript.crockford.com/remedial.html, should correctly + // return 'array' for any Array object, including []. + ns.typeOf = function(value) { + var s = typeof value; + if (s === 'object') { + if (value) { + //NOTE: Crockford used "==" ?????!!!!! mbp Fri Sep 28 08:44:34 2012 + //if (Object.prototype.toString.call(value) == '[object Array]') { + if (Object.prototype.toString.call(value) === '[object Array]') { + s = 'array'; + } + } else { + s = 'null'; + } + } + return s; + }; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /* + * DataValue is a POJSO (plain old javascript object) that simply + * serves as an ecapsulation for several generic + * data-value-related constants and functions. There is no actual + * DataValue model that can be instantiated; all data values are + * instances of either the NumberValue or DatetimeValue model. + */ + + var DataValue = {}; + + DataValue.NUMBER = "number"; + DataValue.DATETIME = "datetime"; + DataValue.UNKNOWN = "unknown"; + + /* + * Return a list of the type constants above + */ + DataValue.types = function () { + return [ DataValue.NUMBER, DataValue.DATETIME, DataValue.UNKNOWN ]; + }; + + /* + * Create a new DataValue subtype of a given type by parsing a string + */ + DataValue.parseType = function (string) { + if (string.toLowerCase() === DataValue.NUMBER) { return DataValue.NUMBER; } + if (string.toLowerCase() === DataValue.DATETIME) { return DataValue.DATETIME; } + throw new Error("unknown DataValue type: " + string); + }; + + /* + * This function converts a "type" enum object to a string. In reality, the objects ARE + * the strings, so we just return the object. + */ + DataValue.serializeType = function (type) { + return type; + }; + + /* + * Return true or false depending on whether obj is an instance of a DataValue type + */ + DataValue.isInstance = function (obj) { + return (obj && (typeof(obj.getRealValue) === "function") && (typeof(obj.compareTo) === "function")); + }; + + /* + * Same as DataValue.isInstance, but also allows the null value + */ + DataValue.isInstanceOrNull = function (obj) { + return ((obj===null) || DataValue.isInstance(obj)); + }; + + /* + * Create a new DataValue subtype of a given type from a real value + */ + DataValue.create = function (type, realValue) { + if (type === DataValue.NUMBER) { + return new ns.NumberValue(realValue); + } else if (type === DataValue.DATETIME) { + return new ns.DatetimeValue(realValue); + } + throw new Error("attempt to parse an unknown DataValue type"); + }; + + /* + * Create a new DataValue subtype of a given type by parsing a string + */ + DataValue.parse = function (type, string) { + if (type === DataValue.NUMBER) { + return ns.NumberValue.parse(string); + } else if (type === DataValue.DATETIME) { + return ns.DatetimeValue.parse(string); + } + throw new Error("attempt to parse an unknown DataValue type"); + }; + + /* + * Enum values for comparison operators. These should be lowercase strings --- they're used as + * actual method names below. + */ + DataValue.LT = "lt"; + DataValue.LE = "le"; + DataValue.EQ = "eq"; + DataValue.GE = "ge"; + DataValue.GT = "gt"; + DataValue.NE = "ne"; + + var comparatorFuncs = {}; + comparatorFuncs[DataValue.LT] = function (x) { return this.compareTo(x) < 0; }; + comparatorFuncs[DataValue.LE] = function (x) { return this.compareTo(x) <= 0; }; + comparatorFuncs[DataValue.EQ] = function (x) { return this.compareTo(x) === 0; }; + comparatorFuncs[DataValue.GE] = function (x) { return this.compareTo(x) >= 0; }; + comparatorFuncs[DataValue.GT] = function (x) { return this.compareTo(x) > 0; }; + comparatorFuncs[DataValue.NE] = function (x) { return this.compareTo(x) !== 0; }; + + /* + * Mix the 5 comparator function into another object: + */ + DataValue.mixinComparators = function (obj) { + obj[DataValue.LT] = comparatorFuncs[DataValue.LT]; + obj[DataValue.LE] = comparatorFuncs[DataValue.LE]; + obj[DataValue.EQ] = comparatorFuncs[DataValue.EQ]; + obj[DataValue.GE] = comparatorFuncs[DataValue.GE]; + obj[DataValue.GT] = comparatorFuncs[DataValue.GT]; + obj[DataValue.NE] = comparatorFuncs[DataValue.NE]; + }; + + /* + * The comparators function returns a list of the 5 comparator + * functions, to be used like an enum type. + */ + DataValue.comparators = function () { + return [ DataValue.LT, DataValue.LE, DataValue.EQ, DataValue.GE, DataValue.GT, DataValue.NE ]; + }; + + /* + * Convert a string to a comparator enum object: + */ + DataValue.parseComparator = function (string) { + if (typeof(string) === "string") { + switch (string.toLowerCase()) { + case "lt": return DataValue.LT; + case "le": return DataValue.LE; + case "eq": return DataValue.EQ; + case "ge": return DataValue.GE; + case "gt": return DataValue.GT; + case "ne": return DataValue.NE; + } + } + throw new Error(string + " should be one of 'lt', 'le', 'eq', 'ge', 'gt', 'ne'."); + }; + + ns.DataValue = DataValue; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + var DataMeasure = {}; + /* + * Return true or false depending on whether obj is an instance of a DataMeasure type + */ + DataMeasure.isInstance = function (obj) { + return (obj && (typeof(obj.getRealValue) === "function") && (!obj.compareTo)); + }; + + /* + * Create a new DataMeasure subtype of a given type by parsing a string + */ + DataMeasure.parse = function (type, string) { + if (type === ns.DataValue.NUMBER) { + return ns.NumberMeasure.parse(string); + } else if (type === ns.DataValue.DATETIME) { + return ns.DatetimeMeasure.parse(string); + } + throw new Error("attempt to parse an unknown DataMeasure type"); + }; + + ns.DataMeasure = DataMeasure; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + var DataFormatter = {}; + /* + * Return true or false depending on whether obj is an instance of a DataFormatter type + */ + DataFormatter.isInstance = function (obj) { + return (obj && (typeof(obj.format) === "function") && (typeof(obj.getMaxLength) === "function")); + }; + + /* + * Create a new DataFormatter subtype of a given type + */ + DataFormatter.create = function (type, format) { + if (type === ns.DataValue.NUMBER) { + return new ns.NumberFormatter(format); + } else if (type === ns.DataValue.DATETIME) { + return new ns.DatetimeFormatter(format); + } + throw new Error("attempt to create an unknown DataFormatter type"); + }; + + ns.DataFormatter = DataFormatter; + +}); +window.multigraph.util.namespace("window.multigraph.math", function (ns) { + "use strict"; + + ns.Box = new window.jermaine.Model("Box", function () { + this.hasA("width").which.isA("number"); + this.hasA("height").which.isA("number"); + this.isBuiltWith("width", "height"); + }); + +}); +window.multigraph.util.namespace("window.multigraph.math", function (ns) { + "use strict"; + + /** + * The Math module provides utility models and functions which correspond to mathematical concepts. + * + * @module multigraph + * @submodule math + * @main math + */ + + /** + * A Displacement represents a geometric position along a line + * segment, expressed in terms of two quantities: a relative + * position called `a`, and an absolute offset called `b`. The + * length of the line segment is not known in advance --- the idea + * is that the Displacement object encapsulates a rule for + * determining a location along ANY line segment. The Displacement + * has methods which take the line segment length as an argument + * and return the computed final position. + * + * There are two different position-calcuating methods, + * corresponding to two different interpretations of the relative + * value `a`: + * + * **relative length**: + * `a` is a number between 0 and 1, representing a fraction of + * the total length of the line segment; the relative + * position determined by `a` is the fraction `a` of the + * total length of the segment. + * In this case, the position-calculating method + * `calculateLength(L)` returns the number `a * L + b`, which + * corresponds to moving `a` of the way along the length L, + * then adding `b`: + * + * [--------------------------------X------------] + * |<---- a * L --->|<---- b ------>| + * |<------------------ L -------------------->| + * + * **relative coordinate**: + * `a` is a number between -1 and 1, representing a coordinate + * value in a [-1,1] coordinate system along the line + * segment. + * In this case, the position-calculating method + * `calculateCoordinate(L)` returns the number `(a+1) * L/2 + + * b`. which corresponds to moving to the position + * determined by the `a` coordinate, then adding `b`: + * + * [------------------------------------X--------] + * |<--- (a+1) * L/2 --->|<---- b ----->| + * |<------------------ L -------------------->| + * + * @class Displacement + * @for Displacement + * @constructor + * @param {Number} a + * @param {Integer} b (OPTIONAL) + */ + ns.Displacement = new window.jermaine.Model("Displacement", function () { + + this.hasA("a").which.validatesWith(function (a) { + return window.multigraph.utilityFunctions.validateNumberRange(a, -1.0, 1.0); + }); + this.hasA("b").which.isA("integer").and.defaultsTo(0); + this.isBuiltWith("a", "%b"); + + this.respondsTo("calculateLength", function (totalLength) { + return this.a() * totalLength + this.b(); + }); + + this.respondsTo("calculateCoordinate", function (totalLength) { + return (this.a() + 1) * totalLength/2.0 + this.b(); + }); + + }); + + ns.Displacement.regExp = /^([\+\-]?[0-9\.]+)([+\-])([0-9\.+\-]+)$/; + + /** + * Parses a string into a Displacement. The string should be of one of the following forms: + * + * "A+B" ==> a=A b=B + * "A-B" ==> a=A b=-B + * "A" ==> a=A b=0 + * "+A" ==> a=A b=0 + * "-A" ==> a=-A b=0 + * + * @method parse + * @param {String} string + * @static + * @author jrfrimme + */ + ns.Displacement.parse = function (string) { + var ar = ns.Displacement.regExp.exec(string), + d, + a, + b, + sign; + if (string === undefined) { + d = new ns.Displacement(1); + } else if (ar !== null) { + a = parseFloat(ar[1]); + b = parseFloat(ar[3]); + switch (ar[2]) { + case "+": + sign = 1; + break; + case "-": + sign = -1; + break; + default: + sign = 0; + break; + } + /* + if (isNaN(a) || sign == 0 || isNaN(b)) { + throw new ParseError('parse error'); + } + */ + d = new ns.Displacement(a, sign * b); + } else { + a = parseFloat(string); + /*n + if (isNaN(a)) { + throw new ParseError('parse error'); + } + */ + d = new ns.Displacement(a); + } + return d; + }; +}); +window.multigraph.util.namespace("window.multigraph.math", function (ns) { + "use strict"; + + var Enum = function (name) { + + var instances = {}; + + var Enum = function (key) { + if (instances[key] !== undefined) { + throw new Error("attempt to redefine "+name+" Enum with key '"+key+"'"); + } + this.enumType = name; + this.key = key; + instances[key] = this; + }; + + Enum.parse = function (key) { + return instances[key]; + }; + + Enum.prototype.toString = function () { + return this.key; + }; + + Enum.isInstance = function (obj) { + return (obj !== undefined && obj !== null && obj.enumType === name); + }; + + return Enum; + }; + + ns.Enum = Enum; +}); +window.multigraph.util.namespace("window.multigraph.math", function (ns) { + "use strict"; + + ns.Insets = new window.jermaine.Model("Insets", function () { + this.hasA("top").which.isA("number"); + this.hasA("left").which.isA("number"); + this.hasA("bottom").which.isA("number"); + this.hasA("right").which.isA("number"); + this.respondsTo("set", function (top, left, bottom, right) { + this.top(top); + this.left(left); + this.bottom(bottom); + this.right(right); + }); + this.isBuiltWith("top", "left", "bottom", "right"); + }); + +}); +window.multigraph.util.namespace("window.multigraph.math", function (ns) { + "use strict"; + + ns.Point = new window.jermaine.Model("Point", function () { + this.hasA("x").which.isA("number"); + this.hasA("y").which.isA("number"); + this.isBuiltWith("x", "y"); + this.respondsTo("eq", function (p) { + return ((this.x()===p.x()) && (this.y()===p.y())); + }); + }); + + ns.Point.regExp = /^\s*([0-9\-\+\.eE]+)(,|\s+|\s*,\s+|\s+,\s*)([0-9\-\+\.eE]+)\s*$/; + + ns.Point.parse = function (string) { + var ar = ns.Point.regExp.exec(string), + p; + // ar[1] is x value + // ar[2] is separator between x and y + // ar[3] is y value + + if (!ar || (ar.length !== 4)) { + throw new Error("cannot parse string '"+string+"' as a Point"); + } + return new ns.Point(parseFloat(ar[1]), parseFloat(ar[3])); + }; +}); +window.multigraph.util.namespace("window.multigraph.math", function (ns) { + "use strict"; + + ns.RGBColor = new window.jermaine.Model("RGBColor", function () { + + this.hasA("r").which.validatesWith(function (r) { + return window.multigraph.utilityFunctions.validateNumberRange(r, 0, 1.0); + }); + this.hasA("g").which.validatesWith(function (g) { + return window.multigraph.utilityFunctions.validateNumberRange(g, 0, 1.0); + }); + this.hasA("b").which.validatesWith(function (b) { + return window.multigraph.utilityFunctions.validateNumberRange(b, 0, 1.0); + }); + + var numberToHex = function (number) { + number = parseInt(number * 255, 10).toString(16); + if (number.length === 1) { + number = "0" + number; + } + return number; + }; + + this.respondsTo("getHexString", function (prefix) { + if (!prefix) { + prefix = "0x"; + } + return prefix + numberToHex(this.r()) + numberToHex(this.g()) + numberToHex(this.b()); + }); + + this.respondsTo("toRGBA", function (alpha) { + if (alpha === undefined) { + alpha = 1.0; + } + if (typeof(alpha) !== "number") { + throw new Error("RGBColor.toRGBA: The argument, if present, must be a number"); + } + return "rgba(" + (255*this.r()) + ", " + (255*this.g()) + ", " + (255*this.b()) + ", " + alpha + ")"; + }); + + this.respondsTo("eq", function (color) { + return ((this.r()===color.r()) && (this.g()===color.g()) && (this.b()===color.b())); + }); + + this.isBuiltWith("r", "g", "b"); + + }); + + + /* + * To remove support for deprecated color names, remove the following function, + * and find all references to it elsewhere in the source code, and remove them, + * along with accompanying code that generates warning message. Also remove + * support for these 9 color names from RGBColor.parse below. + */ + ns.RGBColor.colorNameIsDeprecated = function (colorName) { + switch (colorName) { + case "grey": return "0xeeeeee"; + case "skyblue": return "0x87ceeb"; + case "khaki": return "0xf0e68c"; + case "orange": return "0xffa500"; + case "salmon": return "0xfa8072"; + case "olive": return "0x9acd32"; + case "sienna": return "0xa0522d"; + case "pink": return "0xffb5c5"; + case "violet": return "0xee82ee"; + } + return false; + }; + + ns.RGBColor.parse = function (input) { + var red, + green, + blue, + grey, + parsedInput, + colorObj; + + if (input === undefined) { + return undefined; + } else if (typeof(input) === "string") { + parsedInput = input.toLowerCase(); + + switch (parsedInput) { + case "black": + red = 0; + green = 0; + blue = 0; + break; + case "red": + red = 1; + green = 0; + blue = 0; + break; + case "green": + red = 0; + green = 1; + blue = 0; + break; + case "blue": + red = 0; + green = 0; + blue = 1; + break; + case "yellow": + red = 1; + green = 1; + blue = 0; + break; + case "magenta": + red = 1; + green = 0; + blue = 1; + break; + case "cyan": + red = 0; + green = 1; + blue = 1; + break; + case "white": + red = 1; + green = 1; + blue = 1; + break; + case "grey": + grey = parseInt("ee", 16) / 255; + red = grey; + green = grey; + blue = grey; + break; + case "skyblue": + red = parseInt("87", 16) / 255; + green = parseInt("ce", 16) / 255; + blue = parseInt("eb", 16) / 255; + break; + case "khaki": + red = parseInt("f0", 16) / 255; + green = parseInt("e6", 16) / 255; + blue = parseInt("8c", 16) / 255; + break; + case "orange": + red = parseInt("ff", 16) / 255; + green = parseInt("a5", 16) / 255; + blue = parseInt("00", 16) / 255; + break; + case "salmon": + red = parseInt("fa", 16) / 255; + green = parseInt("80", 16) / 255; + blue = parseInt("72", 16) / 255; + break; + case "olive": + red = parseInt("9a", 16) / 255; + green = parseInt("cd", 16) / 255; + blue = parseInt("32", 16) / 255; + break; + case "sienna": + red = parseInt("a0", 16) / 255; + green = parseInt("52", 16) / 255; + blue = parseInt("2d", 16) / 255; + break; + case "pink": + red = parseInt("ff", 16) / 255; + green = parseInt("b5", 16) / 255; + blue = parseInt("c5", 16) / 255; + break; + case "violet": + red = parseInt("ee", 16) / 255; + green = parseInt("82", 16) / 255; + blue = parseInt("ee", 16) / 255; + break; + default: + parsedInput = parsedInput.replace(/(0(x|X)|#)/, ""); + if (parsedInput.search(new RegExp(/([^0-9a-f])/)) !== -1) { + throw new Error("'" + input + "' is not a valid color"); + } + + if (parsedInput.length === 6) { + red = parseInt(parsedInput.substring(0,2), 16) / 255; + green = parseInt(parsedInput.substring(2,4), 16) / 255; + blue = parseInt(parsedInput.substring(4,6), 16) / 255; + } else if (parsedInput.length === 3) { + red = parseInt(parsedInput.charAt(0), 16) / 15; + green = parseInt(parsedInput.charAt(1), 16) / 15; + blue = parseInt(parsedInput.charAt(2), 16) / 15; + } else { + throw new Error("'" + input + "' is not a valid color"); + } + break; + } + colorObj = new ns.RGBColor(red, green, blue); + return colorObj; + } + throw new Error("'" + input + "' is not a valid color"); + }; +}); +window.multigraph.util.namespace("window.multigraph.math", function (ns) { + "use strict"; + + ns.util = { + "interp": function (x, x0, x1, y0, y1) { + // return the 'y' coordinate of the point on the line segment + // connecting the two points (x0,y0) and (x1,y1) whose 'x' + // coordinate is x + return y0 + ((y1 - y0) * (x - x0)) / (x1 - x0); + }, + "safe_interp": function (x, x0, x1, y0, y1) { + // same as "interp", but if the line is vertical (x0 === x1), return + // the average of the two y values, rather than NaN + if (x0 === x1) { return (y0 + y1) / 2; } + return ns.util.interp(x, x0, x1, y0, y1); + }, + "l2dist" : function (x1, y1, x2, y2) { + var dx = x1 - x2; + var dy = y1 - y2; + return Math.sqrt(dx*dx + dy*dy); + } + }; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var rendererList, + Renderer, + RendererOption, + utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot.renderer), + Type = new window.multigraph.math.Enum("RendererType"); + + Renderer = new window.jermaine.Model("Renderer", function () { + this.hasA("type").which.validatesWith(Type.isInstance); + this.hasA("plot").which.validatesWith(function (plot) { + return plot instanceof ns.Plot; + }); + this.hasA("numberOfVariables").which.isA("number"); + + this.respondsTo("setUpMissing", function () { + // A call to this method results in the addition (or replacement) of a method called "isMissing()" + // that can be used to test whether a value meets the "missing" criteria of one of this renderer's + // plot's data columns. The point of having this "setUpMissing()" method create the "isMissing()" + // method, rather than just coding the "isMissing()" method directly here, is so that we can capture + // a pointer to the plot's data object via a closure, for faster access, rather than coding + // this.plot().data() in "isMissing()", which adds the overhead of 2 getter calls to each invocation. + // + // NOTE: This is awkward. What we really want is for this stuff to happen automatically when + // the renderer's "plot" attribute is set. Can Jermaine be modified to allow us to write + // a custom setter, so that we can execute this code automatically when the render's "plot" + // attribute is set ??? + var plot = this.plot(), + data; + if (!plot) { + console.log("Warning: renderer.setUpMissing() called for renderer that has no plot ref"); + // this should really eventually throw an error + return; + } + + // for ConstantPlot, create function that always returns false, since it has no data + if (plot instanceof ns.ConstantPlot) { + this.isMissing = function (p) { + return false; + }; + return; + } + + if (!plot.data()) { + // this should eventually throw an error + console.log("Warning: renderer.setUpMissing() called for renderer whose plot has no data ref"); + return; + } + data = plot.data(); + this.isMissing = function (p) { + var i; + for (i = 1; i < p.length; ++i) { + if (data.isMissing(p[i], i)) { + return true; + } + } + return false; + }; + }); + + this.isBuiltWith("type"); + + utilityFunctions.insertDefaults(this, defaultValues.plot.renderer, attributes); + + this.respondsTo("transformPoint", function (input) { + var output = [], + haxis = this.plot().horizontalaxis(), + vaxis = this.plot().verticalaxis(), + i; + + output[0] = haxis.dataValueToAxisValue(input[0]); + for (i = 1; i < input.length; ++i) { + output[i] = vaxis.dataValueToAxisValue(input[i]); + } + return output; + }); + + var equalOrUndefined = function (a, b) { + return ((a===b) || ((a===undefined) && (b===undefined))); + }; + + this.respondsTo("setOption", function (name, value, min, max) { + var rendererOpt, + rendererOpts, + i; + if (!this.optionsMetadata[name]) { + throw new Error("attempt to set unknown renderer option '"+name+"'"); + } + rendererOpts = this.options()[name](); + for (i = 0; i < rendererOpts.size(); ++i) { + if (equalOrUndefined(rendererOpts.at(i).min(), min) && + equalOrUndefined(rendererOpts.at(i).max(), max)) { + rendererOpts.at(i).value(value); + return; + } + } + // If we get this far, it means we didn't find an existing option in the list with matching min/max + // settings, so we create a new one and append it to the end of the list: + rendererOpt = new (this.optionsMetadata[name].type)(); + rendererOpt.value(value); + rendererOpt.min(min); + rendererOpt.max(max); + rendererOpts.add(rendererOpt); + }); + + this.respondsTo("setOptionFromString", function (name, stringValue, stringMin, stringMax) { + var plot = this.plot(), + type = this.type(); + + // + // Two blocks of code below provides support for the deprecated "dotsize" and "dotcolor" + // options, which have been replaced by "pointsize" and "pointcolor". Delete these blocks + // when removing support for this. + // + + // + // First block in support of deprecated dotsize/dotcolor options: + // + var warning = undefined; + if (name === "dotsize") { + name = "pointsize"; + warning = new ns.Warning('deprecated "dotsize" option used for "' + type + '" renderer; use "pointsize" instead'); + } else if (name === "dotcolor") { + name = "pointcolor"; + warning = new ns.Warning('deprecated "dotcolor" option used for "' + type + '" renderer; use "pointcolor" instead'); + } + // + // End of first block in support of deprecated dotsize/dotcolor options + // + + var rendererOpt; + if (!this.optionsMetadata[name]) { + // If this renderer has no option named "name", bail out immediately. This should eventually + // throw an error, but for now we just quietly ignore it, to eliminate error conditions coming + // from unimplemented options. + //console.log("WARNING: renderer has no option named '" + name + "'"); + throw new ns.Warning('"' + type + '"' + ' renderer has no option named "' + name + '"'); + } + rendererOpt = new (this.optionsMetadata[name].type)(); + rendererOpt.parseValue(stringValue, this); + if (plot && plot.verticalaxis()) { + if (stringMin !== undefined) { + rendererOpt.min( ns.DataValue.parse( plot.verticalaxis().type(), stringMin )); + } + if (stringMax !== undefined) { + rendererOpt.max( ns.DataValue.parse( plot.verticalaxis().type(), stringMax )); + } + } + this.setOption(name, rendererOpt.value(), rendererOpt.min(), rendererOpt.max()); + + // + // Second block in support of deprecated dotsize/dotcolor options: + // + if (warning) { + throw warning; + } + // + // End of second block in support of deprecated dotsize/dotcolor options: + // + }); + + + this.respondsTo("getOptionValue", function (optionName, /*optional:*/value) { + var i, + options, + optionList; + + options = this.options(); + if (typeof(options[optionName]) !== "function") { + throw new Error('unknown option "'+optionName+'"'); + } + optionList = options[optionName](); + if (!optionList) { + throw new Error('unknown option "'+optionName+'"'); + } + //NOTE: options are stored in reverse order; default one is always in the '0' position. + // Search through them starting at the END of the list, going backwards! + for (i = optionList.size()-1; i >= 0; --i) { + var option = optionList.at(i); + if (((option.min()===undefined) || (value===undefined) || option.min().le(value)) && + ((option.max()===undefined) || (value===undefined) || option.max().gt(value))) { + return option.value(); + } + } + + }); + + // method must be overridden by subclass: + this.respondsTo("begin", function () { + }); + // method must be overridden by subclass: + this.respondsTo("dataPoint", function (point) { + }); + // method must be overridden by subclass: + this.respondsTo("end", function () { + }); + + }); + + /* + * Private list of known renderers. This list is populated from within individual + * renderer submodel implementations by calls to Renderer.addType. + */ + rendererList = []; + + /* + * Add a renderer submodel to the list of known renders. rendererObj should be + * an object with two properties: + * 'type' : the type of the renderer -- a string, which is the value expected + * for the type attribute of the mugl tag. + * 'model' : the renderer submodel + */ + Renderer.addType = function (rendererObj) { + rendererList.push(rendererObj); + }; + + /* + * Factory method: create an instance of a renderer submodel based on its type (a string). + */ + Renderer.create = function (type) { + var i, + renderer; + for (i = 0; i < rendererList.length; ++i) { + if (rendererList[i].type === type) { + renderer = new (rendererList[i].model)(); + renderer.type(type); + return renderer; + } + } + throw new Error("Renderer.create: '" + type + "' is not a known renderer type"); +// throw new Error('Renderer.create: attempt to create a renderer of unknown type'); + }; + + Renderer.declareOptions = function (renderer, OptionsModelName, options) { + var i, + OptionsModel, + optionsMetadata, + declareOption = function(optionName, optionType) { + // NOTE: this call to hasMany() has to be in a function here, rather than just + // being written inline where it is used below, because we need a closure to + // capture value of options[i].type as optionType, for use in the validation + // function. Otherwise, the validator captures the 'options' array and the + // local loop variable i instead, and evaluates options[i].type when validation + // is performed! + OptionsModel.hasMany(optionName).eachOfWhich.validateWith(function (v) { + return v instanceof optionType; + }); + }; + + OptionsModel = window.jermaine.Model(OptionsModelName, function () {}); + optionsMetadata = {}; + for (i = 0; i < options.length; ++i) { + declareOption(options[i].name, options[i].type); + optionsMetadata[options[i].name] = { + "type" : options[i].type, + "default" : options[i]["default"] + }; + } + renderer.hasA("options").isImmutable().defaultsTo(function () { return new OptionsModel(); }); + renderer.prototype.optionsMetadata = optionsMetadata; + + renderer.isBuiltWith(function () { + // populate options with default values stored in options metadata (which was populated by declareOptions): + var optionsMetadata = this.optionsMetadata, + opt, ropt; + for (opt in optionsMetadata) { + if (optionsMetadata.hasOwnProperty(opt)) { + ropt = new (optionsMetadata[opt].type)(optionsMetadata[opt]["default"]); + this.options()[opt]().add( ropt ); + } + } + }); + + }; + + + Renderer.Option = new window.jermaine.Model("Renderer.Option", function () { + this.hasA("min").which.validatesWith(ns.DataValue.isInstance); + this.hasA("max").which.validatesWith(ns.DataValue.isInstance); + }); + + + Renderer.RGBColorOption = new window.jermaine.Model("Renderer.RGBColorOption", function () { + this.isA(Renderer.Option); + this.hasA("value").which.validatesWith(function (v) { + return v instanceof window.multigraph.math.RGBColor || v === null; + }); + this.isBuiltWith("value"); + this.respondsTo("serializeValue", function () { + return this.value().getHexString(); + }); + this.respondsTo("parseValue", function (string) { + this.value( window.multigraph.math.RGBColor.parse(string) ); + }); + this.respondsTo("valueEq", function (value) { + return this.value().eq(value); + }); + + }); + + Renderer.NumberOption = new window.jermaine.Model("Renderer.NumberOption", function () { + this.isA(Renderer.Option); + this.hasA("value").which.isA("number"); + this.isBuiltWith("value"); + this.respondsTo("serializeValue", function () { + return this.value().toString(); + }); + this.respondsTo("parseValue", function (string) { + this.value( parseFloat(string) ); + }); + this.respondsTo("valueEq", function (value) { + return (this.value()===value); + }); + }); + + Renderer.DataValueOption = new window.jermaine.Model("Renderer.DataValueOption", function () { + this.isA(Renderer.Option); + this.hasA("value").which.validatesWith(function (value) { + return ns.DataValue.isInstance(value) || value === null; + }); + this.isBuiltWith("value"); + this.respondsTo("serializeValue", function () { + return this.value(); + }); + this.respondsTo("valueEq", function (value) { + return this.value().eq(value); + }); + }); + + Renderer.VerticalDataValueOption = new window.jermaine.Model("Renderer.DataValueOption", function () { + this.isA(Renderer.DataValueOption); + this.isBuiltWith("value"); + this.respondsTo("parseValue", function (string, renderer) { + this.value( ns.DataValue.parse(renderer.plot().verticalaxis().type(), string) ); + }); + + }); + + Renderer.HorizontalDataValueOption = new window.jermaine.Model("Renderer.DataValueOption", function () { + this.isA(Renderer.DataValueOption); + this.isBuiltWith("value"); + this.respondsTo("parseValue", function (string, renderer) { + this.value( ns.DataValue.parse(renderer.plot().horizontalaxis().type(), string) ); + }); + + }); + + Renderer.DataMeasureOption = new window.jermaine.Model("Renderer.DataMeasureOption", function () { + this.isA(Renderer.Option); + this.hasA("value").which.validatesWith(function (value) { + return ns.DataMeasure.isInstance(value) || value === null; + }); + this.isBuiltWith("value"); + this.respondsTo("serializeValue", function () { + return this.value(); + }); + this.respondsTo("valueEq", function (value) { + return this.value().eq(value); + }); + }); + + Renderer.VerticalDataMeasureOption = new window.jermaine.Model("Renderer.DataMeasureOption", function () { + this.isA(Renderer.DataMeasureOption); + this.respondsTo("parseValue", function (string, renderer) { + this.value( ns.DataMeasure.parse(renderer.plot().verticalaxis().type(), string) ); + }); + + }); + + Renderer.HorizontalDataMeasureOption = new window.jermaine.Model("Renderer.DataMeasureOption", function () { + this.isA(Renderer.DataMeasureOption); + this.isBuiltWith("value"); + this.respondsTo("parseValue", function (string, renderer) { + this.value( ns.DataMeasure.parse(renderer.plot().horizontalaxis().type(), string) ); + }); + + }); + + Renderer.Type = Type; + + ns.Renderer = Renderer; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + ns.EventEmitter = new window.jermaine.Model(function () { + /** + * EventEmitter is a Jermaine model that supports basic event emitting / + * handling for Jermaine objects. + * + * Events are represented as plain old JavaScript objects with at least + * the following two properties: + * + * **type** + * + * > a string giving the type of the event; this can be any + * arbitrary string. The event type is not restricted to be + * from some predetermined list; applications are free to + * use whatever strings they want for their event types. + * + * **target** + * + * > a reference to the object that emitted the event + * + * Event objects may also contain arbitrary other properties that are specific to + * a particular event type. + * + * Any Jermaine model can declare itself to be an event emitter by saying + * "this.isA(EventEmitter)" in its model declaration. + * + * This adds three methods to the model: + * + * **addListener(eventType, listenerFunction)** + * + * > Registers listenerFunction as a listener for events of type + * eventType (a string). listenerFunction should be a function + * that accepts a single argument which will be a reference to an + * event object as described above. When the object emits the + * event, the listener function will be invoked in the context + * where its "this" keyword refers to the object that emitted the + * event (the event target). If listenerFunction is already + * registered as a listener for eventType, this function does + * nothing --- each listener function can be registered only once. + * + * **removeListener(eventType, listenerFunction)** + * + * > Removes the given listenerFunction from the list of listeners + * for this object for events of type eventType. + * + * **emit(event)** + * + * > Causes the object to emit the given event. The argument can be + * either a string, in which case it is assumed to be an event type + * and is converted to an event object with the given 'type' + * property, or an event object with a 'type' property and any + * other desired properties. The emit() method automatically adds + * a 'target' property to the event object, whose value is a + * reference to the object emitting the event. + * + * In most cases the emit() method is only called from within the + * implementation of an EventEmitter object, and code external to the + * object's model will use its addListener() and removeListener() methods + * to process events that the object emits. All three of these methods + * are public methods, though, so it's also possible for code outside of + * an object's implementation to cause it to emit an event, or for the + * object's own code to listen for and process its own events. + * + * Two special types of events are always present for every EventEmitter + * object: the "listenerAdded" and "listenerRemoved" events. These + * events make it possible to monitor the addition or removal of event + * listeners. The "listenerAdded" event is emitted whenever a new + * listener function is added, and the "listenerRemoved" event is emitted + * whenever a listener is removed. Each of these events contain the + * following properties: + * + * **targetType** + * + * > the event type associated with the listener + * being added or removed + * + * **listener** + * + * > the listener function being added or removed + * + * @class EventEmitter + * @for EventEmitter + * @constructor + * @example + * var Person = new window.jermaine.Model(function() { + * this.isA(EventEmitter); + * this.hasA("name").which.isA("string"); + * this.respondsTo("say", function(something) { + * console.log(this.name() + ' says ' + something); + * this.emit({type : "say", message : something}); + * }); + * }); + * var person = new Person().name("Mark"); + * + * var sayListener = function(event) { + * console.log(event.target.name() + ' said ' + event.message); + * }; + * + * person.say('Hello'); + * person.addListener("say", sayListener); + * person.say('Alright'); + * person.removeListener("say", sayListener); + * person.say('Goodbye'); + * + * + * OUTPUT: + * + * Mark says Hello + * Mark says Alright + * Mark said Alright + * Mark said Goodbye + */ + + // listeners is a plain old JS object whose keys are events + // types (strings); the value associated with each key is the + // list of registered listener functions for that event type. + this.hasA("listeners").which.defaultsTo( function() { + // Use a function that returns an empty object as the + // default value, so we get a new listeners object + // created for each EventEmitter instance. + return {}; + }); + + /** + * Adds a listener function for events of a specific type + * emitted by this object. + * + * @method addListener + * @param {string} eventType the type of event + * @param {function} listener a listener function + * @return {boolean} a value indicating whether the listener + * was actually added (a listener is not added if it + * is already registered for the eventType) + */ + this.respondsTo("addListener", function (eventType, listener) { + var listeners = this.listeners(), + i; + + if (listeners[eventType] === undefined) { + listeners[eventType] = []; + } + for (i=0; i 0) { + for (i=nulls.length-1; i>=0; --i) { + listeners.splice(nulls[i],1); + } + } + + }); + + + }); + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.data.variables.variable), + DataVariable = new window.jermaine.Model("DataVariable", function () { + this.hasA("id").which.isA("string"); + this.hasA("column").which.isA("integer"); + this.hasA("type").which.isOneOf(ns.DataValue.types()).and.defaultsTo(ns.DataValue.NUMBER); + this.hasA("data").which.validatesWith(function (data) { + return data instanceof window.multigraph.core.Data; + }); + this.hasA("missingvalue").which.validatesWith(ns.DataValue.isInstance); + + this.hasA("missingop").which.isOneOf(ns.DataValue.comparators()); + this.isBuiltWith("id", "%column", "%type"); + + utilityFunctions.insertDefaults(this, defaultValues.data.variables.variable, attributes); + }); + + ns.DataVariable = DataVariable; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + /** + * @class Data + * @for Data + * @constructor + * @param {DataVariable} columns + */ + var Data = new window.jermaine.Model(function () { + var DataVariable = ns.DataVariable; + + this.isA(ns.EventEmitter); + + /** + * Searches through a jermaine attr_list of DataVariables (columns) for + * an entry having a given id or column number. + * + * @method find + * @private + * @param {String} attrName The name of the attribute to search on; + * should be either "id" or "column". + * @param {String|Integer} attrValue The value to search for. If attrName + * is "id", this value should be a string. If attrName is "column", + * this value should be an int. + * @param {DataVariable Attr_List} columns The attr_list to search through. + * @static + * @return {Integer} The index (an int) of the DataVariable entry having + * the given attribute value, if any, or -1 if none was found + * @author jrfrimme + * + * @example + * + * find("id", "x", columns) + * + * finds the index of the DataVariable in the columns attr_list + * having an id of "x" + * + * find("column", 1, columns) + * + * finds the index of the DataVariable in the columns attr_list + * having a "column" attribute of 1 + */ + var find = function (attrName, attrValue, columns) { + var result = -1, + i; + for (i = 0; i < columns.size(); ++i) { + if (columns.at(i)[attrName]() === attrValue) { + result = i; + break; + } + } + return result; + }; + + /** + * Set the `data` attribute of each of this data object's columns + * to point to the data object itself. + * + * @method initializeColumns + * @author jrfrimme + */ + this.respondsTo("initializeColumns", function () { + var i; + for (i = 0; i < this.columns().size(); ++i) { + this.columns().at(i).data(this); + } + }); + + this.hasMany("columns").eachOfWhich.validateWith(function (column) { + this.message = "Data: constructor parameter should be an array of DataVariable objects"; + return column instanceof DataVariable; + }); + + this.hasA("defaultMissingvalue").which.isA("string"); + this.hasA("defaultMissingop").which.isA("string").and.defaultsTo("eq"); + this.hasA("adapter"); + + /** + * Initialization function --- should be called from isBuiltWith initializer. This is split + * off into a separate function so that it can be called from submodel's isBuiltWith initializers + * as well, since Jermaine does not provide a way to call the parent models' isBuiltWith initializer + * function. + * + * @method init + * @author jrfrimme + */ + this.respondsTo("init", function() { + this.initializeColumns(); + }); + + this.isBuiltWith("columns", function () { + this.init(); + }); + + this.respondsTo("columnIdToColumnNumber", function (id) { + if (typeof(id) !== "string") { + throw new Error("Data: columnIdToColumnNumber expects parameter to be a string"); + } + + var columnIndex = find("id", id, this.columns()), + column = undefined; + + if (columnIndex >= 0) { + column = this.columns().at(columnIndex); + } + + if (column === undefined) { + throw new Error("Data: no column with the label " + id); + } + + return column.column(); + }); + + this.respondsTo("columnIdToDataVariable", function (id) { + if (typeof(id) !== "string") { + throw new Error("Data: columnIdToDataVariable requires a string parameter"); + } + + var columns = this.columns(), + dv = find("id", id, columns) !== -1 ? columns.at(find("id", id, columns)) : undefined; + + if (dv === undefined) { + throw new Error("Data: no column with the label " + id); + } + + return dv; + }); + + this.respondsTo("getColumnId", function (column) { + if (typeof(column) !== "number") { + throw new Error("Data: getColumnId method expects an integer"); + } + + var result = find("column", column, this.columns()); + + if (result === -1) { + throw new Error("Data: column " + column + " does not exist"); + } + + return this.columns().at(result).id(); + }); + + this.respondsTo("getColumns", function () { + var result = [], + columns = this.columns(), + i; + + for (i = 0; i < columns.size(); ++i) { + result.push(columns.at(i)); + } + + return result; + }); + + this.respondsTo("getBounds", function (columnNumber) { + // submodels must implement this + }); + + this.respondsTo("getIterator", function () { + // submodels must implement this + }); + + /* + * The "onReady" contract: + * + * Each submodel of this Data model should do the following: + * + * 1. Emit an "onReady" event whenever new data is available. + * The arguments to the event listener are the min and max + * values of the range of (newly) available data. + * + * 2. Optionally, register a listener for its own "listenerAdded" + * events, which performs whatever actions are needed, if any, + * when a new "onReady" listener is registered. + */ + + this.respondsTo("pause", function() { + //no op + }); + this.respondsTo("resume", function() { + //no op + }); + + this.respondsTo("isMissing", function (value, i) { + // This method should return true if the DataValue "value" meets the "missing" criteria of + // the i-th column + var column; + if (i < 0 || i >= this.columns().size()) { + throw new Error("metadata.isMissing(): index out of range"); + } + column = this.columns().at(i); + if (!column.missingvalue() || !column.missingop()) { + return false; + } + return value[column.missingop()](column.missingvalue()); + }); + }); + + ns.Data = Data; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var Plot; + + Plot = new window.jermaine.Model("Plot", function () { + this.hasA("legend").which.validatesWith(function (legend) { + return legend instanceof ns.PlotLegend; + }); + this.hasA("horizontalaxis").which.validatesWith(function (axis) { + return axis instanceof ns.Axis; + }); + this.hasA("verticalaxis").which.validatesWith(function (axis) { + return axis instanceof ns.Axis; + }); + this.hasA("renderer").which.validatesWith(function (renderer) { + return renderer instanceof ns.Renderer; + }); + }); + + ns.Plot = Plot; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + /** + * @class ArrayData + * @for ArrayData + * @constructor + * @param {array} columns A array of DataVariables + * @param {array} stringArray A array of strings which will later be parsed into DataValues + */ + ns.ArrayData = window.jermaine.Model(function () { + var ArrayData = this; + + this.isA(ns.Data); + this.hasAn("array"); + this.hasA("stringArray"); + this.isBuiltWith("columns", "stringArray", function () { + this.init(); + this.addListener("listenerAdded", function (event) { + if (event.targetType === "dataReady") { + var data = this.array(); + event.listener(data[0][0], data[data.length-1][0]); + } + }); + }); + + /** + * + * + * @method getIterator + * @param {string array} columnIDs + * @param {DataValue} min + * @param {DataValue} max + * @param {Integer} buffer + * @author jrfrimme + */ + this.respondsTo("getIterator", function (columnIds, min, max, buffer) { + return ArrayData.getArrayDataIterator(this, columnIds, min, max, buffer); + }); + + /** + * Determines the upper and lower bounds of a column in a dataset. + * + * @method getBounds + * @param {Integer} columnNumber Column in the dataset to have its bounds determined. + * @return {array} Array in the form: [lowerBound, upperBound]. + * @author jrfrimme + */ + this.respondsTo("getBounds", function (columnNumber) { + var data = this.array(), + min = data[0][columnNumber], + max = min, + i; + + for (i = 1; i < data.length; i++) { + if (data[i][columnNumber] < min) { + min = data[i][columnNumber]; + } + if (data[i][columnNumber] > max) { + max = data[i][columnNumber]; + } + } + + return [min, max]; + }); + + /** + * @method onReady + * @param callback + */ + + /** + * @method getArrayDataIterator + * @static + * @param {ArrayData} arrayData + * @param {string array} columnIDs + * @param {DataValue} min + * @param {DataValue} max + * @param {Integer} buffer + * @return iter + * @author jrfrimme + */ + ArrayData.getArrayDataIterator = function (arrayData, columnIds, min, max, buffer) { + var i, j, + firstIndex, lastIndex, + currentIndex, + columnIndices, + array = arrayData.array(); + + buffer = buffer || 0; + + // columnIds argument should be an array of strings + if (Object.prototype.toString.apply(columnIds) !== "[object Array]") { + throw new Error("ArrayData: getIterator method requires that the first parameter be an array of strings"); + } else { + for (i = 0; i < columnIds.length; ++i) { + if (typeof(columnIds[i]) !== "string") { + throw new Error("ArrayData: getIterator method requires that the first parameter be an array of strings"); + } + } + } + + //min,max arguments should be data values + if (!ns.DataValue.isInstance(min) || !ns.DataValue.isInstance(max)) { + throw new Error("ArrayData: getIterator method requires the second and third argument to be number values"); + } + + //buffer argument should be an integer + if (typeof(buffer) !== "number") { + throw new Error("ArrayData: getIterator method requires last argument to be an integer"); + } + + // if we have no data, return an empty iterator + if (array.length === 0) { + return { + "next" : function () {}, + "hasNext" : function () { return false; } + }; + } + + // find the index of the first row in the array whose column0 value is >= min + for (firstIndex = 0; firstIndex < array.length; ++firstIndex) { + if (array[firstIndex][0].ge(min)) { + break; + } + } + // back up 'buffer' steps + firstIndex = firstIndex - buffer; + if (firstIndex < 0) { + firstIndex = 0; + } + + // find the index of the last row in the array whose column0 value is <= max + if (firstIndex === array.length-1) { + lastIndex = firstIndex; + } else { + for (lastIndex = firstIndex; lastIndex < array.length-1; ++lastIndex) { + if (array[lastIndex+1][0].gt(max)) { + break; + } + } + } + // move forward 'buffer' steps + lastIndex = lastIndex + buffer; + if (lastIndex > array.length-1) { + lastIndex = array.length-1; + } + + columnIndices = []; + for (j = 0; j < columnIds.length; ++j) { + var k = arrayData.columnIdToColumnNumber(columnIds[j]); + columnIndices.push( k ); + } + + currentIndex = firstIndex; + + return { + next : function () { + var projection = [], + i; + if (currentIndex > lastIndex) { + return null; + } + for (i = 0; i < columnIndices.length; ++i) { + projection.push(array[currentIndex][columnIndices[i]]); + } + ++currentIndex; + return projection; + }, + hasNext : function () { + return currentIndex <= lastIndex; + } + }; + }; + + /** + * @method textToDataValuesArray + * @static + * @param {array} dataVariableArray + * @param {string} text + * @return {array} dataValues + * @author jrfrimme + * @todo If the number of comma-separated values on the current line is not the same as the number of columns in the metadata, should throw an error. + */ + ArrayData.textToDataValuesArray = function (dataVariableArray, text) { + //IMPORTANT NOTE: dataVariableArray is a plain javascript array of DataVariable instances; it + //is NOT a jermaine attr_list. + var dataValues = [], + lines = text.split("\n"), + i; + for (i = 0; i < lines.length; ++i) { + if (/\d/.test(lines[i])) { // skip line unless it contains a digit + var stringValuesThisRow = lines[i].split(/\s*,\s*/), + dataValuesThisRow = [], + j; + if (stringValuesThisRow.length === dataVariableArray.length) { + for (j = 0; j < stringValuesThisRow.length; ++j) { + dataValuesThisRow.push(ns.DataValue.parse(dataVariableArray[j].type(), stringValuesThisRow[j])); + } + dataValues.push( dataValuesThisRow ); + //} else { + // we get here if the number of comma-separated values on the current line + // (lines[i]) is not the same as the number of columns in the metadata. This + // should probably throw an error, or something like that. For now, though, we + // just ignore it. + //console.log('bad line: ' + lines[i]); + } + } + } + return dataValues; + }; + + /** + * @method textToStringArray + * @static + * @param {string} text + * @return {array} stringValues + * @author jrfrimme + */ + ArrayData.textToStringArray = function (dataVariables, text) { + var stringValues = [], + lines = text.split("\n"), + stringValuesThisRow, + numColumns, + i; + + // clean up each line + for (i = 0; i < lines.length; ++i) { + lines[i] = lines[i] + .replace(/^\s+/, "") // remove leading whitespace + .replace(/\s+$/, "") // remove trailing whitespace + .replace(/\s*,\s*/g, ",") // remove any whitespace next to commas + .replace(/\s+/g, ","); // replace any remaining whitespace runs with a comma + // now line consists of comma-separated values, with no whitespace + } + + for (i = 0; i < lines.length; ++i) { + if (/\d/.test(lines[i])) { // skip line unless it contains a digit + numColumns = lines[i].split(/,/).length; + break; + } + } + + for (i = 0; i < lines.length; ++i) { + if (/\d/.test(lines[i])) { // skip line unless it contains a digit + stringValuesThisRow = lines[i].split(/,/); + if (stringValuesThisRow.length === numColumns) { + stringValues.push( stringValuesThisRow ); + } else { + throw new Error("Data Parsing Error: The line '" + lines[i] + "' has " + stringValuesThisRow.length + " data columns when it requires " + numColumns + " columns"); + } + } + } + return stringValues; + }; + + /** + * Parses an array of strings into an array of DataValues. + * + * @method textToStringArray + * @static + * @param {array} dataVariableArray plain javascript array of DataVariables + * @param {array} stringArray plain javascript array of strings + * @return {array} plain javascript array of DataValue instances + * @author jrfrimme + */ + ArrayData.stringArrayToDataValuesArray = function (dataVariableArray, stringArray) { + //IMPORTANT NOTE: dataVariableArray is a plain javascript array of DataVariable instances; it + //is NOT a jermaine attr_list. + + var dataValues = [], + dataValuesThisRow, + i, + j; + + for (i = 0; i < stringArray.length; ++i) { + dataValuesThisRow = []; + for (j = 0; j < stringArray[i].length; ++j) { + dataValuesThisRow.push(ns.DataValue.parse(dataVariableArray[j].type(), stringArray[i][j])); + } + dataValues.push( dataValuesThisRow ); + } + return dataValues; + }; + + }); +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + var Axis, + utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.horizontalaxis), + Orientation = new window.multigraph.math.Enum("AxisOrientation"); + + /** + * Axis is a Jermaine model that controls Multigraph axes. + * + * @class Axis + * @for Axis + * @constructor + * @param {AxisOrientation} Orientation + */ + Axis = new window.jermaine.Model("Axis", function () { + + this.isA(ns.EventEmitter); + + this.hasA("title").which.validatesWith(function (title) { + return title instanceof ns.AxisTitle; + }); + this.hasMany("labelers").eachOfWhich.validateWith(function (labelers) { + return labelers instanceof ns.Labeler; + }); + this.hasA("grid").which.validatesWith(function (grid) { + return grid instanceof ns.Grid; + }); + this.hasA("pan").which.validatesWith(function (pan) { + return pan instanceof ns.Pan; + }); + this.hasA("zoom").which.validatesWith(function (zoom) { + return zoom instanceof ns.Zoom; + }); + this.hasA("binding").which.validatesWith(function (binding) { + return binding === null || binding instanceof ns.AxisBinding; + }); + this.hasAn("id").which.isA("string"); + this.hasA("type").which.isOneOf(ns.DataValue.types()); + this.hasA("length").which.validatesWith(function (length) { + return length instanceof window.multigraph.math.Displacement; + }); + this.hasA("position").which.validatesWith(function (position) { + return position instanceof window.multigraph.math.Point; + }); + this.hasA("pregap").which.isA("number"); + this.hasA("postgap").which.isA("number"); + this.hasAn("anchor").which.isA("number"); + this.hasA("base").which.validatesWith(function (base) { + return base instanceof window.multigraph.math.Point; + }); + + /** + * Stores the "min" value from the mugl file as a string, if there was one. + * + * @property min + * @type {String} + * @author jrfrimme + */ + this.hasA("min").which.isA("string"); + + /** + * The current min DataValue for the axis. + * + * @property dataMin + * @type {DataValue} + * @author jrfrimme + */ + this.hasA("dataMin").which.validatesWith(ns.DataValue.isInstance); + /** + * Convenience method for checking to see if dataMin has been set or not + * + * @method hasDataMin + * @author jrfrimme + * @return {Boolean} + */ + this.respondsTo("hasDataMin", function () { + return this.dataMin() !== undefined; + }); + + + this.hasA("minoffset").which.isA("number"); + this.hasA("minposition").which.validatesWith(function (minposition) { + return minposition instanceof window.multigraph.math.Displacement; + }); + + /** + * Stores the "max" value from the mugl file as a string, if there was one. + * + * @property max + * @type {String} + * @author jrfrimme + */ + this.hasA("max").which.isA("string"); + + /** + * The current max DataValue for the axis. + * + * @property dataMax + * @type {DataValue} + * @author jrfrimme + */ + this.hasA("dataMax").which.validatesWith(ns.DataValue.isInstance); + /** + * Convenience method for checking to see if dataMax has been set or not. + * + * @method hasDataMax + * @author jrfrimme + * @return {Boolean} + */ + this.respondsTo("hasDataMax", function () { + return this.dataMax() !== undefined; + }); + + + + this.hasA("maxoffset").which.isA("number"); + this.hasA("maxposition").which.validatesWith(function (maxposition) { + return maxposition instanceof window.multigraph.math.Displacement; + }); + + + this.hasA("positionbase").which.isA("string"); // deprecated + this.hasA("color").which.validatesWith(function (color) { + return color instanceof window.multigraph.math.RGBColor; + }); + this.hasA("tickcolor").which.validatesWith(function (color) { + return color === null || color instanceof window.multigraph.math.RGBColor; + }); + this.hasA("tickwidth").which.isA("integer"); + this.hasA("tickmin").which.isA("integer"); + this.hasA("tickmax").which.isA("integer"); + this.hasA("highlightstyle").which.validatesWith(function (highlightstyle) { + return typeof(highlightstyle) === "string"; + }); + this.hasA("linewidth").which.isA("integer"); + this.hasA("orientation").which.validatesWith(Orientation.isInstance); + this.isBuiltWith("orientation", function () { + this.grid(new ns.Grid()); + this.zoom(new ns.Zoom()); + this.pan(new ns.Pan()); + }); + + this.hasA("pixelLength").which.isA("number"); + this.hasA("parallelOffset").which.isA("number"); + this.hasA("perpOffset").which.isA("number"); + + this.hasA("axisToDataRatio").which.isA("number"); + + this.respondsTo("initializeGeometry", function (graph, graphicsContext) { + var plotBox = graph.plotBox(), + position = this.position(), + base = this.base(), + pixelLength, + i; + if (this.orientation() === Axis.HORIZONTAL) { + pixelLength = this.length().calculateLength( plotBox.width() ); + this.pixelLength(pixelLength); + this.parallelOffset( position.x() + (base.x() + 1) * plotBox.width()/2 - (this.anchor() + 1) * pixelLength / 2 ); + this.perpOffset( position.y() + (base.y() + 1) * plotBox.height() / 2 ); + } else { + pixelLength = this.length().calculateLength( plotBox.height() ); + this.pixelLength(pixelLength); + this.parallelOffset( position.y() + (base.y() + 1) * plotBox.height()/2 - (this.anchor() + 1) * pixelLength / 2 ); + this.perpOffset( position.x() + (base.x() + 1) * plotBox.width() / 2 ); + } + this.minoffset(this.minposition().calculateCoordinate(pixelLength)); + this.maxoffset(pixelLength - this.maxposition().calculateCoordinate(pixelLength)); + if (this.hasDataMin() && this.hasDataMax()) { + this.computeAxisToDataRatio(); + } + for (i = 0; i < this.labelers().size(); ++i) { + this.labelers().at(i).initializeGeometry(graph); + } + if (this.title()) { + this.title().initializeGeometry(graph, graphicsContext); + } + }); + + this.respondsTo("computeAxisToDataRatio", function () { + if (this.hasDataMin() && this.hasDataMax()) { + this.axisToDataRatio((this.pixelLength() - this.maxoffset() - this.minoffset()) / (this.dataMax().getRealValue() - this.dataMin().getRealValue())); + } + }); + + this.respondsTo("dataValueToAxisValue", function (v) { + return this.axisToDataRatio() * ( v.getRealValue() - this.dataMin().getRealValue() ) + this.minoffset() + this.parallelOffset(); + }); + + this.respondsTo("axisValueToDataValue", function (a) { + return ns.DataValue.create( this.type(), + ( this.dataMin().getRealValue() + + ( a - this.minoffset() - this.parallelOffset() ) / this.axisToDataRatio()) ); + }); + + this.hasA("currentLabeler").which.validatesWith(function (labeler) { + return labeler===null || labeler instanceof ns.Labeler; + }); + this.hasA("currentLabelDensity").which.isA("number"); + this.hasA("currentLabelerIndex").which.isA("number"); + + /** + * Decides which labeler to use: take the one with the largest density <= 0.8. + * Unless all have density > 0.8, in which case we take the first one. This assumes + * that the labelers list is ordered in increasing order of label density. + * This function sets the `currentLabeler` and `currentLabelDensity` attributes. + * + * @method prepareRender + * @param {Object} graphicsContext + * @author jrfrimme + */ + this.respondsTo("prepareRender", function (graphicsContext) { + if (!this.hasDataMin() || !this.hasDataMax()) { + // if either endpoint dataMin() or dataMax() hasn't been specified yet, + // return immediately without doing anything + return; + } + var currentLabeler, + currentLabelDensity = 0, + storedDensity = 0, + densityThreshold = 0.8, + labelers = this.labelers(), + nlabelers = labelers.size(), + index = this.currentLabelerIndex(), + storedIndex; + + if (nlabelers <= 0) { + currentLabeler = null; + } else { + var flag = true, + lastLabelerIndex = labelers.size() - 1; + + if (index === undefined) { + index = 0; + } + storedIndex = index; + currentLabelDensity = labelers.at(index).getLabelDensity(graphicsContext); + + if (currentLabelDensity > densityThreshold) { + if (index === 0) { // use labeler at position 0 + flag = false; + } else { // check the prior labeler + storedDensity = currentLabelDensity; + index--; + } + } else if (currentLabelDensity < densityThreshold) { // check the next labeler + storedDensity = currentLabelDensity; + if (index === lastLabelerIndex) { + flag = false; + } else { + index++; + } + } else if (currentLabelDensity === densityThreshold) { // use labeler at position 0 + flag = false; + } + + while (flag) { + currentLabelDensity = labelers.at(index).getLabelDensity(graphicsContext); + if (currentLabelDensity > densityThreshold) { // labeler before current one + if (index === 0) { // use labeler at position 0 + break; + } else if (storedIndex > index) { // going backwards through labelers + storedIndex = index; + storedDensity = currentLabelDensity; + index--; + } else { // the prior labeler had density < threshold and was checking the next labeler + index = storedIndex; + currentLabelDensity = storedDensity; + break; + } + } else if (currentLabelDensity < densityThreshold) { // this labeler or one after it + if (storedIndex > index) { // going backwards through labelers so prior labeler had density > threshold + break; + } else if (index === lastLabelerIndex) { + break; + } else { // check next labeler to see if it has density < threshold + storedIndex = index; + storedDensity = currentLabelDensity; + index++; + } + } else if (currentLabelDensity === densityThreshold) { + break; + } + } + } + currentLabeler = labelers.at(index); + + this.currentLabeler(currentLabeler); + this.currentLabelerIndex(index); + this.currentLabelDensity(currentLabelDensity); + }); + + this.respondsTo("toRealValue", function (value) { + if (typeof(value) === "number") { + return value; + } else if (ns.DataValue.isInstance(value)) { + return value.getRealValue(); + } else { + throw new Error("unknown value type for axis value " + value); + } + }); + + this.respondsTo("toDataValue", function (value) { + if (typeof(value) === "number") { + return ns.DataValue.create(this.type(), value); + } else if (ns.DataValue.isInstance(value)) { + return value; + } else { + throw new Error("unknown value type for axis value " + value); + } + }); + + this.respondsTo("setDataRangeNoBind", function(min, max, dispatch) { + + // NOTE: min and max may either be plain numbers, or + // DataValue instances. If they're plain numbers, they + // get converted to DataValue instances here before being + // passed to the dataMin()/dataMax() setters below. + + var dataValueMin = this.toDataValue(min), + dataValueMax = this.toDataValue(max); + + this.dataMin(dataValueMin); + this.dataMax(dataValueMax); + // if (_graph != null) { _graph.invalidateDisplayList(); } + if (dispatch === undefined) { + dispatch = true; + } + + this.emit({'type' : 'dataRangeSet', + 'min' : dataValueMin, + 'max' : dataValueMax}); +/* + if (dispatch) { + //dispatchEvent(new AxisEvent(AxisEvent.CHANGE,min,max)); + } +*/ + }); + + this.respondsTo("setDataRange", function (min, max, dispatch) { + if (this.binding()) { + this.binding().setDataRange(this, min, max, dispatch); + } else { + this.setDataRangeNoBind(min, max, dispatch); + } + }); + + this.respondsTo("doPan", function (pixelBase, pixelDisplacement) { + var pan = this.pan(), + panMin = pan.min(), + panMax = pan.max(), + offset, + newRealMin, + newRealMax; + + if (!pan.allowed()) { return; } + offset = pixelDisplacement / this.axisToDataRatio(); + newRealMin = this.dataMin().getRealValue() - offset; + newRealMax = this.dataMax().getRealValue() - offset; + + if (panMin && newRealMin < panMin.getRealValue()) { + newRealMax += (panMin.getRealValue() - newRealMin); + newRealMin = panMin.getRealValue(); + } + if (panMax && newRealMax > panMax.getRealValue()) { + newRealMin -= (newRealMax - panMax.getRealValue()); + newRealMax = panMax.getRealValue(); + } + this.setDataRange(ns.DataValue.create(this.type(), newRealMin), + ns.DataValue.create(this.type(), newRealMax)); + }); + + this.respondsTo("doZoom", function (pixelBase, pixelDisplacement) { + var zoom = this.zoom(), + pan = this.pan(), + type = this.type(), + dataMin = this.dataMin(), + dataMax = this.dataMax(), + panMin = pan.min(), + panMax = pan.max(), + zoomMin = zoom.min(), + zoomMax = zoom.max(), + DataValue = ns.DataValue, + baseRealValue, + factor, + newMin, + newMax, + d; + if (!zoom.allowed()) { + return; + } + baseRealValue = this.axisValueToDataValue(pixelBase).getRealValue(); + if (DataValue.isInstance(zoom.anchor())) { + baseRealValue = zoom.anchor().getRealValue(); + } + factor = 10 * Math.abs(pixelDisplacement / (this.pixelLength() - this.maxoffset() - this.minoffset())); + /*TODO: uncomment after this.reversed() has been implemented + if (this.reversed()) { factor = -factor; } + */ + if (pixelDisplacement <= 0) { + newMin = DataValue.create(type, + (dataMin.getRealValue() - baseRealValue) * ( 1 + factor ) + baseRealValue); + newMax = DataValue.create(type, + (dataMax.getRealValue() - baseRealValue) * ( 1 + factor ) + baseRealValue); + } else { + newMin = DataValue.create(type, + (dataMin.getRealValue() - baseRealValue) * ( 1 - factor ) + baseRealValue); + newMax = DataValue.create(type, + (dataMax.getRealValue() - baseRealValue) * ( 1 - factor ) + baseRealValue); + } + if (panMin && newMin.lt(panMin)) { + newMin = panMin; + } + if (panMax && newMax.gt(panMax)) { + newMax = panMax; + } + + if ((dataMin.le(dataMax) && newMin.lt(newMax)) || + (dataMin.ge(dataMax) && newMin.gt(newMax))) { + if (zoomMax && (newMax.gt(newMin.add(zoomMax)))) { + d = (newMax.getRealValue() - newMin.getRealValue() - zoomMax.getRealValue()) / 2; + newMax = newMax.addRealValue(-d); + newMin = newMin.addRealValue(d); + } else if (zoomMin && (newMax.lt(newMin.add(zoomMin)))) { + d = (zoomMin.getRealValue() - (newMax.getRealValue() - newMin.getRealValue())) / 2; + newMax = newMax.addRealValue(d); + newMin = newMin.addRealValue(-d); + } + this.setDataRange(newMin, newMax); + } + }); + + /** + * Compute the distance from an axis to a point. The point + * (x,y) is expressed in pixel coordinates in the same + * coordinate system as the axis. + * + * We use two different kinds of computations depending on + * whether the point lies inside or outside the region bounded + * by the two lines perpendicular to the axis through its + * endpoints. If the point lies inside this region, the + * distance is simply the difference in the perpendicular + * coordinate of the point and the perpendicular coordinate of + * the axis. + * + * If the point lies outside the region, then the distance is + * the L2 distance between the point and the closest endpoint + * of the axis. + * + * @method distanceToPoint + * @param {} x + * @param {} y + * @author jrfrimme + */ + this.respondsTo("distanceToPoint", function (x, y) { + var perpCoord = (this.orientation() === Axis.HORIZONTAL) ? y : x, + parallelCoord = (this.orientation() === Axis.HORIZONTAL) ? x : y, + parallelOffset = this.parallelOffset(), + perpOffset = this.perpOffset(), + pixelLength = this.pixelLength(), + l2dist = window.multigraph.math.util.l2dist; + + if (parallelCoord < parallelOffset) { + // point is under or left of the axis; return L2 distance to bottom or left axis endpoint + return l2dist(parallelCoord, perpCoord, parallelOffset, perpOffset); + } + if (parallelCoord > parallelOffset + pixelLength) { + // point is above or right of the axis; return L2 distance to top or right axis endpoint + return l2dist(parallelCoord, perpCoord, parallelOffset + pixelLength, perpOffset); + } + // point is between the axis endpoints; return difference in perpendicular coords + return Math.abs(perpCoord - perpOffset); + }); + + utilityFunctions.insertDefaults(this, defaultValues.horizontalaxis, attributes); + }); + Axis.HORIZONTAL = new Orientation("horizontal"); + Axis.VERTICAL = new Orientation("vertical"); + + Axis.Orientation = Orientation; + + ns.Axis = Axis; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + /** + * @class axisBinding + * @for axisBinding + * @constructor + */ + ns.AxisBinding = new window.jermaine.Model("AxisBinding", function () { + var AxisBinding = this; + + AxisBinding.instances = {}; + + /** + * + * + * @property id + * @type {String} + * @author jrfrimme + */ + this.hasA("id").which.isA("string"); + + /** + * + * + * @property axes + * @type {Array} + * @author jrfrimme + */ + this.hasA("axes"); // js array + + this.isBuiltWith("id", function() { + AxisBinding.instances[this.id()] = this; + this.axes([]); + }); + + /** + * + * + * @method addAxis + * @param {Axis} axis + * @param {number|DataValue} min + * @param {number|DataValue} max + * @author jrfrimme + */ + this.respondsTo("addAxis", function(axis, min, max, multigraph/*optional*/) { + // NOTE: min/max can be either numbers, or DataValue + // instances, but they CANNOT be strings. + + if (axis.binding()) { + axis.binding().removeAxis(axis); + } + axis.binding(this); + + // convert min/max to numbers + min = axis.toRealValue(min); + max = axis.toRealValue(max); + + this.axes().push({ + axis : axis, + multigraph : multigraph, + factor : 1 / (max - min), + offset : -min / (max - min), + min : min, + max : max + }); + }); + + /** + * + * + * @method removeAxis + * @param {Axis} axis + * @author jrfrimme + */ + this.respondsTo("removeAxis", function(axis) { + var axes = this.axes(), + i; + for (i=0; i plotBox.height()/2) { + position( getValue(titleDefaults["position-horizontal-top"]) ); + } else { + position( getValue(titleDefaults["position-horizontal-bottom"]) ); + } + } else { + if (axisPerpOffset > plotBox.width()/2) { + position( getValue(titleDefaults["position-vertical-right"]) ); + } else { + position( getValue(titleDefaults["position-vertical-left"]) ); + } + } + } + + if (anchor() === undefined) { + if (axisIsHorizontal) { + if (axisPerpOffset > plotBox.height()/2) { + anchor( getValue(titleDefaults["anchor-horizontal-top"]) ); + } else { + anchor( getValue(titleDefaults["anchor-horizontal-bottom"]) ); + } + } else { + if (axisPerpOffset > plotBox.width()/2) { + anchor( getValue(titleDefaults["anchor-vertical-right"]) ); + } else { + anchor( getValue(titleDefaults["anchor-vertical-left"]) ); + } + } + } + + graphicsContext.angle = this.angle(); + this.content().initializeGeometry(graphicsContext); + + return this; + }); + + /** + * Renders the Axis Title. Overridden by implementations in graphics drivers. + * + * @method render + * @private + * @author jrfrimme + */ + this.respondsTo("render", function () {}); + + utilityFunctions.insertDefaults(this, defaultValues.horizontalaxis.title, attributes); + }); + + ns.AxisTitle = AxisTitle; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var Background, + utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.background); + + Background = new window.jermaine.Model("Background", function () { + this.hasA("color").which.validatesWith(function (color) { + return color instanceof window.multigraph.math.RGBColor; + }).defaultsTo(window.multigraph.math.RGBColor.parse(defaultValues.background.color)); + this.hasA("img").which.validatesWith(function (img) { + return img instanceof ns.Img; + }); + }); + + ns.Background = Background; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot); + + ns.ConstantPlot = new window.jermaine.Model("ConstantPlot", function () { + this.isA(ns.Plot); + this.hasA("constantValue").which.validatesWith(ns.DataValue.isInstance); + + this.isBuiltWith("constantValue"); + + utilityFunctions.insertDefaults(this, defaultValues.plot, attributes); + + this.respondsTo("render", function (graph, graphicsContext) { + // graphicsContext is an optional argument passed to ConstantPlot.render() by the + // graphics driver, and used by that driver's implementation of Renderer.begin(). + // It can be any object used by the driver -- usually some kind of graphics + // context object. It can also be omitted if a driver does not need it. + + var haxis = this.horizontalaxis(), + renderer = this.renderer(), + constantValue = this.constantValue(); + + if (!haxis.hasDataMin() || !haxis.hasDataMax()) { + return; + } + + renderer.setUpMissing(); //TODO: this is awkward -- figure out a better way! + renderer.begin(graphicsContext); + renderer.dataPoint([ haxis.dataMin(), constantValue ]); + renderer.dataPoint([ haxis.dataMax(), constantValue ]); + renderer.end(); + + }); + + }); + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var CSVData = window.jermaine.Model(function () { + var ArrayData = ns.ArrayData; + + this.isA(ArrayData); + this.hasA("filename").which.isA("string"); + this.hasA("messageHandler"); + this.hasA("ajaxthrottle"); + this.hasA("dataIsReady").which.isA("boolean").and.defaultsTo(false); + + this.respondsTo("getIterator", function (columnIds, min, max, buffer) { + if (this.dataIsReady()) { + return ArrayData.getArrayDataIterator(this, columnIds, min, max, buffer); + } else { + return { + "next" : function () {}, + "hasNext" : function () { return false; } + }; + } + }); + + this.respondsTo("_displayError", function (e) { + if (this.messageHandler()) { + this.messageHandler().error(e); + } else { + throw e; + } + }); + + this.isBuiltWith("columns", "filename", "%messageHandler", "%ajaxthrottle", function () { + var that = this, + ajaxthrottle = this.ajaxthrottle(); + + if (ajaxthrottle === undefined) { + ajaxthrottle = window.multigraph.jQuery; + } + + this.adapter(ArrayData); + this.init(); + + if (that.filename() !== undefined) { + that.emit({type : 'ajaxEvent', action : 'start'}); + ajaxthrottle.ajax({ + url : that.filename(), + + success : function (data) { + //parse the data + var dataValues = that.adapter().textToStringArray(that.getColumns(), data); + that.stringArray(dataValues); + // renormalize & populate array + that.ajaxNormalize(); + that.dataIsReady(true); + that.emit({type : "dataReady"}); + }, + + error : function (jqXHR, textStatus, errorThrown) { + var message = errorThrown; + if (jqXHR.statusCode().status === 404) { + message = "File not found: '" + that.filename() + '"'; + } else { + if (textStatus) { + message = textStatus + ": " + message; + } + } + that._displayError(new Error(message)); + }, + + // 'complete' callback gets called after either 'success' or 'error', whichever: + complete : function (jqXHR, textStatus) { + that.emit({type : 'ajaxEvent', action : 'complete'}); + } + + }); + } + }); + }); + + ns.CSVData = CSVData; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var DataPlot, + utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot); + + DataPlot = new window.jermaine.Model("DataPlot", function () { + this.isA(ns.Plot); + this.hasMany("variable").eachOfWhich.validateWith(function (variable) { + return variable instanceof ns.DataVariable || variable === null; + }); + this.hasA("filter").which.validatesWith(function (filter) { + return filter instanceof ns.Filter; + }); + this.hasA("datatips").which.validatesWith(function (datatips) { + return datatips instanceof ns.Datatips; + }); + this.hasA("data").which.validatesWith(function (data) { + return data instanceof ns.Data; + }); + + utilityFunctions.insertDefaults(this, defaultValues.plot, attributes); + + this.respondsTo("render", function (graph, graphicsContext) { + // graphicsContext is an optional argument passed to DataPlot.render() by the + // graphics driver, and used by that driver's implementation of Renderer.begin(). + // It can be any objectded by the driver -- usually some kind of graphics + // context object. It can also be omitted if a driver does not need it. + //var data = this.data().arraydata(); + var data = this.data(); + if (! data) { return; } + + var haxis = this.horizontalaxis(), + vaxis = this.verticalaxis(); + + if (!haxis.hasDataMin() || !haxis.hasDataMax()) { + // if this plot's horizontal axis does not have a min or max value yet, + // return immediately without doing anything + return; + } + + var variables = this.variable(), + variableIds = [], + i; + for (i = 0; i < variables.size(); ++i) { + variableIds.push( variables.at(i).id() ); + } + + var iter = data.getIterator(variableIds, haxis.dataMin(), haxis.dataMax(), 1), + renderer = this.renderer(); + + renderer.setUpMissing(); //TODO: this is awkward -- figure out a better way! + renderer.begin(graphicsContext); + while (iter.hasNext()) { + var datap = iter.next(); + renderer.dataPoint(datap); + } + renderer.end(); + + }); + + + }); + + ns.DataPlot = DataPlot; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var Datatips, + utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot.datatips); + + Datatips = new window.jermaine.Model("Datatips", function () { + this.hasMany("variables").eachOfWhich.validateWith(function (variable) { + return variable instanceof ns.DatatipsVariable; + }); + this.hasA("format").which.validatesWith(function (format) { + return typeof(format) === "string"; + }); + this.hasA("bgcolor").which.validatesWith(function (bgcolor) { + return bgcolor instanceof window.multigraph.math.RGBColor; + }); + this.hasA("bgalpha").which.validatesWith(function (bgalpha) { + return typeof(bgalpha) === "string"; + }); + this.hasA("border").which.isA("integer"); + this.hasA("bordercolor").which.validatesWith(function (bordercolor) { + return bordercolor instanceof window.multigraph.math.RGBColor; + }); + this.hasA("pad").which.isA("integer"); + + utilityFunctions.insertDefaults(this, defaultValues.plot.datatips, attributes); + }); + + ns.Datatips = Datatips; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot.datatips.variable), + DatatipsVariable = new window.jermaine.Model("DatatipsVariable", function () { + this.hasA("format").which.validatesWith(function (format) { + return typeof(format) === "string"; + }); + + utilityFunctions.insertDefaults(this, defaultValues.plot.datatips.variable, attributes); + }); + + ns.DatatipsVariable = DatatipsVariable; + +}); +/*global sprintf */ + +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + var DatetimeFormatter = function (format) { + var testString; + if (typeof(format) !== "string") { + throw new Error("format must be a string"); + } + this.formatString = format; + testString = DatetimeFormatter.formatInternally(format, new Date(0)); + this.length = testString.length; + }; + + DatetimeFormatter.prototype.format = function (value) { + return DatetimeFormatter.formatInternally(this.formatString, value.value); + }; + + DatetimeFormatter.prototype.getMaxLength = function () { + return this.length; + }; + + DatetimeFormatter.prototype.getFormatString = function () { + return this.formatString; + }; + + DatetimeFormatter.formatInternally = function (formatString, date) { + var dayNames = { + "shortNames": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + "longNames": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] + }, + monthNames = { + "shortNames": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], + "longNames": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] + }, + state = 0, + c, + i, + t, + output = ""; + + for (i = 0; i < formatString.length; i++) { + c = formatString.charAt(i); + switch (state) { + case 0: + if (c === "%") { + state = 1; + } else { + output += c; + } + break; + case 1: + switch (c) { + case "Y": + // four digit year + output += date.getUTCFullYear().toString(); + break; + case "y": + // two digit year + output += date.getUTCFullYear().toString().substr(2, 2); + break; + case "M": + // 2-digit month number with leading zero + output += sprintf("%02s", (date.getUTCMonth() + 1).toString()); + break; + case "m": + // month number without leading zero + output += (date.getUTCMonth() + 1).toString(); + break; + case "N": + // month name, spelled out + output += monthNames.longNames[date.getUTCMonth()]; + break; + case "n": + // month name, 3 letter abbreviation + output += monthNames.shortNames[date.getUTCMonth()]; + break; + case "D": + // two-digit day of month with leading zero + output += sprintf("%02s", date.getUTCDate().toString()); + break; + case "d": + // day of month without leading zero + output += date.getUTCDate().toString(); + break; + case "W": + // weekday name, spelled out + output += dayNames.longNames[date.getUTCDay()]; + break; + case "w": + // weekday name, 3-letter abbreviation + output += dayNames.shortNames[date.getUTCDay()]; + break; + case "H": + // hour of day, 24 hour clock + output += sprintf("%02s", date.getUTCHours().toString()); + break; + case "h": + // hour of day, 12 hour clock + t = date.getUTCHours() % 12; + if (t === 0) { + output += "12"; + } else { + output += t.toString(); + } + break; + case "i": + // minutes + output += sprintf("%02s", date.getUTCMinutes().toString()); + break; + case "s": + // seconds + output += sprintf("%02s", date.getUTCSeconds().toString()); + break; + case "v": + // deciseconds (10ths of a second) + output += sprintf("%03s", date.getUTCMilliseconds().toString()).substr(0, 1); + break; + case "V": + // centiseconds (100ths of a second) + output += sprintf("%03s", date.getUTCMilliseconds().toString()).substr(0, 2); + break; + case "q": + // milliseconds (1000ths of a second) + output += sprintf("%03s", date.getUTCMilliseconds().toString()); + break; + case "P": + // AM or PM + t = date.getUTCHours(); + if (t < 12) { + output += "AM"; + } else { + output += "PM"; + } + break; + case "p": + // am or pm + t = date.getUTCHours(); + if (t < 12) { + output += "am"; + } else { + output += "pm"; + } + break; + case "L": + // newline + output += "\n"; + break; + case "%": + // % + output += "%"; + break; + default: + throw new Error("Invalid character code for datetime formatting string"); + } + state = 0; + break; + } + } + return output; + }; + + ns.DatetimeFormatter = DatetimeFormatter; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var DatetimeMeasure, + DatetimeUnit = new window.multigraph.math.Enum("DatetimeUnit"); + + DatetimeMeasure = function (measure, unit) { + if (typeof(measure) !== "number" || DatetimeMeasure.isUnit(unit) !== true) { + throw new Error("Improper input for Datetime Measure's constructor"); + } else if (arguments.length !== 2) { + throw new Error("Datetime Measure's contructor requires exactly two arguments"); + } + this.measure = measure; + this.unit = unit; + }; + + DatetimeMeasure.isUnit = function (unit) { + return DatetimeUnit.isInstance(unit); + }; + + DatetimeMeasure.prototype.negative = function () { + return new DatetimeMeasure(-this.measure, this.unit); + }; + + DatetimeMeasure.prototype.getRealValue = function () { + var factor; + switch (this.unit) { + case DatetimeMeasure.MILLISECOND: + factor = 1; + break; + case DatetimeMeasure.SECOND: + factor = 1000; + break; + case DatetimeMeasure.MINUTE: + factor = 60000; + break; + case DatetimeMeasure.HOUR: + factor = 3600000; + break; + case DatetimeMeasure.DAY: + factor = 86400000; + break; + case DatetimeMeasure.WEEK: + factor = 604800000; + break; + case DatetimeMeasure.MONTH: + factor = 2592000000; + break; + case DatetimeMeasure.YEAR: + factor = 31536000000; + break; + } + return this.measure * factor; + }; + + DatetimeMeasure.parse = function (s) { + var re, measure, unit; + + if (typeof(s) !== "string" || s.match(/\s*-?(([0-9]+\.?[0-9]*)|([0-9]*\.?[0-9]+))\s*(ms|s|m|H|D|W|M|Y){1}\s*$/) === null) { + throw new Error("Improper input for Datetime Measure's parse method"); + } + + re = /ms|s|m|H|D|W|M|Y/; + measure = parseFloat(s.replace(re, "")); + unit = s.match(re); // returns an array + + unit = DatetimeUnit.parse(unit[0]); + + return new DatetimeMeasure(measure, unit); + }; + + DatetimeMeasure.findTickmarkWithMillisecondSpacing = function (/*number(milliseconds)*/value, /*number(milliseconds)*/alignment, /*number(milliseconds)*/spacing) { + var offset = value - alignment, + d = Math.floor( offset / spacing ); + if (offset % spacing !== 0) { + ++d; + } + return new ns.DatetimeValue(alignment + d * spacing); + }; + + DatetimeMeasure.findTickmarkWithMonthSpacing = function (/*DatetimeValue*/value, /*DatetimeValue*/alignment, /*number(months)*/monthSpacing) { + var valueD = value.value, //NOTE: ".value" property of DatetimeValue is a javascript Date object + alignD = alignment.value, //NOTE: ".value" property of DatetimeValue is a javascript Date object + monthOffset = 12 * (valueD.getUTCFullYear() - alignD.getUTCFullYear()) + (valueD.getUTCMonth() - alignD.getUTCMonth()), + d = Math.floor( monthOffset / monthSpacing ); + + if (monthOffset % monthSpacing !== 0) { ++d; } + else if (valueD.getUTCDate() > alignD.getUTCDate()) { ++d; } + else if (valueD.getUTCDate() === alignD.getUTCDate() && valueD.getUTCHours() > alignD.getUTCHours()) { ++d; } + else if (valueD.getUTCDate() === alignD.getUTCDate() && valueD.getUTCHours() === alignD.getUTCHours() && valueD.getUTCMinutes() > alignD.getUTCMinutes()) { ++d; } + else if (valueD.getUTCDate() === alignD.getUTCDate() && valueD.getUTCHours() === alignD.getUTCHours() && valueD.getUTCMinutes() === alignD.getUTCMinutes() && valueD.getUTCSeconds() > alignD.getUTCSeconds()) { ++d; } + else if (valueD.getUTCDate() === alignD.getUTCDate() && valueD.getUTCHours() === alignD.getUTCHours() && valueD.getUTCMinutes() === alignD.getUTCMinutes() && valueD.getUTCSeconds() === alignD.getUTCSeconds() && valueD.getUTCMilliseconds() > alignD.getUTCMilliseconds()) { ++d; } + + return alignment.add( DatetimeMeasure.parse((d * monthSpacing) + "M") ); + }; + + + /** + * Consider the regular lattice of points on the Datetime line separated from each other + * by `this` DatetimeMeasure, and aligned at the DatetimeValue `alignment`. This function + * return the smallest DatetimeValue in that lattice which is greater than or equal to + * `value`. + * + * return: a DatetimeValue + */ + DatetimeMeasure.prototype.firstSpacingLocationAtOrAfter = function (/*DatetimeValue*/value, /*DatetimeValue*/alignment) { + switch (this.unit) { + case DatetimeMeasure.MONTH: + return DatetimeMeasure.findTickmarkWithMonthSpacing(value, alignment, this.measure); + case DatetimeMeasure.YEAR: + return DatetimeMeasure.findTickmarkWithMonthSpacing(value, alignment, this.measure * 12); + //case DatetimeMeasure.MILLISECOND: + //case DatetimeMeasure.SECOND: + //case DatetimeMeasure.MINUTE: + //case DatetimeMeasure.HOUR: + //case DatetimeMeasure.DAY: + //case DatetimeMeasure.WEEK: + default: + return DatetimeMeasure.findTickmarkWithMillisecondSpacing(value.getRealValue(), alignment.getRealValue(), this.getRealValue()); + } + }; + + /** + * This function is just like `firstSpacingLocationAtOrAfter` above, but returns the + * greatest DatetimeValue in the lattice that is less than or equal to `value`. + * + * return: a DatetimeValue + */ + DatetimeMeasure.prototype.lastSpacingLocationAtOrBefore = function (/*DatetimeValue*/value, /*DatetimeValue*/alignment) { + var x = this.firstSpacingLocationAtOrAfter(value, alignment); + if (x.eq(value)) { + return x; + } + var y = x.add(this.negative()); + return y; + }; + + DatetimeMeasure.prototype.toString = function () { + return this.measure.toString() + this.unit.toString(); + }; + + DatetimeMeasure.MILLISECOND = new DatetimeUnit("ms"); + DatetimeMeasure.SECOND = new DatetimeUnit("s"); + DatetimeMeasure.MINUTE = new DatetimeUnit("m"); + DatetimeMeasure.HOUR = new DatetimeUnit("H"); + DatetimeMeasure.DAY = new DatetimeUnit("D"); + DatetimeMeasure.WEEK = new DatetimeUnit("W"); + DatetimeMeasure.MONTH = new DatetimeUnit("M"); + DatetimeMeasure.YEAR = new DatetimeUnit("Y"); + + ns.DatetimeMeasure = DatetimeMeasure; + +}); +/*global sprintf */ + +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var DatetimeValue = function (value) { + if (typeof(value) !== "number") { + throw new Error("DatetimeValue requires its parameter to be a number"); + } + this.value = new Date(value); + }; + + DatetimeValue.prototype.getRealValue = function () { + return this.value.getTime(); + }; + + DatetimeValue.prototype.type = ns.DataValue.DATETIME; + + DatetimeValue.prototype.clone = function() { + return new DatetimeValue(this.getRealValue()); + }; + + DatetimeValue.parse = function (string) { + var Y = 0, + M = 0, + D = 1, + H = 0, + m = 0, + s = 0, + ms = 0; + if (typeof(string) === "string") { + string = string.replace(/[\.\-\:\s]/g, ""); + if (string.length === 4) { + Y = parseInt(string, 10); + } else if (string.length === 6) { + Y = parseInt(string.substring(0,4), 10); + M = parseInt(string.substring(4,6), 10) - 1; + } else if (string.length === 8) { + Y = parseInt(string.substring(0,4), 10); + M = parseInt(string.substring(4,6), 10) - 1; + D = parseInt(string.substring(6,8), 10); + } else if (string.length === 10) { + Y = parseInt(string.substring(0,4), 10); + M = parseInt(string.substring(4,6), 10) - 1; + D = parseInt(string.substring(6,8), 10); + H = parseInt(string.substring(8,10), 10); + } else if (string.length === 12) { + Y = parseInt(string.substring(0,4), 10); + M = parseInt(string.substring(4,6), 10) - 1; + D = parseInt(string.substring(6,8), 10); + H = parseInt(string.substring(8,10), 10); + m = parseInt(string.substring(10,12), 10); + } else if (string.length === 14) { + Y = parseInt(string.substring(0,4), 10); + M = parseInt(string.substring(4,6), 10) - 1; + D = parseInt(string.substring(6,8), 10); + H = parseInt(string.substring(8,10), 10); + m = parseInt(string.substring(10,12), 10); + s = parseInt(string.substring(12,14), 10); + } else if (string.length === 15 || string.length === 16 || string.length === 17) { + Y = parseInt(string.substring(0,4), 10); + M = parseInt(string.substring(4,6), 10) - 1; + D = parseInt(string.substring(6,8), 10); + H = parseInt(string.substring(8,10), 10); + m = parseInt(string.substring(10,12), 10); + s = parseInt(string.substring(12,14), 10); + ms = parseInt(string.substring(14,17), 10); + } else if (string === "0") { + // handles the case of "0", which parser should convert to the Unix epoch + Y = 1970; + } else { + throw new Error("Incorrect input format for Datetime Value's parse method"); + } + } else { + throw new Error("Datetime Value's parse method requires its parameter to be a string"); + } + return new DatetimeValue(Date.UTC(Y, M, D, H, m, s, ms)); + }; + + + DatetimeValue.prototype.toString = function () { + var Y, M, D, H, m, s, ms; + + Y = sprintf("%04s", this.value.getUTCFullYear().toString()); + M = sprintf("%02s", (this.value.getUTCMonth() + 1).toString()); + D = sprintf("%02s", this.value.getUTCDate().toString()); + H = sprintf("%02s", this.value.getUTCHours().toString()); + m = sprintf("%02s", this.value.getUTCMinutes().toString()); + s = sprintf("%02s", this.value.getUTCSeconds().toString()); + ms = "." + sprintf("%03s", this.value.getUTCMilliseconds().toString()); + + if (ms === ".000") { + ms = ""; + } + + return Y + M + D + H + m + s + ms; + }; + + + DatetimeValue.prototype.compareTo = function (x) { + if (this.getRealValue() < x.getRealValue()) { + return -1; + } else if (this.getRealValue() > x.getRealValue()) { + return 1; + } + return 0; + }; + + DatetimeValue.prototype.addRealValue = function ( realValueIncr ) { + return new DatetimeValue(this.value.getTime() + realValueIncr); + }; + + DatetimeValue.prototype.add = function ( /*DataMeasure*/ measure) { + var date = new DatetimeValue(this.getRealValue()); + switch (measure.unit) { + case ns.DatetimeMeasure.MILLISECOND: + date.value.setUTCMilliseconds(date.value.getUTCMilliseconds() + measure.measure); + break; + case ns.DatetimeMeasure.SECOND: + date.value.setUTCSeconds(date.value.getUTCSeconds() + measure.measure); + break; + case ns.DatetimeMeasure.MINUTE: + date.value.setUTCMinutes(date.value.getUTCMinutes() + measure.measure); + break; + case ns.DatetimeMeasure.HOUR: + date.value.setUTCHours(date.value.getUTCHours() + measure.measure); + break; + case ns.DatetimeMeasure.DAY: + date.value.setUTCDate(date.value.getUTCDate() + measure.measure); + break; + case ns.DatetimeMeasure.WEEK: + date.value.setUTCDate(date.value.getUTCDate() + measure.measure * 7); + break; + case ns.DatetimeMeasure.MONTH: + date.value.setUTCMonth(date.value.getUTCMonth() + measure.measure); + break; + case ns.DatetimeMeasure.YEAR: + date.value.setUTCFullYear(date.value.getUTCFullYear() + measure.measure); + break; + } + return date; + }; + + ns.DataValue.mixinComparators(DatetimeValue.prototype); + + ns.DatetimeValue = DatetimeValue; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var Filter, + utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot.filter); + + Filter = new window.jermaine.Model("Filter", function () { + this.hasMany("options").eachOfWhich.validatesWith(function (option) { + return option instanceof ns.FilterOption; + }); + this.hasA("type").which.validatesWith(function (type) { + return typeof(type) === "string"; + }); + + utilityFunctions.insertDefaults(this, defaultValues.plot.filter, attributes); + }); + + ns.Filter = Filter; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot.filter.option), + FilterOption = new window.jermaine.Model("FilterOption", function () { + this.hasA("name").which.validatesWith(function (name) { + return typeof(name) === "string"; + }); + this.hasA("value").which.validatesWith(function (value) { + return typeof(value) === "string"; + }); + + utilityFunctions.insertDefaults(this, defaultValues.plot.filter.option, attributes); + }); + + ns.FilterOption = FilterOption; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + var Box = window.multigraph.math.Box; + + /** + * The Graph Jermaine model controls the properties for an individual Graph. + * + * @class Graph + * @for Graph + * @constructor + */ + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues), + Graph = new window.jermaine.Model("Graph", function () { + + /** + * Child model which controls the properties of the Graph's Window. + * + * @property window + * @type {Window} + * @author jrfrimme + */ + this.hasA("window").which.validatesWith(function (w) { + return w instanceof ns.Window; + }); + /** + * Child model which controls the properties of the Graph's Plotarea. + * + * @property plotarea + * @type {Plotarea} + * @author jrfrimme + */ + this.hasA("plotarea").which.validatesWith(function (plotarea) { + return plotarea instanceof ns.Plotarea; + }); + + + /** + * Child model which controls the properties of the Graph's Legend. + * + * @property legend + * @type {Legend} + * @author jrfrimme + */ + this.hasA("legend").which.validatesWith(function (legend) { + return legend instanceof ns.Legend; + }); + /** + * Child model which controls the properties of the Graph's Background. + * + * @property background + * @type {Background} + * @author jrfrimme + */ + this.hasA("background").which.validatesWith(function (background) { + return background instanceof ns.Background; + }); + + /** + * Child model which controls the properties of the Graph's Title. + * + * @property title + * @type {Title} + * @author jrfrimme + */ + this.hasA("title").which.validatesWith(function (title) { + return title instanceof ns.Title; + }); + /** + * Jermaine Attr_List of the Graph's Axes. + * + * @property axes + * @type {Axis} + * @author jrfrimme + */ + this.hasMany("axes").eachOfWhich.validateWith(function (axis) { + return axis instanceof ns.Axis; + }); + /** + * Jermiane Attr_List of the Graph's Plots. + * + * @property plots + * @type {Plot} + * @author jrfrimme + */ + this.hasMany("plots").eachOfWhich.validateWith(function (plot) { + return plot instanceof ns.Plot; + }); + /** + * Jermiane Attr_List of the Graph's Data sets. + * + * @property data + * @type {Data} + * @author jrfrimme + */ + this.hasMany("data").eachOfWhich.validateWith(function (data) { + return data instanceof ns.Data; + }); + + /** + * Stores the computed width and height of the Graph's windowBox. + * + * @property windowBox + * @type {} + * @author jrfrimme + */ + this.hasA("windowBox").which.validatesWith(function (val) { + return val instanceof Box; + }); + /** + * Stores the computed width and height of the Graph's paddingBox. + * + * @property paddingBox + * @type {} + * @author jrfrimme + */ + this.hasA("paddingBox").which.validatesWith(function (val) { + return val instanceof Box; + }); + /** + * Stores the computed width and height of the Graph's plotBox. + * + * @property plotBox + * @type {} + * @author jrfrimme + */ + this.hasA("plotBox").which.validatesWith(function (val) { + return val instanceof Box; + }); + + /** + * The containing Multigraph object + * + * @property multigraph + * @type {} + * @author mbp + */ + this.hasA("multigraph").which.validatesWith(function (val) { + return val instanceof window.multigraph.core.Multigraph; + }); + + this.hasA("x0").which.isA("number"); + this.hasA("y0").which.isA("number"); + + this.isBuiltWith(function () { + this.window( new ns.Window() ); + this.plotarea( new ns.Plotarea() ); + this.background( new ns.Background() ); + }); + + this.respondsTo("postParse", function () { + var i, + that = this, + handleAjaxEvent = function(event) { + if (event.action === 'start') { + if (that.multigraph()) { + that.multigraph().busySpinnerLevel(1); + } + } else if (event.action === 'complete') { + if (that.multigraph()) { + that.multigraph().busySpinnerLevel(-1); + } + } + }; + + for (i=0; i 0, then the + * corners are rounded off using circles whose radius is cornerradius pixels. + * + * @property cornerradius + * @deprecated + * @type {Integer} + * @author jrfrimme + */ + this.hasA("cornerradius").which.isAn("integer"); + /** + * A coordinate pair which gives the relative location of the Title's anchor point. + * + * @property anchor + * @type {Point} + * @author jrfrimme + */ + this.hasA("anchor").which.validatesWith(function (anchor) { + return anchor instanceof window.multigraph.math.Point; + }); + /** + * A coordinate pair which gives the location of the Title's base point, relative to + * its Graph's plot or padding box - determined by the `frame` attribute. + * + * @property base + * @type {Point} + * @author jrfrimme + */ + this.hasA("base").which.validatesWith(function (base) { + return base instanceof window.multigraph.math.Point; + }); + /** + * A coordinate pair of pixel offsets for the base point. + * + * @property position + * @type {Point} + * @author jrfrimme + */ + this.hasA("position").which.validatesWith(function (position) { + return position instanceof window.multigraph.math.Point; + }); + /** + * The font-size of the title. Currently is a constant. + * + * @property font-size + * @type {String} + * @author jrfrimme + */ + this.hasA("fontSize").which.isA("string").and.defaultsTo("18px"); + + /** + * Determines the geometry of the Title's text. + * + * @method initializeGeometry + * @chainable + * @param {Object} graphicsContext + * @author jrfrimme + */ + this.respondsTo("initializeGeometry", function (graphicsContext) { + graphicsContext.fontSize = this.fontSize(); + this.text().initializeGeometry(graphicsContext); + return this; + }); + + /** + * Renders the Graph Title. Overridden by implementations in graphics drivers. + * + * @method render + * @private + * @author jrfrimme + */ + this.respondsTo("render", function () {}); + + this.isBuiltWith("text", "graph"); + + utilityFunctions.insertDefaults(this, defaultValues.title, attributes); + + }); + + ns.Title = Title; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.horizontalaxis.grid), + Grid = new window.jermaine.Model("Grid", function () { + this.hasA("color").which.validatesWith(function (color) { + return color instanceof window.multigraph.math.RGBColor; + }); + this.hasA("visible").which.isA("boolean"); + + utilityFunctions.insertDefaults(this, defaultValues.horizontalaxis.grid, attributes); + }); + + ns.Grid = Grid; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.legend.icon), + Icon = new window.jermaine.Model("Icon", function () { + this.hasA("height").which.isA("integer"); + this.hasA("width").which.isA("integer"); + this.hasA("border").which.isA("integer"); + + utilityFunctions.insertDefaults(this, defaultValues.legend.icon, attributes); + }); + + ns.Icon = Icon; + + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.background.img), + Img = new window.jermaine.Model("Img", function () { + this.hasA("src").which.isA("string"); + this.hasA("anchor").which.validatesWith(function (anchor) { + return anchor instanceof window.multigraph.math.Point; + }); + this.hasA("base").which.validatesWith(function (base) { + return base instanceof window.multigraph.math.Point; + }); + this.hasA("position").which.validatesWith(function (position) { + return position instanceof window.multigraph.math.Point; + }); + this.hasA("frame").which.validatesWith(function (frame) { + return frame === Img.PADDING || frame === Img.PLOT; + }); + this.isBuiltWith("src"); + + utilityFunctions.insertDefaults(this, defaultValues.background.img, attributes); + }); + + Img.PADDING = "padding"; + Img.PLOT = "plot"; + + ns.Img = Img; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.horizontalaxis.labels.label), + Axis = ns.Axis, + DataValue = ns.DataValue, + + Labeler = new window.jermaine.Model("Labeler", function () { + + var getValue = function (valueOrFunction) { + if (typeof(valueOrFunction) === "function") { + return valueOrFunction(); + } else { + return valueOrFunction; + } + }; + + this.hasA("axis").which.validatesWith(function (axis) { + return axis instanceof ns.Axis; + }); + this.hasA("formatter").which.validatesWith(ns.DataFormatter.isInstance); + this.hasA("start").which.validatesWith(ns.DataValue.isInstance); + this.hasA("angle").which.isA("number"); + this.hasA("position").which.validatesWith(function (position) { + return position instanceof window.multigraph.math.Point; + }); + this.hasA("anchor").which.validatesWith(function (anchor) { + return anchor instanceof window.multigraph.math.Point; + }); + this.hasA("spacing").which.validatesWith(ns.DataMeasure.isInstance); + this.hasA("densityfactor").which.isA("number").and.which.defaultsTo(1.0); + + this.hasA("color").which.validatesWith(function (color) { + return color instanceof window.multigraph.math.RGBColor; + }); + + this.hasA("visible").which.isA("boolean").and.which.defaultsTo(true); + + this.isBuiltWith("axis", function () { + var labelsDefaults = defaultValues.horizontalaxis.labels; + if (this.axis().type() === DataValue.DATETIME) { + this.start( getValue(labelsDefaults['start-datetime']) ); + } else { + this.start( getValue(labelsDefaults['start-number']) ); + } + }); + + this.respondsTo("initializeGeometry", function (graph) { + var axis = this.axis(), + plotBox = graph.plotBox(), + labelDefaults = defaultValues.horizontalaxis.labels.label; + + if (this.position() === undefined) { + if (axis.orientation() === Axis.HORIZONTAL) { + if (axis.perpOffset() > plotBox.height()/2) { + this.position( getValue(labelDefaults["position-horizontal-top"]) ); + } else { + this.position( getValue(labelDefaults["position-horizontal-bottom"]) ); + } + } else { + if (axis.perpOffset() > plotBox.width()/2) { + this.position( getValue(labelDefaults["position-vertical-right"]) ); + } else { + this.position( getValue(labelDefaults["position-vertical-left"]) ); + } + } + } + + if (this.anchor() === undefined) { + if (axis.orientation() === Axis.HORIZONTAL) { + if (axis.perpOffset() > plotBox.height()/2) { + this.anchor( getValue(labelDefaults["anchor-horizontal-top"]) ); + } else { + this.anchor( getValue(labelDefaults["anchor-horizontal-bottom"]) ); + } + } else { + if (axis.perpOffset() > plotBox.width()/2) { + this.anchor( getValue(labelDefaults["anchor-vertical-right"]) ); + } else { + this.anchor( getValue(labelDefaults["anchor-vertical-left"]) ); + } + } + } + }); + + this.respondsTo("isEqualExceptForSpacing", function (labeler) { + // return true iff the given labeler and this labeler are equal in every way + // except for their spacing values + return ((this.axis() === labeler.axis() ) && + (this.formatter().getFormatString() === labeler.formatter().getFormatString() ) && + (this.start() .eq( labeler.start() ) ) && + (this.angle() === labeler.angle() ) && + (this.position() .eq( labeler.position() ) ) && + (this.anchor() .eq( labeler.anchor() ) ) && + (this.densityfactor() === labeler.densityfactor() ) + ); + }); + + + this.hasA("iteratorNextValue").which.validatesWith(ns.DataValue.isInstanceOrNull).and.which.defaultsTo(null); + this.hasA("iteratorMinValue").which.validatesWith(ns.DataValue.isInstance); + this.hasA("iteratorMaxValue").which.validatesWith(ns.DataValue.isInstance); + + this.respondsTo("prepare", function (minDataValue, maxDataValue) { + this.iteratorMinValue(minDataValue); + this.iteratorMaxValue(maxDataValue); + this.iteratorNextValue( this.spacing().firstSpacingLocationAtOrAfter(minDataValue, this.start()) ); + }); + + this.respondsTo("hasNext", function () { + var value = this.iteratorNextValue(); + if (value === null || value === undefined) { + return false; + } + return value.le(this.iteratorMaxValue()); + }); + + this.respondsTo("peekNext", function () { + var value = this.iteratorNextValue(), + maxValue = this.iteratorMaxValue(); + if (value === null || value === undefined) { + return undefined; + } + if (maxValue !== undefined && value.gt(maxValue)) { + return undefined; + } + return value; + }); + + this.respondsTo("next", function () { + var value = this.iteratorNextValue(), + maxValue = this.iteratorMaxValue(); + if (value === null || value === undefined) { + return undefined; + } + if (maxValue !== undefined && value.gt(maxValue)) { + return undefined; + } + this.iteratorNextValue( value.add( this.spacing() ) ); + return value; + }); + + this.respondsTo("getLabelDensity", function (graphicsContext) { + var axis = this.axis(), + pixelSpacing = this.spacing().getRealValue() * axis.axisToDataRatio(), + minRealValue = axis.dataMin().getRealValue(), + maxRealValue = axis.dataMax().getRealValue(), + representativeRealValue = minRealValue + 0.51234567 * (maxRealValue - minRealValue), + representativeValue = DataValue.create(axis.type(), representativeRealValue ), + representativeValueString = this.formatter().format(representativeValue); + + // length of the formatted axis representative value, in pixels + var pixelFormattedValue = ( + (axis.orientation() === Axis.HORIZONTAL) ? + this.measureStringWidth(graphicsContext, representativeValueString) : + this.measureStringHeight(graphicsContext, representativeValueString) + ); + // return the ratio -- the fraction of the spacing taken up by the formatted string + return pixelFormattedValue / ( pixelSpacing * this.densityfactor() ); + }); + + + this.respondsTo("measureStringWidth", function (graphicsContext, string) { + // Graphics drivers should replace this method with an actual implementation; this + // is just a placeholder. The implementation should return the width, in pixels, + // of the given string. Of course this is dependent on font choice, size, etc, + // but we gloss over that at the moment. Just return the width of the string + // using some reasonable default font for now. Later on, we'll modify this + // function to use font information. + return string.length*30; + }); + this.respondsTo("measureStringHeight", function (graphicsContext, string) { + // see comment for measureStringWidth() above + return string.length*30; + }); + this.respondsTo("renderLabel", function (graphicsContext, value) { + // Graphics drivers should replace this method with an actual implementation; this + // is just a placeholder. The implementation should draw the string for the given + // value, formatted by the labeler's DataFormatter, in the location along the axis + // determined by the value itself, and the labeler's position, anchor, and angle + // attributes. + }); + + + utilityFunctions.insertDefaults(this, defaultValues.horizontalaxis.labels.label, attributes); + }); + + ns.Labeler = Labeler; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + var Legend, + utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.legend); + + /** + * Legend is a Jermaine model that supports the rendering of Multigraph Legends. + * + * The methods for this object take a parameter called `graphicsContext`, which is a + * driver-specific object that stores whatever state/configuration is needed by the + * driver. Each driver is responsible for creating its own graphicsContext object and + * passing it to these methods, which in turn pass that object on to the driver-specific + * methods that they call. + * + * @class Legend + * @for Legend + * @constructor + * @requires Point,RGBColor,Plot,Icon + */ + Legend = new window.jermaine.Model("Legend", function () { + /** + * The value which determines if the legend will be rendered; a value of `true` means the Legend will + * be drawn while `false` means that it will not. + * + * @property visible + * @type {boolean} + * @author jrfrimme + */ + this.hasA("visible").which.validatesWith(function (visible) { + return typeof visible === "boolean" || visible === null; + }); + + /** + * The value which gives the location of the base point relative to the Legend's frame. + * + * @property base + * @type {Point} + * @author jrfrimme + */ + this.hasA("base").which.validatesWith(function (base) { + return base instanceof window.multigraph.math.Point; + }); + + /** + * The value which gives the location of the Legend's anchor point to be attached to the base point. + * + * @property anchor + * @type {Point} + * @author jrfrimme + */ + this.hasAn("anchor").which.validatesWith(function (anchor) { + return anchor instanceof window.multigraph.math.Point; + }); + + /** + * A coordinate pair of pixel offsets for the base point. + * + * @property position + * @type {Point} + * @author jrfrimme + */ + this.hasA("position").which.validatesWith(function (position) { + return position instanceof window.multigraph.math.Point; + }); + + /** + * The value which determines whether the legend is positioned relative to the plot area or the padding + * box. A value of `plot` means the Legend will be drawn relative to the plot area while `padding` means + * that it will the padding box. + * + * @property frame + * @type {String} + * @author jrfrimme + */ + this.hasA("frame").which.validatesWith(function (frame) { + return frame === "plot" || frame === "padding"; + }); + + /** + * The value which determines the background color of the Legend. + * + * @property color + * @type {RGBColor} + * @author jrfrimme + */ + this.hasA("color").which.validatesWith(function (color) { + return color instanceof window.multigraph.math.RGBColor; + }); + + /** + * The value which determines the bordercolor of the Legend. + * + * @property bordercolor + * @type {RGBColor} + * @author jrfrimme + */ + this.hasA("bordercolor").which.validatesWith(function (bordercolor) { + return bordercolor instanceof window.multigraph.math.RGBColor; + }); + + /** + * The value which determines the opacity of the Legend; depending on where the Legend is positioned it + * may obscure parts of the plot data. + * + * @property opacity + * @type {Float} + * @author jrfrimme + */ + this.hasA("opacity").which.validatesWith(function (opacity) { + return utilityFunctions.validateNumberRange(opacity, 0.0, 1.0); + }); + + /** + * The value which determines the thickness of the border drawn around the Legend; a value of `0` turns + * the border off. + * + * @property border + * @type {Integer} + * @author jrfrimme + */ + this.hasA("border").which.isA("integer"); + + /** + * The value which determines the number of rows to be used for Plot entries in the Legend. If left + * unspecified then rows will be inserted to account for each Plot entry. + * + * @property rows + * @type {Integer} + * @author jrfrimme + */ + this.hasA("rows").which.isA("integer").and.isGreaterThan(0); + + /** + * The value which determines the number of columns to be used for Plot entries in the Legend. If rows + * is set while columns is left unspecified then columns will be inserted to account for each Plot + * entry. + * + * @property columns + * @type {Integer} + * @author jrfrimme + */ + this.hasA("columns").which.isA("integer").and.isGreaterThan(0); + + /** + * The value which determines whether the corners of the legend box are rounded when drawn. A value of + * `0` means that the corners will be drawn square while values greater than `0` mean that the corners + * are rounded off with circles whose radius in pixels is this value. + * + * @property cornerradius + * @type {Integer} + * @author jrfrimme + */ + this.hasA("cornerradius").which.isA("integer"); + + /** + * The value which determines the pixel width of the padding between the Legend border and its entries. + * + * @property padding + * @type {Integer} + * @author jrfrimme + */ + this.hasA("padding").which.isA("integer"); + + /** + * A optional sub-model which determines the appearance of the Icons for the Plot entries. + * + * @property icon + * @type {Icon} + * @author jrfrimme + */ + this.hasAn("icon").which.validatesWith(function (icon) { + return icon instanceof ns.Icon; + }); + + this.isBuiltWith(function () { + this.icon( new ns.Icon() ); + }); + + /** + * Pointers to Plot models that have entries in the Legend. + * + * @property plots + * @type {Plot} + * @author jrfrimme + */ + this.hasMany("plots").eachOfWhich.validateWith(function (plot) { + return plot instanceof ns.Plot; + }); + + /** + * Internal value which determines the number of pixels between an entries icon and its border. + * + * @property iconOffset + * @type {Integer} + * @default 5 + * @private + * @final + * @author jrfrimme + */ + this.hasA("iconOffset").which.isAn("integer").and.defaultsTo(5); + + /** + * Internal value which determines the number of pixels between an entries label and its icon. + * + * @property labelOffset + * @type {Integer} + * @default 5 + * @private + * @final + * @type {} + * @author jrfrimme + */ + this.hasA("labelOffset").which.isAn("integer").and.defaultsTo(5); + + /** + * Internal value which determines the number of pixels between the right end of an entries label and + * its border + * + * @property labelEnding + * @type {Integer} + * @default 15 + * @private + * @final + * @author jrfrimme + */ + this.hasA("labelEnding").which.isAn("integer").defaultsTo(15); + + /** + * Computed value of the width of the Legend. + * + * @property width + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("width").which.isA("number"); + + /** + * Computed value of the height of the Legend. + * + * @property height + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("height").which.isA("number"); + + /** + * Computed `x` value of the Legend's lower left corner relative to its frame. + * + * @property x + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("x").which.isA("number"); + + /** + * Computed `y` value of the Legend's lower left corner relative to its frame. + * + * @property y + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("y").which.isA("number"); + + /** + * Computed width of an individual plot entry. + * + * @property blockWidth + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("blockWidth").which.isA("number"); + + /** + * Computed height of an individual plot entry. + * + * @property blockHeight + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("blockHeight").which.isA("number"); + + /** + * Computed width of the longest label of all plot entries. + * + * @property maxLabelWidth + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("maxLabelWidth").which.isA("number"); + + /** + * Maximum value of the Icon's height and the computed height of the tallest label of all plot entries. + * + * @property maxLabelHeight + * @type {Float} + * @private + * @final + * @author jrfrimme + */ + this.hasA("maxLabelHeight").which.isA("number"); + + this.respondsTo("determineVisibility", function () { + switch (this.visible()) { + case true: + return true; + case false: + return false; + case null: + if (this.plots().size() > 1) { + return true; + } else { + return false; + } + } + }); + + /** + * Initializes the Legend's geometry. Determines values for the internal attributes `maxLabelWidth`, + * `maxLabelHeight`, `blockWidth`, `blockHeight`, `width`, `height`, `x` and `y`; these values + * determine the size and position of the legend and its various internal components, and need + * to be recomputed whenever the geometry of the containing graph changes; this method is + * called by Graph.initializeGeometry(). + * + * @method initializeGeometry + * @chainable + * @param {Graph} graph Jermaine Graph model + * @param {Object} graphicsContext driver-specific graphics context object + * @author jrfrimme + * @todo Find out whether or not padding needs to be taken into consideration. + */ + this.respondsTo("initializeGeometry", function (graph, graphicsContext) { + var anchor = this.anchor(), + base = this.base(), + position = this.position(), + iconOffset = this.iconOffset(), + widths = [], + heights = [], + label, + i; + + if (this.determineVisibility() === false) { + return this; + } + + for (i = 0; i < this.plots().size(); i++) { + label = this.plots().at(i).legend().label(); + if (label !== undefined) { + label.initializeGeometry(graphicsContext); + widths.push(label.origWidth()); + heights.push(label.origHeight()); + } + } + + widths.sort(function (a, b) { + return b - a; + }); + heights.sort(function (a, b) { + return b - a; + }); + this.maxLabelWidth(widths[0]); + this.maxLabelHeight(Math.max(heights[0], this.icon().height())); + + this.blockWidth(iconOffset + this.icon().width() + this.labelOffset() + this.maxLabelWidth() + this.labelEnding()); + this.blockHeight(iconOffset + this.maxLabelHeight()); + +// TODO: find out whether or not padding needs to be taken into consideration + this.width((2 * this.border()) + (this.columns() * this.blockWidth())); + this.height((2 * this.border()) + (this.rows() * this.blockHeight()) + iconOffset); + + if (this.frame() === "padding") { + this.x(((base.x() + 1) * graph.paddingBox().width()/2) - ((anchor.x() + 1) * this.width()/2) + position.x()); + this.y(((base.y() + 1) * graph.paddingBox().height()/2) - ((anchor.y() + 1) * this.height()/2) + position.y()); + } else { + this.x(((base.x() + 1) * graph.plotBox().width()/2) - ((anchor.x() + 1) * this.width()/2) + position.x()); + this.y(((base.y() + 1) * graph.plotBox().height()/2) - ((anchor.y() + 1) * this.height()/2) + position.y()); + } + + return this; + }); + + /** + * Renders the legend; calls various driver-specific graphics functions to do the + * actual drawing of the various parts of the legend (background, borders, icons, + * text). + * + * @method render + * @chainable + * + * @param {Object} graphicsContext driver-specific graphics context object + * + * @author jrfrimme + */ + this.respondsTo("render", function (graphicsContext) { + var plots = this.plots(), + icon = this.icon(), + blockx, blocky, + iconx, icony, + labelx, labely, + plotCount = 0, + r, c; + + if (this.determineVisibility() === false) { + return this; + } + + // perform any neccesary setup + this.begin(graphicsContext); + + // Draw the legend box + this.renderLegend(graphicsContext); + + for (r = 0; r < this.rows(); r++) { + if (plotCount >= plots.size()) { + break; + } + blocky = this.border() + ((this.rows() - r - 1) * this.blockHeight()); + icony = blocky + this.iconOffset(); + labely = icony; + for (c = 0; c < this.columns(); c++) { + if (plotCount >= plots.size()) { + break; + } + blockx = this.border() + (c * this.blockWidth()); + iconx = blockx + this.iconOffset(); + labelx = iconx + icon.width() + this.labelOffset(); + + // Draw the icon + plots.at(plotCount).renderer().renderLegendIcon(graphicsContext, iconx, icony, icon, this.opacity()); + + // Draw the icon border + if (icon.border() > 0) { + icon.renderBorder(graphicsContext, iconx, icony, this.opacity()); + } + + // Write the text + this.renderLabel(plots.at(plotCount).legend().label(), graphicsContext, labelx, labely); + + plotCount++; + } + } + + // preform any neccesary steps at the end of rendering + this.end(graphicsContext); + + return this; + }); + + utilityFunctions.insertDefaults(this, defaultValues.legend, attributes); + }); + + ns.Legend = Legend; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + /** + * The Mixin model provides a convenient way for Jermaine + * applications to "mix in" additional functionality to a model, + * from outside the model's initial definition. + * + * The ability to add features (methods and/or attributes) to a + * Jermaine model outside its initial definition already exists in + * Jermaine -- this Mixin model does not actually add new + * functionality to Jermaine; it just provides a convenient + * pattern for grouping additional features together and applying + * them to a model as a group. + * + * The Mixin model maintains an internal list of functions, called + * mixin functions, and provides an add() method for adding a + * function to that list. + * + * The apply() method calls all of the mixinfunctions that have been + * added to the list, passing each one the same arguments + * that were passed to the apply() function itself. + * + * That's it. That's all the Mixin class does. It's up to you to + * put whatever jermaine-model-extending code you want in the + * mixin functions you add to the Mixin; the Mixin simply serves + * as a place to hold them all, and a convenient way to execute + * them all at once. + * + * @class Mixin + * @for Mixin + * @author mbp + */ + var Mixin = new window.jermaine.Model("Mixin", function () { + + /** + * The internal list of functions to be applied. + * + * @property mixinfuncs + * @private + * @type {} + * @author mbp + */ + this.hasMany("mixinfuncs"); + + /** + * Internal value for tracking whether apply() has been called + * for this Mixin. + * + * @property applied + * @type {} + * @private + * @author mbp + */ + this.hasA("applied").which.isA("boolean").defaultsTo(false); + + /** + * Adds a function to this Mixin's mixin list. Does not check + * to see if the function is already on the list -- just blindly + * appends the given function to the list. + * + * @method add + * @param {} func + * @author mbp + */ + this.respondsTo("add", function (mixinfunc) { + this.mixinfuncs().add(mixinfunc); + }); + + /** + * Call each of this Mixin's mixin functions. Any + * arguments passed to apply() will be passed through to each + * mixin function called. + * + * apply() checks to see whether it has ever been called + * before for this Mixin, and only executes the mixin + * functions if this is the first call to apply(); calls to + * apply() after the first one will have no effect. (This is + * true even if additional mixin functions are added after + * apply() is called; the Mixin maintains a single internal + * Boolean value that tracks whether apply() has been called.) + * + * @method apply + * @author mbp + */ + this.respondsTo("apply", function () { + if (! this.applied()) { + var i; + for (i=0; i 0) { + $(div).width(options.width); + } + if (options.height !== undefined && options.height > 0) { + $(div).height(options.height); + } + + // + // NOTE: each of the Multigraph.create{DRIVER}Graph functions below takes an + // "options" object argument just like Multigraph.createGraph does. In general this + // "options" object is the same as the one passed to this Multigraph.createGraph + // function, but it differs in one way: Instead of containing separate "error" and + // "warning" properties which are optional, the "options" object passed to the + // Multigraph.create{DRIVER}Graph functions requires a single (non-optional!) + // "messageHandler" property, which in turn contains "error" and "warning" properties + // which are functions for handling errors and warnings, respectively. Both the + // "error" and a "warning" properties must be present in the "messageHandler" object + // and must point to valid functions. + // + // The rationale behind this is to allow convenience for callers of the more "public" + // Multigraph.createGraph function, so that they don't have to specify an error or + // warning handler function unless they want to use custom ones. The internal + // Multigraph.create{DRIVER}Graph functions, however, always need access to error and + // warning functions, and often need to pass both of them on to other functions, so + // they're encapsulated together into a single messageHandler object to make this + // easier. + // + // Build the messageHandler object: + messageHandler = {}; + if (typeof(options.error) === "function") { + messageHandler.error = options.error; + } + if (typeof(options.warning) === "function") { + messageHandler.warning = options.warning; + } + + if (! messageHandler.error || ! messageHandler.warning) { + defaultMessageHandler = Multigraph.createDefaultMessageHandlers(div); + if (! messageHandler.error) { + messageHandler.error = defaultMessageHandler.error; + } + if (! messageHandler.warning) { + messageHandler.warning = defaultMessageHandler.warning; + } + } + options.messageHandler = messageHandler; + + if (options.muglString !== undefined) { + // delegate to the driver-specific create function + if (options.driver === "canvas") { + return Multigraph.createCanvasGraphFromString(options); + } else if (options.driver === "raphael") { + return Multigraph.createRaphaelGraphFromString(options); + } else { + options.messageHanlder.error(new Error("invalid graphic driver '" + options.driver + "' specified to Multigraph.createGraph")); + return undefined; + } + } + + // delegate to the driver-specific create function + if (options.driver === "canvas") { + return Multigraph.createCanvasGraph(options); + } else if (options.driver === "raphael") { + return Multigraph.createRaphaelGraph(options); + } else { + options.messageHanlder.error(new Error("invalid graphic driver '" + options.driver + "' specified to Multigraph.createGraph")); + return undefined; + } + }; + + /** + * `window.multigraph.create` is an alias for `window.multigraph.core.Multigraph.createGraph`. + * + * @method window.multigraph.create + * @param {Object} options + * + * @param {String|HTML Element|jQuery Object} options.div (REQUIRED) + * The DOM element div into which the multigraph should be + * placed; this value may be either (a) a string which is taken + * to be the id attribute of a div in the page, (b) a reference + * to the div DOM element itself, or (c) a jQuery object + * corresponding to the div DOM element. + * + * @param {URI} options.mugl (REQUIRED) the URL from which the MUGL + * file for the Multigraph can be loaded + * + * @param {String} options.driver (OPTIONAL) Indicates which + * graphics driver to use; should be one of the strings + * "canvas", "raphael", or "auto". The default (which is + * used if the 'driver' tag is absent) is "auto", which + * causes Multigraph to check the features of the browser + * it is running in and choose the most appropriate driver. + * + * @param {Function} options.error (OPTIONAL) A function for + * displaying error messages to the user. Multigraph will + * call this function if and when it encounters an error. The + * function should receive a single argument which is an + * instance of the JavaScrip Error object. The default is to + * use Multigraph's own internal mechanism for displaying user + * messages. + * + * @param {Function} options.warning (OPTIONAL) A function for + * displaying warning messages to the user. Multigraph will + * call this function if and when it needs to display a + * warning message. The function should receive a single + * argument which is an instance of the JavaScript Error + * object. The default is to use Multigraph's own internal + * mechanism for displaying user messages. + * @return {Promise} jQuery promise which provides interaction with + * the graph through its `done` function. + * @static + * @author jrfrimme + */ + window.multigraph.create = Multigraph.createGraph; + + /** + * Creates default error and warning functions for multigraph. + * + * @method createDefaultMessageHandlers + * @param {HTML Element} div + * @static + * @return {Object} Object keyed by `error` and `warning` which respectively point to + * the generated default error and warning functions. + * @author jrfrimme + */ + Multigraph.createDefaultMessageHandlers = function (div) { + + $(div).css('position', 'relative'); + $(div).errorDisplay({}); + + return { + error : function(e) { + var stackTrace = (e.stack && typeof(e.stack) === "string") ? e.stack.replace(/\n/g, "
  • ") : e.message; + $(div).errorDisplay("displayError", stackTrace, e.message, { + fontColor : '#000000', + backgroundColor : '#ff0000', + indicatorColor : '#ff0000' + }); + }, + + warning : function (w) { + // w can be either a string, or a Warning instance + var message = "Warning: " + ((typeof(w) === "string") ? w : w.message), + stackTrace = (typeof(w) !== "string" && w.stack && typeof(w.stack) === "string") ? w.stack.replace(/\n/g, "
  • ") : message; + $(div).errorDisplay("displayError", stackTrace, message, { + fontColor : '#000000', + backgroundColor : '#e06a1b', + indicatorColor : '#e06a1b' + }); + } + }; + }; + + ns.Multigraph = Multigraph; + +}); +/*global sprintf */ + +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + var NumberFormatter = function (format) { + var testString; + if (typeof(format) !== "string") { + throw new Error("format must be a string"); + } + this.formatString = format; + testString = sprintf(format, 0); + this.length = testString.length; + }; + + NumberFormatter.prototype.format = function (value) { + return sprintf(this.formatString, value.getRealValue()); + }; + + NumberFormatter.prototype.getMaxLength = function () { + return this.length; + }; + + NumberFormatter.prototype.getFormatString = function () { + return this.formatString; + }; + + ns.NumberFormatter = NumberFormatter; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + // Fudge factor for floating point comparisons: + var epsilon = 1E-12; + + var NumberMeasure = function (measure) { + this.measure = measure; + }; + + NumberMeasure.prototype.getRealValue = function () { + return this.measure; + }; + + NumberMeasure.prototype.toString = function () { + return this.measure.toString(); + }; + + NumberMeasure.prototype.firstSpacingLocationAtOrAfter = function (value, alignment) { + var f, + n, + m, + a = alignment.value, + v = value.value, + s = Math.abs(this.measure); + f = (v - a) / s; + n = Math.floor(f); + m = n + 1; + //if ((Math.abs(n - f) < epsilon) || (Math.abs(m - f) < epsilon)) { + //NOTE: by definition of n=floor(f), we know f >= n, so Math.abs(n - f) is the same as (f - n) + //Also by definition, floor(f)+1 >= f, so Math.abs(m - f) is the same as (m - f) + if ((f - n < epsilon) || (m - f < epsilon)) { + return new ns.NumberValue(v); + } + return new ns.NumberValue(a + s * m); + + }; + + NumberMeasure.parse = function (s) { + return new NumberMeasure(parseFloat(s)); + }; + + ns.NumberMeasure = NumberMeasure; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var NumberValue = function (value) { + this.value = value; + }; + + NumberValue.prototype.getRealValue = function () { + return this.value; + }; + + NumberValue.prototype.toString = function () { + return this.value.toString(); + }; + + NumberValue.prototype.compareTo = function (x) { + if (this.value < x.value) { + return -1; + } else if (this.value > x.value) { + return 1; + } + return 0; + }; + + NumberValue.prototype.addRealValue = function ( realValueIncr ) { + return new NumberValue(this.value + realValueIncr); + }; + + NumberValue.prototype.add = function (/*DataMeasure*/ measure) { + // NOTE: deliberately accessing the 'measure' property of a NumberMeasure here, rather + // than calling its getRealValue() method, for convenience and efficiency: + return new NumberValue(this.value + measure.measure); + }; + + NumberValue.prototype.type = ns.DataValue.NUMBER; + + NumberValue.prototype.clone = function() { + return new NumberValue(this.value); + }; + + NumberValue.parse = function (s) { + return new NumberValue(parseFloat(s)); + }; + + ns.DataValue.mixinComparators(NumberValue.prototype); + + ns.NumberValue = NumberValue; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.horizontalaxis.pan), + Pan; + + Pan = new window.jermaine.Model("Pan", function () { + this.hasA("allowed").which.isA("boolean"); + this.hasA("min").which.validatesWith(ns.DataValue.isInstanceOrNull); + this.hasA("max").which.validatesWith(ns.DataValue.isInstanceOrNull); + + //NOTE: the distinction between DataValue and DataMeasure for the zoom & pan model + // attributes might seem confusing, so here's a table to clarify it: + // + // Boolean DataValue DataMeasure + // ------- --------- ----------- + // zoom: allowed anchor min,max + // pan: allowed min,max + + utilityFunctions.insertDefaults(this, defaultValues.horizontalaxis.pan, attributes); + }); + + ns.Pan = Pan; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + /** + * @class PeriodicArrayData + * @for PeriodicArrayData + * @constructor + * @param {array} columns A array of DataVariables + * @param {array} stringArray A array of strings which will later be parsed into DataValues + */ + ns.PeriodicArrayData = window.jermaine.Model(function () { + var PeriodicArrayData = this, + emptyIterator = { + "next" : function () {}, + "hasNext" : function () { return false; } + }; + + this.isA(ns.ArrayData); + this.hasA("period").which.validatesWith(ns.DataMeasure.isInstance); + //this.hasA("column0RelativeRealValues").which.defaultsTo(null); + this.isBuiltWith("columns", "stringArray", "period", function () { + this.init(); + this.addListener("listenerAdded", function (event) { + var data = this.array(); + if (event.targetType === "dataReady") { + event.listener(data[0][0], data[data.length-1][0]); + } + }); + }); + +/* + this.respondsTo("initializeColumn0RelativeRealValues", function() { + var array = this.array(), + column0RelativeRealValues = [], + i; + for (i=0; i= baseMin; + // this is the data point we start with + for (currentIndex = 0; currentIndex < array.length; ++currentIndex) { + if (array[currentIndex][0].ge(baseMin)) { + break; + } + } + if (currentIndex === array.length) { + return emptyIterator; + } + + // + //TODO later: back up 'buffer' steps + // + + // set the current value to be the column0 value at this first index, shifted + // 'forward' by offsetRealValue + var currentValue = DataValue.create(array[currentIndex][0].type, array[currentIndex][0].getRealValue() + offsetRealValue); + + columnIndices = []; + for (j = 0; j < columnIds.length; ++j) { + var k = periodicArrayData.columnIdToColumnNumber(columnIds[j]); + columnIndices.push( k ); + } + + return { + next : function () { + var projection = [], + i, x; + if (currentIndex < 0) { + return null; + } + for (i = 0; i < columnIndices.length; ++i) { + if (columnIndices[i] === 0) { + projection.push(currentValue); + } else { + projection.push(array[currentIndex][columnIndices[i]]); + } + } + ++currentIndex; + if (currentIndex >= array.length) { + currentIndex = 0; + b = b.add(periodicArrayData.period()); + offsetRealValue = b.getRealValue() - baseValue.getRealValue(); + } + currentValue = ns.DataValue.create(array[currentIndex][0].type, array[currentIndex][0].getRealValue() + offsetRealValue); + if (currentValue.gt(max)) { + //TODO: actually need to figure out how to move forward `buffer` steps, but for + // now skip that part. + currentIndex = -1; + } + return projection; + }, + hasNext : function () { + return (currentIndex >= 0); + } + }; + + }; + + }); +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plot.legend), + PlotLegend = new window.jermaine.Model("PlotLegend", function () { + this.hasA("visible").which.isA("boolean"); + this.hasA("label").which.validatesWith(function (label) { + return label instanceof ns.Text; + }); + + utilityFunctions.insertDefaults(this, defaultValues.plot.legend, attributes); + }); + + ns.PlotLegend = PlotLegend; + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.plotarea), + Plotarea = new window.jermaine.Model("Plotarea", function () { + + this.hasA("margin").which.validatesWith(function (margin) { + return margin instanceof window.multigraph.math.Insets; + }); + + this.hasA("border").which.isA("integer"); + + this.hasA("color").which.validatesWith(function (color) { + return color === null || color instanceof window.multigraph.math.RGBColor; + }); + + this.hasA("bordercolor").which.validatesWith(function (bordercolor) { + return bordercolor instanceof window.multigraph.math.RGBColor; + }); + + utilityFunctions.insertDefaults(this, defaultValues.plotarea, attributes); + }); + + ns.Plotarea = Plotarea; +}); +// The Band renderer is a 2-variable renderer which fills the region +// between two data lines with a solid color, and draws a line segment +// between consecutive data points in each line. +// +// It is very similar to the fill renderer except that the filled region +// extends between the two (vertical axis) data values at each data point, instead +// of between a single (vertical axis) value and a horizontal base line. +// +// The line segements should occlude the solid fill. +// +// This renderer accepts the following options: +// +// OPTION NAME: linecolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x000000 (black) +// DESCRIPTION: Color used for line segments. +// +// OPTION NAME: linewidth +// DATA TYPE: number +// DEFAULT VALUE: 1 +// DESCRIPTION: Width, in pixels, of line segments. A +// value of 0 means do not draw line segments. +// +// OPTION NAME: line1color +// DATA TYPE: RGBColor +// DEFAULT VALUE: none (linecolor is used) +// DESCRIPTION: Color used for line segments connecting the +// values of variable 1. If both linecolor and +// line1color are specified, line1color is used. +// +// OPTION NAME: line1width +// DATA TYPE: number +// DEFAULT VALUE: -1 (linewidth is used) +// DESCRIPTION: Width, in pixels, of line segments connecting the +// values of variable 1. A value of 0 means do not +// draw line segments. If both linewidth and +// line1width are specified, line1width is used. +// +// OPTION NAME: line2color +// DATA TYPE: RGBColor +// DEFAULT VALUE: none (linecolor is used) +// DESCRIPTION: Color used for line segments connecting the +// values of variable 2. If both linecolor and +// line2color are specified, line2color is used. +// +// OPTION NAME: line2width +// DATA TYPE: number +// DEFAULT VALUE: -1 (linewidth is used) +// DESCRIPTION: Width, in pixels, of line segments connecting the +// values of variable 2. A value of 0 means do not +// draw line segments. If both linewidth and +// line2width are specified, line2width is used. +// +// OPTION NAME: fillcolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x808080 (dark gray) +// DESCRIPTION: Color used for the fill area. +// +// OPTION NAME: fillopacity +// DATA TYPE: number +// DEFAULT VALUE: 1 +// DESCRIPTION: Opacity used for the fill area. +// +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var BandRenderer; + + BandRenderer = new window.jermaine.Model("BandRenderer", function () { + this.isA(ns.Renderer); + this.hasA("numberOfVariables").which.defaultsTo(3); + }); + + BandRenderer.GRAY = parseInt("80", 16) / 255; + + ns.Renderer.declareOptions(BandRenderer, "BandRendererOptions", [ + { + "name" : "linecolor", + "type" : ns.Renderer.RGBColorOption, + "default" : new window.multigraph.math.RGBColor(0,0,0) + }, + { + "name" : "linewidth", + "type" : ns.Renderer.NumberOption, + "default" : 1 + }, + { + "name" : "line1color", + "type" : ns.Renderer.RGBColorOption, + "default" : null + }, + { + "name" : "line1width", + "type" : ns.Renderer.NumberOption, + "default" : -1 + }, + { + "name" : "line2color", + "type" : ns.Renderer.RGBColorOption, + "default" : null + }, + { + "name" : "line2width", + "type" : ns.Renderer.NumberOption, + "default" : -1 + }, + { + "name" : "fillcolor", + "type" : ns.Renderer.RGBColorOption, + "default" : new window.multigraph.math.RGBColor(BandRenderer.GRAY,BandRenderer.GRAY,BandRenderer.GRAY) + }, + { + "name" : "fillopacity", + "type" : ns.Renderer.NumberOption, + "default" : 1.0 + } + ]); + + ns.Renderer.BAND = new ns.Renderer.Type("band"); + + ns.Renderer.addType({"type" : ns.Renderer.Type.parse("band"), + "model" : BandRenderer}); + + ns.BandRenderer = BandRenderer; +}); +// The Bar renderer is a 1-variable renderer which draws a bar at each +// non-missing data point with an outline around the bar and a solid +// fill between the bar and the horizontal axis. +// +// This renderer accepts the following options: +// +// OPTION NAME: barwidth +// DATA TYPE: DataMeasure +// DEFAULT VALUE: ??? +// DESCRIPTION: Width, in relative terms to the type of the +// axis the plot is on, of the bars. +// +// OPTION NAME: baroffset +// DATA TYPE: number +// DEFAULT VALUE: 0 +// DESCRIPTION: The offset, in pixels, of the left edge of +// each bar from the corresponding data value. +// +// OPTION NAME: barbase +// DATA TYPE: DataValue +// DEFAULT VALUE: null +// DESCRIPTION: The location, relative to the plot's +// vertical axis, of the bottom of the bar; if +// no barbase is specified, the bars will +// extend down to the bottom of the plot area. +// +// OPTION NAME: linecolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x000000 (black) +// DESCRIPTION: The color to be used for the outline around +// each bar. +// +// OPTION NAME: fillcolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x000000 (black) +// DESCRIPTION: The color to be used for the fill inside +// each bar; if barbase is specified, this +// color is used only for bars that extend +// above the base. +// +// OPTION NAME: fillopacity +// DATA TYPE: number +// DEFAULT VALUE: 1 +// DESCRIPTION: Opacity used for the fill inside each bar. +// +// OPTION NAME: hidelines +// DATA TYPE: number +// DEFAULT VALUE: 2 +// DESCRIPTION: Bars which are less wide, in pixels, than +// this number do not render their outlines. +// +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var BarRenderer, + defaultValues = window.multigraph.utilityFunctions.getDefaultValuesFromXSD(), + attributes = window.multigraph.utilityFunctions.getKeys(defaultValues.plot.renderer); + + BarRenderer = new window.jermaine.Model("BarRenderer", function () { + this.isA(ns.Renderer); + this.hasA("numberOfVariables").which.defaultsTo(2); + }); + + ns.Renderer.declareOptions(BarRenderer, "BarRendererOptions", [ + { + "name" : "barwidth", + "type" : ns.Renderer.HorizontalDataMeasureOption, + "default" : new ns.DataMeasure.parse("number", 0) + }, + { + "name" : "baroffset", + "type" : ns.Renderer.NumberOption, + "default" : 0 + }, + { + "name" : "barbase", + "type" : ns.Renderer.VerticalDataValueOption, + "default" : null + }, + { + "name" : "fillcolor", + "type" : ns.Renderer.RGBColorOption, + "default" : new window.multigraph.math.RGBColor(0,0,0) + }, + { + "name" : "fillopacity", + "type" : ns.Renderer.NumberOption, + "default" : 1.0 + }, + { + "name" : "linecolor", + "type" : ns.Renderer.RGBColorOption, + "default" : new window.multigraph.math.RGBColor(0,0,0) + }, + { + "name" : "hidelines", + "type" : ns.Renderer.NumberOption, + "default" : 2 + } + ]); + + ns.Renderer.BAR = new ns.Renderer.Type("bar"); + + ns.Renderer.addType({"type" : ns.Renderer.Type.parse("bar"), + "model" : BarRenderer}); + + ns.BarRenderer = BarRenderer; +}); +// The Fill renderer is a 1-variable renderer which connects consecutive +// non-missing data points with line segments with a solid fill between +// the lines and the horizontal axis. +// +// The line segements should occlude the solid fill. +// +// This renderer accepts the following options: +// +// OPTION NAME: linecolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x000000 (black) +// DESCRIPTION: Color used for line segments +// +// OPTION NAME: linewidth +// DATA TYPE: number +// DEFAULT VALUE: 1 +// DESCRIPTION: Width, in pixels, of line segments. A +// value of 0 means do not draw line segments. +// +// OPTION NAME: fillcolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x808080 (dark gray) +// DESCRIPTION: Color used for the fill area. +// +// OPTION NAME: downfillcolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: null +// DESCRIPTION: Color used for fill area that is below the +// fillbase, if a fillbase is specified. If no +// downfillcolor is specifed, fillcolor will +// be used for all fill areas. +// +// OPTION NAME: fillopacity +// DATA TYPE: number +// DEFAULT VALUE: 1 +// DESCRIPTION: Opacity used for the fill area. +// +// OPTION NAME: fillbase +// DATA TYPE: DataValue +// DEFAULT VALUE: null +// DESCRIPTION: The location along the plot's vertical axis +// of the horizontal line that defines the +// bottom (or top) of the filled region; if no +// fillbase is specified, the fill will extend +// down to the bottom of the plot area. +// +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var FillRenderer, + defaultValues = window.multigraph.utilityFunctions.getDefaultValuesFromXSD(), + attributes = window.multigraph.utilityFunctions.getKeys(defaultValues.plot.renderer); + + FillRenderer = new window.jermaine.Model("FillRenderer", function () { + this.isA(ns.Renderer); + this.hasA("numberOfVariables").which.defaultsTo(2); + }); + + FillRenderer.GRAY = parseInt("80", 16) / 255; + + ns.Renderer.declareOptions(FillRenderer, "FillRendererOptions", [ + { + "name" : "linecolor", + "type" : ns.Renderer.RGBColorOption, + "default" : new window.multigraph.math.RGBColor(0,0,0) + }, + { + "name" : "linewidth", + "type" : ns.Renderer.NumberOption, + "default" : 1 + }, + { + "name" : "fillcolor", + "type" : ns.Renderer.RGBColorOption, + "default" : new window.multigraph.math.RGBColor(FillRenderer.GRAY,FillRenderer.GRAY,FillRenderer.GRAY) + }, + { + "name" : "downfillcolor", + "type" : ns.Renderer.RGBColorOption, + "default" : null + }, + { + "name" : "fillopacity", + "type" : ns.Renderer.NumberOption, + "default" : 1.0 + }, + { + "name" : "fillbase", + "type" : ns.Renderer.VerticalDataValueOption, + "default" : null + } + ]); + + ns.Renderer.FILL = new ns.Renderer.Type("fill"); + + ns.Renderer.addType({"type" : ns.Renderer.Type.parse("fill"), + "model" : FillRenderer}); + + ns.FillRenderer = FillRenderer; +}); +// The Pointline renderer is a 1-variable renderer which draws a shape +// at each non-missing data point, and connects consecutive +// non-missing data points with line segments. The drawing of both +// the points, and the lines, is optional, so this renderer can be +// used to draw just points, just line segments, or both. +// +// When both points and line segments are drawn, the points should +// be drawn on "top of" the line segments. +// +// This renderer accepts the following options: +// +// OPTION NAME: linewidth +// DATA TYPE: number +// DEFAULT VALUE: 1 +// DESCRIPTION: Width, in pixels, of line segments. A +// value of 0 means do not draw line segments. +// +// OPTION NAME: linecolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x000000 (black) +// DESCRIPTION: Color used for line segments +// +// OPTION NAME: pointsize +// DATA TYPE: number +// DEFAULT VALUE: 0 +// DESCRIPTION: The radius of drawn points. A value +// of 0 means do not draw points. +// +// OPTION NAME: pointcolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x000000 (black) +// DESCRIPTION: Color used for drawing points +// +// OPTION NAME: pointshape +// DATA TYPE: One of the constants PointlineRenderer.CIRCLE, +// PointlineRenderer.SQUARE, PointlineRenderer.TRIANGLE, +// PointlineRenderer.DIAMOND, PointlineRenderer.STAR, +// PointlineRenderer.PLUS, or PointlineRenderer.X. These +// correspond to the strings "circle", "square", "triangle", +// "diamond", "star", "plus", and "x" in MUGL files. +// DEFAULT VALUE: PointlineRenderer.CIRCLE +// DESCRIPTION: The shape to use for drawing points. +// +// OPTION NAME: pointopacity +// DATA TYPE: number +// DEFAULT VALUE: 1.0 +// DESCRIPTION: The opactiy of the drawn points, in the range 0-1. +// A value of 1 means completely opaque; a value of 0 +// means completely invisible. +// +// OPTION NAME: pointoutlinewidth +// DATA TYPE: number +// DEFAULT VALUE: 0 +// DESCRIPTION: The width, in pixels, of the outline to be drawn +// around each point. A value of 0 means draw no +// outline. +// +// OPTION NAME: pointoutlinecolor +// DATA TYPE: RGBColor +// DEFAULT VALUE: 0x000000 (black) +// DESCRIPTION: The color to use for the outline around each point. +// +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var PointlineRenderer, + defaultValues = window.multigraph.utilityFunctions.getDefaultValuesFromXSD(), + attributes = window.multigraph.utilityFunctions.getKeys(defaultValues.plot.renderer); + + PointlineRenderer = new window.jermaine.Model("PointlineRenderer", function () { + this.isA(ns.Renderer); + this.hasA("numberOfVariables").which.defaultsTo(2); + // + //this.isBuiltWith(...) NO NO NO!!! + // + // DO NOT CALL isBuiltWith for a renderer subclass; Renderer.declareOptions calls isBuiltWith(), and it + // will break if you also call it here!!! + + }); + + + PointlineRenderer.CIRCLE = "circle"; + PointlineRenderer.SQUARE = "square"; + PointlineRenderer.TRIANGLE = "triangle"; + PointlineRenderer.DIAMOND = "diamond"; + PointlineRenderer.STAR = "star"; + PointlineRenderer.PLUS = "plus"; + PointlineRenderer.X = "x"; + + PointlineRenderer.shapes = [ + PointlineRenderer.CIRCLE, + PointlineRenderer.SQUARE, + PointlineRenderer.TRIANGLE, + PointlineRenderer.DIAMOND, + PointlineRenderer.STAR, + PointlineRenderer.PLUS, + PointlineRenderer.X + ]; + + PointlineRenderer.isShape = function (shape) { + var i; + for (i=0; i maxLength) { + maxLength = testLength; + } + } + + return maxLength * 15; + }); + + /** + * Determines unrotated height for the stored string. Overridden by implementations in graphics + * drivers. + * + * @method measureStringHeight + * @private + * @return {Float} Unrotated height of string. + * @param {Object} graphicsContext + */ + this.respondsTo("measureStringHeight", function (graphicsContext) { + // Graphics drivers should replace this method with an actual implementation; this + // is just a placeholder. The implementation should return the height, in pixels, + // of the given string. Of course this is dependent on font choice, size, etc, + // but we gloss over that at the moment. Just return the height of the string + // using some reasonable default font for now. Later on, we'll modify this + // function to use font information. + if (this.string() === undefined) { + throw new Error("measureStringHeight requires the string attr to be set."); + } + var newlineCount = this.string().match(/\n/g); + return (newlineCount !== null ? (newlineCount.length + 1) : 1) * 12; + }); + }); +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + ns.Warning = function(message) { + this.message = message; + }; + ns.Warning.prototype = new Error(); + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + /** + * @class WebServiceData + * @for WebServiceData + * @constructor + * @extends Data + */ + ns.WebServiceData = window.jermaine.Model(function () { + this.isA(ns.Data); + this.hasA("serviceaddress").which.isA("string"); + this.hasA("serviceaddresspattern").which.isA("string"); + this.hasA("format").which.isA("string"); + this.hasA("formatter").which.validatesWith(ns.DataFormatter.isInstance); + this.hasA("messageHandler"); + this.hasA("ajaxthrottle"); + this.isBuiltWith("columns", "serviceaddress", "%messageHandler", "%ajaxthrottle", function () { + this.init(); + if (this.columns().size() > 0) { + var column0Type = this.columns().at(0).type(); + if (this.format() === undefined) { + this.format(column0Type===ns.DataValue.NUMBER ? "%f" : "%Y%M%D%H%i%s"); + } + this.formatter(ns.DataFormatter.create(column0Type, this.format())); + } + if (this.ajaxthrottle() === undefined) { + this.ajaxthrottle(window.multigraph.jQuery); + } + }); + + this.respondsTo("_displayError", function (e) { + if (this.messageHandler()) { + this.messageHandler().error(e); + } else { + throw e; + } + }); + + this.respondsTo("getBounds", function (columnNumber) { + // TODO: replace this kludge + return [0, 10]; + }); + + this.hasA("arraydata").which.defaultsTo(null).and.validatesWith(function (arraydata) { + return arraydata instanceof ns.ArrayData || arraydata === null; + }); + + /** + * A pointer to the head WebServiceDataCacheNode in this WebServieData's cache. + * + * @property cacheHead + * @type {null|WebServiceDataCacheNode} + * @author jrfrimme + */ + this.hasA("cacheHead").which.defaultsTo(null).and.validatesWith(function (x) { + //NOTE: need "ns." prefix on WebServiceDataCacheNode below, because of file + // load order issues + return x === null || x instanceof ns.WebServiceDataCacheNode; + }); + + /** + * A pointer to the tail WebServiceDataCacheNode in this WebServieData's cache. + * + * @property cacheTail + * @type {null|WebServiceDataCacheNode} + * @author jrfrimme + */ + this.hasA("cacheTail").which.defaultsTo(null).and.validatesWith(function (x) { + //NOTE: need "ns." prefix on WebServiceDataCacheNode below, because of file + // load order issues + return x === null || x instanceof ns.WebServiceDataCacheNode; + }); + + /** + * Return a pointer to the first WebServiceDataCacheNode in this WebServieData's cache + * that actually contains data, if any. If the cache doesn't contain any data, return null. + * + * @method dataHead + * @author jrfrimme + * @return {null|WebServiceDataCacheNode} + */ + this.respondsTo("dataHead", function () { + var head = this.cacheHead(); + if (head === null) { return null; } + if (head.hasData()) { return head; } + return head.dataNext(); + }); + + /** + * Return a pointer to the last WebServiceDataCacheNode in this WebServieData's cache + * that actually contains data, if any. If the cache doesn't contain any data, return null. + * + * @method dataTail + * @author jrfrimme + * @return {null|WebServiceDataCacheNode} + */ + this.respondsTo("dataTail", function () { + var tail = this.cacheTail(); + if (tail === null) { return null; } + if (tail.hasData()) { return tail; } + return tail.dataPrev(); + }); + + /** + * Insert a WebServiceCacheNode into this WebService's cache. + * If this node's coveredMin is less than the cache head's + * coveredMin, insert it at the head; otherwise insert it at + * the tail. Note that nodes are only inserted either at the + * head or at the tail of the cache --- not in the middle. + * + * @method insertCacheNode + * @param {WebServiceCacheNode} node + * @author jrfrimme + */ + this.respondsTo("insertCacheNode", function (node) { + var head = this.cacheHead(), + tail = this.cacheTail(); + if (head === null) { + this.cacheHead(node); + this.cacheTail(node); + } else { + if (node.coveredMin().lt(head.coveredMin())) { + node.next(head); + head.prev(node); + this.cacheHead(node); + } else { + node.prev(tail); + tail.next(node); + this.cacheTail(node); + } + } + }); + + this.respondsTo("constructRequestURL", function (min, max) { + var serviceaddress = this.serviceaddress(), + formatter = this.formatter(); + + if (serviceaddress === undefined) { + throw new Error("WebServiceData.constructRequestURL: undefined service address"); + } + if (formatter === undefined) { + throw new Error("WebServiceData.constructRequestURL: undefined formatter for column 0"); + } + if (this.serviceaddresspattern() === undefined) { + if ((serviceaddress.indexOf("$min") < 0) && + (serviceaddress.indexOf("$max") < 0)) { + this.serviceaddresspattern(serviceaddress + "$min,$max"); + } else { + this.serviceaddresspattern(serviceaddress); + } + } + return (this.serviceaddresspattern() + .replace("$min", formatter.format(min)) + .replace("$max", formatter.format(max))); + }); + + this.hasA("coveredMin").which.defaultsTo(null).and.validatesWith(function (x) { + return x === null || ns.DataValue.isInstance(x); + }); + this.hasA("coveredMax").which.defaultsTo(null).and.validatesWith(function (x) { + return x === null || ns.DataValue.isInstance(x); + }); + + /** + * Initiate requests needed to fetch data between coveredMin and coveredMax, if any. + * + * @method insureCoveredRange + * @author jrfrimme + */ + this.respondsTo("insureCoveredRange", function () { + var head = this.cacheHead(), + tail = this.cacheTail(), + coveredMin = this.coveredMin(), + coveredMax = this.coveredMax(); + + if (coveredMin === null || coveredMax === null) { + return; + } + if (head === null || tail === null) { + this.requestSingleRange(coveredMin, coveredMax); + } else { + if (coveredMin.lt(head.coveredMin())) { + // head's min tail's max + // -----|-------------|-----------------------|---------------- + // coveredMin + this.requestSingleRange(coveredMin, head.coveredMin()); + } + if (coveredMax.gt(tail.coveredMax())) { + // head's min tail's max + // -------------------|-----------------------|-----------|---- + // coveredMax + this.requestSingleRange(tail.coveredMax(), coveredMax); + } + } + }); + + this.respondsTo("requestSingleRange", function (min, max) { + var node, + requestURL, + that = this; + + // create the cache node that will hold the data in this range + node = new ns.WebServiceDataCacheNode(min, max); + + // insert it into the cache linked list + this.insertCacheNode(node); + + // construct the URL for fetching the data in this range + requestURL = this.constructRequestURL(min, max); + + // initiate the fetch request + this.emit({type : 'ajaxEvent', action : 'start'}); + this.ajaxthrottle().ajax({ + url : requestURL, + dataType : "text", + success : function (data) { + // if data contains a tag, extract its text string value + if (data.indexOf("") > 0) { + data = window.multigraph.parser.jquery.stringToJQueryXMLObj(data).find("values").text(); + } + node.parseData(that.getColumns(), data); + + that.emit({type : 'ajaxEvent', action : 'success'}); + that.emit({type : 'dataReady'}); + }, + + error : function (jqXHR, textStatus, errorThrown) { + var message = errorThrown; + if (jqXHR.statusCode().status === 404) { + message = "URL not found: '" + requestURL + '"'; + } else { + if (textStatus) { + message = textStatus + ": " + message; + } + } + that._displayError(new Error(message)); + }, + + // 'complete' callback gets called after either 'success' or 'error', whichever: + complete : function (jqXHR, textStatus) { + that.emit({type : 'ajaxEvent', action : 'complete'}); + } + + }); + }); + + this.respondsTo("getIterator", function (columnIds, min, max, buffer) { + var initialNode, + initialIndex, + n, b, i, tmp, + finalNode, + finalIndex, + columnIndices; + + // if min > max, swap them + if (min.gt(max)) { + tmp = min; + min = max; + max = tmp; + } + + if (this.coveredMin() === null || min.lt(this.coveredMin())) { + this.coveredMin(min.clone()); + } + if (this.coveredMax() === null || max.gt(this.coveredMax())) { + this.coveredMax(max.clone()); + } + + if (!this.paused()) { + this.insureCoveredRange(); + } + + if (this.dataHead() === null) { + // cache is empty, return empty iterator: + return { + "next" : function () {}, + "hasNext" : function () { return false; } + }; + } + // convert columnIds to columnIndices + columnIndices = []; + for (i = 0; i < columnIds.length; ++i) { + columnIndices.push( this.columnIdToColumnNumber(columnIds[i]) ); + } + + // find the data node containing the 'min' value + initialNode = this.dataHead(); + while ((initialNode !== null) && + (initialNode.dataNext() !== null) && + (min.gt(initialNode.dataMax()))) { + initialNode = initialNode.dataNext(); + } + + if (initialNode === null || !initialNode.hasData()) { + initialIndex = -1; + } else { + initialIndex = 0; + // find the index within the initial node corresponding to the 'min' value + while ((initialIndex < initialNode.data().length-1) && + (initialNode.data()[initialIndex][columnIndices[0]].lt(min))) { + ++initialIndex; + } + + // back up 'buffer' steps, being careful not to go further back than the first element of the head node + n = 0; + while (n= finalNode.data().length) { + b = finalNode.dataNext(); + if (b !== null) { + finalNode = b; + finalIndex = 0; + } else { + finalIndex = finalNode.data().length-1; + break; + } + } + ++n; + } + + } + + return new ns.WebServiceDataIterator(columnIndices, initialNode, initialIndex, finalNode, finalIndex); + }); + + this.hasA("paused").which.isA("boolean").and.defaultsTo(false); + this.respondsTo("pause", function() { + this.paused(true); + }); + this.respondsTo("resume", function() { + this.paused(false); + this.emit({type : 'dataReady', + min : this.coveredMin(), + max : this.coveredMax()}); + }); + + }); +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + /** + * A WebServiceDataCacheNode represents a single node in the + * doubly-linked list holding the data for a WebServiceDataCache. + * The WebServiceDataCacheNode has an array of data (which may + * actually be null, if the node's data has not yet been loaded), + * next and prev pointers to the next and previous nodes in the + * linked list, and coveredMin and coveredMax values that indicate + * the min and max values of the "covered" range of data for this + * node. + * + * The "covered" range is the interval of the data number line for + * which this node is responsible for storing data; Multigraph + * uses range this to avoid requesting the same data twice --- it + * never requests data for a range already covered by an existing + * cache node. + * + * Initially, when the WebServiceDataCacheNode is created, the + * limits of the covered range are specified in the constructor. + * Later on, when the node's data is actually populated, the + * limits are potentially adjusted outward, if the range of data + * received is larger than the initially specified covered range. + * So in all cases, the covered range indicates the range for + * which no more data is needed, because it's covered by this + * node. + * + * Note that the covered range is never adjusted to be smaller. + * + * The WebServiceDataCacheNode does not actually fetch any data + * --- it is simply a storage container for fetched data; it's up + * to other code outside of this object to fetch and populate the + * data. + * + * @class WebServiceDataCacheNode + * @for WebServiceDataCacheNode + * @constructor + * @param {DataValue} coveredMin + * @param {DataValue} coveredMax + */ + ns.WebServiceDataCacheNode = window.jermaine.Model(function () { + + /** + * The actual data for this node. + * + * @property data + * @type {Array|null} + * @author jrfrimme + */ + this.hasA("data").which.defaultsTo(null).and.validatesWith(function (data) { + var UF = window.multigraph.util.namespace("window.multigraph.utilityFunctions"); + // accept null + if (data === null) { return true; } + // only accept arrays + if (UF.typeOf(data) !== "array") { + this.message = "WebServiceDataCacheNode's data attribute is not an Array"; + return false; + } + // if the array contains anything, do a cursory check that it looks + // like an array of DataValue arrays (just check the first row) + if (data.length > 0) { + var firstRow = data[0], + i; + if (UF.typeOf(firstRow) !== "array") { + this.message = "WebServiceDataCacheNode's data attribute is not an Array of Arrays"; + return false; + } + for (i = 0; i < firstRow.length; ++i) { + if (!ns.DataValue.isInstance(firstRow[i])) { + this.message = "WebServiceDataCacheNode's data attribute is not an Array of Arrays of DataValues (bad value in position " + i + " of first row"; + return false; + } + } + } + return true; + }); + + /** + * The next node in the cache's linked list + * + * @property next + * @type {WebServiceDataCacheNode|null} + * @author jrfrimme + */ + this.hasA("next").which.defaultsTo(null).and.validatesWith(function (x) { + return x === null || x instanceof ns.WebServiceDataCacheNode; + }); + + /** + * The previous node in the cache's linked list + * + * @property prev + * @type {WebServiceDataCacheNode|null} + * @author jrfrimme + */ + this.hasA("prev").which.defaultsTo(null).and.validatesWith(function (x) { + return x === null || x instanceof ns.WebServiceDataCacheNode; + }); + + /** + * The min of the covered value range + * + * @property coveredMin + * @type {DataValue} + * @author jrfrimme + */ + this.hasA("coveredMin").which.validatesWith(ns.DataValue.isInstance); + + /** + * The max of the covered value range + * + * @property coveredMax + * @type {DataValue} + * @author jrfrimme + */ + this.hasA("coveredMax").which.validatesWith(ns.DataValue.isInstance); + + /** + * Return the next node in the cache that actually has data, + * or null if none exists. + * + * @method dataNext + * @author jrfrimme + * @return {WebServiceDataCacheNode|null} + */ + this.respondsTo("dataNext", function () { + var node = this.next(); + while (node !== null && !node.hasData()) { + node = node.next(); + } + return node; + }); + + /** + * Return the previous node in the cache that actually has data, + * or null if none exists. + * + * @method dataPrev + * @author jrfrimme + * @return {WebServiceDataCacheNode|null} + */ + this.respondsTo("dataPrev", function () { + var node = this.prev(); + while (node !== null && !node.hasData()) { + node = node.prev(); + } + return node; + }); + + /** + * Return the minimum (column 0) data value for this node. Returns null + * if the node has no data yet. + * + * @method dataMin + * @author jrfrimme + * @return {DataValue|null} + */ + this.respondsTo("dataMin", function () { + var data = this.data(); + if (data === null) { return null; } + if (data.length === 0) { return null; } + if (data[0] === null) { return null; } + if (data[0].length === 0) { return null; } + return data[0][0]; + }); + + /** + * Return the maximum (column 0) data value for this node. Returns null + * if the node has no data yet. + * + * @method dataMax + * @author jrfrimme + * @return {DataValue|null} + */ + this.respondsTo("dataMax", function() { + var data = this.data(); + if (data === null) { return null; } + if (data.length === 0) { return null; } + if (data[data.length-1] === null) { return null; } + if (data[data.length-1].length === 0) { return null; } + return data[data.length-1][0]; + }); + + /** + * Return true if this node has data; false if not. + * + * @method hasData + * @author jrfrimme + * @return Boolean + */ + this.respondsTo("hasData", function() { + return this.data() !== null; + }); + + this.isBuiltWith("coveredMin", "coveredMax"); + + /** + * Populate this node's data array by parsing the values + * contained in the 'dataText' string, which should be a + * string of comma-separated values of the same sort expected + * by ArrayData and CSVData. The first argument, `columns`, + * should be a plain javascript array of DataVariable instances, + * of the sort returned by `Data.getColumns()`. + * + * This method examines other nodes in the cache in order + * insure that values included in this node's data array + * are (a) strictly greater than the maximum value present in the + * cache prior to this node, and (b) strictly less than the + * minimum value present in the cache after this node. + * This guarantees that there is no overlap between the + * data in this node and other nodes in the cache. + * + * @method parseData + * @param {DataVariable Attr_List} columns + * @param {String} dataText + * @author jrfrimme + */ + this.respondsTo("parseData", function (columns, dataText) { + var i, b, + maxPrevValue = null, + minNextValue = null, + arrayDataArray, + data, + row; + + // set maxPrevValue to the max value in column0 in the cache prior to this block, if any: + b = this.dataPrev(); + if (b !== null) { + maxPrevValue = b.dataMax(); + } + + // set minNextValue to the min value in column0 in the cache after this block, if any: + b = this.dataNext(); + if (b !== null) { + minNextValue = b.dataMin(); + } + + // convert the csv dataText string to an array + arrayDataArray = ns.ArrayData.textToDataValuesArray(columns, dataText); + + // populate the data array by copying values from the converted array, skipping any + // values that are already within the range covered by the rest of the cache + data = []; + for (i = 0; i < arrayDataArray.length; ++i) { + row = arrayDataArray[i]; + if ((maxPrevValue === null || row[0].gt(maxPrevValue)) && + (minNextValue === null || row[0].lt(minNextValue))) { + data.push( row ); + } + } + + // if we didn't get any new values, we're done + if (data.length === 0) { + return; + } + + // lower the coveredMin value if the actual data received is lower than the current coveredMin value + if (data[0][0].lt(this.coveredMin())) { + this.coveredMin(data[0][0]); + } + + // raise the coveredMax value if the actual data received is higher than the current coveredMax value + if (data[data.length-1][0].gt(this.coveredMax())) { + this.coveredMax(data[data.length-1][0]); + } + + // load the data + this.data( data ); + }); + }); + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + /** + * @module multigraph + * @submodule core + */ + + var UF = window.multigraph.util.namespace("window.multigraph.utilityFunctions"); + + /** + * An iterator for stepping through data values stored in a linked list of + * WebServiceDataCacheNodes. The constructor takes 5 arguments: + * + * @class WebServiceDataIterator + * @for WebServiceDataIterator + * @constructor + * + * @param {Array} columnIndices + * JavaScript array of the indices of the columns + * of data to return + * @param {WebServiceDataCacheNode} initialNode + * Pointer to the WebServiceDataCacheNode containing the first + * value to iterate over + * @param {integer} initialIndex + * Index, within initialNode, of the first value to iterate over + * @param {WebServiceDataCacheNode} finalNode + * Pointer to the WebServiceDataCacheNode containing the last + * value to iterate over + * @param {integer} finalIndex + * Index, within finalNode, of the last value to iterate over + */ + ns.WebServiceDataIterator = window.jermaine.Model(function () { + var WebServiceDataIterator = this; + + this.hasA("currentNode").which.validatesWith(function(x) { + return x instanceof ns.WebServiceDataCacheNode; + }); + this.hasA("currentIndex").which.isA("integer"); + this.hasA("columnIndices").which.validatesWith(function(x) { + return UF.typeOf(x) === "array"; + }); + + this.hasA("initialNode").which.validatesWith(function(x) { + return x instanceof ns.WebServiceDataCacheNode; + }); + this.hasA("finalNode").which.validatesWith(function(x) { + return x instanceof ns.WebServiceDataCacheNode; + }); + this.hasA("initialIndex").which.isA("integer"); + this.hasA("finalIndex").which.isA("integer"); + + this.isBuiltWith("columnIndices", "initialNode", "initialIndex", "finalNode", "finalIndex", function() { + this.currentNode(this.initialNode()); + this.currentIndex(this.initialIndex()); + }); + + this.respondsTo("hasNext", function() { + if (this.currentNode() === null || this.currentIndex() < 0) { return false; } + if (this.currentNode() !== this.finalNode()) { + return true; + } + return this.currentIndex() <= this.finalIndex(); + }); + + this.respondsTo("next", function() { + var vals = [], + columnIndices = this.columnIndices(), + currentIndex = this.currentIndex(), + finalIndex = this.finalIndex(), + currentNode = this.currentNode(), + i; + + if (currentNode === this.finalNode()) { + if (currentIndex > finalIndex) { return null; } + for (i=0; i= currentNode.data().length) { + this.currentNode(currentNode.dataNext()); + this.currentIndex(0); + } + return vals; + } + }); + + }); + +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.window), + Window = new window.jermaine.Model("Window", function () { + + this.hasA("width").which.isA("integer"); + + this.hasA("height").which.isA("integer"); + + this.hasA("border").which.isA("integer"); + + this.hasA("margin").which.validatesWith(function (margin) { + return margin instanceof window.multigraph.math.Insets; + }); + + this.hasA("padding").which.validatesWith(function (padding) { + return padding instanceof window.multigraph.math.Insets; + }); + + this.hasA("bordercolor").which.validatesWith(function (bordercolor) { + return bordercolor instanceof window.multigraph.math.RGBColor; + }); + + utilityFunctions.insertDefaults(this, defaultValues.window, attributes); + }); + + ns.Window = Window; +}); +window.multigraph.util.namespace("window.multigraph.core", function (ns) { + "use strict"; + + var utilityFunctions = window.multigraph.utilityFunctions, + defaultValues = utilityFunctions.getDefaultValuesFromXSD(), + attributes = utilityFunctions.getKeys(defaultValues.horizontalaxis.zoom), + Zoom = new window.jermaine.Model("Zoom", function () { + + this.hasA("allowed").which.isA("boolean"); + this.hasA("min").which.validatesWith(function (min) { + return ns.DataMeasure.isInstance(min); + }); + this.hasA("max").which.validatesWith(function (max) { + return ns.DataMeasure.isInstance(max); + }); + this.hasA("anchor").which.validatesWith(function (anchor) { + return ns.DataValue.isInstance(anchor) || anchor === null; + }); + + utilityFunctions.insertDefaults(this, defaultValues.horizontalaxis.zoom, attributes); + }); + + ns.Zoom = Zoom; + +}); +window.multigraph.util.namespace("window.multigraph.parser.jquery", function (ns) { + "use strict"; + + ns.mixin = new window.multigraph.core.Mixin(); + +}); +window.multigraph.util.namespace("window.multigraph.parser.jquery", function (ns) { + "use strict"; + + ns.mixin.add(function (ns, parse) { + + var parseLabels = function (xml, axis) { + var spacingStrings = [], + spacingString, + labelsTag = xml.find("labels"), + labelTags = xml.find("label"), + labelers = axis.labelers(), + Labeler = ns.core.Labeler, + $ = ns.jQuery, + i; + spacingString = $.trim(labelsTag.attr("spacing")); + if (spacingString !== "") { + spacingStrings = spacingString.split(/\s+/); + } + if (spacingStrings.length > 0) { + // If there was a spacing attr on the tag, create a new labeler for + // each spacing present in it, using the other values from the tag + for (i = 0; i < spacingStrings.length; ++i) { + labelers.add(Labeler[parse](labelsTag, axis, undefined, spacingStrings[i])); + } + } else if (labelTags.length > 0) { + // If there are