mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-20 04:28:13 +08:00
588 lines
162 KiB
JavaScript
588 lines
162 KiB
JavaScript
|
/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */
|
||
|
!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each(
|
||
|
|
||
|
return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&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 m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</tex
|
||
|
return new Za.prototype.init(a,b,c,d,e)}m.Tween=Za,Za.prototype={constructor:Za,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")},cur:function(){var a=Za.propHooks[this.prop];return a&&a.get?a.get(this):Za.propHooks._default.get(this)},run:function(a){var b,c=Za.propHooks[this.prop];return this.options.duration?this.pos=b=m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Za.propHooks._default.set(this),this}},Za.prototype.init.prototype=Za.prototype,Za.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Za.propHooks.scrollTop=Za.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Za.prototype.init,m.fx.step={};var $a,_a,ab=/^(?:toggle|show|hide)$/,bb=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cb=/queueHooks$/,db=[ib],eb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bb.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bb.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fb(){return setTimeout(function(){$a=void 0}),$a=m.now()}function gb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hb(a,b,c){for(var d,e=(eb[b]||[]).concat(eb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fa(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fa(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ab.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fa(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hb(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=db.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$a||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h
|
||
|
|
||
|
/* Javascript plotting library for jQuery, version 0.8.3.
|
||
|
|
||
|
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||
|
Licensed under the MIT license.
|
||
|
|
||
|
*/
|
||
|
(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);(function($){var hasOwnProperty=Object.prototype.hasOwnProperty;if(!$.fn.detach){$.fn.detach=function(){return this.each(function(){if(this.parentNode){this.parentNode.removeChild(this)}})}}function Canvas(cls,container){var element=container.children("."+cls)[0];if(element==null){element=document.createElement("canvas");element.className=cls;$(element).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(container);if(!element.getContext){if(window.G_vmlCanvasManager){element=window.G_vmlCanvasManager.initElement(element)}else{throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.")}}}this.element=element;var context=this.context=element.getContext("2d");var devicePixelRatio=window.devicePixelRatio||1,backingStoreRatio=context.webkitBackingStorePixelRatio||context.mozBackingSto
|
||
|
if(yrange.from==null)yrange.from=yrange.axis.min;if(yrange.to==null)yrange.to=yrange.axis.max;if(xrange.to<xrange.axis.min||xrange.from>xrange.axis.max||yrange.to<yrange.axis.min||yrange.from>yrange.axis.max)continue;xrange.from=Math.max(xrange.from,xrange.axis.min);xrange.to=Math.min(xrange.to,xrange.axis.max);yrange.from=Math.max(yrange.from,yrange.axis.min);yrange.to=Math.min(yrange.to,yrange.axis.max);var xequal=xrange.from===xrange.to,yequal=yrange.from===yrange.to;if(xequal&&yequal){continue}xrange.from=Math.floor(xrange.axis.p2c(xrange.from));xrange.to=Math.floor(xrange.axis.p2c(xrange.to));yrange.from=Math.floor(yrange.axis.p2c(yrange.from));yrange.to=Math.floor(yrange.axis.p2c(yrange.to));if(xequal||yequal){var lineWidth=m.lineWidth||options.grid.markingsLineWidth,subPixel=lineWidth%2?.5:0;ctx.beginPath();ctx.strokeStyle=m.color||options.grid.markingsColor;ctx.lineWidth=lineWidth;if(xequal){ctx.moveTo(xrange.to+subPixel,yrange.from);ctx.lineTo(xrange.to+subPixel,yrange.to)}else{ctx.moveTo(xrange.from,yrange.to+subPixel);ctx.lineTo(xrange.to,yrange.to+subPixel)}ctx.stroke()}else{ctx.fillStyle=m.color||options.grid.markingsColor;ctx.fillRect(xrange.from,yrange.to,xrange.to-xrange.from,yrange.from-yrange.to)}}}axes=allAxes();bw=options.grid.borderWidth;for(var j=0;j<axes.length;++j){var axis=axes[j],box=axis.box,t=axis.tickLength,x,y,xoff,yoff;if(!axis.show||axis.ticks.length==0)continue;ctx.lineWidth=1;if(axis.direction=="x"){x=0;if(t=="full")y=axis.position=="top"?0:plotHeight;else y=box.top-plotOffset.top+(axis.position=="top"?box.height:0)}else{y=0;if(t=="full")x=axis.position=="left"?0:plotWidth;else x=box.left-plotOffset.left+(axis.position=="left"?box.width:0)}if(!axis.innermost){ctx.strokeStyle=axis.options.color;ctx.beginPath();xoff=yoff=0;if(axis.direction=="x")xoff=plotWidth+1;else yoff=plotHeight+1;if(ctx.lineWidth==1){if(axis.direction=="x"){y=Math.floor(y)+.5}else{x=Math.floor(x)+.5}}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff);ctx.stroke()}ctx.strokeStyle=axis.options.tickColor;ctx.beginPath();for(i=0;i<axis.ticks.length;++i){var v=axis.ticks[i].v;xoff=yoff=0;if(isNaN(v)||v<axis.min||v>axis.max||t=="full"&&(typeof bw=="object"&&bw[axis.position]>0||bw>0)&&(v==axis.min||v==axis.max))continue;if(axis.direction=="x"){x=axis.p2c(v);yoff=t=="full"?-plotHeight:t;if(axis.position=="top")yoff=-yoff}else{y=axis.p2c(v);xoff=t=="full"?-plotWidth:t;if(axis.position=="left")xoff=-xoff}if(ctx.lineWidth==1){if(axis.direction=="x")x=Math.floor(x)+.5;else y=Math.floor(y)+.5}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff)}ctx.stroke()}if(bw){bc=options.grid.borderColor;if(typeof bw=="object"||typeof bc=="object"){if(typeof bw!=="object"){bw={top:bw,right:bw,bottom:bw,left:bw}}if(typeof bc!=="object"){bc={top:bc,right:bc,bottom:bc,left:bc}}if(bw.top>0){ctx.strokeStyle=bc.top;ctx.lineWidth=bw.top;ctx.beginPath();ctx.moveTo(0-bw.left,0-bw.top/2);ctx.lineTo(plotWidth,0-bw.top/2);ctx.stroke()}if(bw.right>0){ctx.strokeStyle=bc.right;ctx.lineWidth=bw.right;ctx.beginPath();ctx.moveTo(plotWidth+bw.right/2,0-bw.top);ctx.lineTo(plotWidth+bw.right/2,plotHeight);ctx.stroke()}if(bw.bottom>0){ctx.strokeStyle=bc.bottom;ctx.lineWidth=bw.bottom;ctx.beginPath();ctx.moveTo(plotWidth+bw.right,plotHeight+bw.bottom/2);ctx.lineTo(0,plotHeight+bw.bottom/2);ctx.stroke()}if(bw.left>0){ctx.strokeStyle=bc.left;ctx.lineWidth=bw.left;ctx.beginPath();ctx.moveTo(0-bw.left/2,plotHeight+bw.bottom);ctx.lineTo(0-bw.left/2,0);ctx.stroke()}}else{ctx.lineWidth=bw;ctx.strokeStyle=options.grid.borderColor;ctx.strokeRect(-bw/2,-bw/2,plotWidth+bw,plotHeight+bw)}}ctx.restore()}function drawAxisLabels(){$.each(allAxes(),function(_,axis){var box=axis.box,legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=axis.options.font||"flot-tick-label tickLabel",tick,x,y,halign,valign;surface.removeText(layer);if(!axis.show||axis.ticks.length==0)return;for(var i=0;i<axis.ticks.length;++i){tick=axis.ticks[i];if(!tick.label||tick.v<axis.min||tick.v>axis.max)continue;if(axis.directi
|
||
|
|
||
|
|
||
|
/* Pretty handling of time axes.
|
||
|
|
||
|
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||
|
Licensed under the MIT license.
|
||
|
|
||
|
Set axis.mode to "time" to enable. See the section "Time series data" in
|
||
|
API.txt for details.
|
||
|
|
||
|
*/
|
||
|
|
||
|
(function($) {
|
||
|
|
||
|
var options = {
|
||
|
xaxis: {
|
||
|
timezone: null, // "browser" for local to the client or timezone for timezone-js
|
||
|
timeformat: null, // format string to use
|
||
|
twelveHourClock: false, // 12 or 24 time in time mode
|
||
|
monthNames: null // list of names of months
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// round to nearby lower multiple of base
|
||
|
|
||
|
function floorInBase(n, base) {
|
||
|
return base * Math.floor(n / base);
|
||
|
}
|
||
|
|
||
|
// Returns a string with the date d formatted according to fmt.
|
||
|
// A subset of the Open Group's strftime format is supported.
|
||
|
|
||
|
function formatDate(d, fmt, monthNames, dayNames) {
|
||
|
|
||
|
if (typeof d.strftime == "function") {
|
||
|
return d.strftime(fmt);
|
||
|
}
|
||
|
|
||
|
var leftPad = function(n, pad) {
|
||
|
n = "" + n;
|
||
|
pad = "" + (pad == null ? "0" : pad);
|
||
|
return n.length == 1 ? pad + n : n;
|
||
|
};
|
||
|
|
||
|
var r = [];
|
||
|
var escape = false;
|
||
|
var hours = d.getHours();
|
||
|
var isAM = hours < 12;
|
||
|
|
||
|
if (monthNames == null) {
|
||
|
monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||
|
}
|
||
|
|
||
|
if (dayNames == null) {
|
||
|
dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||
|
}
|
||
|
|
||
|
var hours12;
|
||
|
|
||
|
if (hours > 12) {
|
||
|
hours12 = hours - 12;
|
||
|
} else if (hours == 0) {
|
||
|
hours12 = 12;
|
||
|
} else {
|
||
|
hours12 = hours;
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < fmt.length; ++i) {
|
||
|
|
||
|
var c = fmt.charAt(i);
|
||
|
|
||
|
if (escape) {
|
||
|
switch (c) {
|
||
|
case 'a': c = "" + dayNames[d.getDay()]; break;
|
||
|
case 'b': c = "" + monthNames[d.getMonth()]; break;
|
||
|
case 'd': c = leftPad(d.getDate()); break;
|
||
|
case 'e': c = leftPad(d.getDate(), " "); break;
|
||
|
case 'h': // For back-compat with 0.7; remove in 1.0
|
||
|
case 'H': c = leftPad(hours); break;
|
||
|
case 'I': c = leftPad(hours12); break;
|
||
|
case 'l': c = leftPad(hours12, " "); break;
|
||
|
case 'm': c = leftPad(d.getMonth() + 1); break;
|
||
|
case 'M': c = leftPad(d.getMinutes()); break;
|
||
|
// quarters not in Open Group's strftime specification
|
||
|
case 'q':
|
||
|
c = "" + (Math.floor(d.getMonth() / 3) + 1); break;
|
||
|
case 'S': c = leftPad(d.getSeconds()); break;
|
||
|
case 'y': c = leftPad(d.getFullYear() % 100); break;
|
||
|
case 'Y': c = "" + d.getFullYear(); break;
|
||
|
case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
|
||
|
case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
|
||
|
case 'w': c = "" + d.getDay(); break;
|
||
|
}
|
||
|
r.push(c);
|
||
|
escape = false;
|
||
|
} else {
|
||
|
if (c == "%") {
|
||
|
escape = true;
|
||
|
} else {
|
||
|
r.push(c);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return r.join("");
|
||
|
}
|
||
|
|
||
|
// To have a consistent view of time-based data independent of which time
|
||
|
// zone the client happens to be in we need a date-like object independent
|
||
|
// of time zones. This is done through a wrapper that only calls the UTC
|
||
|
// versions of the accessor methods.
|
||
|
|
||
|
function makeUtcWrapper(d) {
|
||
|
|
||
|
function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) {
|
||
|
sourceObj[sourceMethod] = function() {
|
||
|
return targetObj[targetMethod].apply(targetObj, arguments);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
var utc = {
|
||
|
date: d
|
||
|
};
|
||
|
|
||
|
// support strftime, if found
|
||
|
|
||
|
if (d.strftime != undefined) {
|
||
|
addProxyMethod(utc, "strftime", d, "strftime");
|
||
|
}
|
||
|
|
||
|
addProxyMethod(utc, "getTime", d, "getTime");
|
||
|
addProxyMethod(utc, "setTime", d, "setTime");
|
||
|
|
||
|
var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"];
|
||
|
|
||
|
for (var p = 0; p < props.length; p++) {
|
||
|
addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]);
|
||
|
addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]);
|
||
|
}
|
||
|
|
||
|
return utc;
|
||
|
};
|
||
|
|
||
|
// select time zone strategy. This returns a date-like object tied to the
|
||
|
// desired timezone
|
||
|
|
||
|
function dateGenerator(ts, opts) {
|
||
|
if (opts.timezone == "browser") {
|
||
|
return new Date(ts);
|
||
|
} else if (!opts.timezone || opts.timezone == "utc") {
|
||
|
return makeUtcWrapper(new Date(ts));
|
||
|
} else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") {
|
||
|
var d = new timezoneJS.Date();
|
||
|
// timezone-js is fickle, so be sure to set the time zone before
|
||
|
// setting the time.
|
||
|
d.setTimezone(opts.timezone);
|
||
|
d.setTime(ts);
|
||
|
return d;
|
||
|
} else {
|
||
|
return makeUtcWrapper(new Date(ts));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// map of app. size of time units in milliseconds
|
||
|
|
||
|
var timeUnitSize = {
|
||
|
"second": 1000,
|
||
|
"minute": 60 * 1000,
|
||
|
"hour": 60 * 60 * 1000,
|
||
|
"day": 24 * 60 * 60 * 1000,
|
||
|
"month": 30 * 24 * 60 * 60 * 1000,
|
||
|
"quarter": 3 * 30 * 24 * 60 * 60 * 1000,
|
||
|
"year": 365.2425 * 24 * 60 * 60 * 1000
|
||
|
};
|
||
|
|
||
|
// the allowed tick sizes, after 1 year we use
|
||
|
// an integer algorithm
|
||
|
|
||
|
var baseSpec = [
|
||
|
[1, "second"], [2, "second"], [5, "second"], [10, "second"],
|
||
|
[30, "second"],
|
||
|
[1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
|
||
|
[30, "minute"],
|
||
|
[1, "hour"], [2, "hour"], [4, "hour"],
|
||
|
[8, "hour"], [12, "hour"],
|
||
|
[1, "day"], [2, "day"], [3, "day"],
|
||
|
[0.25, "month"], [0.5, "month"], [1, "month"],
|
||
|
[2, "month"]
|
||
|
];
|
||
|
|
||
|
// we don't know which variant(s) we'll need yet, but generating both is
|
||
|
// cheap
|
||
|
|
||
|
var specMonths = baseSpec.concat([[3, "month"], [6, "month"],
|
||
|
[1, "year"]]);
|
||
|
var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"],
|
||
|
[1, "year"]]);
|
||
|
|
||
|
function init(plot) {
|
||
|
plot.hooks.processOptions.push(function (plot, options) {
|
||
|
$.each(plot.getAxes(), function(axisName, axis) {
|
||
|
|
||
|
var opts = axis.options;
|
||
|
|
||
|
if (opts.mode == "time") {
|
||
|
axis.tickGenerator = function(axis) {
|
||
|
|
||
|
var ticks = [];
|
||
|
var d = dateGenerator(axis.min, opts);
|
||
|
var minSize = 0;
|
||
|
|
||
|
// make quarter use a possibility if quarters are
|
||
|
// mentioned in either of these options
|
||
|
|
||
|
var spec = (opts.tickSize && opts.tickSize[1] ===
|
||
|
"quarter") ||
|
||
|
(opts.minTickSize && opts.minTickSize[1] ===
|
||
|
"quarter") ? specQuarters : specMonths;
|
||
|
|
||
|
if (opts.minTickSize != null) {
|
||
|
if (typeof opts.tickSize == "number") {
|
||
|
minSize = opts.tickSize;
|
||
|
} else {
|
||
|
minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < spec.length - 1; ++i) {
|
||
|
if (axis.delta < (spec[i][0] * timeUnitSize[spec[i][1]]
|
||
|
+ spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
|
||
|
&& spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var size = spec[i][0];
|
||
|
var unit = spec[i][1];
|
||
|
|
||
|
// special-case the possibility of several years
|
||
|
|
||
|
if (unit == "year") {
|
||
|
|
||
|
// if given a minTickSize in years, just use it,
|
||
|
// ensuring that it's an integer
|
||
|
|
||
|
if (opts.minTickSize != null && opts.minTickSize[1] == "year") {
|
||
|
size = Math.floor(opts.minTickSize[0]);
|
||
|
} else {
|
||
|
|
||
|
var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10));
|
||
|
var norm = (axis.delta / timeUnitSize.year) / magn;
|
||
|
|
||
|
if (norm < 1.5) {
|
||
|
size = 1;
|
||
|
} else if (norm < 3) {
|
||
|
size = 2;
|
||
|
} else if (norm < 7.5) {
|
||
|
size = 5;
|
||
|
} else {
|
||
|
size = 10;
|
||
|
}
|
||
|
|
||
|
size *= magn;
|
||
|
}
|
||
|
|
||
|
// minimum size for years is 1
|
||
|
|
||
|
if (size < 1) {
|
||
|
size = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
axis.tickSize = opts.tickSize || [size, unit];
|
||
|
var tickSize = axis.tickSize[0];
|
||
|
unit = axis.tickSize[1];
|
||
|
|
||
|
var step = tickSize * timeUnitSize[unit];
|
||
|
|
||
|
if (unit == "second") {
|
||
|
d.setSeconds(floorInBase(d.getSeconds(), tickSize));
|
||
|
} else if (unit == "minute") {
|
||
|
d.setMinutes(floorInBase(d.getMinutes(), tickSize));
|
||
|
} else if (unit == "hour") {
|
||
|
d.setHours(floorInBase(d.getHours(), tickSize));
|
||
|
} else if (unit == "month") {
|
||
|
d.setMonth(floorInBase(d.getMonth(), tickSize));
|
||
|
} else if (unit == "quarter") {
|
||
|
d.setMonth(3 * floorInBase(d.getMonth() / 3,
|
||
|
tickSize));
|
||
|
} else if (unit == "year") {
|
||
|
d.setFullYear(floorInBase(d.getFullYear(), tickSize));
|
||
|
}
|
||
|
|
||
|
// reset smaller components
|
||
|
|
||
|
d.setMilliseconds(0);
|
||
|
|
||
|
if (step >= timeUnitSize.minute) {
|
||
|
d.setSeconds(0);
|
||
|
}
|
||
|
if (step >= timeUnitSize.hour) {
|
||
|
d.setMinutes(0);
|
||
|
}
|
||
|
if (step >= timeUnitSize.day) {
|
||
|
d.setHours(0);
|
||
|
}
|
||
|
if (step >= timeUnitSize.day * 4) {
|
||
|
d.setDate(1);
|
||
|
}
|
||
|
if (step >= timeUnitSize.month * 2) {
|
||
|
d.setMonth(floorInBase(d.getMonth(), 3));
|
||
|
}
|
||
|
if (step >= timeUnitSize.quarter * 2) {
|
||
|
d.setMonth(floorInBase(d.getMonth(), 6));
|
||
|
}
|
||
|
if (step >= timeUnitSize.year) {
|
||
|
d.setMonth(0);
|
||
|
}
|
||
|
|
||
|
var carry = 0;
|
||
|
var v = Number.NaN;
|
||
|
var prev;
|
||
|
|
||
|
do {
|
||
|
|
||
|
prev = v;
|
||
|
v = d.getTime();
|
||
|
ticks.push(v);
|
||
|
|
||
|
if (unit == "month" || unit == "quarter") {
|
||
|
if (tickSize < 1) {
|
||
|
|
||
|
// a bit complicated - we'll divide the
|
||
|
// month/quarter up but we need to take
|
||
|
// care of fractions so we don't end up in
|
||
|
// the middle of a day
|
||
|
|
||
|
d.setDate(1);
|
||
|
var start = d.getTime();
|
||
|
d.setMonth(d.getMonth() +
|
||
|
(unit == "quarter" ? 3 : 1));
|
||
|
var end = d.getTime();
|
||
|
d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
|
||
|
carry = d.getHours();
|
||
|
d.setHours(0);
|
||
|
} else {
|
||
|
d.setMonth(d.getMonth() +
|
||
|
tickSize * (unit == "quarter" ? 3 : 1));
|
||
|
}
|
||
|
} else if (unit == "year") {
|
||
|
d.setFullYear(d.getFullYear() + tickSize);
|
||
|
} else {
|
||
|
d.setTime(v + step);
|
||
|
}
|
||
|
} while (v < axis.max && v != prev);
|
||
|
|
||
|
return ticks;
|
||
|
};
|
||
|
|
||
|
axis.tickFormatter = function (v, axis) {
|
||
|
|
||
|
var d = dateGenerator(v, axis.options);
|
||
|
|
||
|
// first check global format
|
||
|
|
||
|
if (opts.timeformat != null) {
|
||
|
return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames);
|
||
|
}
|
||
|
|
||
|
// possibly use quarters if quarters are mentioned in
|
||
|
// any of these places
|
||
|
|
||
|
var useQuarters = (axis.options.tickSize &&
|
||
|
axis.options.tickSize[1] == "quarter") ||
|
||
|
(axis.options.minTickSize &&
|
||
|
axis.options.minTickSize[1] == "quarter");
|
||
|
|
||
|
var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
|
||
|
var span = axis.max - axis.min;
|
||
|
var suffix = (opts.twelveHourClock) ? " %p" : "";
|
||
|
var hourCode = (opts.twelveHourClock) ? "%I" : "%H";
|
||
|
var fmt;
|
||
|
|
||
|
if (t < timeUnitSize.minute) {
|
||
|
fmt = hourCode + ":%M:%S" + suffix;
|
||
|
} else if (t < timeUnitSize.day) {
|
||
|
if (span < 2 * timeUnitSize.day) {
|
||
|
fmt = hourCode + ":%M" + suffix;
|
||
|
} else {
|
||
|
fmt = "%b %d " + hourCode + ":%M" + suffix;
|
||
|
}
|
||
|
} else if (t < timeUnitSize.month) {
|
||
|
fmt = "%b %d";
|
||
|
} else if ((useQuarters && t < timeUnitSize.quarter) ||
|
||
|
(!useQuarters && t < timeUnitSize.year)) {
|
||
|
if (span < timeUnitSize.year) {
|
||
|
fmt = "%b";
|
||
|
} else {
|
||
|
fmt = "%b %Y";
|
||
|
}
|
||
|
} else if (useQuarters && t < timeUnitSize.year) {
|
||
|
if (span < timeUnitSize.year) {
|
||
|
fmt = "Q%q";
|
||
|
} else {
|
||
|
fmt = "Q%q %Y";
|
||
|
}
|
||
|
} else {
|
||
|
fmt = "%Y";
|
||
|
}
|
||
|
|
||
|
var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames);
|
||
|
|
||
|
return rt;
|
||
|
};
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
$.plot.plugins.push({
|
||
|
init: init,
|
||
|
options: options,
|
||
|
name: 'time',
|
||
|
version: '1.0'
|
||
|
});
|
||
|
|
||
|
// Time-axis support used to be in Flot core, which exposed the
|
||
|
// formatDate function on the plot object. Various plugins depend
|
||
|
// on the function, so we need to re-expose it here.
|
||
|
|
||
|
$.plot.formatDate = formatDate;
|
||
|
$.plot.dateGenerator = dateGenerator;
|
||
|
|
||
|
})(jQuery);
|
||
|
|
||
|
var ws = null;
|
||
|
var connected = false;
|
||
|
|
||
|
$(document).ready(function() {
|
||
|
var startTime = Date.now();
|
||
|
var graphDurationSeconds = 30;
|
||
|
|
||
|
// Initialize graph
|
||
|
var createGraph = function(title) {
|
||
|
var $c = $('<div class="graph"/>').appendTo('#graphs');
|
||
|
var past = Date.now() - graphDurationSeconds * 1000;
|
||
|
var options = {
|
||
|
lines: {
|
||
|
xfill: true,
|
||
|
lineWidth: 1,
|
||
|
xfillColor: {colors: [ { opacity: 0 }, { opacity: 1 } ] }
|
||
|
},
|
||
|
grid: { borderWidth: 1, borderColor: '#ccc'},
|
||
|
xaxis: { mode: 'time', ticks: 5 },
|
||
|
legend: { labelBoxBorderColor: '#fff' },
|
||
|
xcolors: [ '#fec', '#396', '#e39', '#9e2' ],
|
||
|
hooks: {
|
||
|
draw: [function(plot, canvas) {
|
||
|
canvas.font = '15px sans-serif';
|
||
|
canvas.fillStyle = '#999';
|
||
|
canvas.fillText(title, 35, 25);
|
||
|
}]
|
||
|
}
|
||
|
};
|
||
|
return $.plot($c, [], options);
|
||
|
};
|
||
|
|
||
|
var updateGraph = function(g) {
|
||
|
if (!connected) return;
|
||
|
var now = Date.now();
|
||
|
//if (now - g.lastUpdateTime < 50) return;
|
||
|
g.lastUpdateTime = now;
|
||
|
var oldest = now - graphDurationSeconds * 1000;
|
||
|
g.data[0].data = [[oldest, null], [now, null]];
|
||
|
|
||
|
// Remove old points
|
||
|
$.each(g.data, function(di, d) {
|
||
|
while (d.data.length > 0 && d.data[0][0] < oldest) {
|
||
|
d.data.shift();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
g.plot.setData(g.data);
|
||
|
g.plot.setupGrid();
|
||
|
g.plot.draw();
|
||
|
};
|
||
|
|
||
|
var graphs = {
|
||
|
led: {
|
||
|
title: 'LED state',
|
||
|
plot: null,
|
||
|
lastUpdateTime: null,
|
||
|
data: [
|
||
|
{ show: false, data: [] },
|
||
|
{ label: "LED state", color: '#36c', data: [] },
|
||
|
]
|
||
|
},
|
||
|
accel: {
|
||
|
title: 'Accelerometer',
|
||
|
plot: null,
|
||
|
lastUpdateTime: null,
|
||
|
data: [
|
||
|
{ show: false, data: [] },
|
||
|
{ label: "x", color: '#f00', data: [] },
|
||
|
{ label: "y", color: '#0f0', data: [] },
|
||
|
{ label: "z", color: '#00f', data: [] },
|
||
|
]
|
||
|
},
|
||
|
temp: {
|
||
|
title: 'Sensor die temperature',
|
||
|
plot: null,
|
||
|
lastUpdateTime: null,
|
||
|
data: [
|
||
|
{ show: false, data: [] },
|
||
|
{ label: 'Celsius', color: '#36c', data: []},
|
||
|
]
|
||
|
},
|
||
|
};
|
||
|
|
||
|
$.each(graphs, function(k, v) {
|
||
|
v.plot = createGraph(v.title);
|
||
|
setInterval(function() { updateGraph(v); }, 100);
|
||
|
});
|
||
|
|
||
|
function wsConnect() {
|
||
|
if (ws != null) return;
|
||
|
var wsAddr = 'ws://' + location.host;
|
||
|
console.log('Connecting to', wsAddr);
|
||
|
ws = new WebSocket(wsAddr);
|
||
|
ws.onopen = function() {
|
||
|
console.log('Connected');
|
||
|
connected = true;
|
||
|
};
|
||
|
ws.onclose = function() {
|
||
|
console.log('Disconnected');
|
||
|
connected = false;
|
||
|
ws = null;
|
||
|
};
|
||
|
ws.onmessage = handleWsMessage;
|
||
|
}
|
||
|
|
||
|
function handleWsMessage(ev) {
|
||
|
try {
|
||
|
var obj = JSON.parse(ev.data);
|
||
|
//var timestamp = startTime + parseInt(obj.ts * 1000);
|
||
|
var timestamp = Date.now();
|
||
|
|
||
|
if (obj.t == 0) {
|
||
|
graphs.temp.data[1].data.push([timestamp, obj.dt]);
|
||
|
updateGraph(graphs.temp);
|
||
|
} else if (obj.t == 1) {
|
||
|
graphs.led.data[1].data.push([timestamp, obj.v]);
|
||
|
updateGraph(graphs.led);
|
||
|
} else if (obj.t == 2) {
|
||
|
graphs.accel.data[1].data.push([timestamp, obj.x]);
|
||
|
graphs.accel.data[2].data.push([timestamp, obj.y]);
|
||
|
graphs.accel.data[3].data.push([timestamp, obj.z]);
|
||
|
updateGraph(graphs.accel);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
console.log(e, ev.data);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
$(document).on('click', '#on_off_button', function() {
|
||
|
var state = $(this).text().match(/off/) ? 0 : 1;
|
||
|
$(this).text(state ? 'Switch LED off' : 'Switch LED on');
|
||
|
ws.send(JSON.stringify({ t: 1, v: state }));
|
||
|
});
|
||
|
|
||
|
wsConnect();
|
||
|
setInterval(wsConnect, 1000);
|
||
|
});
|