Messify everything and updated to flot

pull/1/head
chrono 2013-11-29 19:39:11 +01:00
rodzic 273857b6c8
commit f2edfd57d9
11 zmienionych plików z 4281 dodań i 489 usunięć

Wyświetl plik

@ -1,7 +1,14 @@
body {
background: #b9b6af;
}
@font-face{
font-family: "LCDN";
src: url('/picoreflow/assets/fonts/LCDN.eot');
src: local("LCD Normal"),
url('/picoreflow/assets/fonts/LCDN.woff') format("woff"),
url('/picoreflow/assets/fonts/LCDN.ttf') format("truetype");
}
body {
background: #b9b6af;
}
.display {
display: inline-block;
@ -24,6 +31,9 @@ box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.75),inset 0 0 9px 2px #000;
border-color: #000000;
}
.ds-num {
font-family: "LCDN";
}
#main_status {
margin-top: 15px;
@ -81,6 +91,7 @@ background: #3F3E3A;
.progress-bar {
background-color: #75890c;
color: #000;
}
.btn-success {
@ -120,3 +131,10 @@ border-color: #b92c28;
}
.graph {
width: 100%;
height: 300px;
font-size: 14px;
line-height: 1.2em;
}

Wyświetl plik

@ -1,87 +1,114 @@
.form-control .select2-choice {
border: 0;
border-radius: 2px;
/**
* Select2 Bootstrap CSS 1.0
* Compatible with select2 3.3.2 and bootstrap 2.3.1
* MIT License
*/
.select2-container {
vertical-align: middle;
}
.select2-container.input-mini {
width: 60px;
}
.select2-container.input-small {
width: 90px;
}
.select2-container.input-medium {
width: 150px;
}
.select2-container.input-large {
width: 210px;
}
.select2-container.input-xlarge {
width: 270px;
}
.select2-container.input-xxlarge {
width: 530px;
}
.select2-container.input-default {
width: 220px;
}
.select2-container[class*="span"] {
float: none;
margin-left: 0;
}
.form-control .select2-choice .select2-arrow {
border-radius: 0 2px 2px 0;
.select2-container .select2-choice,
.select2-container-multi .select2-choices {
height: 28px;
line-height: 29px;
border: 1px solid #cccccc;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
background: none;
background-color: white;
filter: none;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.form-control.select2-container {
height: auto !important;
padding: 0px;
.select2-container .select2-choice div, .select2-container .select2-choice .select2-arrow,
.select2-container.select2-container-disabled .select2-choice div,
.select2-container.select2-container-disabled .select2-choice .select2-arrow {
border-left: none;
background: none;
filter: none;
}
.form-control.select2-container.select2-dropdown-open {
border-color: #5897FB;
border-radius: 3px 3px 0 0;
.control-group.error [class^="select2-choice"] {
border-color: #b94a48;
}
.form-control .select2-container.select2-dropdown-open .select2-choices {
border-radius: 3px 3px 0 0;
.select2-container-multi .select2-choices .select2-search-field {
height: 28px;
line-height: 27px;
}
.form-control.select2-container .select2-choices {
border: 0 !important;
border-radius: 3px;
.select2-drop.select2-drop-active,
.select2-container-active .select2-choice,
.select2-container-multi.select2-container-active .select2-choices {
border-color: red;
outline: none;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}
.control-group.warning .select2-container .select2-choice,
.control-group.warning .select2-container .select2-choices,
.control-group.warning .select2-container-active .select2-choice,
.control-group.warning .select2-container-active .select2-choices,
.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.warning .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #C09853 !important;
[class^="input-"] .select2-container {
font-size: 14px;
}
.control-group.warning .select2-container .select2-choice div {
border-left: 1px solid #C09853 !important;
background: #FCF8E3 !important;
.input-prepend [class^="select2-choice"] {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.control-group.error .select2-container .select2-choice,
.control-group.error .select2-container .select2-choices,
.control-group.error .select2-container-active .select2-choice,
.control-group.error .select2-container-active .select2-choices,
.control-group.error .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.error .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.error .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #B94A48 !important;
.input-append [class^="select2-choice"] {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.control-group.error .select2-container .select2-choice div {
border-left: 1px solid #B94A48 !important;
background: #F2DEDE !important;
.select2-dropdown-open [class^="select2-choice"] {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.control-group.info .select2-container .select2-choice,
.control-group.info .select2-container .select2-choices,
.control-group.info .select2-container-active .select2-choice,
.control-group.info .select2-container-active .select2-choices,
.control-group.info .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.info .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.info .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #3A87AD !important;
.select2-dropdown-open.select2-drop-above [class^="select2-choice"] {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.control-group.info .select2-container .select2-choice div {
border-left: 1px solid #3A87AD !important;
background: #D9EDF7 !important;
[class^="input-"] .select2-offscreen {
position: absolute;
}
.control-group.success .select2-container .select2-choice,
.control-group.success .select2-container .select2-choices,
.control-group.success .select2-container-active .select2-choice,
.control-group.success .select2-container-active .select2-choices,
.control-group.success .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.success .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.success .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #468847 !important;
}
.control-group.success .select2-container .select2-choice div {
border-left: 1px solid #468847 !important;
background: #DFF0D8 !important;
/**
* This stops the quick flash when a native selectbox is shown and
* then replaced by a select2 input when javascript kicks in. This can be
* removed if javascript is not present
*/
select.select2 {
height: 28px;
visibility: hidden;
}

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,402 @@
/*!
* jquery.event.drag - v 2.2
* Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
* Open Source MIT License - http://threedubmedia.com/code/license
*/
// Created: 2008-06-04
// Updated: 2012-05-21
// REQUIRES: jquery 1.7.x
;(function( $ ){
// add the jquery instance method
$.fn.drag = function( str, arg, opts ){
// figure out the event type
var type = typeof str == "string" ? str : "",
// figure out the event handler...
fn = $.isFunction( str ) ? str : $.isFunction( arg ) ? arg : null;
// fix the event type
if ( type.indexOf("drag") !== 0 )
type = "drag"+ type;
// were options passed
opts = ( str == fn ? arg : opts ) || {};
// trigger or bind event handler
return fn ? this.bind( type, opts, fn ) : this.trigger( type );
};
// local refs (increase compression)
var $event = $.event,
$special = $event.special,
// configure the drag special event
drag = $special.drag = {
// these are the default settings
defaults: {
which: 1, // mouse button pressed to start drag sequence
distance: 0, // distance dragged before dragstart
not: ':input', // selector to suppress dragging on target elements
handle: null, // selector to match handle target elements
relative: false, // true to use "position", false to use "offset"
drop: true, // false to suppress drop events, true or selector to allow
click: false // false to suppress click events after dragend (no proxy)
},
// the key name for stored drag data
datakey: "dragdata",
// prevent bubbling for better performance
noBubble: true,
// count bound related events
add: function( obj ){
// read the interaction data
var data = $.data( this, drag.datakey ),
// read any passed options
opts = obj.data || {};
// count another realted event
data.related += 1;
// extend data options bound with this event
// don't iterate "opts" in case it is a node
$.each( drag.defaults, function( key, def ){
if ( opts[ key ] !== undefined )
data[ key ] = opts[ key ];
});
},
// forget unbound related events
remove: function(){
$.data( this, drag.datakey ).related -= 1;
},
// configure interaction, capture settings
setup: function(){
// check for related events
if ( $.data( this, drag.datakey ) )
return;
// initialize the drag data with copied defaults
var data = $.extend({ related:0 }, drag.defaults );
// store the interaction data
$.data( this, drag.datakey, data );
// bind the mousedown event, which starts drag interactions
$event.add( this, "touchstart mousedown", drag.init, data );
// prevent image dragging in IE...
if ( this.attachEvent )
this.attachEvent("ondragstart", drag.dontstart );
},
// destroy configured interaction
teardown: function(){
var data = $.data( this, drag.datakey ) || {};
// check for related events
if ( data.related )
return;
// remove the stored data
$.removeData( this, drag.datakey );
// remove the mousedown event
$event.remove( this, "touchstart mousedown", drag.init );
// enable text selection
drag.textselect( true );
// un-prevent image dragging in IE...
if ( this.detachEvent )
this.detachEvent("ondragstart", drag.dontstart );
},
// initialize the interaction
init: function( event ){
// sorry, only one touch at a time
if ( drag.touched )
return;
// the drag/drop interaction data
var dd = event.data, results;
// check the which directive
if ( event.which != 0 && dd.which > 0 && event.which != dd.which )
return;
// check for suppressed selector
if ( $( event.target ).is( dd.not ) )
return;
// check for handle selector
if ( dd.handle && !$( event.target ).closest( dd.handle, event.currentTarget ).length )
return;
drag.touched = event.type == 'touchstart' ? this : null;
dd.propagates = 1;
dd.mousedown = this;
dd.interactions = [ drag.interaction( this, dd ) ];
dd.target = event.target;
dd.pageX = event.pageX;
dd.pageY = event.pageY;
dd.dragging = null;
// handle draginit event...
results = drag.hijack( event, "draginit", dd );
// early cancel
if ( !dd.propagates )
return;
// flatten the result set
results = drag.flatten( results );
// insert new interaction elements
if ( results && results.length ){
dd.interactions = [];
$.each( results, function(){
dd.interactions.push( drag.interaction( this, dd ) );
});
}
// remember how many interactions are propagating
dd.propagates = dd.interactions.length;
// locate and init the drop targets
if ( dd.drop !== false && $special.drop )
$special.drop.handler( event, dd );
// disable text selection
drag.textselect( false );
// bind additional events...
if ( drag.touched )
$event.add( drag.touched, "touchmove touchend", drag.handler, dd );
else
$event.add( document, "mousemove mouseup", drag.handler, dd );
// helps prevent text selection or scrolling
if ( !drag.touched || dd.live )
return false;
},
// returns an interaction object
interaction: function( elem, dd ){
var offset = $( elem )[ dd.relative ? "position" : "offset" ]() || { top:0, left:0 };
return {
drag: elem,
callback: new drag.callback(),
droppable: [],
offset: offset
};
},
// handle drag-releatd DOM events
handler: function( event ){
// read the data before hijacking anything
var dd = event.data;
// handle various events
switch ( event.type ){
// mousemove, check distance, start dragging
case !dd.dragging && 'touchmove':
event.preventDefault();
case !dd.dragging && 'mousemove':
// drag tolerance, x² + y² = distance²
if ( Math.pow( event.pageX-dd.pageX, 2 ) + Math.pow( event.pageY-dd.pageY, 2 ) < Math.pow( dd.distance, 2 ) )
break; // distance tolerance not reached
event.target = dd.target; // force target from "mousedown" event (fix distance issue)
drag.hijack( event, "dragstart", dd ); // trigger "dragstart"
if ( dd.propagates ) // "dragstart" not rejected
dd.dragging = true; // activate interaction
// mousemove, dragging
case 'touchmove':
event.preventDefault();
case 'mousemove':
if ( dd.dragging ){
// trigger "drag"
drag.hijack( event, "drag", dd );
if ( dd.propagates ){
// manage drop events
if ( dd.drop !== false && $special.drop )
$special.drop.handler( event, dd ); // "dropstart", "dropend"
break; // "drag" not rejected, stop
}
event.type = "mouseup"; // helps "drop" handler behave
}
// mouseup, stop dragging
case 'touchend':
case 'mouseup':
default:
if ( drag.touched )
$event.remove( drag.touched, "touchmove touchend", drag.handler ); // remove touch events
else
$event.remove( document, "mousemove mouseup", drag.handler ); // remove page events
if ( dd.dragging ){
if ( dd.drop !== false && $special.drop )
$special.drop.handler( event, dd ); // "drop"
drag.hijack( event, "dragend", dd ); // trigger "dragend"
}
drag.textselect( true ); // enable text selection
// if suppressing click events...
if ( dd.click === false && dd.dragging )
$.data( dd.mousedown, "suppress.click", new Date().getTime() + 5 );
dd.dragging = drag.touched = false; // deactivate element
break;
}
},
// re-use event object for custom events
hijack: function( event, type, dd, x, elem ){
// not configured
if ( !dd )
return;
// remember the original event and type
var orig = { event:event.originalEvent, type:event.type },
// is the event drag related or drog related?
mode = type.indexOf("drop") ? "drag" : "drop",
// iteration vars
result, i = x || 0, ia, $elems, callback,
len = !isNaN( x ) ? x : dd.interactions.length;
// modify the event type
event.type = type;
// remove the original event
event.originalEvent = null;
// initialize the results
dd.results = [];
// handle each interacted element
do if ( ia = dd.interactions[ i ] ){
// validate the interaction
if ( type !== "dragend" && ia.cancelled )
continue;
// set the dragdrop properties on the event object
callback = drag.properties( event, dd, ia );
// prepare for more results
ia.results = [];
// handle each element
$( elem || ia[ mode ] || dd.droppable ).each(function( p, subject ){
// identify drag or drop targets individually
callback.target = subject;
// force propagtion of the custom event
event.isPropagationStopped = function(){ return false; };
// handle the event
result = subject ? $event.dispatch.call( subject, event, callback ) : null;
// stop the drag interaction for this element
if ( result === false ){
if ( mode == "drag" ){
ia.cancelled = true;
dd.propagates -= 1;
}
if ( type == "drop" ){
ia[ mode ][p] = null;
}
}
// assign any dropinit elements
else if ( type == "dropinit" )
ia.droppable.push( drag.element( result ) || subject );
// accept a returned proxy element
if ( type == "dragstart" )
ia.proxy = $( drag.element( result ) || ia.drag )[0];
// remember this result
ia.results.push( result );
// forget the event result, for recycling
delete event.result;
// break on cancelled handler
if ( type !== "dropinit" )
return result;
});
// flatten the results
dd.results[ i ] = drag.flatten( ia.results );
// accept a set of valid drop targets
if ( type == "dropinit" )
ia.droppable = drag.flatten( ia.droppable );
// locate drop targets
if ( type == "dragstart" && !ia.cancelled )
callback.update();
}
while ( ++i < len )
// restore the original event & type
event.type = orig.type;
event.originalEvent = orig.event;
// return all handler results
return drag.flatten( dd.results );
},
// extend the callback object with drag/drop properties...
properties: function( event, dd, ia ){
var obj = ia.callback;
// elements
obj.drag = ia.drag;
obj.proxy = ia.proxy || ia.drag;
// starting mouse position
obj.startX = dd.pageX;
obj.startY = dd.pageY;
// current distance dragged
obj.deltaX = event.pageX - dd.pageX;
obj.deltaY = event.pageY - dd.pageY;
// original element position
obj.originalX = ia.offset.left;
obj.originalY = ia.offset.top;
// adjusted element position
obj.offsetX = obj.originalX + obj.deltaX;
obj.offsetY = obj.originalY + obj.deltaY;
// assign the drop targets information
obj.drop = drag.flatten( ( ia.drop || [] ).slice() );
obj.available = drag.flatten( ( ia.droppable || [] ).slice() );
return obj;
},
// determine is the argument is an element or jquery instance
element: function( arg ){
if ( arg && ( arg.jquery || arg.nodeType == 1 ) )
return arg;
},
// flatten nested jquery objects and arrays into a single dimension array
flatten: function( arr ){
return $.map( arr, function( member ){
return member && member.jquery ? $.makeArray( member ) :
member && member.length ? drag.flatten( member ) : member;
});
},
// toggles text selection attributes ON (true) or OFF (false)
textselect: function( bool ){
$( document )[ bool ? "unbind" : "bind" ]("selectstart", drag.dontstart )
.css("MozUserSelect", bool ? "" : "none" );
// .attr("unselectable", bool ? "off" : "on" )
document.unselectable = bool ? "off" : "on";
},
// suppress "selectstart" and "ondragstart" events
dontstart: function(){
return false;
},
// a callback instance contructor
callback: function(){}
};
// callback methods
drag.callback.prototype = {
update: function(){
if ( $special.drop && this.available.length )
$.each( this.available, function( i ){
$special.drop.locate( this, i );
});
}
};
// patch $.event.$dispatch to allow suppressing clicks
var $dispatch = $event.dispatch;
$event.dispatch = function( event ){
if ( $.data( this, "suppress."+ event.type ) - new Date().getTime() > 0 ){
$.removeData( this, "suppress."+ event.type );
return;
}
return $dispatch.apply( this, arguments );
};
// event fix hooks for touch events...
var touchHooks =
$event.fixHooks.touchstart =
$event.fixHooks.touchmove =
$event.fixHooks.touchend =
$event.fixHooks.touchcancel = {
props: "clientX clientY pageX pageY screenX screenY".split( " " ),
filter: function( event, orig ) {
if ( orig ){
var touched = ( orig.touches && orig.touches[0] )
|| ( orig.changedTouches && orig.changedTouches[0] )
|| null;
// iOS webkit: touchstart, touchmove, touchend
if ( touched )
$.each( touchHooks.props, function( i, prop ){
event[ prop ] = touched[ prop ];
});
}
return event;
}
};
// share the same special event configuration with related events...
$special.draginit = $special.dragstart = $special.dragend = drag;
})( jQuery );

Wyświetl plik

@ -0,0 +1,158 @@
/*
Author: Zach Dwiel
Flot plugin for adding point dragging capabilities to a plot.
Heavy inspiration from Chris Leonello. Thank you!
Example usage:
plot = $.plot(...);
Options:
// to set the draggable properties of all series:
grid, xaxis, yaxis : {
draggable: boolean
}
// to set the draggable properties of a single series:
// can also be set in the data series rather than the options, see example
series : {
draggable : boolean,
draggablex : boolean,
draggabley : boolean
}
// series specifc options over-ride 'global' options
*/
// dependencies: jquery.event.drag.js, we put them inline here to save people
// the effort of downloading them.
/*
jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
*/
(function ($) {
var options = {
xaxis: {
draggable: false,
}, yaxis: {
draggable: false,
}, grid: {
draggable: false,
}
},
drag = { pos: { x:null, y:null}, active: false };
function init(plot) {
function bindEvents(plot, eventHolder) {
var o = plot.getOptions();
var i;
var series_draggable = false;
var series = plot.getData();
for (i = 0; i < series.length; ++i) {
if(series[i].draggable || series[i].draggablex || series[i].draggabley) {
series_draggable = true;
}
}
if (o.grid.draggable || o.xaxis.draggable || o.yaxis.draggable || series_draggable) {
eventHolder.bind("dragstart", { distance: 10 }, function (e) {
if (e.which != 1) // only accept left-click
return false;
var plotOffset = plot.getPlotOffset();
var offset = eventHolder.offset(),
pos = { pageX: e.pageX, pageY: e.pageY },
canvasX = e.pageX - offset.left - plotOffset.left,
canvasY = e.pageY - offset.top - plotOffset.top;
drag.gridOffset = {top: offset.top + plotOffset.top, left: offset.left + plotOffset.left};
drag.item = plot.findNearbyItem(canvasX, canvasY, function (s) { return s["draggable"] != false; });
if (drag.item) {
drag.item.pageX = parseInt(drag.item.series.xaxis.p2c(drag.item.datapoint[0]) + offset.left + plotOffset.left);
drag.item.pageY = parseInt(drag.item.series.yaxis.p2c(drag.item.datapoint[1]) + offset.top + plotOffset.top);
drag.active = true;
}
});
eventHolder.bind("drag", function (pos) {
var axes = plot.getAxes();
var ax = axes.xaxis;
var ay = axes.yaxis;
var ax2 = axes.x2axis;
var ay2 = axes.y2axis;
var sidx = drag.item.seriesIndex;
var didx = drag.item.dataIndex;
var s = plot.getData()[sidx];
if (drag.item.series.yaxis == ay2)
ay = ay2;
if (drag.item.series.xaxis == ax2)
ax = ax2;
var newx = ax.min + (pos.pageX-drag.gridOffset.left)/ax.scale;
var newy = ay.max - (pos.pageY-drag.gridOffset.top)/ay.scale;
// // this version will change the data itself rather than
// // the points and then reprocess all the data and redraw.
// // NOTE: reuqires exposing plot.processData as a public
// // function in jquery.flot.js
// series[sidx].data[didx] = [newx, newy];
// plot.processData();
// change the raw data instead of processing every point all over again, not as clean, but faster
var points = s.datapoints.points;
var ps = s.datapoints.pointsize;
if((o.grid.draggable || o.xaxis.draggable || s.draggablex || s.draggable) && (s.draggablex != false)) {
points[didx*ps] = newx;
}
if((o.grid.draggable || o.yaxis.draggable || s.draggabley || s.draggable) && (s.draggabley != false)) {
points[didx*ps+1] = newy;
}
plot.draw();
var retx = points[didx*ps];
var rety = points[didx*ps+1];
// uncomment if you are using Jonathan Leto's log plugin
// var yaxisBase = o.yaxis.base;
// var xaxisBase = o.xaxis.base;
// if (s.yaxis == axes.y2axis)
// yaxisBase = o.y2axis.base;
// if (s.xaxis == axes.x2axis)
// xaxisBase = o.x2axis.base;
//
// if ( yaxisBase > 1 ) {
// rety = Math.exp(newy*Math.LN10);
// }
//
// if ( xaxisBase > 1 ) {
// retx = Math.exp(newx*Math.LN10);
// }
plot.getPlaceholder().trigger('plotSeriesChange', [sidx, didx, retx, rety])
});
eventHolder.bind("dragend", function (e) {
var sidx = drag.item.seriesIndex;
var didx = drag.item.dataIndex;
var s = plot.getData()[sidx];
var ps = s.datapoints.pointsize;
plot.getPlaceholder().trigger('plotFinalSeriesChange', [sidx, didx, s.datapoints.points[didx*ps], s.datapoints.points[didx*ps+1]])
});
}
}
plot.hooks.bindEvents.push(bindEvents);
}
$.plot.plugins.push({
init: init,
options: options,
name: 'draggable',
version: '1.0'
});
})(jQuery);

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,60 @@
/* Flot plugin for automatically redrawing plots as the placeholder resizes.
Copyright (c) 2007-2013 IOLA and Ole Laursen.
Licensed under the MIT license.
It works by listening for changes on the placeholder div (through the jQuery
resize event plugin) - if the size changes, it will redraw the plot.
There are no options. If you need to disable the plugin for some plots, you
can just fix the size of their placeholders.
*/
/* Inline dependency:
* jQuery resize event - v1.1 - 3/14/2010
* http://benalman.com/projects/jquery-resize-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($,t,n){function p(){for(var n=r.length-1;n>=0;n--){var o=$(r[n]);if(o[0]==t||o.is(":visible")){var h=o.width(),d=o.height(),v=o.data(a);!v||h===v.w&&d===v.h?i[f]=i[l]:(i[f]=i[c],o.trigger(u,[v.w=h,v.h=d]))}else v=o.data(a),v.w=0,v.h=0}s!==null&&(s=t.requestAnimationFrame(p))}var r=[],i=$.resize=$.extend($.resize,{}),s,o="setTimeout",u="resize",a=u+"-special-event",f="delay",l="pendingDelay",c="activeDelay",h="throttleWindow";i[l]=250,i[c]=20,i[f]=i[l],i[h]=!0,$.event.special[u]={setup:function(){if(!i[h]&&this[o])return!1;var t=$(this);r.push(this),t.data(a,{w:t.width(),h:t.height()}),r.length===1&&(s=n,p())},teardown:function(){if(!i[h]&&this[o])return!1;var t=$(this);for(var n=r.length-1;n>=0;n--)if(r[n]==this){r.splice(n,1);break}t.removeData(a),r.length||(cancelAnimationFrame(s),s=null)},add:function(t){function s(t,i,s){var o=$(this),u=o.data(a);u.w=i!==n?i:o.width(),u.h=s!==n?s:o.height(),r.apply(this,arguments)}if(!i[h]&&this[o])return!1;var r;if($.isFunction(t))return r=t,s;r=t.handler,t.handler=s}},t.requestAnimationFrame||(t.requestAnimationFrame=function(){return t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||t.msRequestAnimationFrame||function(e,n){return t.setTimeout(e,i[f])}}()),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(){return t.webkitCancelRequestAnimationFrame||t.mozCancelRequestAnimationFrame||t.oCancelRequestAnimationFrame||t.msCancelRequestAnimationFrame||clearTimeout}())})(jQuery,this);
(function ($) {
var options = { }; // no options
function init(plot) {
function onResize() {
var placeholder = plot.getPlaceholder();
// somebody might have hidden us and we can't plot
// when we don't have the dimensions
if (placeholder.width() == 0 || placeholder.height() == 0)
return;
plot.resize();
plot.setupGrid();
plot.draw();
}
function bindEvents(plot, eventHolder) {
plot.getPlaceholder().resize(onResize);
}
function shutdown(plot, eventHolder) {
plot.getPlaceholder().unbind("resize", onResize);
}
plot.hooks.bindEvents.push(bindEvents);
plot.hooks.shutdown.push(shutdown);
}
$.plot.plugins.push({
init: init,
options: options,
name: 'resize',
version: '1.0'
});
})(jQuery);

Wyświetl plik

@ -127,405 +127,11 @@ function update_profile(id) {
}
Highcharts.theme = {
colors: ["#D8D3C5", "#75890c", "#c70000", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee",
"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
chart: {
/*
backgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0, '#686764'],
[1, '#383734']
]
},
* */
backgroundColor:'rgba(255, 255, 255, 0)',
borderWidth: 0,
borderRadius: 0,
plotBackgroundColor: null,
plotShadow: true,
plotBorderWidth: 0,
marginBottom: 50
},
title: {
style: {
color: '#FFF',
font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
}
},
subtitle: {
style: {
color: '#DDD',
font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
}
},
xAxis: {
gridLineWidth: 1,
gridLineColor: 'rgba(255, 255, 255, .1)',
lineColor: 'rgba(255, 255, 255, .1)',
tickColor: 'rgba(255, 255, 255, .1)',
labels: {
style: {
paddingTop: '4px',
color: '#D8D3C5',
font: '15px Arial, Helvetica, sans-serif'
}
},
title: {
style: {
color: '#FFF',
font: '12px Arial, Helvetica, sans-serif'
}
}
},
yAxis: {
alternateGridColor: null,
minorTickInterval: null,
gridLineColor: 'rgba(255, 255, 255, .1)',
minorGridLineColor: 'rgba(255,255,255,0.05)',
lineWidth: 0,
tickWidth: 0,
labels: {
style: {
color: '#D8D3C5',
font: '15px Arial, Helvetica, sans-serif'
}
},
title: {
style: {
color: '#FFF',
font: '12px Arial, Helvetica, sans-serif'
}
}
},
legend: {
enabled: false,
itemStyle: {
color: '#CCC'
},
itemHoverStyle: {
color: '#FFF'
},
itemHiddenStyle: {
color: '#333'
},
borderRadius: 0,
borderWidth: 0
},
labels: {
style: {
color: '#CCC'
}
},
tooltip: {
backgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0, 'rgba(96, 96, 96, .8)'],
[1, 'rgba(16, 16, 16, .8)']
]
},
borderWidth: 0,
style: {
color: '#FFF'
}
},
plotOptions: {
series: {
shadow: true
},
line: {
dataLabels: {
color: '#CCC'
},
marker: {
lineColor: '#333'
}
},
spline: {
marker: {
lineColor: '#333'
}
}
},
toolbar: {
itemStyle: {
color: '#CCC'
}
},
navigation: {
buttonOptions: {
symbolStroke: '#DDDDDD',
hoverSymbolStroke: '#FFFFFF',
theme: {
fill: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0.4, '#606060'],
[0.6, '#333333']
]
},
stroke: '#000000'
}
}
},
// scroll charts
rangeSelector: {
buttonTheme: {
fill: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0.4, '#888'],
[0.6, '#555']
]
},
stroke: '#000000',
style: {
color: '#CCC',
fontWeight: 'bold'
},
states: {
hover: {
fill: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0.4, '#BBB'],
[0.6, '#888']
]
},
stroke: '#000000',
style: {
color: 'white'
}
},
select: {
fill: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0.1, '#000'],
[0.3, '#333']
]
},
stroke: '#000000',
style: {
color: 'yellow'
}
}
}
},
inputStyle: {
backgroundColor: '#333',
color: 'silver'
},
labelStyle: {
color: 'silver'
}
},
navigator: {
handles: {
backgroundColor: '#666',
borderColor: '#AAA'
},
outlineColor: '#CCC',
maskFill: 'rgba(16, 16, 16, 0.5)',
series: {
color: '#7798BF',
lineColor: '#A6C7ED'
}
},
scrollbar: {
barBackgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0.4, '#888'],
[0.6, '#555']
]
},
barBorderColor: '#CCC',
buttonArrowColor: '#CCC',
buttonBackgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0.4, '#888'],
[0.6, '#555']
]
},
buttonBorderColor: '#CCC',
rifleColor: '#FFF',
trackBackgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0, '#000'],
[1, '#333']
]
},
trackBorderColor: '#666'
},
// special colors for some of the demo examples
legendBackgroundColor: 'rgba(48, 48, 48, 0.8)',
legendBackgroundColorSolid: 'rgb(70, 70, 70)',
dataLabelsColor: '#444',
textColor: '#E0E0E0',
maskColor: 'rgba(255,255,255,0.3)'
};
function getHCOptions() {
var options =
{
title: { text: '' },
xAxis: {
title: { text: 'Time (s)' },
type: 'integer',
tickPixelInterval: 60
},
yAxis: {
title: { text: 'Temperature (\xB0C)' },
tickInterval: 25,
min: 0,
max: 300
},
tooltip: {
formatter: function() {
return Highcharts.numberFormat(this.y, 0);
}
},
chart: {
type: 'line',
renderTo: 'graph_container',
animation: true,
//zoomType: 'x',
marginTop: 30,
marginRight: 30,
events: {
load: function() {
var series = this.series[1];
eta=0;
ws_status.onmessage = function(e)
{
x = JSON.parse(e.data);
if(state!="EDIT")
{
state = x.state;
if(state=="RUNNING")
{
$("#nav_start").hide();
$("#nav_stop").show();
series.addPoint([x.runtime, x.temperature], true, false);
left = parseInt(x.totaltime-x.runtime);
var minutes = Math.floor(left / 60);
var seconds = left - minutes * 60;
eta = minutes+':'+ (seconds < 10 ? "0" : "") + seconds;
}
else
{
$("#nav_start").show();
$("#nav_stop").hide();
}
}
$('#state').html(state);
updateProgress(parseFloat(x.runtime)/parseFloat(x.totaltime)*100,eta);
$('#act_temp').html(Highcharts.numberFormat(x.temperature, 0) + ' \xB0C');
$('#power').css("background-color", (x.power > 0.5 ? "#75890c" : "#1F1E1A") );
if (x.target == 0)
{
$('#target_temp').html('OFF');
}
else
{
$('#target_temp').html(Highcharts.numberFormat(x.target, 0) + ' \xB0C');
}
}
}
},
resetZoomButton: {
position: {
align: 'right',
verticalAlign: 'top'
}
}
},
plotOptions: {
series: {
cursor: 'move',
point: {
events: {
/*
drag: function (e) {
$('#drag').html('Dragging <b>' + this.series.name + '</b>, <b>' + this.category + '</b> to <b>' + Highcharts.numberFormat(e.newY, 0) + '</b>');
},
drop: function () {
$('#drop').html('In <b>' + this.series.name + '</b>, <b>' + this.category + '</b> was set to <b>' + Highcharts.numberFormat(this.y, 0) + '</b>');
}*/
}
},
stickyTracking: false
},
},
credits: {
enabled: false
},
series: [{
name: 'Ref',
data: [
[1, 25 ],
[70, 150 ],
[180, 183 ],
[210, 230 ],
[240, 183 ],
[300, 25 ]
],
draggableX: false,
draggableY: false,
dragMinY: 0,
dragMaxY: 250,
marker: {
enabled: false
}
},
{
name: 'Act',
data: [
[0,0]
],
marker: {
enabled: false
}
}]
};
return (options);
}
@ -542,13 +148,23 @@ $(document).ready(function() {
ws_status.onopen = function()
{
console.log("Status Socket has been opened");
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>Yay</b><br/>I'm alive", {
ele: 'body', // which element to append to
type: 'success', // (null, 'info', 'error', 'success')
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
align: 'center', // ('left', 'right', or 'center')
width: 385, // (integer, or 'auto')
delay: 2500,
allow_dismiss: true,
stackup_spacing: 10 // spacing between consecutively stacked growls.
});
};
ws_status.onclose = function()
{
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>ERROR 1:</b><br/>Status Websocket not available", {
ele: 'body', // which element to append to
type: 'alert', // (null, 'info', 'error', 'success')
type: 'error', // (null, 'info', 'error', 'success')
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
align: 'center', // ('left', 'right', or 'center')
width: 385, // (integer, or 'auto')
@ -652,24 +268,6 @@ $("#e2").on("change", function(e) {
// Apply the theme
var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
$(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
graph = new Highcharts.Chart(getHCOptions());
});
}
});

Wyświetl plik

@ -6,18 +6,397 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="assets/js/jquery-1.10.2.min.js"></script>
<script src="assets/js/highcharts.js"></script>
<script src="assets/js/draggable-points.js"></script>
<script src="assets/js/jquery.event.drag-2.2.js"></script>
<script src="assets/js/jquery.flot.js"></script>
<script src="assets/js/jquery.flot.resize.js"></script>
<script src="assets/js/jquery.flot.draggable.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/jquery.bootstrap-growl.min.js"></script>
<script src="assets/js/select2.min.js"></script>
<script src="assets/js/picoreflow.js"></script>
<link rel="stylesheet" href="assets/css/bootstrap.min.css"/>
<link rel="stylesheet" href="assets/css/bootstrap-theme.min.css"/>
<link rel="stylesheet" href="assets/css/select2.css"/>
<link rel="stylesheet" href="assets/css/picoreflow.css"/>
<script type="text/javascript">
var state = "IDLE";
var graph = [ 'profile', 'live'];
var points = [];
var profiles = [];
var selected_profile = 0;
var selected_profile_name = "leadfree";
var host = "ws://" + window.location.hostname + ":8080";
var ws_status = new WebSocket(host+"/status");
var ws_control = new WebSocket(host+"/control");
var ws_storage = new WebSocket(host+"/storage");
graph.profile = {
label: "Profile",
data: [],
points: { show: false },
color: "#75890c",
draggable: false
};
graph.live = {
label: "Live",
data: [],
points: { show: false },
color: "#d8d3c5",
draggable: false
};
function update_profile(id) {
selected_profile = id;
$('#sel_prof').html(profiles[id].name);
graph.profile.data = profiles[id].data;
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ] , getOptions());
}
function updateProgress(percentage, eta){
if(state=="RUNNING") {
if(percentage > 100) percentage = 100;
$('#progressBar').css('width', percentage+'%');
if(percentage>9) $('#progressBar').html(parseInt(percentage)+'% - '+ eta);
} else {
$('#progressBar').css('width', 0+'%');
$('#progressBar').html('');
}
}
function runTask() {
var test = {
"cmd": "RUN",
"profile": profiles[selected_profile]
}
//console.log(JSON.stringify(test));
ws_control.send(JSON.stringify(test));
graph.series[1].setData([]);
}
function abortTask() {
var test = {"cmd": "STOP"};
//console.log(JSON.stringify(test));
ws_control.send(JSON.stringify(test));
}
function enterEditMode() {
state="EDIT"
$('#main_status').slideUp();
$('#saveas').show();
$('#e2').select2('container').hide();
$('#nav_start').hide();
$('#btn_edit').hide();
$('#btn_exit').show();
$('#form_profile_name').attr('value', profiles[selected_profile].name);
graph.profile.points.show = true;
graph.profile.draggable = true;
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
/*
graph.series[0].options.marker.enabled=true;
graph.series[0].options.draggableX=true;
graph.series[0].options.draggableY=true;
graph.render();
*/
}
function leaveEditMode() {
state="IDLE";
$('#saveas').hide();
$('#e2').select2('container').show();
$('#main_status').slideDown();
$('#nav_start').show();
$('#btn_edit').show();
$('#btn_exit').hide();
graph.profile.points.show = false;
graph.profile.draggable = false;
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
/*
graph.series[0].options.marker.enabled=false;
graph.series[0].options.draggableX=false;
graph.series[0].options.draggableY=false;
graph.render();
*/
}
function saveProfile() {
name = $('#form_profile_name').val();
//console.log('Trying to save profile: ' + name);
var rawdata = graph.series[0].data;
var data = [];
var last = -1;
for(var i=0; i<rawdata.length;i++)
{
if(rawdata[i].x > last)
{
data.push([rawdata[i].x, rawdata[i].y]);
}
else
{
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>ERROR 88:</b><br/>An oven is not a time-machine", {
ele: 'body', // which element to append to
type: 'alert', // (null, 'info', 'error', 'success')
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
align: 'center', // ('left', 'right', or 'center')
width: 385, // (integer, or 'auto')
delay: 5000,
allow_dismiss: true,
stackup_spacing: 10 // spacing between consecutively stacked growls.
});
return false;
}
last = rawdata[i].x;
}
var profile = { "type": "profile", "data": data, "name": name }
var put = { "cmd": "PUT", "profile": profile }
var put_cmd = JSON.stringify(put);
ws_storage.send(put_cmd);
//console.log('came to this: ' + put_cmd);
selected_profile_name = name;
leaveEditMode();
}
function getOptions()
{
var options =
{
series:
{
lines: { show: true },
points: { show: true }
},
xaxis:
{
tickSize: 30,
min: 0,
tickColor: 'rgba(216, 211, 197, 0.2)',
font:
{
size: 12,
lineHeight: 14,
weight: "normal",
family: "LCDN",
variant: "small-caps",
color: "rgba(216, 211, 197, 0.85)"
}
},
yaxis:
{
tickSize: 25,
min: 0,
max: 250,
tickDecimals: 0,
draggable: false,
tickColor: 'rgba(216, 211, 197, 0.2)',
font:
{
size: 12,
lineHeight: 14,
weight: "normal",
family: "LCDN",
variant: "small-caps",
color: "rgba(216, 211, 197, 0.85)"
}
},
grid:
{
color: 'rgba(216, 211, 197, 0.55)',
borderWidth: 1,
labelMargin: 10,
mouseActiveRadius: 50
},
legend:
{
show: false
}
}
return options;
}
$(document).ready(function() {
if(!("WebSocket" in window)){
$('#chatLog, input, button, #examples').fadeOut("fast");
$('<p>Oh no, you need a browser that supports WebSockets. How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');
}else{
// Status Socket ////////////////////////////////
ws_status.onopen = function()
{
console.log("Status Socket has been opened");
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>Yay</b><br/>I'm alive", {
ele: 'body', // which element to append to
type: 'success', // (null, 'info', 'error', 'success')
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
align: 'center', // ('left', 'right', or 'center')
width: 385, // (integer, or 'auto')
delay: 2500,
allow_dismiss: true,
stackup_spacing: 10 // spacing between consecutively stacked growls.
});
};
ws_status.onclose = function()
{
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>ERROR 1:</b><br/>Status Websocket not available", {
ele: 'body', // which element to append to
type: 'error', // (null, 'info', 'error', 'success')
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
align: 'center', // ('left', 'right', or 'center')
width: 385, // (integer, or 'auto')
delay: 5000,
allow_dismiss: true,
stackup_spacing: 10 // spacing between consecutively stacked growls.
});
};
// Control Socket ////////////////////////////////
ws_control.onopen = function()
{
ws_control.onmessage = function(e)
{
console.log (e.data);
}
console.log("Control Socket has been opened");
}
// Storage Socket ///////////////////////////////
ws_storage.onopen = function()
{
console.log("Storage Socket has been opened");
ws_storage.onmessage = function(e)
{
console.log('Storage MSG:' + e.data);
message = JSON.parse(e.data);
console.log("Parsed message:" + message);
if(message.resp)
{
console.log("RESP");
if(message.resp == "FAIL")
{
console.log("FAIL");
if (confirm('Overwrite?')) {
//message.cmd="PUT";
message.force=true;
console.log("Sending: " + JSON.stringify(message));
ws_storage.send(JSON.stringify(message));
} else {
//do nothing
}
}
return;
}
//the message is an array of profiles
//FIXME: this should be better, maybe a {"profiles": ...} container?
profiles = message;
//delete old options in select
$('#e2')
.find('option')
.remove()
.end();
// fill select with new options from websocket
for (var i=0; i<profiles.length; i++)
{
var profile = profiles[i];
console.log(profile.name);
$('#e2').append('<option value="'+i+'">'+profile.name+'</option>');
if (profile.name == selected_profile_name)
{
selected_profile = i;
$('#e2').select2('val', i);
update_profile(i);
}
}
//graph.render();
}
console.log('Requesting stored profiles');
ws_storage.send('GET');
}
$("#e2").select2({
placeholder: "Select Profile",
allowClear: false
});
$("#e2").on("change", function(e) {
update_profile(e.val);
});
}
});
</script>
</head>
<body>
@ -25,8 +404,8 @@
<div id="main_status">
<div class="pull-left" style="margin: 14px">
<span id="act_temp" class="display" style="color: #75890c">25 &deg;C</span>
<span id="target_temp" class="display">OFF</span>
<span id="act_temp" class="display ds-num" style="color: #75890c">25 &deg;C</span>
<span id="target_temp" class="display ds-num">OFF</span>
<span id="state" class="display" style="font-size: 14px; text-align: center; padding-right:0">Idle</span>
<span id="power" class="display" style="width: 35px;">&nbsp;</span>
<span id="cyclic" class="display" style="width: 35px;">&nbsp;</span>
@ -46,7 +425,14 @@
<div class="panel panel-default">
<div class="panel-heading">
<select id="e2" style="margin-top: 4px"></select>
<div id="selectp" class="input-group" style="width: 50%">
<span class="input-group-addon">Profile Name</span>
<select id="e2" class="select2" style="margin-top: 4px"></select>
<button id="btn_edit" type="button" class="btn btn-default" onclick="enterEditMode()"><span class="glyphicon glyphicon-pencil"></span></button>
</div>
<div id="saveas" class="input-group" style="display:none;">
<span class="input-group-addon">Profile Name</span>
@ -57,9 +443,6 @@
</span>
</div>
<div class="btn-group btn-group-sm">
<button id="btn_edit" type="button" class="btn btn-default" onclick="enterEditMode()"><span class="glyphicon glyphicon-pencil"></span></button>
</div>
<div class="pull-right" style="margin-top: 3px">
<button id="nav_start" type="button" class="btn btn-success" data-toggle="modal" data-target="#myModal" style="display:none"><span class="glyphicon glyphicon-play"></span> Start</button>
@ -67,8 +450,9 @@
</div>
</div>
<div class="panel-body" style='padding: 0'>
<div id="graph_container" style="height: 400px; margin: 0 auto"></div>
<div class="panel-body">
<div id="graph_container" class="graph"></div>
</div>
</div>
@ -98,5 +482,7 @@
</div>
</div>
</body>
</html>