mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Update jquery and related libraries (#3069)
* Update jquery, jquery ui, jquery validate and flot to current versions update jquery to 3.3.1 update jqueryui to 1.12.1 update jquery validate to 1.17.0 update jquery flot to 0.8.3 * Replace deprecated removed jquery functions * Fix initial tab content loading in detailView * Fix logout for new jquery version * Fix tooltip detail displaying for new JQuery version * Fix view all trigger in detailView for new JQuery version * Fix breadcrumb click event handler for JQuery update * Fix displaying of preselected zone in instanceWizard for new jQuery verion
This commit is contained in:
parent
ac73e7e671
commit
093ab722b3
@ -102,7 +102,7 @@
|
||||
<p><translate key="message.select.a.zone"/></p>
|
||||
<div class="select-area">
|
||||
<div class="desc"></div>
|
||||
<select name="zoneid" class="required">
|
||||
<select name="zoneid" class="required" required>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -18,162 +18,163 @@
|
||||
*
|
||||
* V. 1.1: Fix error handling so e.g. parsing an empty string does
|
||||
* produce a color rather than just crashing.
|
||||
*/
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
$.color = {};
|
||||
$.color = {};
|
||||
|
||||
// construct color object with some convenient chainable helpers
|
||||
$.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;
|
||||
// construct color object with some convenient chainable helpers
|
||||
$.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.0) {
|
||||
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();
|
||||
}
|
||||
|
||||
// extract CSS color property from element, going up in the DOM
|
||||
// if it's "transparent"
|
||||
$.color.extract = function (elem, css) {
|
||||
var c;
|
||||
do {
|
||||
c = elem.css(css).toLowerCase();
|
||||
// keep going until we find an element that has color, or
|
||||
// we hit the body
|
||||
if (c != '' && c != 'transparent')
|
||||
break;
|
||||
elem = elem.parent();
|
||||
} while (!$.nodeName(elem.get(0), "body"));
|
||||
|
||||
// catch Safari's way of signalling transparent
|
||||
if (c == "rgba(0, 0, 0, 0)")
|
||||
c = "transparent";
|
||||
|
||||
return $.color.parse(c);
|
||||
}
|
||||
|
||||
// parse CSS color string (like "rgb(10, 32, 43)" or "#fff"),
|
||||
// returns color object, if parsing failed, you get black (0, 0,
|
||||
// 0) out
|
||||
$.color.parse = function (str) {
|
||||
var res, m = $.color.make;
|
||||
|
||||
// Look for rgb(num,num,num)
|
||||
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));
|
||||
|
||||
// Look for rgba(num,num,num,num)
|
||||
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]));
|
||||
|
||||
// Look for rgb(num%,num%,num%)
|
||||
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);
|
||||
|
||||
// Look for rgba(num%,num%,num%,num)
|
||||
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]));
|
||||
|
||||
// Look for #a0b1c2
|
||||
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));
|
||||
|
||||
// Look for #fff
|
||||
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));
|
||||
|
||||
// Otherwise, we're most likely dealing with a named color
|
||||
var name = $.trim(str).toLowerCase();
|
||||
if (name == "transparent")
|
||||
return m(255, 255, 255, 0);
|
||||
else {
|
||||
// default to black
|
||||
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]
|
||||
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.0) {
|
||||
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();
|
||||
}
|
||||
|
||||
// extract CSS color property from element, going up in the DOM
|
||||
// if it's "transparent"
|
||||
$.color.extract = function (elem, css) {
|
||||
var c;
|
||||
|
||||
do {
|
||||
c = elem.css(css).toLowerCase();
|
||||
// keep going until we find an element that has color, or
|
||||
// we hit the body or root (have no parent)
|
||||
if (c != '' && c != 'transparent')
|
||||
break;
|
||||
elem = elem.parent();
|
||||
} while (elem.length && !$.nodeName(elem.get(0), "body"));
|
||||
|
||||
// catch Safari's way of signalling transparent
|
||||
if (c == "rgba(0, 0, 0, 0)")
|
||||
c = "transparent";
|
||||
|
||||
return $.color.parse(c);
|
||||
}
|
||||
|
||||
// parse CSS color string (like "rgb(10, 32, 43)" or "#fff"),
|
||||
// returns color object, if parsing failed, you get black (0, 0,
|
||||
// 0) out
|
||||
$.color.parse = function (str) {
|
||||
var res, m = $.color.make;
|
||||
|
||||
// Look for rgb(num,num,num)
|
||||
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));
|
||||
|
||||
// Look for rgba(num,num,num,num)
|
||||
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]));
|
||||
|
||||
// Look for rgb(num%,num%,num%)
|
||||
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);
|
||||
|
||||
// Look for rgba(num%,num%,num%,num)
|
||||
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]));
|
||||
|
||||
// Look for #a0b1c2
|
||||
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));
|
||||
|
||||
// Look for #fff
|
||||
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));
|
||||
|
||||
// Otherwise, we're most likely dealing with a named color
|
||||
var name = $.trim(str).toLowerCase();
|
||||
if (name == "transparent")
|
||||
return m(255, 255, 255, 0);
|
||||
else {
|
||||
// default to black
|
||||
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);
|
||||
|
||||
@ -1,29 +1,31 @@
|
||||
/*
|
||||
Flot plugin for showing crosshairs, thin lines, when the mouse hovers
|
||||
over the plot.
|
||||
/* Flot plugin for showing crosshairs when the mouse hovers over the plot.
|
||||
|
||||
crosshair: {
|
||||
mode: null or "x" or "y" or "xy"
|
||||
color: color
|
||||
lineWidth: number
|
||||
}
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
Set the mode to one of "x", "y" or "xy". The "x" mode enables a
|
||||
vertical crosshair that lets you trace the values on the x axis, "y"
|
||||
enables a horizontal crosshair and "xy" enables them both. "color" is
|
||||
the color of the crosshair (default is "rgba(170, 0, 0, 0.80)"),
|
||||
"lineWidth" is the width of the drawn lines (default is 1).
|
||||
The plugin supports these options:
|
||||
|
||||
crosshair: {
|
||||
mode: null or "x" or "y" or "xy"
|
||||
color: color
|
||||
lineWidth: number
|
||||
}
|
||||
|
||||
Set the mode to one of "x", "y" or "xy". The "x" mode enables a vertical
|
||||
crosshair that lets you trace the values on the x axis, "y" enables a
|
||||
horizontal crosshair and "xy" enables them both. "color" is the color of the
|
||||
crosshair (default is "rgba(170, 0, 0, 0.80)"), "lineWidth" is the width of
|
||||
the drawn lines (default is 1).
|
||||
|
||||
The plugin also adds four public methods:
|
||||
|
||||
- setCrosshair(pos)
|
||||
- setCrosshair( pos )
|
||||
|
||||
Set the position of the crosshair. Note that this is cleared if
|
||||
the user moves the mouse. "pos" is in coordinates of the plot and
|
||||
should be on the form { x: xpos, y: ypos } (you can use x2/x3/...
|
||||
if you're using multiple axes), which is coincidentally the same
|
||||
format as what you get from a "plothover" event. If "pos" is null,
|
||||
the crosshair is cleared.
|
||||
Set the position of the crosshair. Note that this is cleared if the user
|
||||
moves the mouse. "pos" is in coordinates of the plot and should be on the
|
||||
form { x: xpos, y: ypos } (you can use x2/x3/... if you're using multiple
|
||||
axes), which is coincidentally the same format as what you get from a
|
||||
"plothover" event. If "pos" is null, the crosshair is cleared.
|
||||
|
||||
- clearCrosshair()
|
||||
|
||||
@ -31,22 +33,25 @@ The plugin also adds four public methods:
|
||||
|
||||
- lockCrosshair(pos)
|
||||
|
||||
Cause the crosshair to lock to the current location, no longer
|
||||
updating if the user moves the mouse. Optionally supply a position
|
||||
(passed on to setCrosshair()) to move it to.
|
||||
Cause the crosshair to lock to the current location, no longer updating if
|
||||
the user moves the mouse. Optionally supply a position (passed on to
|
||||
setCrosshair()) to move it to.
|
||||
|
||||
Example usage:
|
||||
var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
|
||||
$("#graph").bind("plothover", function (evt, position, item) {
|
||||
if (item) {
|
||||
// Lock the crosshair to the data point being hovered
|
||||
myFlot.lockCrosshair({ x: item.datapoint[0], y: item.datapoint[1] });
|
||||
}
|
||||
else {
|
||||
// Return normal crosshair operation
|
||||
myFlot.unlockCrosshair();
|
||||
}
|
||||
});
|
||||
|
||||
var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
|
||||
$("#graph").bind( "plothover", function ( evt, position, item ) {
|
||||
if ( item ) {
|
||||
// Lock the crosshair to the data point being hovered
|
||||
myFlot.lockCrosshair({
|
||||
x: item.datapoint[ 0 ],
|
||||
y: item.datapoint[ 1 ]
|
||||
});
|
||||
} else {
|
||||
// Return normal crosshair operation
|
||||
myFlot.unlockCrosshair();
|
||||
}
|
||||
});
|
||||
|
||||
- unlockCrosshair()
|
||||
|
||||
@ -54,114 +59,118 @@ The plugin also adds four public methods:
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
crosshair: {
|
||||
mode: null, // one of null, "x", "y" or "xy",
|
||||
color: "rgba(170, 0, 0, 0.80)",
|
||||
lineWidth: 1
|
||||
}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
// position of crosshair in pixels
|
||||
var crosshair = { x: -1, y: -1, locked: false };
|
||||
|
||||
plot.setCrosshair = function setCrosshair(pos) {
|
||||
if (!pos)
|
||||
crosshair.x = -1;
|
||||
else {
|
||||
var o = plot.p2c(pos);
|
||||
crosshair.x = Math.max(0, Math.min(o.left, plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(o.top, plot.height()));
|
||||
}
|
||||
|
||||
plot.triggerRedrawOverlay();
|
||||
};
|
||||
|
||||
plot.clearCrosshair = plot.setCrosshair; // passes null for pos
|
||||
|
||||
plot.lockCrosshair = function lockCrosshair(pos) {
|
||||
if (pos)
|
||||
plot.setCrosshair(pos);
|
||||
crosshair.locked = true;
|
||||
}
|
||||
|
||||
plot.unlockCrosshair = function unlockCrosshair() {
|
||||
crosshair.locked = false;
|
||||
}
|
||||
|
||||
function onMouseOut(e) {
|
||||
if (crosshair.locked)
|
||||
return;
|
||||
|
||||
if (crosshair.x != -1) {
|
||||
crosshair.x = -1;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(e) {
|
||||
if (crosshair.locked)
|
||||
return;
|
||||
|
||||
if (plot.getSelection && plot.getSelection()) {
|
||||
crosshair.x = -1; // hide the crosshair while selecting
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = plot.offset();
|
||||
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(function (plot, eventHolder) {
|
||||
if (!plot.getOptions().crosshair.mode)
|
||||
return;
|
||||
|
||||
eventHolder.mouseout(onMouseOut);
|
||||
eventHolder.mousemove(onMouseMove);
|
||||
});
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
var c = plot.getOptions().crosshair;
|
||||
if (!c.mode)
|
||||
return;
|
||||
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
if (crosshair.x != -1) {
|
||||
ctx.strokeStyle = c.color;
|
||||
ctx.lineWidth = c.lineWidth;
|
||||
ctx.lineJoin = "round";
|
||||
|
||||
ctx.beginPath();
|
||||
if (c.mode.indexOf("x") != -1) {
|
||||
ctx.moveTo(crosshair.x, 0);
|
||||
ctx.lineTo(crosshair.x, plot.height());
|
||||
}
|
||||
if (c.mode.indexOf("y") != -1) {
|
||||
ctx.moveTo(0, crosshair.y);
|
||||
ctx.lineTo(plot.width(), crosshair.y);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
});
|
||||
|
||||
plot.hooks.shutdown.push(function (plot, eventHolder) {
|
||||
eventHolder.unbind("mouseout", onMouseOut);
|
||||
eventHolder.unbind("mousemove", onMouseMove);
|
||||
});
|
||||
var options = {
|
||||
crosshair: {
|
||||
mode: null, // one of null, "x", "y" or "xy",
|
||||
color: "rgba(170, 0, 0, 0.80)",
|
||||
lineWidth: 1
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'crosshair',
|
||||
version: '1.0'
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
// position of crosshair in pixels
|
||||
var crosshair = { x: -1, y: -1, locked: false };
|
||||
|
||||
plot.setCrosshair = function setCrosshair(pos) {
|
||||
if (!pos)
|
||||
crosshair.x = -1;
|
||||
else {
|
||||
var o = plot.p2c(pos);
|
||||
crosshair.x = Math.max(0, Math.min(o.left, plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(o.top, plot.height()));
|
||||
}
|
||||
|
||||
plot.triggerRedrawOverlay();
|
||||
};
|
||||
|
||||
plot.clearCrosshair = plot.setCrosshair; // passes null for pos
|
||||
|
||||
plot.lockCrosshair = function lockCrosshair(pos) {
|
||||
if (pos)
|
||||
plot.setCrosshair(pos);
|
||||
crosshair.locked = true;
|
||||
};
|
||||
|
||||
plot.unlockCrosshair = function unlockCrosshair() {
|
||||
crosshair.locked = false;
|
||||
};
|
||||
|
||||
function onMouseOut(e) {
|
||||
if (crosshair.locked)
|
||||
return;
|
||||
|
||||
if (crosshair.x != -1) {
|
||||
crosshair.x = -1;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(e) {
|
||||
if (crosshair.locked)
|
||||
return;
|
||||
|
||||
if (plot.getSelection && plot.getSelection()) {
|
||||
crosshair.x = -1; // hide the crosshair while selecting
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = plot.offset();
|
||||
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(function (plot, eventHolder) {
|
||||
if (!plot.getOptions().crosshair.mode)
|
||||
return;
|
||||
|
||||
eventHolder.mouseout(onMouseOut);
|
||||
eventHolder.mousemove(onMouseMove);
|
||||
});
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
var c = plot.getOptions().crosshair;
|
||||
if (!c.mode)
|
||||
return;
|
||||
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
if (crosshair.x != -1) {
|
||||
var adj = plot.getOptions().crosshair.lineWidth % 2 ? 0.5 : 0;
|
||||
|
||||
ctx.strokeStyle = c.color;
|
||||
ctx.lineWidth = c.lineWidth;
|
||||
ctx.lineJoin = "round";
|
||||
|
||||
ctx.beginPath();
|
||||
if (c.mode.indexOf("x") != -1) {
|
||||
var drawX = Math.floor(crosshair.x) + adj;
|
||||
ctx.moveTo(drawX, 0);
|
||||
ctx.lineTo(drawX, plot.height());
|
||||
}
|
||||
if (c.mode.indexOf("y") != -1) {
|
||||
var drawY = Math.floor(crosshair.y) + adj;
|
||||
ctx.moveTo(0, drawY);
|
||||
ctx.lineTo(plot.width(), drawY);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
});
|
||||
|
||||
plot.hooks.shutdown.push(function (plot, eventHolder) {
|
||||
eventHolder.unbind("mouseout", onMouseOut);
|
||||
eventHolder.unbind("mousemove", onMouseMove);
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'crosshair',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
@ -1,183 +1,226 @@
|
||||
/*
|
||||
Flot plugin for computing bottoms for filled line and bar charts.
|
||||
/* Flot plugin for computing bottoms for filled line and bar charts.
|
||||
|
||||
The case: you've got two series that you want to fill the area
|
||||
between. In Flot terms, you need to use one as the fill bottom of the
|
||||
other. You can specify the bottom of each data point as the third
|
||||
coordinate manually, or you can use this plugin to compute it for you.
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
In order to name the other series, you need to give it an id, like this
|
||||
The case: you've got two series that you want to fill the area between. In Flot
|
||||
terms, you need to use one as the fill bottom of the other. You can specify the
|
||||
bottom of each data point as the third coordinate manually, or you can use this
|
||||
plugin to compute it for you.
|
||||
|
||||
var dataset = [
|
||||
{ data: [ ... ], id: "foo" } , // use default bottom
|
||||
{ data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
|
||||
];
|
||||
In order to name the other series, you need to give it an id, like this:
|
||||
|
||||
$.plot($("#placeholder"), dataset, { line: { show: true, fill: true }});
|
||||
var dataset = [
|
||||
{ data: [ ... ], id: "foo" } , // use default bottom
|
||||
{ data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
|
||||
];
|
||||
|
||||
$.plot($("#placeholder"), dataset, { lines: { show: true, fill: true }});
|
||||
|
||||
As a convenience, if the id given is a number that doesn't appear as an id in
|
||||
the series, it is interpreted as the index in the array instead (so fillBetween:
|
||||
0 can also mean the first series).
|
||||
|
||||
Internally, the plugin modifies the datapoints in each series. For line series,
|
||||
extra data points might be inserted through interpolation. Note that at points
|
||||
where the bottom line is not defined (due to a null point or start/end of line),
|
||||
the current line will show a gap too. The algorithm comes from the
|
||||
jquery.flot.stack.js plugin, possibly some code could be shared.
|
||||
|
||||
As a convenience, if the id given is a number that doesn't appear as
|
||||
an id in the series, it is interpreted as the index in the array
|
||||
instead (so fillBetween: 0 can also mean the first series).
|
||||
|
||||
Internally, the plugin modifies the datapoints in each series. For
|
||||
line series, extra data points might be inserted through
|
||||
interpolation. Note that at points where the bottom line is not
|
||||
defined (due to a null point or start/end of line), the current line
|
||||
will show a gap too. The algorithm comes from the jquery.flot.stack.js
|
||||
plugin, possibly some code could be shared.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { fillBetween: null } // or number
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function findBottomSeries(s, allseries) {
|
||||
var i;
|
||||
for (i = 0; i < allseries.length; ++i) {
|
||||
if (allseries[i].id == s.fillBetween)
|
||||
return allseries[i];
|
||||
}
|
||||
(function ( $ ) {
|
||||
|
||||
if (typeof s.fillBetween == "number") {
|
||||
i = s.fillBetween;
|
||||
|
||||
if (i < 0 || i >= allseries.length)
|
||||
return null;
|
||||
|
||||
return allseries[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function computeFillBottoms(plot, s, datapoints) {
|
||||
if (s.fillBetween == null)
|
||||
return;
|
||||
|
||||
var other = findBottomSeries(s, plot.getData());
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize,
|
||||
points = datapoints.points,
|
||||
otherps = other.datapoints.pointsize,
|
||||
otherpoints = other.datapoints.points,
|
||||
newpoints = [],
|
||||
px, py, intery, qx, qy, bottom,
|
||||
withlines = s.lines.show,
|
||||
withbottom = ps > 2 && datapoints.format[2].y,
|
||||
withsteps = withlines && s.lines.steps,
|
||||
fromgap = true,
|
||||
i = 0, j = 0, l;
|
||||
|
||||
while (true) {
|
||||
if (i >= points.length)
|
||||
break;
|
||||
|
||||
l = newpoints.length;
|
||||
|
||||
if (points[i] == null) {
|
||||
// copy gaps
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else if (j >= otherpoints.length) {
|
||||
// for lines, we can't use the rest of the points
|
||||
if (!withlines) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
}
|
||||
i += ps;
|
||||
}
|
||||
else if (otherpoints[j] == null) {
|
||||
// oops, got a gap
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(null);
|
||||
fromgap = true;
|
||||
j += otherps;
|
||||
}
|
||||
else {
|
||||
// cases where we actually got two points
|
||||
px = points[i];
|
||||
py = points[i + 1];
|
||||
qx = otherpoints[j];
|
||||
qy = otherpoints[j + 1];
|
||||
bottom = 0;
|
||||
|
||||
if (px == qx) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
//newpoints[l + 1] += qy;
|
||||
bottom = qy;
|
||||
|
||||
i += ps;
|
||||
j += otherps;
|
||||
}
|
||||
else if (px > qx) {
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
if (withlines && i > 0 && points[i - ps] != null) {
|
||||
intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
|
||||
newpoints.push(qx);
|
||||
newpoints.push(intery)
|
||||
for (m = 2; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
}
|
||||
else { // px < qx
|
||||
if (fromgap && withlines) {
|
||||
// if we come from a gap, we just skip this point
|
||||
i += ps;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
// we might be able to interpolate a point below,
|
||||
// this can give us a better y
|
||||
if (withlines && j > 0 && otherpoints[j - otherps] != null)
|
||||
bottom = qy + (otherpoints[j - otherps + 1] - qy) * (px - qx) / (otherpoints[j - otherps] - qx);
|
||||
|
||||
//newpoints[l + 1] += bottom;
|
||||
|
||||
i += ps;
|
||||
}
|
||||
|
||||
fromgap = false;
|
||||
|
||||
if (l != newpoints.length && withbottom)
|
||||
newpoints[l + 2] = bottom;
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
if (withsteps && l != newpoints.length && l > 0
|
||||
&& newpoints[l] != null
|
||||
&& newpoints[l] != newpoints[l - ps]
|
||||
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints[l + ps + m] = newpoints[l + m];
|
||||
newpoints[l + 1] = newpoints[l - ps + 1];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(computeFillBottoms);
|
||||
var options = {
|
||||
series: {
|
||||
fillBetween: null // or number
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'fillbetween',
|
||||
version: '1.0'
|
||||
});
|
||||
};
|
||||
|
||||
function init( plot ) {
|
||||
|
||||
function findBottomSeries( s, allseries ) {
|
||||
|
||||
var i;
|
||||
|
||||
for ( i = 0; i < allseries.length; ++i ) {
|
||||
if ( allseries[ i ].id === s.fillBetween ) {
|
||||
return allseries[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
if ( typeof s.fillBetween === "number" ) {
|
||||
if ( s.fillBetween < 0 || s.fillBetween >= allseries.length ) {
|
||||
return null;
|
||||
}
|
||||
return allseries[ s.fillBetween ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function computeFillBottoms( plot, s, datapoints ) {
|
||||
|
||||
if ( s.fillBetween == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var other = findBottomSeries( s, plot.getData() );
|
||||
|
||||
if ( !other ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ps = datapoints.pointsize,
|
||||
points = datapoints.points,
|
||||
otherps = other.datapoints.pointsize,
|
||||
otherpoints = other.datapoints.points,
|
||||
newpoints = [],
|
||||
px, py, intery, qx, qy, bottom,
|
||||
withlines = s.lines.show,
|
||||
withbottom = ps > 2 && datapoints.format[2].y,
|
||||
withsteps = withlines && s.lines.steps,
|
||||
fromgap = true,
|
||||
i = 0,
|
||||
j = 0,
|
||||
l, m;
|
||||
|
||||
while ( true ) {
|
||||
|
||||
if ( i >= points.length ) {
|
||||
break;
|
||||
}
|
||||
|
||||
l = newpoints.length;
|
||||
|
||||
if ( points[ i ] == null ) {
|
||||
|
||||
// copy gaps
|
||||
|
||||
for ( m = 0; m < ps; ++m ) {
|
||||
newpoints.push( points[ i + m ] );
|
||||
}
|
||||
|
||||
i += ps;
|
||||
|
||||
} else if ( j >= otherpoints.length ) {
|
||||
|
||||
// for lines, we can't use the rest of the points
|
||||
|
||||
if ( !withlines ) {
|
||||
for ( m = 0; m < ps; ++m ) {
|
||||
newpoints.push( points[ i + m ] );
|
||||
}
|
||||
}
|
||||
|
||||
i += ps;
|
||||
|
||||
} else if ( otherpoints[ j ] == null ) {
|
||||
|
||||
// oops, got a gap
|
||||
|
||||
for ( m = 0; m < ps; ++m ) {
|
||||
newpoints.push( null );
|
||||
}
|
||||
|
||||
fromgap = true;
|
||||
j += otherps;
|
||||
|
||||
} else {
|
||||
|
||||
// cases where we actually got two points
|
||||
|
||||
px = points[ i ];
|
||||
py = points[ i + 1 ];
|
||||
qx = otherpoints[ j ];
|
||||
qy = otherpoints[ j + 1 ];
|
||||
bottom = 0;
|
||||
|
||||
if ( px === qx ) {
|
||||
|
||||
for ( m = 0; m < ps; ++m ) {
|
||||
newpoints.push( points[ i + m ] );
|
||||
}
|
||||
|
||||
//newpoints[ l + 1 ] += qy;
|
||||
bottom = qy;
|
||||
|
||||
i += ps;
|
||||
j += otherps;
|
||||
|
||||
} else if ( px > qx ) {
|
||||
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
|
||||
if ( withlines && i > 0 && points[ i - ps ] != null ) {
|
||||
intery = py + ( points[ i - ps + 1 ] - py ) * ( qx - px ) / ( points[ i - ps ] - px );
|
||||
newpoints.push( qx );
|
||||
newpoints.push( intery );
|
||||
for ( m = 2; m < ps; ++m ) {
|
||||
newpoints.push( points[ i + m ] );
|
||||
}
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
|
||||
} else { // px < qx
|
||||
|
||||
// if we come from a gap, we just skip this point
|
||||
|
||||
if ( fromgap && withlines ) {
|
||||
i += ps;
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( m = 0; m < ps; ++m ) {
|
||||
newpoints.push( points[ i + m ] );
|
||||
}
|
||||
|
||||
// we might be able to interpolate a point below,
|
||||
// this can give us a better y
|
||||
|
||||
if ( withlines && j > 0 && otherpoints[ j - otherps ] != null ) {
|
||||
bottom = qy + ( otherpoints[ j - otherps + 1 ] - qy ) * ( px - qx ) / ( otherpoints[ j - otherps ] - qx );
|
||||
}
|
||||
|
||||
//newpoints[l + 1] += bottom;
|
||||
|
||||
i += ps;
|
||||
}
|
||||
|
||||
fromgap = false;
|
||||
|
||||
if ( l !== newpoints.length && withbottom ) {
|
||||
newpoints[ l + 2 ] = bottom;
|
||||
}
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
|
||||
if ( withsteps && l !== newpoints.length && l > 0 &&
|
||||
newpoints[ l ] !== null &&
|
||||
newpoints[ l ] !== newpoints[ l - ps ] &&
|
||||
newpoints[ l + 1 ] !== newpoints[ l - ps + 1 ] ) {
|
||||
for (m = 0; m < ps; ++m) {
|
||||
newpoints[ l + ps + m ] = newpoints[ l + m ];
|
||||
}
|
||||
newpoints[ l + 1 ] = newpoints[ l - ps + 1 ];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push( computeFillBottoms );
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: "fillbetween",
|
||||
version: "1.0"
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
||||
@ -1,238 +1,241 @@
|
||||
/*
|
||||
Flot plugin for plotting images, e.g. useful for putting ticks on a
|
||||
prerendered complex visualization.
|
||||
/* Flot plugin for plotting images.
|
||||
|
||||
The data syntax is [[image, x1, y1, x2, y2], ...] where (x1, y1) and
|
||||
(x2, y2) are where you intend the two opposite corners of the image to
|
||||
end up in the plot. Image must be a fully loaded Javascript image (you
|
||||
can make one with new Image()). If the image is not complete, it's
|
||||
skipped when plotting.
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
There are two helpers included for retrieving images. The easiest work
|
||||
the way that you put in URLs instead of images in the data (like
|
||||
["myimage.png", 0, 0, 10, 10]), then call $.plot.image.loadData(data,
|
||||
options, callback) where data and options are the same as you pass in
|
||||
to $.plot. This loads the images, replaces the URLs in the data with
|
||||
the corresponding images and calls "callback" when all images are
|
||||
loaded (or failed loading). In the callback, you can then call $.plot
|
||||
with the data set. See the included example.
|
||||
The data syntax is [ [ image, x1, y1, x2, y2 ], ... ] where (x1, y1) and
|
||||
(x2, y2) are where you intend the two opposite corners of the image to end up
|
||||
in the plot. Image must be a fully loaded Javascript image (you can make one
|
||||
with new Image()). If the image is not complete, it's skipped when plotting.
|
||||
|
||||
A more low-level helper, $.plot.image.load(urls, callback) is also
|
||||
included. Given a list of URLs, it calls callback with an object
|
||||
mapping from URL to Image object when all images are loaded or have
|
||||
failed loading.
|
||||
There are two helpers included for retrieving images. The easiest work the way
|
||||
that you put in URLs instead of images in the data, like this:
|
||||
|
||||
Options for the plugin are
|
||||
[ "myimage.png", 0, 0, 10, 10 ]
|
||||
|
||||
series: {
|
||||
images: {
|
||||
show: boolean
|
||||
anchor: "corner" or "center"
|
||||
alpha: [0,1]
|
||||
}
|
||||
}
|
||||
Then call $.plot.image.loadData( data, options, callback ) where data and
|
||||
options are the same as you pass in to $.plot. This loads the images, replaces
|
||||
the URLs in the data with the corresponding images and calls "callback" when
|
||||
all images are loaded (or failed loading). In the callback, you can then call
|
||||
$.plot with the data set. See the included example.
|
||||
|
||||
which can be specified for a specific series
|
||||
A more low-level helper, $.plot.image.load(urls, callback) is also included.
|
||||
Given a list of URLs, it calls callback with an object mapping from URL to
|
||||
Image object when all images are loaded or have failed loading.
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], images: { ... } ])
|
||||
The plugin supports these options:
|
||||
|
||||
Note that because the data format is different from usual data points,
|
||||
you can't use images with anything else in a specific data series.
|
||||
series: {
|
||||
images: {
|
||||
show: boolean
|
||||
anchor: "corner" or "center"
|
||||
alpha: [ 0, 1 ]
|
||||
}
|
||||
}
|
||||
|
||||
Setting "anchor" to "center" causes the pixels in the image to be
|
||||
anchored at the corner pixel centers inside of at the pixel corners,
|
||||
effectively letting half a pixel stick out to each side in the plot.
|
||||
They can be specified for a specific series:
|
||||
|
||||
$.plot( $("#placeholder"), [{
|
||||
data: [ ... ],
|
||||
images: { ... }
|
||||
])
|
||||
|
||||
A possible future direction could be support for tiling for large
|
||||
images (like Google Maps).
|
||||
Note that because the data format is different from usual data points, you
|
||||
can't use images with anything else in a specific data series.
|
||||
|
||||
Setting "anchor" to "center" causes the pixels in the image to be anchored at
|
||||
the corner pixel centers inside of at the pixel corners, effectively letting
|
||||
half a pixel stick out to each side in the plot.
|
||||
|
||||
A possible future direction could be support for tiling for large images (like
|
||||
Google Maps).
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: {
|
||||
images: {
|
||||
show: false,
|
||||
alpha: 1,
|
||||
anchor: "corner" // or "center"
|
||||
}
|
||||
var options = {
|
||||
series: {
|
||||
images: {
|
||||
show: false,
|
||||
alpha: 1,
|
||||
anchor: "corner" // or "center"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.plot.image = {};
|
||||
|
||||
$.plot.image.loadDataImages = function (series, options, callback) {
|
||||
var urls = [], points = [];
|
||||
|
||||
var defaultShow = options.series.images.show;
|
||||
|
||||
$.each(series, function (i, s) {
|
||||
if (!(defaultShow || s.images.show))
|
||||
return;
|
||||
|
||||
if (s.data)
|
||||
s = s.data;
|
||||
|
||||
$.each(s, function (i, p) {
|
||||
if (typeof p[0] == "string") {
|
||||
urls.push(p[0]);
|
||||
points.push(p);
|
||||
}
|
||||
};
|
||||
|
||||
$.plot.image = {};
|
||||
|
||||
$.plot.image.loadDataImages = function (series, options, callback) {
|
||||
var urls = [], points = [];
|
||||
|
||||
var defaultShow = options.series.images.show;
|
||||
|
||||
$.each(series, function (i, s) {
|
||||
if (!(defaultShow || s.images.show))
|
||||
return;
|
||||
|
||||
if (s.data)
|
||||
s = s.data;
|
||||
|
||||
$.each(s, function (i, p) {
|
||||
if (typeof p[0] == "string") {
|
||||
urls.push(p[0]);
|
||||
points.push(p);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$.plot.image.load(urls, function (loadedImages) {
|
||||
$.each(points, function (i, p) {
|
||||
var url = p[0];
|
||||
if (loadedImages[url])
|
||||
p[0] = loadedImages[url];
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.image.load = function (urls, callback) {
|
||||
var missing = urls.length, loaded = {};
|
||||
if (missing == 0)
|
||||
callback({});
|
||||
|
||||
$.each(urls, function (i, url) {
|
||||
var handler = function () {
|
||||
--missing;
|
||||
|
||||
loaded[url] = this;
|
||||
|
||||
if (missing == 0)
|
||||
callback(loaded);
|
||||
};
|
||||
|
||||
$('<img />').load(handler).error(handler).attr('src', url);
|
||||
});
|
||||
}
|
||||
|
||||
function drawSeries(plot, ctx, series) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
if (!series.images || !series.images.show)
|
||||
return;
|
||||
|
||||
var points = series.datapoints.points,
|
||||
ps = series.datapoints.pointsize;
|
||||
|
||||
for (var i = 0; i < points.length; i += ps) {
|
||||
var img = points[i],
|
||||
x1 = points[i + 1], y1 = points[i + 2],
|
||||
x2 = points[i + 3], y2 = points[i + 4],
|
||||
xaxis = series.xaxis, yaxis = series.yaxis,
|
||||
tmp;
|
||||
|
||||
// actually we should check img.complete, but it
|
||||
// appears to be a somewhat unreliable indicator in
|
||||
// IE6 (false even after load event)
|
||||
if (!img || img.width <= 0 || img.height <= 0)
|
||||
continue;
|
||||
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
// if the anchor is at the center of the pixel, expand the
|
||||
// image by 1/2 pixel in each direction
|
||||
if (series.images.anchor == "center") {
|
||||
tmp = 0.5 * (x2-x1) / (img.width - 1);
|
||||
x1 -= tmp;
|
||||
x2 += tmp;
|
||||
tmp = 0.5 * (y2-y1) / (img.height - 1);
|
||||
y1 -= tmp;
|
||||
y2 += tmp;
|
||||
}
|
||||
|
||||
// clip
|
||||
if (x1 == x2 || y1 == y2 ||
|
||||
x1 >= xaxis.max || x2 <= xaxis.min ||
|
||||
y1 >= yaxis.max || y2 <= yaxis.min)
|
||||
continue;
|
||||
|
||||
var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
|
||||
if (x1 < xaxis.min) {
|
||||
sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
|
||||
x1 = xaxis.min;
|
||||
}
|
||||
|
||||
if (x2 > xaxis.max) {
|
||||
sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
|
||||
x2 = xaxis.max;
|
||||
}
|
||||
|
||||
if (y1 < yaxis.min) {
|
||||
sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
|
||||
y1 = yaxis.min;
|
||||
}
|
||||
|
||||
if (y2 > yaxis.max) {
|
||||
sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
|
||||
y2 = yaxis.max;
|
||||
}
|
||||
|
||||
x1 = xaxis.p2c(x1);
|
||||
x2 = xaxis.p2c(x2);
|
||||
y1 = yaxis.p2c(y1);
|
||||
y2 = yaxis.p2c(y2);
|
||||
|
||||
// the transformation may have swapped us
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
tmp = ctx.globalAlpha;
|
||||
ctx.globalAlpha *= series.images.alpha;
|
||||
ctx.drawImage(img,
|
||||
sx1, sy1, sx2 - sx1, sy2 - sy1,
|
||||
x1 + plotOffset.left, y1 + plotOffset.top,
|
||||
x2 - x1, y2 - y1);
|
||||
ctx.globalAlpha = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
function processRawData(plot, series, data, datapoints) {
|
||||
if (!series.images.show)
|
||||
return;
|
||||
|
||||
// format is Image, x1, y1, x2, y2 (opposite corners)
|
||||
datapoints.format = [
|
||||
{ required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true }
|
||||
];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processRawData.push(processRawData);
|
||||
plot.hooks.drawSeries.push(drawSeries);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'image',
|
||||
version: '1.1'
|
||||
});
|
||||
});
|
||||
|
||||
$.plot.image.load(urls, function (loadedImages) {
|
||||
$.each(points, function (i, p) {
|
||||
var url = p[0];
|
||||
if (loadedImages[url])
|
||||
p[0] = loadedImages[url];
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.image.load = function (urls, callback) {
|
||||
var missing = urls.length, loaded = {};
|
||||
if (missing == 0)
|
||||
callback({});
|
||||
|
||||
$.each(urls, function (i, url) {
|
||||
var handler = function () {
|
||||
--missing;
|
||||
|
||||
loaded[url] = this;
|
||||
|
||||
if (missing == 0)
|
||||
callback(loaded);
|
||||
};
|
||||
|
||||
$('<img />').load(handler).error(handler).attr('src', url);
|
||||
});
|
||||
};
|
||||
|
||||
function drawSeries(plot, ctx, series) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
if (!series.images || !series.images.show)
|
||||
return;
|
||||
|
||||
var points = series.datapoints.points,
|
||||
ps = series.datapoints.pointsize;
|
||||
|
||||
for (var i = 0; i < points.length; i += ps) {
|
||||
var img = points[i],
|
||||
x1 = points[i + 1], y1 = points[i + 2],
|
||||
x2 = points[i + 3], y2 = points[i + 4],
|
||||
xaxis = series.xaxis, yaxis = series.yaxis,
|
||||
tmp;
|
||||
|
||||
// actually we should check img.complete, but it
|
||||
// appears to be a somewhat unreliable indicator in
|
||||
// IE6 (false even after load event)
|
||||
if (!img || img.width <= 0 || img.height <= 0)
|
||||
continue;
|
||||
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
// if the anchor is at the center of the pixel, expand the
|
||||
// image by 1/2 pixel in each direction
|
||||
if (series.images.anchor == "center") {
|
||||
tmp = 0.5 * (x2-x1) / (img.width - 1);
|
||||
x1 -= tmp;
|
||||
x2 += tmp;
|
||||
tmp = 0.5 * (y2-y1) / (img.height - 1);
|
||||
y1 -= tmp;
|
||||
y2 += tmp;
|
||||
}
|
||||
|
||||
// clip
|
||||
if (x1 == x2 || y1 == y2 ||
|
||||
x1 >= xaxis.max || x2 <= xaxis.min ||
|
||||
y1 >= yaxis.max || y2 <= yaxis.min)
|
||||
continue;
|
||||
|
||||
var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
|
||||
if (x1 < xaxis.min) {
|
||||
sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
|
||||
x1 = xaxis.min;
|
||||
}
|
||||
|
||||
if (x2 > xaxis.max) {
|
||||
sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
|
||||
x2 = xaxis.max;
|
||||
}
|
||||
|
||||
if (y1 < yaxis.min) {
|
||||
sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
|
||||
y1 = yaxis.min;
|
||||
}
|
||||
|
||||
if (y2 > yaxis.max) {
|
||||
sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
|
||||
y2 = yaxis.max;
|
||||
}
|
||||
|
||||
x1 = xaxis.p2c(x1);
|
||||
x2 = xaxis.p2c(x2);
|
||||
y1 = yaxis.p2c(y1);
|
||||
y2 = yaxis.p2c(y2);
|
||||
|
||||
// the transformation may have swapped us
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
tmp = ctx.globalAlpha;
|
||||
ctx.globalAlpha *= series.images.alpha;
|
||||
ctx.drawImage(img,
|
||||
sx1, sy1, sx2 - sx1, sy2 - sy1,
|
||||
x1 + plotOffset.left, y1 + plotOffset.top,
|
||||
x2 - x1, y2 - y1);
|
||||
ctx.globalAlpha = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
function processRawData(plot, series, data, datapoints) {
|
||||
if (!series.images.show)
|
||||
return;
|
||||
|
||||
// format is Image, x1, y1, x2, y2 (opposite corners)
|
||||
datapoints.format = [
|
||||
{ required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true }
|
||||
];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processRawData.push(processRawData);
|
||||
plot.hooks.drawSeries.push(drawSeries);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'image',
|
||||
version: '1.1'
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,336 +1,346 @@
|
||||
/*
|
||||
Flot plugin for adding panning and zooming capabilities to a plot.
|
||||
/* Flot plugin for adding the ability to pan and zoom the plot.
|
||||
|
||||
The default behaviour is double click and scrollwheel up/down to zoom
|
||||
in, drag to pan. The plugin defines plot.zoom({ center }),
|
||||
plot.zoomOut() and plot.pan(offset) so you easily can add custom
|
||||
controls. It also fires a "plotpan" and "plotzoom" event when
|
||||
something happens, useful for synchronizing plots.
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
Options:
|
||||
The default behaviour is double click and scrollwheel up/down to zoom in, drag
|
||||
to pan. The plugin defines plot.zoom({ center }), plot.zoomOut() and
|
||||
plot.pan( offset ) so you easily can add custom controls. It also fires
|
||||
"plotpan" and "plotzoom" events, useful for synchronizing plots.
|
||||
|
||||
zoom: {
|
||||
interactive: false
|
||||
trigger: "dblclick" // or "click" for single click
|
||||
amount: 1.5 // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
}
|
||||
|
||||
pan: {
|
||||
interactive: false
|
||||
cursor: "move" // CSS mouse cursor value used when dragging, e.g. "pointer"
|
||||
frameRate: 20
|
||||
}
|
||||
The plugin supports these options:
|
||||
|
||||
zoom: {
|
||||
interactive: false
|
||||
trigger: "dblclick" // or "click" for single click
|
||||
amount: 1.5 // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
}
|
||||
|
||||
pan: {
|
||||
interactive: false
|
||||
cursor: "move" // CSS mouse cursor value used when dragging, e.g. "pointer"
|
||||
frameRate: 20
|
||||
}
|
||||
|
||||
xaxis, yaxis, x2axis, y2axis: {
|
||||
zoomRange: null // or [ number, number ] (min range, max range) or false
|
||||
panRange: null // or [ number, number ] (min, max) or false
|
||||
}
|
||||
|
||||
xaxis, yaxis, x2axis, y2axis: {
|
||||
zoomRange: null // or [number, number] (min range, max range) or false
|
||||
panRange: null // or [number, number] (min, max) or false
|
||||
}
|
||||
|
||||
"interactive" enables the built-in drag/click behaviour. If you enable
|
||||
interactive for pan, then you'll have a basic plot that supports
|
||||
moving around; the same for zoom.
|
||||
interactive for pan, then you'll have a basic plot that supports moving
|
||||
around; the same for zoom.
|
||||
|
||||
"amount" specifies the default amount to zoom in (so 1.5 = 150%)
|
||||
relative to the current viewport.
|
||||
"amount" specifies the default amount to zoom in (so 1.5 = 150%) relative to
|
||||
the current viewport.
|
||||
|
||||
"cursor" is a standard CSS mouse cursor string used for visual
|
||||
feedback to the user when dragging.
|
||||
"cursor" is a standard CSS mouse cursor string used for visual feedback to the
|
||||
user when dragging.
|
||||
|
||||
"frameRate" specifies the maximum number of times per second the plot
|
||||
will update itself while the user is panning around on it (set to null
|
||||
to disable intermediate pans, the plot will then not update until the
|
||||
mouse button is released).
|
||||
"frameRate" specifies the maximum number of times per second the plot will
|
||||
update itself while the user is panning around on it (set to null to disable
|
||||
intermediate pans, the plot will then not update until the mouse button is
|
||||
released).
|
||||
|
||||
"zoomRange" is the interval in which zooming can happen, e.g. with
|
||||
zoomRange: [1, 100] the zoom will never scale the axis so that the
|
||||
difference between min and max is smaller than 1 or larger than 100.
|
||||
You can set either end to null to ignore, e.g. [1, null]. If you set
|
||||
zoomRange to false, zooming on that axis will be disabled.
|
||||
"zoomRange" is the interval in which zooming can happen, e.g. with zoomRange:
|
||||
[1, 100] the zoom will never scale the axis so that the difference between min
|
||||
and max is smaller than 1 or larger than 100. You can set either end to null
|
||||
to ignore, e.g. [1, null]. If you set zoomRange to false, zooming on that axis
|
||||
will be disabled.
|
||||
|
||||
"panRange" confines the panning to stay within a range, e.g. with
|
||||
panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
|
||||
other. Either can be null, e.g. [-10, null]. If you set
|
||||
panRange to false, panning on that axis will be disabled.
|
||||
"panRange" confines the panning to stay within a range, e.g. with panRange:
|
||||
[-10, 20] panning stops at -10 in one end and at 20 in the other. Either can
|
||||
be null, e.g. [-10, null]. If you set panRange to false, panning on that axis
|
||||
will be disabled.
|
||||
|
||||
Example API usage:
|
||||
|
||||
plot = $.plot(...);
|
||||
|
||||
// zoom default amount in on the pixel (10, 20)
|
||||
plot.zoom({ center: { left: 10, top: 20 } });
|
||||
plot = $.plot(...);
|
||||
|
||||
// zoom out again
|
||||
plot.zoomOut({ center: { left: 10, top: 20 } });
|
||||
// zoom default amount in on the pixel ( 10, 20 )
|
||||
plot.zoom({ center: { left: 10, top: 20 } });
|
||||
|
||||
// zoom 200% in on the pixel (10, 20)
|
||||
plot.zoom({ amount: 2, center: { left: 10, top: 20 } });
|
||||
|
||||
// pan 100 pixels to the left and 20 down
|
||||
plot.pan({ left: -100, top: 20 })
|
||||
// zoom out again
|
||||
plot.zoomOut({ center: { left: 10, top: 20 } });
|
||||
|
||||
Here, "center" specifies where the center of the zooming should
|
||||
happen. Note that this is defined in pixel space, not the space of the
|
||||
data points (you can use the p2c helpers on the axes in Flot to help
|
||||
you convert between these).
|
||||
// zoom 200% in on the pixel (10, 20)
|
||||
plot.zoom({ amount: 2, center: { left: 10, top: 20 } });
|
||||
|
||||
// pan 100 pixels to the left and 20 down
|
||||
plot.pan({ left: -100, top: 20 })
|
||||
|
||||
Here, "center" specifies where the center of the zooming should happen. Note
|
||||
that this is defined in pixel space, not the space of the data points (you can
|
||||
use the p2c helpers on the axes in Flot to help you convert between these).
|
||||
|
||||
"amount" is the amount to zoom the viewport relative to the current range, so
|
||||
1 is 100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out). You
|
||||
can set the default in the options.
|
||||
|
||||
"amount" is the amount to zoom the viewport relative to the current
|
||||
range, so 1 is 100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is
|
||||
70% (zoom out). You can set the default in the options.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// First two dependencies, jquery.event.drag.js and
|
||||
// jquery.mousewheel.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)
|
||||
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(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);
|
||||
|
||||
(function(a){function e(h){var k,j=this,l=h.data||{};if(l.elem)j=h.dragTarget=l.elem,h.dragProxy=d.proxy||j,h.cursorOffsetX=l.pageX-l.left,h.cursorOffsetY=l.pageY-l.top,h.offsetX=h.pageX-h.cursorOffsetX,h.offsetY=h.pageY-h.cursorOffsetY;else if(d.dragging||l.which>0&&h.which!=l.which||a(h.target).is(l.not))return;switch(h.type){case"mousedown":return a.extend(l,a(j).offset(),{elem:j,target:h.target,pageX:h.pageX,pageY:h.pageY}),b.add(document,"mousemove mouseup",e,l),i(j,!1),d.dragging=null,!1;case!d.dragging&&"mousemove":if(g(h.pageX-l.pageX)+g(h.pageY-l.pageY)<l.distance)break;h.target=l.target,k=f(h,"dragstart",j),k!==!1&&(d.dragging=j,d.proxy=h.dragProxy=a(k||j)[0]);case"mousemove":if(d.dragging){if(k=f(h,"drag",j),c.drop&&(c.drop.allowed=k!==!1,c.drop.handler(h)),k!==!1)break;h.type="mouseup"}case"mouseup":b.remove(document,"mousemove mouseup",e),d.dragging&&(c.drop&&c.drop.handler(h),f(h,"dragend",j)),i(j,!0),d.dragging=d.proxy=l.elem=!1}return!0}function f(b,c,d){b.type=c;var e=a.event.dispatch.call(d,b);return e===!1?!1:e||b.result}function g(a){return Math.pow(a,2)}function h(){return d.dragging===!1}function i(a,b){a&&(a.unselectable=b?"off":"on",a.onselectstart=function(){return b},a.style&&(a.style.MozUserSelect=b?"":"none"))}a.fn.drag=function(a,b,c){return b&&this.bind("dragstart",a),c&&this.bind("dragend",c),a?this.bind("drag",b?b:a):this.trigger("drag")};var b=a.event,c=b.special,d=c.drag={not:":input",distance:0,which:1,dragging:!1,setup:function(c){c=a.extend({distance:d.distance,which:d.which,not:d.not},c||{}),c.distance=g(c.distance),b.add(this,"mousedown",e,c),this.attachEvent&&this.attachEvent("ondragstart",h)},teardown:function(){b.remove(this,"mousedown",e),this===d.dragging&&(d.dragging=d.proxy=!1),i(this,!0),this.detachEvent&&this.detachEvent("ondragstart",h)}};c.dragstart=c.dragend={setup:function(){},teardown:function(){}}})(jQuery);
|
||||
|
||||
/* jquery.mousewheel.min.js
|
||||
* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
|
||||
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
||||
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
||||
* 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
|
||||
*
|
||||
* Version: 3.0.2
|
||||
*
|
||||
* Requires: 1.2.2+
|
||||
*/
|
||||
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);
|
||||
(function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;void 0!==b.axis&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);void 0!==b.wheelDeltaY&&(g=b.wheelDeltaY/120);void 0!==b.wheelDeltaX&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,!1);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,!1);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
|
||||
|
||||
|
||||
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
xaxis: {
|
||||
zoomRange: null, // or [number, number] (min range, max range)
|
||||
panRange: null // or [number, number] (min, max)
|
||||
},
|
||||
zoom: {
|
||||
interactive: false,
|
||||
trigger: "dblclick", // or "click" for single click
|
||||
amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
},
|
||||
pan: {
|
||||
interactive: false,
|
||||
cursor: "move",
|
||||
frameRate: 20
|
||||
}
|
||||
var options = {
|
||||
xaxis: {
|
||||
zoomRange: null, // or [number, number] (min range, max range)
|
||||
panRange: null // or [number, number] (min, max)
|
||||
},
|
||||
zoom: {
|
||||
interactive: false,
|
||||
trigger: "dblclick", // or "click" for single click
|
||||
amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
},
|
||||
pan: {
|
||||
interactive: false,
|
||||
cursor: "move",
|
||||
frameRate: 20
|
||||
}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function onZoomClick(e, zoomOut) {
|
||||
var c = plot.offset();
|
||||
c.left = e.pageX - c.left;
|
||||
c.top = e.pageY - c.top;
|
||||
if (zoomOut)
|
||||
plot.zoomOut({ center: c });
|
||||
else
|
||||
plot.zoom({ center: c });
|
||||
}
|
||||
|
||||
function onMouseWheel(e, delta) {
|
||||
e.preventDefault();
|
||||
onZoomClick(e, delta < 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
var prevCursor = 'default', prevPageX = 0, prevPageY = 0,
|
||||
panTimeout = null;
|
||||
|
||||
function onDragStart(e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return false;
|
||||
var c = plot.getPlaceholder().css('cursor');
|
||||
if (c)
|
||||
prevCursor = c;
|
||||
plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor);
|
||||
prevPageX = e.pageX;
|
||||
prevPageY = e.pageY;
|
||||
}
|
||||
|
||||
function onDrag(e) {
|
||||
var frameRate = plot.getOptions().pan.frameRate;
|
||||
if (panTimeout || !frameRate)
|
||||
return;
|
||||
|
||||
panTimeout = setTimeout(function () {
|
||||
plot.pan({ left: prevPageX - e.pageX,
|
||||
top: prevPageY - e.pageY });
|
||||
prevPageX = e.pageX;
|
||||
prevPageY = e.pageY;
|
||||
|
||||
panTimeout = null;
|
||||
}, 1 / frameRate * 1000);
|
||||
}
|
||||
|
||||
function onDragEnd(e) {
|
||||
if (panTimeout) {
|
||||
clearTimeout(panTimeout);
|
||||
panTimeout = null;
|
||||
}
|
||||
|
||||
plot.getPlaceholder().css('cursor', prevCursor);
|
||||
plot.pan({ left: prevPageX - e.pageX,
|
||||
top: prevPageY - e.pageY });
|
||||
}
|
||||
|
||||
function bindEvents(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.zoom.interactive) {
|
||||
eventHolder[o.zoom.trigger](onZoomClick);
|
||||
eventHolder.mousewheel(onMouseWheel);
|
||||
}
|
||||
|
||||
if (o.pan.interactive) {
|
||||
eventHolder.bind("dragstart", { distance: 10 }, onDragStart);
|
||||
eventHolder.bind("drag", onDrag);
|
||||
eventHolder.bind("dragend", onDragEnd);
|
||||
}
|
||||
}
|
||||
|
||||
plot.zoomOut = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
if (!args.amount)
|
||||
args.amount = plot.getOptions().zoom.amount;
|
||||
|
||||
args.amount = 1 / args.amount;
|
||||
plot.zoom(args);
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function onZoomClick(e, zoomOut) {
|
||||
var c = plot.offset();
|
||||
c.left = e.pageX - c.left;
|
||||
c.top = e.pageY - c.top;
|
||||
if (zoomOut)
|
||||
plot.zoomOut({ center: c });
|
||||
else
|
||||
plot.zoom({ center: c });
|
||||
}
|
||||
plot.zoom = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
function onMouseWheel(e, delta) {
|
||||
onZoomClick(e, delta < 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
var prevCursor = 'default', prevPageX = 0, prevPageY = 0,
|
||||
panTimeout = null;
|
||||
var c = args.center,
|
||||
amount = args.amount || plot.getOptions().zoom.amount,
|
||||
w = plot.width(), h = plot.height();
|
||||
|
||||
function onDragStart(e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return false;
|
||||
var c = plot.getPlaceholder().css('cursor');
|
||||
if (c)
|
||||
prevCursor = c;
|
||||
plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor);
|
||||
prevPageX = e.pageX;
|
||||
prevPageY = e.pageY;
|
||||
}
|
||||
|
||||
function onDrag(e) {
|
||||
var frameRate = plot.getOptions().pan.frameRate;
|
||||
if (panTimeout || !frameRate)
|
||||
return;
|
||||
if (!c)
|
||||
c = { left: w / 2, top: h / 2 };
|
||||
|
||||
panTimeout = setTimeout(function () {
|
||||
plot.pan({ left: prevPageX - e.pageX,
|
||||
top: prevPageY - e.pageY });
|
||||
prevPageX = e.pageX;
|
||||
prevPageY = e.pageY;
|
||||
|
||||
panTimeout = null;
|
||||
}, 1 / frameRate * 1000);
|
||||
}
|
||||
|
||||
function onDragEnd(e) {
|
||||
if (panTimeout) {
|
||||
clearTimeout(panTimeout);
|
||||
panTimeout = null;
|
||||
}
|
||||
|
||||
plot.getPlaceholder().css('cursor', prevCursor);
|
||||
plot.pan({ left: prevPageX - e.pageX,
|
||||
top: prevPageY - e.pageY });
|
||||
}
|
||||
|
||||
function bindEvents(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.zoom.interactive) {
|
||||
eventHolder[o.zoom.trigger](onZoomClick);
|
||||
eventHolder.mousewheel(onMouseWheel);
|
||||
var xf = c.left / w,
|
||||
yf = c.top / h,
|
||||
minmax = {
|
||||
x: {
|
||||
min: c.left - xf * w / amount,
|
||||
max: c.left + (1 - xf) * w / amount
|
||||
},
|
||||
y: {
|
||||
min: c.top - yf * h / amount,
|
||||
max: c.top + (1 - yf) * h / amount
|
||||
}
|
||||
};
|
||||
|
||||
if (o.pan.interactive) {
|
||||
eventHolder.bind("dragstart", { distance: 10 }, onDragStart);
|
||||
eventHolder.bind("drag", onDrag);
|
||||
eventHolder.bind("dragend", onDragEnd);
|
||||
}
|
||||
$.each(plot.getAxes(), function(_, axis) {
|
||||
var opts = axis.options,
|
||||
min = minmax[axis.direction].min,
|
||||
max = minmax[axis.direction].max,
|
||||
zr = opts.zoomRange,
|
||||
pr = opts.panRange;
|
||||
|
||||
if (zr === false) // no zooming on this axis
|
||||
return;
|
||||
|
||||
min = axis.c2p(min);
|
||||
max = axis.c2p(max);
|
||||
if (min > max) {
|
||||
// make sure min < max
|
||||
var tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
|
||||
plot.zoomOut = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
if (!args.amount)
|
||||
args.amount = plot.getOptions().zoom.amount
|
||||
|
||||
args.amount = 1 / args.amount;
|
||||
plot.zoom(args);
|
||||
}
|
||||
|
||||
plot.zoom = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
var c = args.center,
|
||||
amount = args.amount || plot.getOptions().zoom.amount,
|
||||
w = plot.width(), h = plot.height();
|
||||
|
||||
if (!c)
|
||||
c = { left: w / 2, top: h / 2 };
|
||||
|
||||
var xf = c.left / w,
|
||||
yf = c.top / h,
|
||||
minmax = {
|
||||
x: {
|
||||
min: c.left - xf * w / amount,
|
||||
max: c.left + (1 - xf) * w / amount
|
||||
},
|
||||
y: {
|
||||
min: c.top - yf * h / amount,
|
||||
max: c.top + (1 - yf) * h / amount
|
||||
}
|
||||
};
|
||||
|
||||
$.each(plot.getAxes(), function(_, axis) {
|
||||
var opts = axis.options,
|
||||
min = minmax[axis.direction].min,
|
||||
max = minmax[axis.direction].max,
|
||||
zr = opts.zoomRange;
|
||||
|
||||
if (zr === false) // no zooming on this axis
|
||||
return;
|
||||
|
||||
min = axis.c2p(min);
|
||||
max = axis.c2p(max);
|
||||
if (min > max) {
|
||||
// make sure min < max
|
||||
var tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
|
||||
var range = max - min;
|
||||
if (zr &&
|
||||
((zr[0] != null && range < zr[0]) ||
|
||||
(zr[1] != null && range > zr[1])))
|
||||
return;
|
||||
|
||||
opts.min = min;
|
||||
opts.max = max;
|
||||
});
|
||||
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotzoom", [ plot ]);
|
||||
//Check that we are in panRange
|
||||
if (pr) {
|
||||
if (pr[0] != null && min < pr[0]) {
|
||||
min = pr[0];
|
||||
}
|
||||
if (pr[1] != null && max > pr[1]) {
|
||||
max = pr[1];
|
||||
}
|
||||
}
|
||||
|
||||
plot.pan = function (args) {
|
||||
var delta = {
|
||||
x: +args.left,
|
||||
y: +args.top
|
||||
};
|
||||
var range = max - min;
|
||||
if (zr &&
|
||||
((zr[0] != null && range < zr[0] && amount >1) ||
|
||||
(zr[1] != null && range > zr[1] && amount <1)))
|
||||
return;
|
||||
|
||||
if (isNaN(delta.x))
|
||||
delta.x = 0;
|
||||
if (isNaN(delta.y))
|
||||
delta.y = 0;
|
||||
opts.min = min;
|
||||
opts.max = max;
|
||||
});
|
||||
|
||||
$.each(plot.getAxes(), function (_, axis) {
|
||||
var opts = axis.options,
|
||||
min, max, d = delta[axis.direction];
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
min = axis.c2p(axis.p2c(axis.min) + d),
|
||||
max = axis.c2p(axis.p2c(axis.max) + d);
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotzoom", [ plot, args ]);
|
||||
};
|
||||
|
||||
var pr = opts.panRange;
|
||||
if (pr === false) // no panning on this axis
|
||||
return;
|
||||
|
||||
if (pr) {
|
||||
// check whether we hit the wall
|
||||
if (pr[0] != null && pr[0] > min) {
|
||||
d = pr[0] - min;
|
||||
min += d;
|
||||
max += d;
|
||||
}
|
||||
|
||||
if (pr[1] != null && pr[1] < max) {
|
||||
d = pr[1] - max;
|
||||
min += d;
|
||||
max += d;
|
||||
}
|
||||
}
|
||||
|
||||
opts.min = min;
|
||||
opts.max = max;
|
||||
});
|
||||
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotpan", [ plot ]);
|
||||
plot.pan = function (args) {
|
||||
var delta = {
|
||||
x: +args.left,
|
||||
y: +args.top
|
||||
};
|
||||
|
||||
if (isNaN(delta.x))
|
||||
delta.x = 0;
|
||||
if (isNaN(delta.y))
|
||||
delta.y = 0;
|
||||
|
||||
$.each(plot.getAxes(), function (_, axis) {
|
||||
var opts = axis.options,
|
||||
min, max, d = delta[axis.direction];
|
||||
|
||||
min = axis.c2p(axis.p2c(axis.min) + d),
|
||||
max = axis.c2p(axis.p2c(axis.max) + d);
|
||||
|
||||
var pr = opts.panRange;
|
||||
if (pr === false) // no panning on this axis
|
||||
return;
|
||||
|
||||
if (pr) {
|
||||
// check whether we hit the wall
|
||||
if (pr[0] != null && pr[0] > min) {
|
||||
d = pr[0] - min;
|
||||
min += d;
|
||||
max += d;
|
||||
}
|
||||
|
||||
if (pr[1] != null && pr[1] < max) {
|
||||
d = pr[1] - max;
|
||||
min += d;
|
||||
max += d;
|
||||
}
|
||||
}
|
||||
|
||||
function shutdown(plot, eventHolder) {
|
||||
eventHolder.unbind(plot.getOptions().zoom.trigger, onZoomClick);
|
||||
eventHolder.unbind("mousewheel", onMouseWheel);
|
||||
eventHolder.unbind("dragstart", onDragStart);
|
||||
eventHolder.unbind("drag", onDrag);
|
||||
eventHolder.unbind("dragend", onDragEnd);
|
||||
if (panTimeout)
|
||||
clearTimeout(panTimeout);
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(bindEvents);
|
||||
plot.hooks.shutdown.push(shutdown);
|
||||
opts.min = min;
|
||||
opts.max = max;
|
||||
});
|
||||
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotpan", [ plot, args ]);
|
||||
};
|
||||
|
||||
function shutdown(plot, eventHolder) {
|
||||
eventHolder.unbind(plot.getOptions().zoom.trigger, onZoomClick);
|
||||
eventHolder.unbind("mousewheel", onMouseWheel);
|
||||
eventHolder.unbind("dragstart", onDragStart);
|
||||
eventHolder.unbind("drag", onDrag);
|
||||
eventHolder.unbind("dragend", onDragEnd);
|
||||
if (panTimeout)
|
||||
clearTimeout(panTimeout);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'navigate',
|
||||
version: '1.3'
|
||||
});
|
||||
|
||||
plot.hooks.bindEvents.push(bindEvents);
|
||||
plot.hooks.shutdown.push(shutdown);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'navigate',
|
||||
version: '1.3'
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,60 +1,59 @@
|
||||
/*
|
||||
Flot plugin for automatically redrawing plots when the placeholder
|
||||
size changes, e.g. on window resizes.
|
||||
/* Flot plugin for automatically redrawing plots as the placeholder resizes.
|
||||
|
||||
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.
|
||||
Copyright (c) 2007-2014 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.
|
||||
|
||||
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:
|
||||
/* 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($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this);
|
||||
|
||||
(function($,e,t){"$:nomunge";var i=[],n=$.resize=$.extend($.resize,{}),a,r=false,s="setTimeout",u="resize",m=u+"-special-event",o="pendingDelay",l="activeDelay",f="throttleWindow";n[o]=200;n[l]=20;n[f]=true;$.event.special[u]={setup:function(){if(!n[f]&&this[s]){return false}var e=$(this);i.push(this);e.data(m,{w:e.width(),h:e.height()});if(i.length===1){a=t;h()}},teardown:function(){if(!n[f]&&this[s]){return false}var e=$(this);for(var t=i.length-1;t>=0;t--){if(i[t]==this){i.splice(t,1);break}}e.removeData(m);if(!i.length){if(r){cancelAnimationFrame(a)}else{clearTimeout(a)}a=null}},add:function(e){if(!n[f]&&this[s]){return false}var i;function a(e,n,a){var r=$(this),s=r.data(m)||{};s.w=n!==t?n:r.width();s.h=a!==t?a:r.height();i.apply(this,arguments)}if($.isFunction(e)){i=e;return a}else{i=e.handler;e.handler=a}}};function h(t){if(r===true){r=t||1}for(var s=i.length-1;s>=0;s--){var l=$(i[s]);if(l[0]==e||l.is(":visible")){var f=l.width(),c=l.height(),d=l.data(m);if(d&&(f!==d.w||c!==d.h)){l.trigger(u,[d.w=f,d.h=c]);r=t||true}}else{d=l.data(m);d.w=0;d.h=0}}if(a!==null){if(r&&(t==null||t-r<1e3)){a=e.requestAnimationFrame(h)}else{a=setTimeout(h,n[o]);r=false}}}if(!e.requestAnimationFrame){e.requestAnimationFrame=function(){return e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(t,i){return e.setTimeout(function(){t((new Date).getTime())},n[l])}}()}if(!e.cancelAnimationFrame){e.cancelAnimationFrame=function(){return e.webkitCancelRequestAnimationFrame||e.mozCancelRequestAnimationFrame||e.oCancelRequestAnimationFrame||e.msCancelRequestAnimationFrame||clearTimeout}()}})(jQuery,this);
|
||||
|
||||
(function ($) {
|
||||
var options = { }; // no options
|
||||
var options = { }; // no options
|
||||
|
||||
function init(plot) {
|
||||
function onResize() {
|
||||
var placeholder = plot.getPlaceholder();
|
||||
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;
|
||||
// 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.resize();
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'resize',
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
@ -1,344 +1,360 @@
|
||||
/*
|
||||
Flot plugin for selecting regions.
|
||||
/* Flot plugin for selecting regions of a plot.
|
||||
|
||||
The plugin defines the following options:
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
selection: {
|
||||
mode: null or "x" or "y" or "xy",
|
||||
color: color
|
||||
}
|
||||
The plugin supports these options:
|
||||
|
||||
Selection support is enabled by setting the mode to one of "x", "y" or
|
||||
"xy". In "x" mode, the user will only be able to specify the x range,
|
||||
similarly for "y" mode. For "xy", the selection becomes a rectangle
|
||||
where both ranges can be specified. "color" is color of the selection
|
||||
(if you need to change the color later on, you can get to it with
|
||||
plot.getOptions().selection.color).
|
||||
selection: {
|
||||
mode: null or "x" or "y" or "xy",
|
||||
color: color,
|
||||
shape: "round" or "miter" or "bevel",
|
||||
minSize: number of pixels
|
||||
}
|
||||
|
||||
When selection support is enabled, a "plotselected" event will be
|
||||
emitted on the DOM element you passed into the plot function. The
|
||||
event handler gets a parameter with the ranges selected on the axes,
|
||||
like this:
|
||||
Selection support is enabled by setting the mode to one of "x", "y" or "xy".
|
||||
In "x" mode, the user will only be able to specify the x range, similarly for
|
||||
"y" mode. For "xy", the selection becomes a rectangle where both ranges can be
|
||||
specified. "color" is color of the selection (if you need to change the color
|
||||
later on, you can get to it with plot.getOptions().selection.color). "shape"
|
||||
is the shape of the corners of the selection.
|
||||
|
||||
placeholder.bind("plotselected", function(event, ranges) {
|
||||
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
|
||||
// similar for yaxis - with multiple axes, the extra ones are in
|
||||
// x2axis, x3axis, ...
|
||||
});
|
||||
"minSize" is the minimum size a selection can be in pixels. This value can
|
||||
be customized to determine the smallest size a selection can be and still
|
||||
have the selection rectangle be displayed. When customizing this value, the
|
||||
fact that it refers to pixels, not axis units must be taken into account.
|
||||
Thus, for example, if there is a bar graph in time mode with BarWidth set to 1
|
||||
minute, setting "minSize" to 1 will not make the minimum selection size 1
|
||||
minute, but rather 1 pixel. Note also that setting "minSize" to 0 will prevent
|
||||
"plotunselected" events from being fired when the user clicks the mouse without
|
||||
dragging.
|
||||
|
||||
The "plotselected" event is only fired when the user has finished
|
||||
making the selection. A "plotselecting" event is fired during the
|
||||
process with the same parameters as the "plotselected" event, in case
|
||||
you want to know what's happening while it's happening,
|
||||
When selection support is enabled, a "plotselected" event will be emitted on
|
||||
the DOM element you passed into the plot function. The event handler gets a
|
||||
parameter with the ranges selected on the axes, like this:
|
||||
|
||||
A "plotunselected" event with no arguments is emitted when the user
|
||||
clicks the mouse to remove the selection.
|
||||
placeholder.bind( "plotselected", function( event, ranges ) {
|
||||
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
|
||||
// similar for yaxis - with multiple axes, the extra ones are in
|
||||
// x2axis, x3axis, ...
|
||||
});
|
||||
|
||||
The "plotselected" event is only fired when the user has finished making the
|
||||
selection. A "plotselecting" event is fired during the process with the same
|
||||
parameters as the "plotselected" event, in case you want to know what's
|
||||
happening while it's happening,
|
||||
|
||||
A "plotunselected" event with no arguments is emitted when the user clicks the
|
||||
mouse to remove the selection. As stated above, setting "minSize" to 0 will
|
||||
destroy this behavior.
|
||||
|
||||
The plugin allso adds the following methods to the plot object:
|
||||
|
||||
- setSelection(ranges, preventEvent)
|
||||
- setSelection( ranges, preventEvent )
|
||||
|
||||
Set the selection rectangle. The passed in ranges is on the same
|
||||
form as returned in the "plotselected" event. If the selection mode
|
||||
is "x", you should put in either an xaxis range, if the mode is "y"
|
||||
you need to put in an yaxis range and both xaxis and yaxis if the
|
||||
selection mode is "xy", like this:
|
||||
Set the selection rectangle. The passed in ranges is on the same form as
|
||||
returned in the "plotselected" event. If the selection mode is "x", you
|
||||
should put in either an xaxis range, if the mode is "y" you need to put in
|
||||
an yaxis range and both xaxis and yaxis if the selection mode is "xy", like
|
||||
this:
|
||||
|
||||
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
|
||||
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
|
||||
|
||||
setSelection will trigger the "plotselected" event when called. If
|
||||
you don't want that to happen, e.g. if you're inside a
|
||||
"plotselected" handler, pass true as the second parameter. If you
|
||||
are using multiple axes, you can specify the ranges on any of those,
|
||||
e.g. as x2axis/x3axis/... instead of xaxis, the plugin picks the
|
||||
first one it sees.
|
||||
|
||||
- clearSelection(preventEvent)
|
||||
setSelection will trigger the "plotselected" event when called. If you don't
|
||||
want that to happen, e.g. if you're inside a "plotselected" handler, pass
|
||||
true as the second parameter. If you are using multiple axes, you can
|
||||
specify the ranges on any of those, e.g. as x2axis/x3axis/... instead of
|
||||
xaxis, the plugin picks the first one it sees.
|
||||
|
||||
- clearSelection( preventEvent )
|
||||
|
||||
Clear the selection rectangle. Pass in true to avoid getting a
|
||||
"plotunselected" event.
|
||||
|
||||
- getSelection()
|
||||
|
||||
Returns the current selection in the same format as the
|
||||
"plotselected" event. If there's currently no selection, the
|
||||
function returns null.
|
||||
Returns the current selection in the same format as the "plotselected"
|
||||
event. If there's currently no selection, the function returns null.
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
function init(plot) {
|
||||
var selection = {
|
||||
first: { x: -1, y: -1}, second: { x: -1, y: -1},
|
||||
show: false,
|
||||
active: false
|
||||
};
|
||||
function init(plot) {
|
||||
var selection = {
|
||||
first: { x: -1, y: -1}, second: { x: -1, y: -1},
|
||||
show: false,
|
||||
active: false
|
||||
};
|
||||
|
||||
// FIXME: The drag handling implemented here should be
|
||||
// abstracted out, there's some similar code from a library in
|
||||
// the navigation plugin, this should be massaged a bit to fit
|
||||
// the Flot cases here better and reused. Doing this would
|
||||
// make this plugin much slimmer.
|
||||
var savedhandlers = {};
|
||||
// FIXME: The drag handling implemented here should be
|
||||
// abstracted out, there's some similar code from a library in
|
||||
// the navigation plugin, this should be massaged a bit to fit
|
||||
// the Flot cases here better and reused. Doing this would
|
||||
// make this plugin much slimmer.
|
||||
var savedhandlers = {};
|
||||
|
||||
var mouseUpHandler = null;
|
||||
|
||||
function onMouseMove(e) {
|
||||
if (selection.active) {
|
||||
updateSelection(e);
|
||||
|
||||
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
|
||||
}
|
||||
}
|
||||
var mouseUpHandler = null;
|
||||
|
||||
function onMouseDown(e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return;
|
||||
|
||||
// cancel out any text selections
|
||||
document.body.focus();
|
||||
|
||||
// prevent text selection and drag in old-school browsers
|
||||
if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
|
||||
savedhandlers.onselectstart = document.onselectstart;
|
||||
document.onselectstart = function () { return false; };
|
||||
}
|
||||
if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
|
||||
savedhandlers.ondrag = document.ondrag;
|
||||
document.ondrag = function () { return false; };
|
||||
}
|
||||
|
||||
setSelectionPos(selection.first, e);
|
||||
|
||||
selection.active = true;
|
||||
|
||||
// this is a bit silly, but we have to use a closure to be
|
||||
// able to whack the same handler again
|
||||
mouseUpHandler = function (e) { onMouseUp(e); };
|
||||
|
||||
$(document).one("mouseup", mouseUpHandler);
|
||||
}
|
||||
|
||||
function onMouseUp(e) {
|
||||
mouseUpHandler = null;
|
||||
|
||||
// revert drag stuff for old-school browsers
|
||||
if (document.onselectstart !== undefined)
|
||||
document.onselectstart = savedhandlers.onselectstart;
|
||||
if (document.ondrag !== undefined)
|
||||
document.ondrag = savedhandlers.ondrag;
|
||||
|
||||
// no more dragging
|
||||
selection.active = false;
|
||||
updateSelection(e);
|
||||
|
||||
if (selectionIsSane())
|
||||
triggerSelectedEvent();
|
||||
else {
|
||||
// this counts as a clear
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
plot.getPlaceholder().trigger("plotselecting", [ null ]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSelection() {
|
||||
if (!selectionIsSane())
|
||||
return null;
|
||||
|
||||
var r = {}, c1 = selection.first, c2 = selection.second;
|
||||
$.each(plot.getAxes(), function (name, axis) {
|
||||
if (axis.used) {
|
||||
var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
|
||||
r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
|
||||
}
|
||||
});
|
||||
return r;
|
||||
}
|
||||
|
||||
function triggerSelectedEvent() {
|
||||
var r = getSelection();
|
||||
|
||||
plot.getPlaceholder().trigger("plotselected", [ r ]);
|
||||
|
||||
// backwards-compat stuff, to be removed in future
|
||||
if (r.xaxis && r.yaxis)
|
||||
plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
|
||||
}
|
||||
|
||||
function clamp(min, value, max) {
|
||||
return value < min ? min: (value > max ? max: value);
|
||||
}
|
||||
|
||||
function setSelectionPos(pos, e) {
|
||||
var o = plot.getOptions();
|
||||
var offset = plot.getPlaceholder().offset();
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
|
||||
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
|
||||
|
||||
if (o.selection.mode == "y")
|
||||
pos.x = pos == selection.first ? 0 : plot.width();
|
||||
|
||||
if (o.selection.mode == "x")
|
||||
pos.y = pos == selection.first ? 0 : plot.height();
|
||||
}
|
||||
|
||||
function updateSelection(pos) {
|
||||
if (pos.pageX == null)
|
||||
return;
|
||||
|
||||
setSelectionPos(selection.second, pos);
|
||||
if (selectionIsSane()) {
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
else
|
||||
clearSelection(true);
|
||||
}
|
||||
|
||||
function clearSelection(preventEvent) {
|
||||
if (selection.show) {
|
||||
selection.show = false;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent)
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
}
|
||||
}
|
||||
|
||||
// function taken from markings support in Flot
|
||||
function extractRange(ranges, coord) {
|
||||
var axis, from, to, key, axes = plot.getAxes();
|
||||
|
||||
for (var k in axes) {
|
||||
axis = axes[k];
|
||||
if (axis.direction == coord) {
|
||||
key = coord + axis.n + "axis";
|
||||
if (!ranges[key] && axis.n == 1)
|
||||
key = coord + "axis"; // support x1axis as xaxis
|
||||
if (ranges[key]) {
|
||||
from = ranges[key].from;
|
||||
to = ranges[key].to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// backwards-compat stuff - to be removed in future
|
||||
if (!ranges[key]) {
|
||||
axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0];
|
||||
from = ranges[coord + "1"];
|
||||
to = ranges[coord + "2"];
|
||||
}
|
||||
|
||||
// auto-reverse as an added bonus
|
||||
if (from != null && to != null && from > to) {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
|
||||
return { from: from, to: to, axis: axis };
|
||||
}
|
||||
|
||||
function setSelection(ranges, preventEvent) {
|
||||
var axis, range, o = plot.getOptions();
|
||||
|
||||
if (o.selection.mode == "y") {
|
||||
selection.first.x = 0;
|
||||
selection.second.x = plot.width();
|
||||
}
|
||||
else {
|
||||
range = extractRange(ranges, "x");
|
||||
|
||||
selection.first.x = range.axis.p2c(range.from);
|
||||
selection.second.x = range.axis.p2c(range.to);
|
||||
}
|
||||
|
||||
if (o.selection.mode == "x") {
|
||||
selection.first.y = 0;
|
||||
selection.second.y = plot.height();
|
||||
}
|
||||
else {
|
||||
range = extractRange(ranges, "y");
|
||||
|
||||
selection.first.y = range.axis.p2c(range.from);
|
||||
selection.second.y = range.axis.p2c(range.to);
|
||||
}
|
||||
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent && selectionIsSane())
|
||||
triggerSelectedEvent();
|
||||
}
|
||||
|
||||
function selectionIsSane() {
|
||||
var minSize = 5;
|
||||
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
|
||||
Math.abs(selection.second.y - selection.first.y) >= minSize;
|
||||
}
|
||||
|
||||
plot.clearSelection = clearSelection;
|
||||
plot.setSelection = setSelection;
|
||||
plot.getSelection = getSelection;
|
||||
|
||||
plot.hooks.bindEvents.push(function(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.selection.mode != null) {
|
||||
eventHolder.mousemove(onMouseMove);
|
||||
eventHolder.mousedown(onMouseDown);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
// draw selection
|
||||
if (selection.show && selectionIsSane()) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
var o = plot.getOptions();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
var c = $.color.parse(o.selection.color);
|
||||
|
||||
ctx.strokeStyle = c.scale('a', 0.8).toString();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.lineJoin = "round";
|
||||
ctx.fillStyle = c.scale('a', 0.4).toString();
|
||||
|
||||
var x = Math.min(selection.first.x, selection.second.x),
|
||||
y = Math.min(selection.first.y, selection.second.y),
|
||||
w = Math.abs(selection.second.x - selection.first.x),
|
||||
h = Math.abs(selection.second.y - selection.first.y);
|
||||
|
||||
ctx.fillRect(x, y, w, h);
|
||||
ctx.strokeRect(x, y, w, h);
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
|
||||
plot.hooks.shutdown.push(function (plot, eventHolder) {
|
||||
eventHolder.unbind("mousemove", onMouseMove);
|
||||
eventHolder.unbind("mousedown", onMouseDown);
|
||||
|
||||
if (mouseUpHandler)
|
||||
$(document).unbind("mouseup", mouseUpHandler);
|
||||
});
|
||||
function onMouseMove(e) {
|
||||
if (selection.active) {
|
||||
updateSelection(e);
|
||||
|
||||
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
|
||||
}
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: {
|
||||
selection: {
|
||||
mode: null, // one of null, "x", "y" or "xy"
|
||||
color: "#e8cfac"
|
||||
}
|
||||
},
|
||||
name: 'selection',
|
||||
version: '1.1'
|
||||
function onMouseDown(e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return;
|
||||
|
||||
// cancel out any text selections
|
||||
document.body.focus();
|
||||
|
||||
// prevent text selection and drag in old-school browsers
|
||||
if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
|
||||
savedhandlers.onselectstart = document.onselectstart;
|
||||
document.onselectstart = function () { return false; };
|
||||
}
|
||||
if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
|
||||
savedhandlers.ondrag = document.ondrag;
|
||||
document.ondrag = function () { return false; };
|
||||
}
|
||||
|
||||
setSelectionPos(selection.first, e);
|
||||
|
||||
selection.active = true;
|
||||
|
||||
// this is a bit silly, but we have to use a closure to be
|
||||
// able to whack the same handler again
|
||||
mouseUpHandler = function (e) { onMouseUp(e); };
|
||||
|
||||
$(document).one("mouseup", mouseUpHandler);
|
||||
}
|
||||
|
||||
function onMouseUp(e) {
|
||||
mouseUpHandler = null;
|
||||
|
||||
// revert drag stuff for old-school browsers
|
||||
if (document.onselectstart !== undefined)
|
||||
document.onselectstart = savedhandlers.onselectstart;
|
||||
if (document.ondrag !== undefined)
|
||||
document.ondrag = savedhandlers.ondrag;
|
||||
|
||||
// no more dragging
|
||||
selection.active = false;
|
||||
updateSelection(e);
|
||||
|
||||
if (selectionIsSane())
|
||||
triggerSelectedEvent();
|
||||
else {
|
||||
// this counts as a clear
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
plot.getPlaceholder().trigger("plotselecting", [ null ]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSelection() {
|
||||
if (!selectionIsSane())
|
||||
return null;
|
||||
|
||||
if (!selection.show) return null;
|
||||
|
||||
var r = {}, c1 = selection.first, c2 = selection.second;
|
||||
$.each(plot.getAxes(), function (name, axis) {
|
||||
if (axis.used) {
|
||||
var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
|
||||
r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
|
||||
}
|
||||
});
|
||||
return r;
|
||||
}
|
||||
|
||||
function triggerSelectedEvent() {
|
||||
var r = getSelection();
|
||||
|
||||
plot.getPlaceholder().trigger("plotselected", [ r ]);
|
||||
|
||||
// backwards-compat stuff, to be removed in future
|
||||
if (r.xaxis && r.yaxis)
|
||||
plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
|
||||
}
|
||||
|
||||
function clamp(min, value, max) {
|
||||
return value < min ? min: (value > max ? max: value);
|
||||
}
|
||||
|
||||
function setSelectionPos(pos, e) {
|
||||
var o = plot.getOptions();
|
||||
var offset = plot.getPlaceholder().offset();
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
|
||||
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
|
||||
|
||||
if (o.selection.mode == "y")
|
||||
pos.x = pos == selection.first ? 0 : plot.width();
|
||||
|
||||
if (o.selection.mode == "x")
|
||||
pos.y = pos == selection.first ? 0 : plot.height();
|
||||
}
|
||||
|
||||
function updateSelection(pos) {
|
||||
if (pos.pageX == null)
|
||||
return;
|
||||
|
||||
setSelectionPos(selection.second, pos);
|
||||
if (selectionIsSane()) {
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
else
|
||||
clearSelection(true);
|
||||
}
|
||||
|
||||
function clearSelection(preventEvent) {
|
||||
if (selection.show) {
|
||||
selection.show = false;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent)
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
}
|
||||
}
|
||||
|
||||
// function taken from markings support in Flot
|
||||
function extractRange(ranges, coord) {
|
||||
var axis, from, to, key, axes = plot.getAxes();
|
||||
|
||||
for (var k in axes) {
|
||||
axis = axes[k];
|
||||
if (axis.direction == coord) {
|
||||
key = coord + axis.n + "axis";
|
||||
if (!ranges[key] && axis.n == 1)
|
||||
key = coord + "axis"; // support x1axis as xaxis
|
||||
if (ranges[key]) {
|
||||
from = ranges[key].from;
|
||||
to = ranges[key].to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// backwards-compat stuff - to be removed in future
|
||||
if (!ranges[key]) {
|
||||
axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0];
|
||||
from = ranges[coord + "1"];
|
||||
to = ranges[coord + "2"];
|
||||
}
|
||||
|
||||
// auto-reverse as an added bonus
|
||||
if (from != null && to != null && from > to) {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
|
||||
return { from: from, to: to, axis: axis };
|
||||
}
|
||||
|
||||
function setSelection(ranges, preventEvent) {
|
||||
var axis, range, o = plot.getOptions();
|
||||
|
||||
if (o.selection.mode == "y") {
|
||||
selection.first.x = 0;
|
||||
selection.second.x = plot.width();
|
||||
}
|
||||
else {
|
||||
range = extractRange(ranges, "x");
|
||||
|
||||
selection.first.x = range.axis.p2c(range.from);
|
||||
selection.second.x = range.axis.p2c(range.to);
|
||||
}
|
||||
|
||||
if (o.selection.mode == "x") {
|
||||
selection.first.y = 0;
|
||||
selection.second.y = plot.height();
|
||||
}
|
||||
else {
|
||||
range = extractRange(ranges, "y");
|
||||
|
||||
selection.first.y = range.axis.p2c(range.from);
|
||||
selection.second.y = range.axis.p2c(range.to);
|
||||
}
|
||||
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent && selectionIsSane())
|
||||
triggerSelectedEvent();
|
||||
}
|
||||
|
||||
function selectionIsSane() {
|
||||
var minSize = plot.getOptions().selection.minSize;
|
||||
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
|
||||
Math.abs(selection.second.y - selection.first.y) >= minSize;
|
||||
}
|
||||
|
||||
plot.clearSelection = clearSelection;
|
||||
plot.setSelection = setSelection;
|
||||
plot.getSelection = getSelection;
|
||||
|
||||
plot.hooks.bindEvents.push(function(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.selection.mode != null) {
|
||||
eventHolder.mousemove(onMouseMove);
|
||||
eventHolder.mousedown(onMouseDown);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
// draw selection
|
||||
if (selection.show && selectionIsSane()) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
var o = plot.getOptions();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
var c = $.color.parse(o.selection.color);
|
||||
|
||||
ctx.strokeStyle = c.scale('a', 0.8).toString();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.lineJoin = o.selection.shape;
|
||||
ctx.fillStyle = c.scale('a', 0.4).toString();
|
||||
|
||||
var x = Math.min(selection.first.x, selection.second.x) + 0.5,
|
||||
y = Math.min(selection.first.y, selection.second.y) + 0.5,
|
||||
w = Math.abs(selection.second.x - selection.first.x) - 1,
|
||||
h = Math.abs(selection.second.y - selection.first.y) - 1;
|
||||
|
||||
ctx.fillRect(x, y, w, h);
|
||||
ctx.strokeRect(x, y, w, h);
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
|
||||
plot.hooks.shutdown.push(function (plot, eventHolder) {
|
||||
eventHolder.unbind("mousemove", onMouseMove);
|
||||
eventHolder.unbind("mousedown", onMouseDown);
|
||||
|
||||
if (mouseUpHandler)
|
||||
$(document).unbind("mouseup", mouseUpHandler);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: {
|
||||
selection: {
|
||||
mode: null, // one of null, "x", "y" or "xy"
|
||||
color: "#e8cfac",
|
||||
shape: "round", // one of "round", "miter", or "bevel"
|
||||
minSize: 5 // minimum number of pixels
|
||||
}
|
||||
},
|
||||
name: 'selection',
|
||||
version: '1.1'
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
@ -1,184 +1,188 @@
|
||||
/*
|
||||
Flot plugin for stacking data sets, i.e. putting them on top of each
|
||||
other, for accumulative graphs.
|
||||
/* Flot plugin for stacking data sets rather than overlyaing them.
|
||||
|
||||
The plugin assumes the data is sorted on x (or y if stacking
|
||||
horizontally). For line charts, it is assumed that if a line has an
|
||||
undefined gap (from a null point), then the line above it should have
|
||||
the same gap - insert zeros instead of "null" if you want another
|
||||
behaviour. This also holds for the start and end of the chart. Note
|
||||
that stacking a mix of positive and negative values in most instances
|
||||
doesn't make sense (so it looks weird).
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
Two or more series are stacked when their "stack" attribute is set to
|
||||
the same key (which can be any number or string or just "true"). To
|
||||
specify the default stack, you can set
|
||||
The plugin assumes the data is sorted on x (or y if stacking horizontally).
|
||||
For line charts, it is assumed that if a line has an undefined gap (from a
|
||||
null point), then the line above it should have the same gap - insert zeros
|
||||
instead of "null" if you want another behaviour. This also holds for the start
|
||||
and end of the chart. Note that stacking a mix of positive and negative values
|
||||
in most instances doesn't make sense (so it looks weird).
|
||||
|
||||
series: {
|
||||
stack: null or true or key (number/string)
|
||||
}
|
||||
Two or more series are stacked when their "stack" attribute is set to the same
|
||||
key (which can be any number or string or just "true"). To specify the default
|
||||
stack, you can set the stack option like this:
|
||||
|
||||
or specify it for a specific series
|
||||
series: {
|
||||
stack: null/false, true, or a key (number/string)
|
||||
}
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], stack: true }])
|
||||
|
||||
The stacking order is determined by the order of the data series in
|
||||
the array (later series end up on top of the previous).
|
||||
You can also specify it for a single series, like this:
|
||||
|
||||
$.plot( $("#placeholder"), [{
|
||||
data: [ ... ],
|
||||
stack: true
|
||||
}])
|
||||
|
||||
The stacking order is determined by the order of the data series in the array
|
||||
(later series end up on top of the previous).
|
||||
|
||||
Internally, the plugin modifies the datapoints in each series, adding an
|
||||
offset to the y value. For line series, extra data points are inserted through
|
||||
interpolation. If there's a second y value, it's also adjusted (e.g for bar
|
||||
charts or filled areas).
|
||||
|
||||
Internally, the plugin modifies the datapoints in each series, adding
|
||||
an offset to the y value. For line series, extra data points are
|
||||
inserted through interpolation. If there's a second y value, it's also
|
||||
adjusted (e.g for bar charts or filled areas).
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { stack: null } // or number/string
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function findMatchingSeries(s, allseries) {
|
||||
var res = null
|
||||
for (var i = 0; i < allseries.length; ++i) {
|
||||
if (s == allseries[i])
|
||||
break;
|
||||
|
||||
if (allseries[i].stack == s.stack)
|
||||
res = allseries[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function stackData(plot, s, datapoints) {
|
||||
if (s.stack == null)
|
||||
return;
|
||||
var options = {
|
||||
series: { stack: null } // or number/string
|
||||
};
|
||||
|
||||
var other = findMatchingSeries(s, plot.getData());
|
||||
if (!other)
|
||||
return;
|
||||
function init(plot) {
|
||||
function findMatchingSeries(s, allseries) {
|
||||
var res = null;
|
||||
for (var i = 0; i < allseries.length; ++i) {
|
||||
if (s == allseries[i])
|
||||
break;
|
||||
|
||||
var ps = datapoints.pointsize,
|
||||
points = datapoints.points,
|
||||
otherps = other.datapoints.pointsize,
|
||||
otherpoints = other.datapoints.points,
|
||||
newpoints = [],
|
||||
px, py, intery, qx, qy, bottom,
|
||||
withlines = s.lines.show,
|
||||
horizontal = s.bars.horizontal,
|
||||
withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
|
||||
withsteps = withlines && s.lines.steps,
|
||||
fromgap = true,
|
||||
keyOffset = horizontal ? 1 : 0,
|
||||
accumulateOffset = horizontal ? 0 : 1,
|
||||
i = 0, j = 0, l;
|
||||
if (allseries[i].stack == s.stack)
|
||||
res = allseries[i];
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (i >= points.length)
|
||||
break;
|
||||
|
||||
l = newpoints.length;
|
||||
|
||||
if (points[i] == null) {
|
||||
// copy gaps
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else if (j >= otherpoints.length) {
|
||||
// for lines, we can't use the rest of the points
|
||||
if (!withlines) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
}
|
||||
i += ps;
|
||||
}
|
||||
else if (otherpoints[j] == null) {
|
||||
// oops, got a gap
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(null);
|
||||
fromgap = true;
|
||||
j += otherps;
|
||||
}
|
||||
else {
|
||||
// cases where we actually got two points
|
||||
px = points[i + keyOffset];
|
||||
py = points[i + accumulateOffset];
|
||||
qx = otherpoints[j + keyOffset];
|
||||
qy = otherpoints[j + accumulateOffset];
|
||||
bottom = 0;
|
||||
|
||||
if (px == qx) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
newpoints[l + accumulateOffset] += qy;
|
||||
bottom = qy;
|
||||
|
||||
i += ps;
|
||||
j += otherps;
|
||||
}
|
||||
else if (px > qx) {
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
if (withlines && i > 0 && points[i - ps] != null) {
|
||||
intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
|
||||
newpoints.push(qx);
|
||||
newpoints.push(intery + qy);
|
||||
for (m = 2; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
}
|
||||
else { // px < qx
|
||||
if (fromgap && withlines) {
|
||||
// if we come from a gap, we just skip this point
|
||||
i += ps;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
// we might be able to interpolate a point below,
|
||||
// this can give us a better y
|
||||
if (withlines && j > 0 && otherpoints[j - otherps] != null)
|
||||
bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);
|
||||
|
||||
newpoints[l + accumulateOffset] += bottom;
|
||||
|
||||
i += ps;
|
||||
}
|
||||
|
||||
fromgap = false;
|
||||
|
||||
if (l != newpoints.length && withbottom)
|
||||
newpoints[l + 2] += bottom;
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
if (withsteps && l != newpoints.length && l > 0
|
||||
&& newpoints[l] != null
|
||||
&& newpoints[l] != newpoints[l - ps]
|
||||
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints[l + ps + m] = newpoints[l + m];
|
||||
newpoints[l + 1] = newpoints[l - ps + 1];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(stackData);
|
||||
return res;
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'stack',
|
||||
version: '1.2'
|
||||
});
|
||||
|
||||
function stackData(plot, s, datapoints) {
|
||||
if (s.stack == null || s.stack === false)
|
||||
return;
|
||||
|
||||
var other = findMatchingSeries(s, plot.getData());
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize,
|
||||
points = datapoints.points,
|
||||
otherps = other.datapoints.pointsize,
|
||||
otherpoints = other.datapoints.points,
|
||||
newpoints = [],
|
||||
px, py, intery, qx, qy, bottom,
|
||||
withlines = s.lines.show,
|
||||
horizontal = s.bars.horizontal,
|
||||
withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
|
||||
withsteps = withlines && s.lines.steps,
|
||||
fromgap = true,
|
||||
keyOffset = horizontal ? 1 : 0,
|
||||
accumulateOffset = horizontal ? 0 : 1,
|
||||
i = 0, j = 0, l, m;
|
||||
|
||||
while (true) {
|
||||
if (i >= points.length)
|
||||
break;
|
||||
|
||||
l = newpoints.length;
|
||||
|
||||
if (points[i] == null) {
|
||||
// copy gaps
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else if (j >= otherpoints.length) {
|
||||
// for lines, we can't use the rest of the points
|
||||
if (!withlines) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
}
|
||||
i += ps;
|
||||
}
|
||||
else if (otherpoints[j] == null) {
|
||||
// oops, got a gap
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(null);
|
||||
fromgap = true;
|
||||
j += otherps;
|
||||
}
|
||||
else {
|
||||
// cases where we actually got two points
|
||||
px = points[i + keyOffset];
|
||||
py = points[i + accumulateOffset];
|
||||
qx = otherpoints[j + keyOffset];
|
||||
qy = otherpoints[j + accumulateOffset];
|
||||
bottom = 0;
|
||||
|
||||
if (px == qx) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
newpoints[l + accumulateOffset] += qy;
|
||||
bottom = qy;
|
||||
|
||||
i += ps;
|
||||
j += otherps;
|
||||
}
|
||||
else if (px > qx) {
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
if (withlines && i > 0 && points[i - ps] != null) {
|
||||
intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
|
||||
newpoints.push(qx);
|
||||
newpoints.push(intery + qy);
|
||||
for (m = 2; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
}
|
||||
else { // px < qx
|
||||
if (fromgap && withlines) {
|
||||
// if we come from a gap, we just skip this point
|
||||
i += ps;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
// we might be able to interpolate a point below,
|
||||
// this can give us a better y
|
||||
if (withlines && j > 0 && otherpoints[j - otherps] != null)
|
||||
bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);
|
||||
|
||||
newpoints[l + accumulateOffset] += bottom;
|
||||
|
||||
i += ps;
|
||||
}
|
||||
|
||||
fromgap = false;
|
||||
|
||||
if (l != newpoints.length && withbottom)
|
||||
newpoints[l + 2] += bottom;
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
if (withsteps && l != newpoints.length && l > 0
|
||||
&& newpoints[l] != null
|
||||
&& newpoints[l] != newpoints[l - ps]
|
||||
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints[l + ps + m] = newpoints[l + m];
|
||||
newpoints[l + 1] = newpoints[l - ps + 1];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(stackData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'stack',
|
||||
version: '1.2'
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
@ -1,70 +1,71 @@
|
||||
/*
|
||||
Flot plugin that adds some extra symbols for plotting points.
|
||||
/* Flot plugin that adds some extra symbols for plotting points.
|
||||
|
||||
The symbols are accessed as strings through the standard symbol
|
||||
choice:
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
series: {
|
||||
points: {
|
||||
symbol: "square" // or "diamond", "triangle", "cross"
|
||||
}
|
||||
}
|
||||
The symbols are accessed as strings through the standard symbol options:
|
||||
|
||||
series: {
|
||||
points: {
|
||||
symbol: "square" // or "diamond", "triangle", "cross"
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
function processRawData(plot, series, datapoints) {
|
||||
// we normalize the area of each symbol so it is approximately the
|
||||
// same as a circle of the given radius
|
||||
function processRawData(plot, series, datapoints) {
|
||||
// we normalize the area of each symbol so it is approximately the
|
||||
// same as a circle of the given radius
|
||||
|
||||
var handlers = {
|
||||
square: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.rect(x - size, y - size, size + size, size + size);
|
||||
},
|
||||
diamond: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 2s^2 => s = r * sqrt(pi/2)
|
||||
var size = radius * Math.sqrt(Math.PI / 2);
|
||||
ctx.moveTo(x - size, y);
|
||||
ctx.lineTo(x, y - size);
|
||||
ctx.lineTo(x + size, y);
|
||||
ctx.lineTo(x, y + size);
|
||||
ctx.lineTo(x - size, y);
|
||||
},
|
||||
triangle: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3))
|
||||
var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3));
|
||||
var height = size * Math.sin(Math.PI / 3);
|
||||
ctx.moveTo(x - size/2, y + height/2);
|
||||
ctx.lineTo(x + size/2, y + height/2);
|
||||
if (!shadow) {
|
||||
ctx.lineTo(x, y - height/2);
|
||||
ctx.lineTo(x - size/2, y + height/2);
|
||||
}
|
||||
},
|
||||
cross: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.moveTo(x - size, y - size);
|
||||
ctx.lineTo(x + size, y + size);
|
||||
ctx.moveTo(x - size, y + size);
|
||||
ctx.lineTo(x + size, y - size);
|
||||
}
|
||||
var handlers = {
|
||||
square: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.rect(x - size, y - size, size + size, size + size);
|
||||
},
|
||||
diamond: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 2s^2 => s = r * sqrt(pi/2)
|
||||
var size = radius * Math.sqrt(Math.PI / 2);
|
||||
ctx.moveTo(x - size, y);
|
||||
ctx.lineTo(x, y - size);
|
||||
ctx.lineTo(x + size, y);
|
||||
ctx.lineTo(x, y + size);
|
||||
ctx.lineTo(x - size, y);
|
||||
},
|
||||
triangle: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3))
|
||||
var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3));
|
||||
var height = size * Math.sin(Math.PI / 3);
|
||||
ctx.moveTo(x - size/2, y + height/2);
|
||||
ctx.lineTo(x + size/2, y + height/2);
|
||||
if (!shadow) {
|
||||
ctx.lineTo(x, y - height/2);
|
||||
ctx.lineTo(x - size/2, y + height/2);
|
||||
}
|
||||
},
|
||||
cross: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.moveTo(x - size, y - size);
|
||||
ctx.lineTo(x + size, y + size);
|
||||
ctx.moveTo(x - size, y + size);
|
||||
ctx.lineTo(x + size, y - size);
|
||||
}
|
||||
};
|
||||
|
||||
var s = series.points.symbol;
|
||||
if (handlers[s])
|
||||
series.points.symbol = handlers[s];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processDatapoints.push(processRawData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
name: 'symbols',
|
||||
version: '1.0'
|
||||
});
|
||||
var s = series.points.symbol;
|
||||
if (handlers[s])
|
||||
series.points.symbol = handlers[s];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processDatapoints.push(processRawData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
name: 'symbols',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
@ -1,103 +1,142 @@
|
||||
/*
|
||||
Flot plugin for thresholding data. Controlled through the option
|
||||
"threshold" in either the global series options
|
||||
/* Flot plugin for thresholding data.
|
||||
|
||||
series: {
|
||||
threshold: {
|
||||
below: number
|
||||
color: colorspec
|
||||
}
|
||||
}
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
or in a specific series
|
||||
The plugin supports these options:
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], threshold: { ... }}])
|
||||
series: {
|
||||
threshold: {
|
||||
below: number
|
||||
color: colorspec
|
||||
}
|
||||
}
|
||||
|
||||
The data points below "below" are drawn with the specified color. This
|
||||
makes it easy to mark points below 0, e.g. for budget data.
|
||||
It can also be applied to a single series, like this:
|
||||
|
||||
$.plot( $("#placeholder"), [{
|
||||
data: [ ... ],
|
||||
threshold: { ... }
|
||||
}])
|
||||
|
||||
An array can be passed for multiple thresholding, like this:
|
||||
|
||||
threshold: [{
|
||||
below: number1
|
||||
color: color1
|
||||
},{
|
||||
below: number2
|
||||
color: color2
|
||||
}]
|
||||
|
||||
These multiple threshold objects can be passed in any order since they are
|
||||
sorted by the processing function.
|
||||
|
||||
The data points below "below" are drawn with the specified color. This makes
|
||||
it easy to mark points below 0, e.g. for budget data.
|
||||
|
||||
Internally, the plugin works by splitting the data into two series, above and
|
||||
below the threshold. The extra series below the threshold will have its label
|
||||
cleared and the special "originSeries" attribute set to the original series.
|
||||
You may need to check for this in hover events.
|
||||
|
||||
Internally, the plugin works by splitting the data into two series,
|
||||
above and below the threshold. The extra series below the threshold
|
||||
will have its label cleared and the special "originSeries" attribute
|
||||
set to the original series. You may need to check for this in hover
|
||||
events.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { threshold: null } // or { below: number, color: color spec}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function thresholdData(plot, s, datapoints) {
|
||||
if (!s.threshold)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize, i, x, y, p, prevp,
|
||||
thresholded = $.extend({}, s); // note: shallow copy
|
||||
var options = {
|
||||
series: { threshold: null } // or { below: number, color: color spec}
|
||||
};
|
||||
|
||||
thresholded.datapoints = { points: [], pointsize: ps };
|
||||
thresholded.label = null;
|
||||
thresholded.color = s.threshold.color;
|
||||
thresholded.threshold = null;
|
||||
thresholded.originSeries = s;
|
||||
thresholded.data = [];
|
||||
function init(plot) {
|
||||
function thresholdData(plot, s, datapoints, below, color) {
|
||||
var ps = datapoints.pointsize, i, x, y, p, prevp,
|
||||
thresholded = $.extend({}, s); // note: shallow copy
|
||||
|
||||
var below = s.threshold.below,
|
||||
origpoints = datapoints.points,
|
||||
addCrossingPoints = s.lines.show;
|
||||
thresholded.datapoints = { points: [], pointsize: ps, format: datapoints.format };
|
||||
thresholded.label = null;
|
||||
thresholded.color = color;
|
||||
thresholded.threshold = null;
|
||||
thresholded.originSeries = s;
|
||||
thresholded.data = [];
|
||||
|
||||
threspoints = [];
|
||||
newpoints = [];
|
||||
var origpoints = datapoints.points,
|
||||
addCrossingPoints = s.lines.show;
|
||||
|
||||
for (i = 0; i < origpoints.length; i += ps) {
|
||||
x = origpoints[i]
|
||||
y = origpoints[i + 1];
|
||||
var threspoints = [];
|
||||
var newpoints = [];
|
||||
var m;
|
||||
|
||||
prevp = p;
|
||||
if (y < below)
|
||||
p = threspoints;
|
||||
else
|
||||
p = newpoints;
|
||||
for (i = 0; i < origpoints.length; i += ps) {
|
||||
x = origpoints[i];
|
||||
y = origpoints[i + 1];
|
||||
|
||||
if (addCrossingPoints && prevp != p && x != null
|
||||
&& i > 0 && origpoints[i - ps] != null) {
|
||||
var interx = (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]) * (below - y) + x;
|
||||
prevp.push(interx);
|
||||
prevp.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
prevp.push(origpoints[i + m]);
|
||||
|
||||
p.push(null); // start new segment
|
||||
p.push(null);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
p.push(interx);
|
||||
p.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
}
|
||||
prevp = p;
|
||||
if (y < below)
|
||||
p = threspoints;
|
||||
else
|
||||
p = newpoints;
|
||||
|
||||
p.push(x);
|
||||
p.push(y);
|
||||
}
|
||||
if (addCrossingPoints && prevp != p && x != null
|
||||
&& i > 0 && origpoints[i - ps] != null) {
|
||||
var interx = x + (below - y) * (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]);
|
||||
prevp.push(interx);
|
||||
prevp.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
prevp.push(origpoints[i + m]);
|
||||
|
||||
datapoints.points = newpoints;
|
||||
thresholded.datapoints.points = threspoints;
|
||||
|
||||
if (thresholded.datapoints.points.length > 0)
|
||||
plot.getData().push(thresholded);
|
||||
|
||||
// FIXME: there are probably some edge cases left in bars
|
||||
p.push(null); // start new segment
|
||||
p.push(null);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
p.push(interx);
|
||||
p.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(thresholdData);
|
||||
|
||||
p.push(x);
|
||||
p.push(y);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
thresholded.datapoints.points = threspoints;
|
||||
|
||||
if (thresholded.datapoints.points.length > 0) {
|
||||
var origIndex = $.inArray(s, plot.getData());
|
||||
// Insert newly-generated series right after original one (to prevent it from becoming top-most)
|
||||
plot.getData().splice(origIndex + 1, 0, thresholded);
|
||||
}
|
||||
|
||||
// FIXME: there are probably some edge cases left in bars
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'threshold',
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
function processThresholds(plot, s, datapoints) {
|
||||
if (!s.threshold)
|
||||
return;
|
||||
|
||||
if (s.threshold instanceof Array) {
|
||||
s.threshold.sort(function(a, b) {
|
||||
return a.below - b.below;
|
||||
});
|
||||
|
||||
$(s.threshold).each(function(i, th) {
|
||||
thresholdData(plot, s, datapoints, th.below, th.color);
|
||||
});
|
||||
}
|
||||
else {
|
||||
thresholdData(plot, s, datapoints, s.threshold.below, s.threshold.color);
|
||||
}
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(processThresholds);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'threshold',
|
||||
version: '1.2'
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
15791
ui/lib/jquery-ui/js/jquery-ui.js
vendored
Executable file → Normal file
15791
ui/lib/jquery-ui/js/jquery-ui.js
vendored
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
19186
ui/lib/jquery.js
vendored
19186
ui/lib/jquery.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
982
ui/lib/jquery.validate.js
vendored
982
ui/lib/jquery.validate.js
vendored
File diff suppressed because it is too large
Load Diff
@ -384,7 +384,7 @@
|
||||
args.complete($chart);
|
||||
}
|
||||
|
||||
if ($chart.find('.connector-line.highlighted').size()) {
|
||||
if ($chart.find('.connector-line.highlighted').length) {
|
||||
$info.appendTo($chart).append(
|
||||
$('<span>').addClass('color-key'),
|
||||
$('<span>').html('= Contains a public network')
|
||||
|
||||
@ -450,10 +450,10 @@
|
||||
});
|
||||
|
||||
// Logout action
|
||||
$('#user-options a').live('click', function() {
|
||||
loginArgs.logoutAction({
|
||||
context: cloudStack.context
|
||||
});
|
||||
$(document).on('click', '#user-options a', function() {
|
||||
loginArgs.logoutAction({
|
||||
context: cloudStack.context
|
||||
});
|
||||
});
|
||||
|
||||
window._reloadUI = function() {
|
||||
|
||||
@ -2445,7 +2445,7 @@
|
||||
var $tierSelect = $(".ui-dialog-content").find('.tier-select select');
|
||||
|
||||
// if $tierSelect is not initialized, return; tierSelect() will refresh listView and come back here later
|
||||
if ($tierSelect.size() == 0) {
|
||||
if ($tierSelect.length == 0) {
|
||||
args.response.success({
|
||||
data: null
|
||||
});
|
||||
|
||||
@ -761,7 +761,7 @@ var addGuestNetworkDialog = {
|
||||
} else { //domain-specific
|
||||
array1.push("&acltype=domain");
|
||||
|
||||
if ($form.find('.form-item[rel=subdomainaccess]:visible input:checked').size())
|
||||
if ($form.find('.form-item[rel=subdomainaccess]:visible input:checked').length)
|
||||
array1.push("&subdomainaccess=true");
|
||||
else
|
||||
array1.push("&subdomainaccess=false");
|
||||
|
||||
@ -94,7 +94,7 @@
|
||||
|
||||
$wizard.click(function(event) {
|
||||
var $target = $(event.target);
|
||||
if ($target.closest('button.next').size()) {
|
||||
if ($target.closest('button.next').length) {
|
||||
$form.validate();
|
||||
if ($form.valid()) {
|
||||
completeAction();
|
||||
@ -104,7 +104,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ($target.closest('button.cancel').size()) {
|
||||
if ($target.closest('button.cancel').length) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
@ -112,14 +112,14 @@
|
||||
|
||||
if (ldapStatus) {
|
||||
var $table = $wizard.find('.ldap-account-choice tbody');
|
||||
$("#label_ldap_group_name").live("keypress", function(event) {
|
||||
$("#label_ldap_group_name").on("keypress", function(event) {
|
||||
if ($table.find("#tr-groupname-message").length === 0) {
|
||||
$("<tr id='tr-groupname-message'>").appendTo($table).append("<td colspan=\"4\">"+_l('message.ldap.group.import')+"</td>");
|
||||
}
|
||||
$table.find("tr").hide();
|
||||
$table.find("#tr-groupname-message").show();
|
||||
});
|
||||
$("#label_ldap_group_name").live("blur", function(event) {
|
||||
$("#label_ldap_group_name").on("blur", function(event) {
|
||||
if (!$(this).val()) {
|
||||
$table.find("tr").show();
|
||||
$table.find("#tr-groupname-message").hide();
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
|
||||
if (!$dataList.find(
|
||||
'input[type=radio]:checked, input[type=checkbox]:checked'
|
||||
).size()) {
|
||||
).length) {
|
||||
cloudStack.dialog.notice({
|
||||
message: _l('message.select.instance')
|
||||
});
|
||||
|
||||
@ -60,12 +60,12 @@
|
||||
data['new-network-ip'] = $form.find('.new-network .select.advanced .specify-ip input[type=text]').val();
|
||||
|
||||
// Handle multi-disk service offerings
|
||||
if ($form.find('.multi-disk-select-container').size()) {
|
||||
if ($form.find('.multi-disk-select-container').length) {
|
||||
data['disk-offerings-multi'] = [];
|
||||
|
||||
var $diskGroups = $form.find('.disk-select-group');
|
||||
var $selectedDisks = $.grep($diskGroups, function (diskGroup) {
|
||||
return $(diskGroup).find('input[type=checkbox]:checked').size();
|
||||
return $(diskGroup).find('input[type=checkbox]:checked').length;
|
||||
});
|
||||
|
||||
$selectedDisks.map(function (disk) {
|
||||
@ -86,7 +86,7 @@
|
||||
success: function(args) {
|
||||
var $listView = $('.list-view.instances');
|
||||
|
||||
if ($listView.size()) {
|
||||
if ($listView.length) {
|
||||
var $loading = $('.list-view.instances').listView('prependItem', {
|
||||
data: [{
|
||||
name: data.displayname ? data.displayname : _l('label.new.vm'),
|
||||
@ -104,7 +104,7 @@
|
||||
listViewArgs.complete({
|
||||
_custom: args._custom,
|
||||
messageArgs: cloudStack.serializeForm($form),
|
||||
$item: $listView.size() ? $loading : $('<div>')
|
||||
$item: $listView.length ? $loading : $('<div>')
|
||||
});
|
||||
|
||||
close();
|
||||
@ -158,17 +158,17 @@
|
||||
|
||||
var $checkedOtherSelect = $otherSelects.filter(function() {
|
||||
return $(this).not('.single-select') &&
|
||||
$(this).find('input[type=checkbox]:checked').size() &&
|
||||
$(this).find('input[type=radio]:checked').size();
|
||||
$(this).find('input[type=checkbox]:checked').length &&
|
||||
$(this).find('input[type=radio]:checked').length;
|
||||
});
|
||||
|
||||
if (!$checkedOtherSelect.size() &&
|
||||
!$('.new-network:visible input[type=radio]:checked').size()) {
|
||||
if (!$checkedOtherSelect.length &&
|
||||
!$('.new-network:visible input[type=radio]:checked').length) {
|
||||
$(this).closest('.select').find('input[type=radio]').click();
|
||||
}
|
||||
}
|
||||
|
||||
if ((!$otherSelects.size()) &&
|
||||
if ((!$otherSelects.length) &&
|
||||
$newNetwork.find('input[type=checkbox]').is(':unchecked')) {
|
||||
// Set as default
|
||||
$(this).closest('.select').find('input[type=radio]').click();
|
||||
@ -268,10 +268,9 @@
|
||||
|
||||
var dataGenerators = {
|
||||
setup: function($step, formData) {
|
||||
var originalValues = function(formData) {
|
||||
$step.find('select').val(
|
||||
formData.zoneid
|
||||
);
|
||||
var originalValues = function(formData, initialValue) {
|
||||
var selectedValue = formData.zoneid || initialValue;
|
||||
$step.find('select').val(selectedValue);
|
||||
|
||||
$step.find('input[type=radio]').filter(function() {
|
||||
return $(this).val() == formData['select-template'];
|
||||
@ -282,7 +281,11 @@
|
||||
response: {
|
||||
success: function(args) {
|
||||
// Zones
|
||||
$(args.data.zones).each(function() {
|
||||
var initialValue = '';
|
||||
$(args.data.zones).each(function( index ) {
|
||||
if(index == 0){
|
||||
initialValue = this.id;
|
||||
}
|
||||
$step.find('.select-zone select').append(
|
||||
$('<option>')
|
||||
.attr({
|
||||
@ -293,7 +296,7 @@
|
||||
);
|
||||
});
|
||||
|
||||
originalValues(formData);
|
||||
originalValues(formData, initialValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -309,7 +312,7 @@
|
||||
return $(this).val() == formData.templateid;
|
||||
});
|
||||
|
||||
if (!$selected.size()) {
|
||||
if (!$selected.length) {
|
||||
$inputs.filter(':first').click();
|
||||
} else {
|
||||
$selected.click();
|
||||
@ -541,7 +544,7 @@
|
||||
return $(this).val() == formData.diskofferingid;
|
||||
}).click();
|
||||
|
||||
if (!$targetInput.size()) {
|
||||
if (!$targetInput.length) {
|
||||
$step.find('input[type=radio]:visible').filter(':first').click();
|
||||
}
|
||||
};
|
||||
@ -620,7 +623,7 @@
|
||||
$group.toggleClass('selected');
|
||||
$group.find('.select:first input[type=radio]').click();
|
||||
|
||||
if (!$multiDiskSelect.find('input[type=checkbox]:checked').size()) {
|
||||
if (!$multiDiskSelect.find('input[type=checkbox]:checked').length) {
|
||||
$step.find('.no-thanks input[type=radio]').click();
|
||||
} else {
|
||||
$step.find('.no-thanks input[type=radio]').attr('checked', false);
|
||||
@ -655,10 +658,10 @@
|
||||
var item = $.grep(args.data.diskOfferings, function(elem) {
|
||||
return elem.id == val;
|
||||
})[0];
|
||||
var isMultiDisk = $step.find('.multi-disk-select').size();
|
||||
var isMultiDisk = $step.find('.multi-disk-select').length;
|
||||
|
||||
// Uncheck any multi-select groups
|
||||
if ($target.closest('.no-thanks').size() && isMultiDisk) {
|
||||
if ($target.closest('.no-thanks').length && isMultiDisk) {
|
||||
$step.find('.disk-select-group input[type=checkbox]:checked').click();
|
||||
$(this).attr('checked', true);
|
||||
|
||||
@ -881,7 +884,7 @@
|
||||
var $checkbox = $step.find('.new-network input[type=checkbox]');
|
||||
var $newNetwork = $checkbox.closest('.new-network');
|
||||
|
||||
if ($step.find('.select.my-networks .select-container .select:visible').size()) {
|
||||
if ($step.find('.select.my-networks .select-container .select:visible').length) {
|
||||
$checkbox.attr('checked', false);
|
||||
$newNetwork.addClass('unselected');
|
||||
} else {
|
||||
@ -1023,7 +1026,7 @@
|
||||
);
|
||||
|
||||
// Cleanup
|
||||
if ($select.closest('.new-network').size()) {
|
||||
if ($select.closest('.new-network').length) {
|
||||
$select.find('.advanced-options, .specify-ip').remove();
|
||||
}
|
||||
|
||||
@ -1077,10 +1080,10 @@
|
||||
fieldName = $input.html();
|
||||
} else if ($input.is('input[type=radio]')) {
|
||||
// Choosen New network as default
|
||||
if ($input.parents('div.new-network').size()) {
|
||||
if ($input.parents('div.new-network').length) {
|
||||
fieldName = $input.closest('div.new-network').find('input[name="new-network-name"]').val();
|
||||
// Choosen Network from existed
|
||||
} else if ($input.parents('div.my-networks').size()) {
|
||||
} else if ($input.parents('div.my-networks').length) {
|
||||
fieldName = $input.closest('div.select').find('.select-desc .name').html();
|
||||
} else {
|
||||
fieldName = $input.parent().find('.select-desc .name').html();
|
||||
@ -1124,7 +1127,7 @@
|
||||
var targetIndex = index - 1;
|
||||
|
||||
if (index <= 1) targetIndex = 0;
|
||||
if (targetIndex == $steps.size()) {
|
||||
if (targetIndex == $steps.length) {
|
||||
completeAction();
|
||||
return;
|
||||
}
|
||||
@ -1182,7 +1185,7 @@
|
||||
}).fadeOut('slow');
|
||||
|
||||
setTimeout(function() {
|
||||
if (!$targetStep.find('input[type=radio]:checked').size()) {
|
||||
if (!$targetStep.find('input[type=radio]:checked').length) {
|
||||
$targetStep.find('input[type=radio]:first').click();
|
||||
}
|
||||
}, 50);
|
||||
@ -1194,10 +1197,10 @@
|
||||
var $activeStep = $form.find('.step:visible');
|
||||
|
||||
// Next button
|
||||
if ($target.closest('div.button.next').size()) {
|
||||
if ($target.closest('div.button.next').length) {
|
||||
//step 2 - select template/ISO
|
||||
if($activeStep.hasClass('select-iso')) {
|
||||
if ($activeStep.find('.content:visible input:checked').size() == 0) {
|
||||
if ($activeStep.find('.content:visible input:checked').length == 0) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'message.step.1.continue'
|
||||
});
|
||||
@ -1210,7 +1213,7 @@
|
||||
}
|
||||
|
||||
//step 6 - select network
|
||||
if ($activeStep.find('.wizard-step-conditional.select-network:visible').size() > 0) {
|
||||
if ($activeStep.find('.wizard-step-conditional.select-network:visible').length > 0) {
|
||||
var data = $activeStep.data('my-networks');
|
||||
|
||||
if (!data) {
|
||||
@ -1219,7 +1222,7 @@
|
||||
)['my-networks']);
|
||||
}
|
||||
|
||||
if ($activeStep.find('input[type=checkbox]:checked').size() == 0) { //if no checkbox is checked
|
||||
if ($activeStep.find('input[type=checkbox]:checked').length == 0) { //if no checkbox is checked
|
||||
cloudStack.dialog.notice({
|
||||
message: 'message.step.4.continue'
|
||||
});
|
||||
@ -1234,7 +1237,7 @@
|
||||
if (advSGFilter == 0) { //when total number of selected sg networks is 0, then 'Select Security Group' is skipped, go to step 6 directly
|
||||
showStep(6);
|
||||
} else { //when total number of selected sg networks > 0
|
||||
if ($activeStep.find('input[type=checkbox]:checked').size() > 1) { //when total number of selected networks > 1
|
||||
if ($activeStep.find('input[type=checkbox]:checked').length > 1) { //when total number of selected networks > 1
|
||||
cloudStack.dialog.notice({
|
||||
message: "Can't create a vm with multiple networks one of which is Security Group enabled"
|
||||
});
|
||||
@ -1246,7 +1249,7 @@
|
||||
|
||||
//step 6 - review (spcifiy displyname, group as well)
|
||||
if ($activeStep.hasClass('review')) {
|
||||
if ($activeStep.find('input[name=displayname]').size() > 0 && $activeStep.find('input[name=displayname]').val().length > 0) {
|
||||
if ($activeStep.find('input[name=displayname]').length > 0 && $activeStep.find('input[name=displayname]').val().length > 0) {
|
||||
//validate
|
||||
var b = cloudStack.validate.vmHostName($activeStep.find('input[name=displayname]').val());
|
||||
if (b == false)
|
||||
@ -1255,7 +1258,7 @@
|
||||
}
|
||||
|
||||
if (!$form.valid()) {
|
||||
if ($form.find('input.error:visible, select.error:visible').size()) {
|
||||
if ($form.find('input.error:visible, select.error:visible').length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1270,7 +1273,7 @@
|
||||
}
|
||||
|
||||
// Previous button
|
||||
if ($target.closest('div.button.previous').size()) {
|
||||
if ($target.closest('div.button.previous').length) {
|
||||
var $step = $steps.filter(':visible');
|
||||
var $networkStep = $steps.filter('.network');
|
||||
var index = $step.index();
|
||||
@ -1278,10 +1281,10 @@
|
||||
$networkStep.removeClass('next-use-security-groups');
|
||||
|
||||
if (index) {
|
||||
if (index == $steps.size() - 1 && $networkStep.hasClass('next-use-security-groups')) {
|
||||
if (index == $steps.length - 1 && $networkStep.hasClass('next-use-security-groups')) {
|
||||
showStep(5);
|
||||
} else if ($activeStep.find('.select-security-group:visible').size() &&
|
||||
$activeStep.find('.select-network.no-add-network').size()) {
|
||||
} else if ($activeStep.find('.select-security-group:visible').length &&
|
||||
$activeStep.find('.select-network.no-add-network').length) {
|
||||
showStep(5);
|
||||
} else {
|
||||
showStep(index);
|
||||
@ -1292,14 +1295,14 @@
|
||||
}
|
||||
|
||||
// Close button
|
||||
if ($target.closest('div.button.cancel').size()) {
|
||||
if ($target.closest('div.button.cancel').length) {
|
||||
close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Edit link
|
||||
if ($target.closest('div.edit').size()) {
|
||||
if ($target.closest('div.edit').length) {
|
||||
var $edit = $target.closest('div.edit');
|
||||
|
||||
showStep($edit.find('a').attr('href'));
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
return $dashboard
|
||||
.click(function(event) {
|
||||
var $target = $(event.target);
|
||||
if ($target.closest('[view-all-target]').size()) {
|
||||
if ($target.closest('[view-all-target]').length) {
|
||||
var targetID = $target.closest('[view-all-target]').attr('view-all-target');
|
||||
args.$browser.cloudBrowser('addPanel', {
|
||||
title: $target.closest('[view-all-title]').attr('view-all-title'),
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
$plugin.click(function() {
|
||||
var $mainSection = $('#navigation ul li').filter('.' + plugin.id);
|
||||
|
||||
if ($mainSection.size()) {
|
||||
if ($mainSection.length) {
|
||||
$mainSection.click();
|
||||
|
||||
return;
|
||||
|
||||
@ -275,7 +275,7 @@
|
||||
var $management = $panel.find('.management');
|
||||
var $managementInvite = $panel.find('.management-invite');
|
||||
|
||||
if ($management.size()) {
|
||||
if ($management.length) {
|
||||
$management.children().remove();
|
||||
$management.append(pageElems.userManagement({
|
||||
context: cloudStack.context
|
||||
@ -284,7 +284,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($managementInvite.size()) {
|
||||
if ($managementInvite.length) {
|
||||
$managementInvite.children().remove();
|
||||
$managementInvite.append(pageElems.userManagement({
|
||||
context: cloudStack.context,
|
||||
@ -635,7 +635,7 @@
|
||||
|
||||
// Initial load
|
||||
loadData(function() {
|
||||
if (!$list.find('li').size()) {
|
||||
if (!$list.find('li').length) {
|
||||
cloudStack.dialog.notice({
|
||||
message: isAdmin() || isDomainAdmin() || g_userProjectsEnabled ? _l('message.no.projects') : _l('message.no.projects.adminOnly')
|
||||
}).closest('.ui-dialog');
|
||||
|
||||
@ -117,7 +117,7 @@
|
||||
return $(this).index() == index;
|
||||
});
|
||||
|
||||
if ($tr.size() && $tr.hasClass('active')) {
|
||||
if ($tr.length && $tr.hasClass('active')) {
|
||||
$(this).addClass('disabled ui-state-disabled');
|
||||
} else {
|
||||
$(this).removeClass('disabled ui-state-disabled');
|
||||
@ -126,7 +126,7 @@
|
||||
if ($(this).is('.ui-tabs-selected.ui-state-disabled')) {
|
||||
$snapshots.find('form').show();
|
||||
|
||||
if ($snapshots.find('li.ui-state-disabled').size() == $snapshots.find('li').size()) {
|
||||
if ($snapshots.find('li.ui-state-disabled').length == $snapshots.find('li').length) {
|
||||
$snapshots.find('form').hide();
|
||||
} else {
|
||||
$snapshots.find('li:not(.ui-state-disabled):first a').click();
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
var $li = $target.closest('li');
|
||||
var region, url;
|
||||
|
||||
if ($li.size() && !$li.hasClass('active')) {
|
||||
if ($li.length && !$li.hasClass('active')) {
|
||||
region = $li.data('region-data');
|
||||
url = region.endpoint;
|
||||
id = region.id;
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
if (!$uploadVolume.find(
|
||||
'input[type=radio]:checked, input[type=checkbox]:checked'
|
||||
).size()) {
|
||||
).length) {
|
||||
cloudStack.dialog.notice({
|
||||
message: _l('message.select.instance')
|
||||
});
|
||||
|
||||
@ -409,7 +409,7 @@
|
||||
|
||||
// Title shows tier details
|
||||
$title.click(function() {
|
||||
if ($browser && $browser.size()) { // Fix null exception, if add tier returns error
|
||||
if ($browser && $browser.length) { // Fix null exception, if add tier returns error
|
||||
$browser.cloudBrowser('addPanel', {
|
||||
title: name,
|
||||
maximizeIfSelected: true,
|
||||
@ -545,7 +545,7 @@
|
||||
);
|
||||
|
||||
var showAddTierDialog = function() {
|
||||
if ($(this).find('.loading-overlay').size()) {
|
||||
if ($(this).find('.loading-overlay').length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
if (!options) options = {};
|
||||
|
||||
var $forms = $wizard.find('form').filter(function() {
|
||||
return !options.all ? !$(this).closest('.multi-edit').size() : true;
|
||||
return !options.all ? !$(this).closest('.multi-edit').length : true;
|
||||
});
|
||||
var $physicalNetworkItems = $wizard.find(
|
||||
'.steps .setup-physical-network .select-container.multi'
|
||||
@ -33,7 +33,7 @@
|
||||
'.steps .setup-storage-traffic .data-body .data-item');
|
||||
var groupedForms = {};
|
||||
|
||||
if ($physicalNetworkItems.find('li.traffic-type-draggable.storage').size()) {
|
||||
if ($physicalNetworkItems.find('li.traffic-type-draggable.storage').length) {
|
||||
$wizard.find('li.conditional.storage-traffic').show();
|
||||
} else {
|
||||
$wizard.find('li.conditional.storage-traffic').hide();
|
||||
@ -93,7 +93,7 @@
|
||||
// Traffic type configuration data
|
||||
trafficTypeConfiguration: trafficTypeConfiguration,
|
||||
|
||||
guestConfiguration: $guestForm.size() ? cloudStack.serializeForm($guestForm) : null
|
||||
guestConfiguration: $guestForm.length ? cloudStack.serializeForm($guestForm) : null
|
||||
};
|
||||
}
|
||||
);
|
||||
@ -172,7 +172,7 @@
|
||||
*/
|
||||
var customValidation = {
|
||||
networkRanges: function($form) {
|
||||
if ($form.closest('.multi-edit').find('.data-item').size()) {
|
||||
if ($form.closest('.multi-edit').find('.data-item').length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@
|
||||
|
||||
physicalNetworks: function($form) {
|
||||
var $enabledPhysicalNetworks = $form.filter(':not(.disabled)').filter(function() {
|
||||
return $(this).find('.traffic-type-draggable').size();
|
||||
return $(this).find('.traffic-type-draggable').length;
|
||||
});
|
||||
var $trafficTypes = $enabledPhysicalNetworks.find('.traffic-type-draggable');
|
||||
var $configuredTrafficTypes = $trafficTypes.filter(function() {
|
||||
@ -193,8 +193,8 @@
|
||||
return ($trafficType.data('traffic-type-data') != null);
|
||||
});
|
||||
|
||||
if ($enabledPhysicalNetworks.size() > 1 &&
|
||||
$configuredTrafficTypes.size() != $trafficTypes.size()) {
|
||||
if ($enabledPhysicalNetworks.length > 1 &&
|
||||
$configuredTrafficTypes.length != $trafficTypes.length) {
|
||||
cloudStack.dialog.notice({
|
||||
message: _l('message.configure.all.traffic.types')
|
||||
});
|
||||
@ -215,9 +215,9 @@
|
||||
var $physicalNetworks = $step.find('.select-container.multi');
|
||||
var isCustomValidated;
|
||||
|
||||
if ($multiEditForm.size()) {
|
||||
if ($multiEditForm.length) {
|
||||
isCustomValidated = customValidation.networkRanges($multiEditForm);
|
||||
} else if ($physicalNetworks.size()) {
|
||||
} else if ($physicalNetworks.length) {
|
||||
isCustomValidated = customValidation.physicalNetworks($physicalNetworks);
|
||||
} else {
|
||||
isCustomValidated = true;
|
||||
@ -240,7 +240,7 @@
|
||||
var $existingPhysicalNetworks = physicalNetwork.getNetworks($wizard);
|
||||
|
||||
// Initialize physical networks
|
||||
if (!$existingPhysicalNetworks.size()) {
|
||||
if (!$existingPhysicalNetworks.length) {
|
||||
physicalNetwork.add($wizard);
|
||||
} else if (!isAdvancedNetwork($wizard)) {
|
||||
$existingPhysicalNetworks.filter(':first').siblings().each(function() {
|
||||
@ -459,12 +459,12 @@
|
||||
return $(this).attr('traffic-type-id') == trafficTypeID;
|
||||
});
|
||||
|
||||
if (physicalNetwork.isTrafficTypeClone($trafficType) && !$container.closest('.select-container.multi').size()) {
|
||||
if (physicalNetwork.isTrafficTypeClone($trafficType) && !$container.closest('.select-container.multi').length) {
|
||||
// Get traffic type from original container
|
||||
return $trafficType.filter(function() {
|
||||
return $(this).closest(
|
||||
physicalNetwork.getOriginalTrafficContainer($trafficType)
|
||||
).size();
|
||||
).length;
|
||||
});
|
||||
}
|
||||
|
||||
@ -516,10 +516,10 @@
|
||||
var $trafficType = physicalNetwork.getTrafficType(trafficTypeID, $container);
|
||||
var $dropArea = $physicalNetwork.find('.drop-container ul');
|
||||
|
||||
if ($physicalNetwork.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').size()) return false;
|
||||
if ($physicalNetwork.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').length) return false;
|
||||
|
||||
if (physicalNetwork.isTrafficTypeClone($trafficType)) {
|
||||
if (!physicalNetwork.getTrafficType(trafficTypeID, $physicalNetwork).size()) {
|
||||
if (!physicalNetwork.getTrafficType(trafficTypeID, $physicalNetwork).length) {
|
||||
$trafficType = $trafficType.clone()
|
||||
.removeClass('disabled')
|
||||
.appendTo($dropArea)
|
||||
@ -563,7 +563,7 @@
|
||||
);
|
||||
|
||||
if (physicalNetwork.isTrafficTypeClone($trafficType) &&
|
||||
$physicalNetworks.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').size() > 1) {
|
||||
$physicalNetworks.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').length > 1) {
|
||||
$trafficType.remove();
|
||||
}
|
||||
}
|
||||
@ -580,10 +580,10 @@
|
||||
return false;
|
||||
|
||||
var $emptyContainers = $containers.filter(function() {
|
||||
return !$(this).find('li').size();
|
||||
return !$(this).find('li').length;
|
||||
});
|
||||
|
||||
return !$emptyContainers.size() ? $containers.size() : false;
|
||||
return !$emptyContainers.length ? $containers.length : false;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -598,7 +598,7 @@
|
||||
$allPhysicalNetworks.each(function() {
|
||||
var $ul = $(this).find('.drop-container ul');
|
||||
|
||||
if (!$(this).find('li').size()) {
|
||||
if (!$(this).find('li').length) {
|
||||
$(this).addClass('disabled');
|
||||
$ul.fadeOut();
|
||||
} else {
|
||||
@ -609,8 +609,8 @@
|
||||
|
||||
$containers.each(function() {
|
||||
var $currentContainer = $(this);
|
||||
if (!$currentContainer.find('li').size() &&
|
||||
$containers.size() > containerTotal) {
|
||||
if (!$currentContainer.find('li').length &&
|
||||
$containers.length > containerTotal) {
|
||||
$currentContainer.remove();
|
||||
}
|
||||
});
|
||||
@ -753,7 +753,7 @@
|
||||
|
||||
$ul.addClass('active');
|
||||
|
||||
if (!$ul.find('li').size()) {
|
||||
if (!$ul.find('li').length) {
|
||||
$(this).closest('.select-container.multi').removeClass('disabled');
|
||||
$ul.fadeIn();
|
||||
}
|
||||
@ -772,7 +772,7 @@
|
||||
var trafficTypeData = ui.draggable.data('traffic-type-data');
|
||||
|
||||
if (trafficTypeID == 'guest' &&
|
||||
ui.draggable.closest('.select-container.multi').size()) {
|
||||
ui.draggable.closest('.select-container.multi').length) {
|
||||
ui.draggable.remove();
|
||||
}
|
||||
|
||||
@ -880,7 +880,7 @@
|
||||
|
||||
// Only use networks w/ guest traffic type
|
||||
$physicalNetworks = $physicalNetworks.filter(function() {
|
||||
return $(this).find('li.guest').size();
|
||||
return $(this).find('li.guest').length;
|
||||
|
||||
return true;
|
||||
});
|
||||
@ -1101,7 +1101,7 @@
|
||||
var targetIndex = index - 1;
|
||||
|
||||
if (index <= 1) targetIndex = 0;
|
||||
if (targetIndex == $steps.size()) {
|
||||
if (targetIndex == $steps.length) {
|
||||
completeAction();
|
||||
}
|
||||
|
||||
@ -1130,7 +1130,7 @@
|
||||
}
|
||||
|
||||
if (formID) {
|
||||
if (!$targetStep.find('form').size()) {
|
||||
if (!$targetStep.find('form').length) {
|
||||
makeForm(args, formID, formState).appendTo($targetStep.find('.content.input-area .select-container'));
|
||||
|
||||
setTimeout(function() {
|
||||
@ -1185,7 +1185,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ($uiCustom.size()) {
|
||||
if ($uiCustom.length) {
|
||||
$uiCustom.each(function() {
|
||||
var $item = $(this);
|
||||
var id = $item.attr('ui-custom');
|
||||
@ -1210,7 +1210,7 @@
|
||||
$nextButton.removeClass('final post-launch');
|
||||
|
||||
// Show launch button if last step
|
||||
if ($targetStep.index() == $steps.size() - 1 || options.nextStep) {
|
||||
if ($targetStep.index() == $steps.length - 1 || options.nextStep) {
|
||||
$nextButton.find('span').html(options.nextStep ? _l('label.save.changes') : _l('label.launch.zone'));
|
||||
$nextButton.addClass('final');
|
||||
|
||||
@ -1225,7 +1225,7 @@
|
||||
}).toggleClass('active');
|
||||
|
||||
setTimeout(function() {
|
||||
if (!$targetStep.find('input[type=radio]:checked').size()) {
|
||||
if (!$targetStep.find('input[type=radio]:checked').length) {
|
||||
$targetStep.find('input[type=radio]:first').click();
|
||||
}
|
||||
}, 50);
|
||||
@ -1329,25 +1329,25 @@
|
||||
}
|
||||
|
||||
// Next button
|
||||
if ($target.closest('div.button.next').size()) {
|
||||
if ($target.closest('div.button.next').length) {
|
||||
var $step = $steps.filter(':visible');
|
||||
// Validation
|
||||
var $form = $('form:visible').filter(function() {
|
||||
// Don't include multi-edit (validation happens separately)
|
||||
return !$(this).closest('.multi-edit').size();
|
||||
return !$(this).closest('.multi-edit').length;
|
||||
});
|
||||
|
||||
// Handle validation for custom UI components
|
||||
var isCustomValidated = checkCustomValidation($step);
|
||||
if (($form.size() && !$form.valid()) || !isCustomValidated) {
|
||||
if (($form && $form.find('.error:visible').size()) || !isCustomValidated)
|
||||
if (($form.length && !$form.valid()) || !isCustomValidated) {
|
||||
if (($form && $form.find('.error:visible').length) || !isCustomValidated)
|
||||
return false;
|
||||
}
|
||||
|
||||
//when hypervisor is BareMetal (begin)
|
||||
var data = getData($wizard);
|
||||
if (('zone' in data) && (data.zone.hypervisor == 'BareMetal')) {
|
||||
if ($('.zone-wizard:visible').find('#add_zone_guest_traffic_desc:visible').size() > 0) { //$steps.filter(':visible').index() == 6
|
||||
if ($('.zone-wizard:visible').find('#add_zone_guest_traffic_desc:visible').length > 0) { //$steps.filter(':visible').index() == 6
|
||||
showStep('launch');
|
||||
completeAction();
|
||||
return false;
|
||||
@ -1355,10 +1355,10 @@
|
||||
}
|
||||
//when hypervisor is BareMetal (end)
|
||||
|
||||
if (!$target.closest('.button.next.final').size())
|
||||
if (!$target.closest('.button.next.final').length)
|
||||
showStep($steps.filter(':visible').index() + 2);
|
||||
else {
|
||||
if ($target.closest('.button.next.final.post-launch').size()) {
|
||||
if ($target.closest('.button.next.final.post-launch').length) {
|
||||
showStep('launch');
|
||||
}
|
||||
|
||||
@ -1369,21 +1369,21 @@
|
||||
}
|
||||
|
||||
// Previous button
|
||||
if ($target.closest('div.button.previous').size()) {
|
||||
if ($target.closest('div.button.previous').length) {
|
||||
showStep($steps.filter(':visible').index(), true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Close button
|
||||
if ($target.closest('div.button.cancel').size()) {
|
||||
if ($target.closest('div.button.cancel').length) {
|
||||
close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Edit link
|
||||
if ($target.closest('div.edit').size()) {
|
||||
if ($target.closest('div.edit').length) {
|
||||
var $edit = $target.closest('div.edit');
|
||||
|
||||
showStep($edit.find('a').attr('href'));
|
||||
@ -1395,7 +1395,7 @@
|
||||
var $editTrafficTypeButton = $target.closest('.drop-container .traffic-type-draggable .edit-traffic-type');
|
||||
var $trafficType = $editTrafficTypeButton.closest('.traffic-type-draggable');
|
||||
|
||||
if ($editTrafficTypeButton.size()) {
|
||||
if ($editTrafficTypeButton.length) {
|
||||
physicalNetwork.editTrafficTypeDialog($trafficType);
|
||||
|
||||
return false;
|
||||
|
||||
@ -181,7 +181,7 @@
|
||||
}).join(',')
|
||||
);
|
||||
|
||||
if ($target.closest('.select.project-view').size()) {
|
||||
if ($target.closest('.select.project-view').length) {
|
||||
$('#cloudStack3-container').addClass('project-view');
|
||||
$projectSwitcher.addClass('alt');
|
||||
$projectSwitcher.find('.select.project-view').addClass('active')
|
||||
@ -404,9 +404,9 @@
|
||||
function checkHoveredLabel($target) {
|
||||
var $multiWizard = $('div.ui-dialog div.multi-wizard');
|
||||
if (($target.is('label[for]') && !$target.parents('body.login')) ||
|
||||
($multiWizard.size() &&
|
||||
($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) ||
|
||||
($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size())
|
||||
($multiWizard.length &&
|
||||
($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').length) ||
|
||||
($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').length)
|
||||
))
|
||||
return true;
|
||||
|
||||
@ -419,7 +419,7 @@
|
||||
if (checkHoveredLabel($target)) {
|
||||
$target.addClass('label-hovered');
|
||||
}
|
||||
if ($target.closest('#user, #user-options').size()) {
|
||||
if ($target.closest('#user, #user-options').length) {
|
||||
return false;
|
||||
} else $('#user-options').hide();
|
||||
|
||||
@ -441,19 +441,19 @@
|
||||
var $multiWizard = $('div.ui-dialog div.multi-wizard');
|
||||
|
||||
// Wizard: trigger click event for input when click it label
|
||||
if ($multiWizard.size()) {
|
||||
if ($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) {
|
||||
if ($multiWizard.length) {
|
||||
if ($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').length) {
|
||||
$target.prev('input').trigger('click');
|
||||
}
|
||||
if ($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size()) {
|
||||
if ($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').length) {
|
||||
$target.parent('div.select-desc').prev('input').trigger('click');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$container.size()) return true;
|
||||
if (!$container.length) return true;
|
||||
|
||||
// Navigation items
|
||||
if ($target.closest('li.navigation-item').size() && $target.closest('#navigation').size()) {
|
||||
if ($target.closest('li.navigation-item').length && $target.closest('#navigation').length) {
|
||||
var $navItem = $target.closest('li.navigation-item');
|
||||
|
||||
if ($navItem.is('.disabled')) return false;
|
||||
@ -463,7 +463,7 @@
|
||||
}
|
||||
|
||||
// Browser expand
|
||||
if ($target.hasClass('control expand') && $target.closest('div.panel div.toolbar').size()) {
|
||||
if ($target.hasClass('control expand') && $target.closest('div.panel div.toolbar').length) {
|
||||
$browser.cloudBrowser('toggleMaximizePanel', {
|
||||
panel: $target.closest('div.panel')
|
||||
});
|
||||
@ -478,7 +478,7 @@
|
||||
}
|
||||
|
||||
// User options
|
||||
if ($target.closest('#user div.icon.options').size()) {
|
||||
if ($target.closest('#user div.icon.options').length) {
|
||||
$('#user-options').toggle();
|
||||
|
||||
return false;
|
||||
|
||||
@ -382,7 +382,7 @@
|
||||
|
||||
// Make sure all data is loaded to pass to select fn
|
||||
dependsOnLoaded = $.inArray(
|
||||
true, $dependsOn.map(function(index, item) { return $(item).find('option').size() ? true : false; })
|
||||
true, $dependsOn.map(function(index, item) { return $(item).find('option').length ? true : false; })
|
||||
) > -1;
|
||||
|
||||
if (!dependsOnLoaded) {
|
||||
@ -776,7 +776,7 @@
|
||||
|
||||
if (!$formContainer.find('form').valid()) {
|
||||
// Ignore hidden field validation
|
||||
if ($formContainer.find('input.error:visible, select.error:visible').size()) {
|
||||
if ($formContainer.find('input.error:visible, select.error:visible').length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -970,7 +970,7 @@
|
||||
click: function() {
|
||||
if (!$listView.find(
|
||||
'input[type=radio]:checked, input[type=checkbox]:checked'
|
||||
).size()) {
|
||||
).length) {
|
||||
cloudStack.dialog.notice({
|
||||
message: _l('message.select.instance')
|
||||
});
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
var data, elem;
|
||||
|
||||
$elem = $target.closest('.cloudStack-elem.' + widget);
|
||||
if (!$elem.size())
|
||||
if (!$elem.length)
|
||||
return true;
|
||||
|
||||
$widget = $('.cloudStack-widget.' + widget);
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
*/
|
||||
width: function($container, options) {
|
||||
options = options ? options : {};
|
||||
var width = $container.find('div.panel').size() < 1 || !options.partial ?
|
||||
var width = $container.find('div.panel').length < 1 || !options.partial ?
|
||||
$container.width() : $container.width() - $container.width() / 4;
|
||||
|
||||
return width;
|
||||
@ -105,7 +105,7 @@
|
||||
* Get left position
|
||||
*/
|
||||
position: function($container, options) {
|
||||
return $container.find('div.panel').size() <= 1 || !options.partial ?
|
||||
return $container.find('div.panel').length <= 1 || !options.partial ?
|
||||
0 : _panel.width($container, options) - _panel.width($container, options) / 1.5;
|
||||
},
|
||||
|
||||
@ -340,7 +340,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
$('#breadcrumbs li').live('click', cloudStack.ui.event.bind(
|
||||
$(document).on('click', '#breadcrumbs li', cloudStack.ui.event.bind(
|
||||
'cloudBrowser', {
|
||||
'breadcrumb': function($target, $browser, data) {
|
||||
|
||||
|
||||
@ -228,9 +228,9 @@
|
||||
$tbody.width($thead.width());
|
||||
}
|
||||
|
||||
if ($ths.size() > $tds.size()) {
|
||||
if ($ths.length > $tds.length) {
|
||||
$ths.width(
|
||||
$table.width() / $ths.size()
|
||||
$table.width() / $ths.length
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -281,7 +281,7 @@
|
||||
|
||||
var init = function() {
|
||||
var noSelect = options && options.noSelect == true ? true : false;
|
||||
if (!$table.closest('div.data-table').size() && !$table.hasClass('no-split')) {
|
||||
if (!$table.closest('div.data-table').length && !$table.hasClass('no-split')) {
|
||||
reattachTable();
|
||||
$table.find('tbody').closest('table').addClass('body');
|
||||
}
|
||||
@ -304,7 +304,7 @@
|
||||
$table.bind('click', function(event) {
|
||||
var $tr = $(event.target).closest('tr');
|
||||
|
||||
if (!$tr.size() || noSelect) return true;
|
||||
if (!$tr.length || noSelect) return true;
|
||||
var rowIndex = $tr.index();
|
||||
|
||||
toggleSelectRow(rowIndex);
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
var $listView = $row.closest('.list-view');
|
||||
|
||||
if (!$listView.parents('html').size()) return;
|
||||
if (!$listView.parents('html').length) return;
|
||||
|
||||
var $newRow;
|
||||
var jsonObj = $row.data('json-obj');
|
||||
@ -56,6 +56,15 @@
|
||||
}
|
||||
};
|
||||
|
||||
var tabEvents = {
|
||||
create: function(event, ui) {
|
||||
manageTabsContent(event, ui);
|
||||
},
|
||||
activate: function(event, ui) {
|
||||
manageTabsContent(event, ui);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Available UI actions to perform for buttons
|
||||
*/
|
||||
@ -114,7 +123,7 @@
|
||||
}
|
||||
).appendTo($detailView);
|
||||
|
||||
$detailView.tabs();
|
||||
$detailView.tabs(tabEvents);
|
||||
};
|
||||
|
||||
var performAction = function(data, options) {
|
||||
@ -172,7 +181,7 @@
|
||||
viewArgs.onActionComplete();
|
||||
}
|
||||
|
||||
if (!$detailView.parents('html').size()) {
|
||||
if (!$detailView.parents('html').length) {
|
||||
replaceListViewItem(null, args.data, {
|
||||
$row: $row
|
||||
});
|
||||
@ -222,7 +231,7 @@
|
||||
cloudStack.ui.notifications.add(
|
||||
notification,
|
||||
function(args2) { //name parameter as "args2" instead of "args" to avoid override "args" from success: function(args) {
|
||||
if ($detailView.parents('html').size()) {
|
||||
if ($detailView.parents('html').length) {
|
||||
$loading.remove();
|
||||
|
||||
if (!noRefresh && !viewArgs.compact) {
|
||||
@ -376,7 +385,7 @@
|
||||
var $tbody = $row.closest('tbody');
|
||||
|
||||
$row.remove();
|
||||
if (!$tbody.find('tr').size()) {
|
||||
if (!$tbody.find('tr').length) {
|
||||
$("<tr>").addClass('empty').append(
|
||||
$("<td>").html(_l('label.no.data'))
|
||||
).appendTo($tbody);
|
||||
@ -413,7 +422,7 @@
|
||||
var $tbody = $row.closest('tbody');
|
||||
|
||||
$row.remove();
|
||||
if (!$tbody.find('tr').size()) {
|
||||
if (!$tbody.find('tr').length) {
|
||||
$("<tr>").addClass('empty').append(
|
||||
$("<td>").html(_l('label.no.data'))
|
||||
).appendTo($tbody);
|
||||
@ -439,11 +448,11 @@
|
||||
$detailView.addClass('edit-mode');
|
||||
var token_value = "";
|
||||
|
||||
if ($detailView.find('.button.done').size()) return false;
|
||||
if ($detailView.find('.button.done').length) return false;
|
||||
|
||||
// Convert value TDs
|
||||
var $inputs = $detailView.find('input, select, textarea').filter(function() {
|
||||
return !$(this).closest('.tagger').size() && !$(this).attr('type') == 'submit';
|
||||
return !$(this).closest('.tagger').length && !$(this).attr('type') == 'submit';
|
||||
});
|
||||
var action = args.actions[args.actionName];
|
||||
var id = $detailView.data('view-args').id;
|
||||
@ -476,7 +485,7 @@
|
||||
var $token;
|
||||
var tags_value = "";
|
||||
$inputs.each(function() {
|
||||
if ($(this).closest('.tagger').size()) return true;
|
||||
if ($(this).closest('.tagger').length) return true;
|
||||
|
||||
var $input = $(this);
|
||||
var $value = $input.closest('td.value span');
|
||||
@ -525,9 +534,9 @@
|
||||
|
||||
// Remove Edit form
|
||||
var $form = $detailView.find('form').filter(function() {
|
||||
return !$(this).closest('.tagger').size();
|
||||
return !$(this).closest('.tagger').length;
|
||||
});
|
||||
if ($form.size()) {
|
||||
if ($form.length) {
|
||||
var $mainGroups = $form.find('div.main-groups').detach();
|
||||
$form.parent('div').append($mainGroups);
|
||||
$form.remove();
|
||||
@ -539,7 +548,7 @@
|
||||
// Put in original values
|
||||
var cancelEdits = function($inputs, $editButton) {
|
||||
$inputs.each(function() {
|
||||
if ($(this).closest('.tagger').size()) return true;
|
||||
if ($(this).closest('.tagger').length) return true;
|
||||
|
||||
var $input = $(this);
|
||||
var $value = $input.closest('td.value span');
|
||||
@ -561,7 +570,7 @@
|
||||
};
|
||||
|
||||
var applyEdits = function($inputs, $editButton) {
|
||||
if ($inputs.size()) {
|
||||
if ($inputs.length) {
|
||||
$inputs.animate({
|
||||
opacity: 0.5
|
||||
}, 500);
|
||||
@ -634,16 +643,16 @@
|
||||
|
||||
$editButton.click(function() {
|
||||
var $inputs = $detailView.find('input, select, textarea').filter(function() {
|
||||
return !$(this).closest('.tagger').size();
|
||||
return !$(this).closest('.tagger').length;
|
||||
});
|
||||
var $form = $detailView.find('form').filter(function() {
|
||||
return !$(this).closest('.tagger').size();
|
||||
return !$(this).closest('.tagger').length;
|
||||
});
|
||||
|
||||
if ($(this).hasClass('done')) {
|
||||
if (!$form.valid()) {
|
||||
// Ignore hidden field validation
|
||||
if ($form.find('input.error:visible, select.error:visible').size()) {
|
||||
if ($form.find('input.error:visible, select.error:visible').length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -796,7 +805,7 @@
|
||||
return true;
|
||||
});
|
||||
|
||||
if ($detailView.find('td.value span:data(detail-view-is-editable)').size()) {
|
||||
if ($detailView.find('td.value span:data(detail-view-is-editable)').length) {
|
||||
var $detailsEdit = $detailView.find('div.main-groups').detach(),
|
||||
$detailsEditForm = $('<form>').append($detailsEdit);
|
||||
|
||||
@ -805,7 +814,7 @@
|
||||
|
||||
// Setup form validation
|
||||
var $form = $detailView.find('form').filter(function() {
|
||||
return !$(this).closest('.tagger').size();
|
||||
return !$(this).closest('.tagger').length;
|
||||
});
|
||||
$form.validate();
|
||||
$form.find('input, select').each(function() {
|
||||
@ -976,7 +985,7 @@
|
||||
});
|
||||
|
||||
var $actionButtons = $actions.find('div.action:not(.text)');
|
||||
if ($actionButtons.size() == 1)
|
||||
if ($actionButtons.length == 1)
|
||||
$actionButtons.addClass('single');
|
||||
else {
|
||||
$actionButtons.filter(':first').addClass('first');
|
||||
@ -1180,7 +1189,7 @@
|
||||
context: context
|
||||
}) : true
|
||||
) : true;
|
||||
if ($actions && ($actions.find('div.action').size() || (detailViewArgs.viewAll && showViewAll))) {
|
||||
if ($actions && ($actions.find('div.action').length || (detailViewArgs.viewAll && showViewAll))) {
|
||||
$actions.prependTo($firstRow.closest('div.detail-group').closest('.details'));
|
||||
}
|
||||
if (detailViewArgs.viewAll && showViewAll) {
|
||||
@ -1559,12 +1568,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
$detailView.tabs({
|
||||
select: function() {
|
||||
$detailView.tabs(
|
||||
$.extend(true, {}, tabEvents, {
|
||||
select: function() {
|
||||
// Cleanup old tab content
|
||||
$detailView.find('.detail-group').children().remove();
|
||||
}
|
||||
});
|
||||
}}
|
||||
)
|
||||
);
|
||||
|
||||
return $detailView;
|
||||
};
|
||||
@ -1588,16 +1599,13 @@
|
||||
return true;
|
||||
};
|
||||
|
||||
$(document).bind('tabscreate',manageTabsContent);
|
||||
$(document).bind('tabsactivate',manageTabsContent);
|
||||
|
||||
// View all links
|
||||
$('a').live('click', function(event) {
|
||||
$(document).on('click', 'a', function(event) {
|
||||
var $target = $(event.target);
|
||||
var $viewAll = $target.closest('td.view-all a');
|
||||
var viewAllArgs;
|
||||
|
||||
if ($target.closest('div.detail-view').size() && $target.closest('td.view-all a').size()) {
|
||||
if ($target.closest('div.detail-view').length && $target.closest('td.view-all a').length) {
|
||||
viewAllArgs = $viewAll.data('detail-view-link-view-all');
|
||||
viewAll(
|
||||
viewAllArgs.custom ?
|
||||
@ -1625,7 +1633,7 @@
|
||||
var $target = $(event.target);
|
||||
|
||||
// Refresh
|
||||
if ($target.closest('div.toolbar div.refresh').size()) {
|
||||
if ($target.closest('div.toolbar div.refresh').length) {
|
||||
loadTabContent(
|
||||
$target.closest('div.detail-view').find('div.detail-group:visible'),
|
||||
$target.closest('div.detail-view').data('view-args'),
|
||||
@ -1636,8 +1644,8 @@
|
||||
}
|
||||
|
||||
// Detail action
|
||||
if ($target.closest('div.detail-view [detail-action], div.detail-view .action.text').size() &&
|
||||
!$target.closest('.list-view').size()) {
|
||||
if ($target.closest('div.detail-view [detail-action], div.detail-view .action.text').length &&
|
||||
!$target.closest('.list-view').length) {
|
||||
var $action = $target.closest('.action').find('[detail-action]');
|
||||
var actionName = $action.attr('detail-action');
|
||||
var actionCallback = $action.data('detail-view-action-callback');
|
||||
|
||||
@ -294,7 +294,7 @@
|
||||
}
|
||||
|
||||
if (needsRefresh) {
|
||||
if ($listView.closest('.detail-view').size()) {
|
||||
if ($listView.closest('.detail-view').length) {
|
||||
$('.detail-view:last .button.refresh').click();
|
||||
} else {
|
||||
$loading.remove();
|
||||
@ -375,7 +375,7 @@
|
||||
}
|
||||
|
||||
if (needsRefresh) {
|
||||
if (!$listView.closest('.detail-view').size()) {
|
||||
if (!$listView.closest('.detail-view').length) {
|
||||
$loading.remove();
|
||||
}
|
||||
}
|
||||
@ -1148,7 +1148,7 @@
|
||||
|
||||
if (!(data && data.length)) {
|
||||
$listView.data('end-of-table', true);
|
||||
if (!$tbody.find('tr').size()) {
|
||||
if (!$tbody.find('tr').length) {
|
||||
return [
|
||||
$('<tr>').addClass('empty last').append(
|
||||
$('<td>').html(_l('label.no.data'))
|
||||
@ -1186,8 +1186,8 @@
|
||||
.addClass('multiSelectCheckbox')
|
||||
.click(function() {
|
||||
var checked = $(this).is(':checked');
|
||||
var numRows = $(this).parents('tbody').find('input.multiSelectCheckbox').size();
|
||||
var numRowsChecked = $(this).parents('tbody').find('input.multiSelectCheckbox:checked').size();
|
||||
var numRows = $(this).parents('tbody').find('input.multiSelectCheckbox').length;
|
||||
var numRowsChecked = $(this).parents('tbody').find('input.multiSelectCheckbox:checked').length;
|
||||
var enabled = checked || (numRowsChecked > 0);
|
||||
|
||||
toggleMultiSelectActions($td.closest('.list-view'), enabled);
|
||||
@ -1326,7 +1326,7 @@
|
||||
true, {},
|
||||
$tr.closest('.list-view').data('view-args').context
|
||||
);
|
||||
var rowIndex = $tr.closest('tbody').find('tr').size() - ($tr.index());
|
||||
var rowIndex = $tr.closest('tbody').find('tr').length - ($tr.index());
|
||||
|
||||
context[viewArgs.activeSection] = $tr.data('json-obj');
|
||||
|
||||
@ -1630,11 +1630,11 @@
|
||||
position: 'absolute',
|
||||
left: $quickView.offset().left + $quickView.outerWidth() - $quickViewTooltip.width() - 2*(parseInt($quickView.css('border-left-width')) + parseInt($quickView.css('border-right-width'))),
|
||||
top: $quickView.offset().top,
|
||||
zIndex: $tr.closest('.panel').zIndex() + 1
|
||||
zIndex: $tr.closest('.panel').css("zIndex") + 1
|
||||
});
|
||||
|
||||
$quickViewTooltip.mouseleave(function() {
|
||||
if (!$('.overlay:visible').size()) {
|
||||
if (!$('.overlay:visible').length) {
|
||||
$quickViewTooltip.remove();
|
||||
}
|
||||
});
|
||||
@ -1662,7 +1662,7 @@
|
||||
$('<td>')
|
||||
.addClass('loading icon')
|
||||
.attr({
|
||||
'colspan': $table.find('th').size()
|
||||
'colspan': $table.find('th').length
|
||||
})
|
||||
);
|
||||
|
||||
@ -1830,7 +1830,7 @@
|
||||
|
||||
// Clear out any existing list view
|
||||
var $existingListView = $container.find('div.list-view');
|
||||
if ($existingListView.size()) {
|
||||
if ($existingListView.length) {
|
||||
$existingListView.remove();
|
||||
}
|
||||
|
||||
@ -1884,7 +1884,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ($switcher && $switcher.find('option').size() == 1) {
|
||||
if ($switcher && $switcher.find('option').length == 1) {
|
||||
listViewData = args.sections[
|
||||
$switcher.find('select').val()
|
||||
].listView;
|
||||
@ -2018,7 +2018,7 @@
|
||||
var code = (event.keyCode ? event.keyCode : event.which);
|
||||
var $input = $listView.find('input:focus');
|
||||
|
||||
if ($input.size() && $input.hasClass('edit') && code === 13) {
|
||||
if ($input.length && $input.hasClass('edit') && code === 13) {
|
||||
uiActions.edit($input.closest('tr'), {
|
||||
callback: listViewData.actions.edit.action
|
||||
});
|
||||
@ -2078,7 +2078,7 @@
|
||||
return true;
|
||||
});
|
||||
$listView.find('select').bind('change', function(event) {
|
||||
if ($(event.target).closest('.section-select').size()) return true;
|
||||
if ($(event.target).closest('.section-select').length) return true;
|
||||
if ((event.type == 'click' ||
|
||||
event.type == 'mouseup') &&
|
||||
($(event.target).is('select') ||
|
||||
@ -2124,7 +2124,7 @@
|
||||
};
|
||||
|
||||
$listView.find('.advanced-search .icon').bind('click', function(event) {
|
||||
if ($listView.find('.advanced-search .form-container:visible').size()) {
|
||||
if ($listView.find('.advanced-search .form-container:visible').length) {
|
||||
closeAdvancedSearch();
|
||||
|
||||
return false;
|
||||
@ -2181,7 +2181,7 @@
|
||||
listView = args.sections[args.activeSection].listView;
|
||||
}
|
||||
if (listView && listView.disableInfiniteScrolling) return false;
|
||||
if ($listView.find('tr.last, td.loading:visible').size()) return false;
|
||||
if ($listView.find('tr.last, td.loading:visible').length) return false;
|
||||
|
||||
clearTimeout(infScrollTimer);
|
||||
infScrollTimer = setTimeout(function() {
|
||||
@ -2246,12 +2246,12 @@
|
||||
var id = $target.closest('tr').data('list-view-item-id');
|
||||
var jsonObj = $target.closest('tr').data('jsonObj');
|
||||
var detailViewArgs;
|
||||
var detailViewPresent = ($target.closest('div.data-table tr td.first').size() &&
|
||||
listViewData.detailView && !$target.closest('div.edit').size()) && !listViewData.detailView.noPanelView;
|
||||
var detailViewPresent = ($target.closest('div.data-table tr td.first').length &&
|
||||
listViewData.detailView && !$target.closest('div.edit').length) && !listViewData.detailView.noPanelView;
|
||||
var uiCustom = args.uiCustom == true ? true : false;
|
||||
|
||||
// Click on first item will trigger detail view (if present)
|
||||
if (detailViewPresent && !uiCustom && !$target.closest('.empty, .loading').size()) {
|
||||
if (detailViewPresent && !uiCustom && !$target.closest('.empty, .loading').length) {
|
||||
var $loading = $('<div>').addClass('loading-overlay');
|
||||
$target.closest('div.data-table').prepend($loading); //overlay the whole listView, so users can't click another row until click-handling for this row is done (e.g. API response is back)
|
||||
|
||||
@ -2317,9 +2317,9 @@
|
||||
|
||||
// Action icons
|
||||
if (!$target.closest('td.actions').hasClass('reorder') &&
|
||||
($target.closest('td.actions').size() ||
|
||||
$target.closest('.action.add').size() ||
|
||||
$target.closest('.action.main-action').size())) {
|
||||
($target.closest('td.actions').length ||
|
||||
$target.closest('.action.add').length ||
|
||||
$target.closest('.action.main-action').length)) {
|
||||
var actionID = $target.closest('.action').data('list-view-action-id');
|
||||
var $tr;
|
||||
|
||||
@ -2327,8 +2327,8 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($target.closest('.action.add').size() ||
|
||||
$target.closest('.action.main-action:not(.multiSelectAction)').size()) {
|
||||
if ($target.closest('.action.add').length ||
|
||||
$target.closest('.action.main-action:not(.multiSelectAction)').length) {
|
||||
$tr = $target.closest('div.list-view').find('tr:first'); // Dummy row
|
||||
} else {
|
||||
if (listViewData.actions[actionID].isMultiSelectAction) {
|
||||
@ -2360,7 +2360,7 @@
|
||||
}
|
||||
|
||||
// Section switcher
|
||||
if ($target.is('a') && $target.closest('div.section-switcher').size()) {
|
||||
if ($target.is('a') && $target.closest('div.section-switcher').length) {
|
||||
makeListView($container, args, $target.data('list-view-section-id'));
|
||||
|
||||
return false;
|
||||
@ -2460,7 +2460,7 @@
|
||||
|
||||
if (preFilter) {
|
||||
$selectedVMs = $listView.find('tbody tr').filter(function() {
|
||||
return $(this).find('td.multiselect input[type=checkbox]:checked').size()
|
||||
return $(this).find('td.multiselect input[type=checkbox]:checked').length
|
||||
});
|
||||
context[$listView.data('view-args').activeSection] = $selectedVMs.map(function(index, item) {
|
||||
return $(item).data('json-obj');
|
||||
|
||||
@ -229,7 +229,7 @@
|
||||
$td.append($select);
|
||||
}
|
||||
else {
|
||||
var matchingValue = $matchingOption.size() ?
|
||||
var matchingValue = $matchingOption.length ?
|
||||
$matchingOption.html() : data[fieldName];
|
||||
|
||||
$td.append($('<span>').html(_s(matchingValue)));
|
||||
@ -243,7 +243,7 @@
|
||||
|
||||
var $subItems = $td.closest('.data-item').find('.expandable-listing tr');
|
||||
|
||||
if ($subItems.size()) {
|
||||
if ($subItems.length) {
|
||||
context.subItemData = $subItems.map(function() {
|
||||
return $(this).data('json-obj');
|
||||
});
|
||||
@ -598,7 +598,7 @@
|
||||
text: _l('label.apply'),
|
||||
'class': 'ok',
|
||||
click: function() {
|
||||
if (!$listView.find('input[type=radio]:checked, input[type=checkbox]:checked').size()) {
|
||||
if (!$listView.find('input[type=radio]:checked, input[type=checkbox]:checked').length) {
|
||||
cloudStack.dialog.notice({
|
||||
message: _l('message.select.item')
|
||||
});
|
||||
@ -660,7 +660,7 @@
|
||||
);
|
||||
|
||||
$multi.find('.data tr').filter(function() {
|
||||
return !$(this).closest('.expandable-listing').size();
|
||||
return !$(this).closest('.expandable-listing').length;
|
||||
}).each(function() {
|
||||
var $tr = $(this);
|
||||
|
||||
@ -929,8 +929,8 @@
|
||||
$loading.prependTo($multi);
|
||||
reorder.moveDrag.action({
|
||||
targetIndex: ui.item.index(),
|
||||
nextItem: ui.item.next().size() ? ui.item.next().data('json-obj') : null,
|
||||
prevItem: ui.item.prev().size() ? ui.item.prev().data('json-obj') : null,
|
||||
nextItem: ui.item.next().length ? ui.item.next().data('json-obj') : null,
|
||||
prevItem: ui.item.prev().length ? ui.item.prev().data('json-obj') : null,
|
||||
context: $.extend(true, {}, context, {
|
||||
// Passes all rules, so that each index can be updated
|
||||
multiRule: [ui.item.data('json-obj')]
|
||||
@ -1121,7 +1121,7 @@
|
||||
$addVM.bind('click', function() {
|
||||
// Validate form first
|
||||
if (!$multiForm.valid()) {
|
||||
if ($multiForm.find('input.error:visible').size()) {
|
||||
if ($multiForm.find('input.error:visible').length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,8 +145,8 @@
|
||||
resetTotal: function($popup) {
|
||||
var $total = $popup.data('notifications-attach-to').find('div.total span');
|
||||
var $items = $popup.find('ul li');
|
||||
var total = $items.size();
|
||||
var completed = $items.filter(':not(.pending)').size();
|
||||
var total = $items.length;
|
||||
var completed = $items.filter(':not(.pending)').length;
|
||||
var newTotal = total - completed;
|
||||
|
||||
if (newTotal < 0) newTotal = completed;
|
||||
@ -331,7 +331,7 @@
|
||||
var $attachTo, $popup;
|
||||
|
||||
// Notifications header area
|
||||
if ($target.closest('.notifications').size()) {
|
||||
if ($target.closest('.notifications').length) {
|
||||
$attachTo = $target.closest('.notifications');
|
||||
$popup = $attachTo.data('notifications-popup');
|
||||
notifications.popup.show($popup, $attachTo);
|
||||
@ -352,11 +352,11 @@
|
||||
}
|
||||
|
||||
// Popup
|
||||
if ($target.closest('div.notification-box').size()) {
|
||||
if ($target.closest('div.notification-box').length) {
|
||||
$popup = $target.closest('div.notification-box');
|
||||
|
||||
// Clear list
|
||||
if ($target.closest('.button.clear-list').size()) {
|
||||
if ($target.closest('.button.clear-list').length) {
|
||||
notifications.clear($popup);
|
||||
}
|
||||
|
||||
@ -379,7 +379,7 @@
|
||||
$(window).resize(function(event) {
|
||||
var $popup = $('div.notification-box:visible');
|
||||
|
||||
if ($popup.size())
|
||||
if ($popup.length)
|
||||
notifications.popup.reposition($popup, $popup.data('notifications-attach-to'));
|
||||
});
|
||||
})(window.jQuery, window.cloudStack, window._l);
|
||||
|
||||
@ -165,7 +165,7 @@
|
||||
|
||||
// Fix overlay
|
||||
setTimeout(function() {
|
||||
$('.tooltip-box').zIndex($(':ui-dialog').zIndex() + 10);
|
||||
$('.tooltip-box').css( "zIndex", $(':ui-dialog').css("zIndex") + 10);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
var $li = $target.closest('li');
|
||||
|
||||
if ($target.is('li div.expand') && $li.data('tree-view-item-obj')) {
|
||||
if ($li.find('ul').size()) {
|
||||
if ($li.find('ul').length) {
|
||||
$li.find('ul').remove();
|
||||
$li.removeClass('expanded');
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
$treeView.find('li .name').removeClass('selected');
|
||||
$target.addClass('selected');
|
||||
|
||||
if ($browser && $browser.size()) {
|
||||
if ($browser && $browser.length) {
|
||||
$browser.cloudBrowser('addPanel', {
|
||||
partial: true,
|
||||
title: $target.html(),
|
||||
|
||||
@ -1430,7 +1430,7 @@
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
if(jQuery('#details-tab-aclRules').siblings('div.toolbar').children('div.add').size() === 0){
|
||||
if(jQuery('#details-tab-aclRules').siblings('div.toolbar').children('div.add').length === 0){
|
||||
var $addAclRuleDivButton = jQuery('<div>').addClass('button add');
|
||||
var $spanAddAclRuleButtonMessage = jQuery('<span>').html(_l('label.add.ACL'));
|
||||
|
||||
@ -1474,7 +1474,7 @@
|
||||
});
|
||||
jQuery('#details-tab-aclRules').siblings('div.toolbar').append($addAclRuleDivButton);
|
||||
}
|
||||
if(jQuery('#details-tab-aclRules').siblings('div.toolbar').children('div.export').size() === 0){
|
||||
if(jQuery('#details-tab-aclRules').siblings('div.toolbar').children('div.export').length === 0){
|
||||
var $exportAclsDivButton = jQuery('<div>').addClass('button export');
|
||||
var $linkExportAclRulesButtonMessage = jQuery('<a>').html(_l('label.acl.export'));
|
||||
|
||||
|
||||
@ -43,11 +43,11 @@
|
||||
var $toolbar = $listView.find('> .toolbar');
|
||||
var $table = $listView.find('> .data-table');
|
||||
|
||||
equal($listView.size(), 1, 'List view present');
|
||||
equal($toolbar.size(), 1, 'Toolbar present');
|
||||
equal($table.size(), 1, 'Data table div present');
|
||||
equal($table.find('> .fixed-header table thead tr').size(), 1, 'Fixed header present');
|
||||
equal($table.find('> table.body tbody').size(), 1, 'Body table present');
|
||||
equal($listView.length, 1, 'List view present');
|
||||
equal($toolbar.length, 1, 'Toolbar present');
|
||||
equal($table.length, 1, 'Data table div present');
|
||||
equal($table.find('> .fixed-header table thead tr').length, 1, 'Fixed header present');
|
||||
equal($table.find('> table.body tbody').length, 1, 'Body table present');
|
||||
});
|
||||
|
||||
test('Fields: basic', function() {
|
||||
@ -60,7 +60,7 @@
|
||||
});
|
||||
var $fields = $listView.find('.fixed-header table thead tr th');
|
||||
|
||||
equal($fields.size(), 1, 'Column present');
|
||||
equal($fields.length, 1, 'Column present');
|
||||
ok($fields.hasClass('fieldA'), 'Has ID as classname');
|
||||
equal($fields.html(), 'TestFieldA', 'Has correct label');
|
||||
});
|
||||
@ -82,7 +82,7 @@
|
||||
$.each(testFields, function(k, v) {
|
||||
var $field = $fields.filter('.' + k);
|
||||
|
||||
equal($field.size(), 1, k + '-> Column present');
|
||||
equal($field.length, 1, k + '-> Column present');
|
||||
equal($field.html(), v.label, k + '-> Has correct label');
|
||||
});
|
||||
});
|
||||
@ -90,8 +90,8 @@
|
||||
test('Data loading state', function() {
|
||||
var $listView = listView();
|
||||
|
||||
equal($listView.find('table.body tr.loading').size(), 1, 'Row has loading state');
|
||||
equal($listView.find('table.body tr.loading td.loading.icon').size(), 1, 'Row cell has loading icon');
|
||||
equal($listView.find('table.body tr.loading').length, 1, 'Row has loading state');
|
||||
equal($listView.find('table.body tr.loading td.loading.icon').length, 1, 'Row cell has loading icon');
|
||||
});
|
||||
|
||||
asyncTest('Data provider: basic', function() {
|
||||
@ -111,7 +111,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
equal($listView.find('.data-table table.body tbody tr.empty td').size(), 1, 'Body table has empty table row');
|
||||
equal($listView.find('.data-table table.body tbody tr.empty td').length, 1, 'Body table has empty table row');
|
||||
equal($listView.find('.data-table table.body tbody tr.empty td').html(), 'label.no.data', 'Empty contents notice displayed');
|
||||
});
|
||||
|
||||
@ -134,8 +134,8 @@
|
||||
}
|
||||
});
|
||||
|
||||
equal($listView.find('table.body tbody tr').size(), 1, 'Body table has table row');
|
||||
equal($listView.find('table.body tbody tr td').size(), 2, 'Body table has table cells');
|
||||
equal($listView.find('table.body tbody tr').length, 1, 'Body table has table row');
|
||||
equal($listView.find('table.body tbody tr td').length, 2, 'Body table has table cells');
|
||||
equal($listView.find('table.body tbody tr td.fieldA > span').html(), 'FieldDataA', 'FieldDataA content present');
|
||||
equal($listView.find('table.body tbody tr td.fieldB > span').html(), 'FieldDataB', 'FieldDataB content present');
|
||||
});
|
||||
@ -163,7 +163,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
equal($listView.find('table.body tbody tr').size(), 3, 'Body table has correct # of table rows');
|
||||
equal($listView.find('table.body tbody tr').length, 3, 'Body table has correct # of table rows');
|
||||
|
||||
$(testData).map(function(index, data) {
|
||||
var $tr = $listView.find('table.body tbody tr').filter(function() {
|
||||
@ -198,9 +198,9 @@
|
||||
}
|
||||
});
|
||||
|
||||
equal($listView.find('table tr th').size(), 2, 'Correct number of header columns present');
|
||||
equal($listView.find('table.body tbody tr td').size(), 2, 'Correct number of data body columns present');
|
||||
ok(!$listView.find('table.body tbody td.fieldHidden').size(), 'Hidden field not present');
|
||||
equal($listView.find('table tr th').length, 2, 'Correct number of header columns present');
|
||||
equal($listView.find('table.body tbody tr td').length, 2, 'Correct number of data body columns present');
|
||||
ok(!$listView.find('table.body tbody td.fieldHidden').length, 'Hidden field not present');
|
||||
});
|
||||
|
||||
test('Filter dropdown', function() {
|
||||
@ -229,7 +229,7 @@
|
||||
var $filters = $listView.find('.filters select');
|
||||
|
||||
var testFilterDropdownContent = function() {
|
||||
equal($filters.find('option').size(), 2, 'Correct # of filters present');
|
||||
equal($filters.find('option').length, 2, 'Correct # of filters present');
|
||||
equal($filters.find('option:first').html(), 'FilterOnLabel', 'Filter on label present');
|
||||
equal($filters.find('option:last').html(), 'FilterOffLabel', 'Filter off label present');
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user