You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by tr...@apache.org on 2014/12/18 19:45:02 UTC
[06/82] [abbrv] incubator-flink git commit: Moved WebInfoServer and
WebInterfaceServer resources into resource folders of respective projects.
Jetty uses the jar as base directory.
http://git-wip-us.apache.org/repos/asf/incubator-flink/blob/76d603c0/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.pie.js
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.pie.js b/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.pie.js
new file mode 100755
index 0000000..70941dd
--- /dev/null
+++ b/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.pie.js
@@ -0,0 +1,750 @@
+/*
+Flot plugin for rendering pie charts. The plugin assumes the data is
+coming is as a single data value for each series, and each of those
+values is a positive value or zero (negative numbers don't make
+any sense and will cause strange effects). The data values do
+NOT need to be passed in as percentage values because it
+internally calculates the total and percentages.
+
+* Created by Brian Medendorp, June 2009
+* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars
+
+* Changes:
+ 2009-10-22: lineJoin set to round
+ 2009-10-23: IE full circle fix, donut
+ 2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera
+ 2009-11-17: Added IE hover capability submitted by Anthony Aragues
+ 2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well)
+
+
+Available options are:
+series: {
+ pie: {
+ show: true/false
+ radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
+ innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
+ startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
+ tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
+ offset: {
+ top: integer value to move the pie up or down
+ left: integer value to move the pie left or right, or 'auto'
+ },
+ stroke: {
+ color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
+ width: integer pixel width of the stroke
+ },
+ label: {
+ show: true/false, or 'auto'
+ formatter: a user-defined function that modifies the text/style of the label text
+ radius: 0-1 for percentage of fullsize, or a specified pixel length
+ background: {
+ color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
+ opacity: 0-1
+ },
+ threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
+ },
+ combine: {
+ threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
+ color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
+ label: any text value of what the combined slice should be labeled
+ }
+ highlight: {
+ opacity: 0-1
+ }
+ }
+}
+
+More detail and specific examples can be found in the included HTML file.
+
+*/
+
+(function ($)
+{
+ function init(plot) // this is the "body" of the plugin
+ {
+ var canvas = null;
+ var target = null;
+ var maxRadius = null;
+ var centerLeft = null;
+ var centerTop = null;
+ var total = 0;
+ var redraw = true;
+ var redrawAttempts = 10;
+ var shrink = 0.95;
+ var legendWidth = 0;
+ var processed = false;
+ var raw = false;
+
+ // interactive variables
+ var highlights = [];
+
+ // add hook to determine if pie plugin in enabled, and then perform necessary operations
+ plot.hooks.processOptions.push(checkPieEnabled);
+ plot.hooks.bindEvents.push(bindEvents);
+
+ // check to see if the pie plugin is enabled
+ function checkPieEnabled(plot, options)
+ {
+ if (options.series.pie.show)
+ {
+ //disable grid
+ options.grid.show = false;
+
+ // set labels.show
+ if (options.series.pie.label.show=='auto')
+ if (options.legend.show)
+ options.series.pie.label.show = false;
+ else
+ options.series.pie.label.show = true;
+
+ // set radius
+ if (options.series.pie.radius=='auto')
+ if (options.series.pie.label.show)
+ options.series.pie.radius = 3/4;
+ else
+ options.series.pie.radius = 1;
+
+ // ensure sane tilt
+ if (options.series.pie.tilt>1)
+ options.series.pie.tilt=1;
+ if (options.series.pie.tilt<0)
+ options.series.pie.tilt=0;
+
+ // add processData hook to do transformations on the data
+ plot.hooks.processDatapoints.push(processDatapoints);
+ plot.hooks.drawOverlay.push(drawOverlay);
+
+ // add draw hook
+ plot.hooks.draw.push(draw);
+ }
+ }
+
+ // bind hoverable events
+ function bindEvents(plot, eventHolder)
+ {
+ var options = plot.getOptions();
+
+ if (options.series.pie.show && options.grid.hoverable)
+ eventHolder.unbind('mousemove').mousemove(onMouseMove);
+
+ if (options.series.pie.show && options.grid.clickable)
+ eventHolder.unbind('click').click(onClick);
+ }
+
+
+ // debugging function that prints out an object
+ function alertObject(obj)
+ {
+ var msg = '';
+ function traverse(obj, depth)
+ {
+ if (!depth)
+ depth = 0;
+ for (var i = 0; i < obj.length; ++i)
+ {
+ for (var j=0; j<depth; j++)
+ msg += '\t';
+
+ if( typeof obj[i] == "object")
+ { // its an object
+ msg += ''+i+':\n';
+ traverse(obj[i], depth+1);
+ }
+ else
+ { // its a value
+ msg += ''+i+': '+obj[i]+'\n';
+ }
+ }
+ }
+ traverse(obj);
+ alert(msg);
+ }
+
+ function calcTotal(data)
+ {
+ for (var i = 0; i < data.length; ++i)
+ {
+ var item = parseFloat(data[i].data[0][1]);
+ if (item)
+ total += item;
+ }
+ }
+
+ function processDatapoints(plot, series, data, datapoints)
+ {
+ if (!processed)
+ {
+ processed = true;
+
+ canvas = plot.getCanvas();
+ target = $(canvas).parent();
+ options = plot.getOptions();
+
+ plot.setData(combine(plot.getData()));
+ }
+ }
+
+ function setupPie()
+ {
+ legendWidth = target.children().filter('.legend').children().width();
+
+ // calculate maximum radius and center point
+ maxRadius = Math.min(canvas.width,(canvas.height/options.series.pie.tilt))/2;
+ centerTop = (canvas.height/2)+options.series.pie.offset.top;
+ centerLeft = (canvas.width/2);
+
+ if (options.series.pie.offset.left=='auto')
+ if (options.legend.position.match('w'))
+ centerLeft += legendWidth/2;
+ else
+ centerLeft -= legendWidth/2;
+ else
+ centerLeft += options.series.pie.offset.left;
+
+ if (centerLeft<maxRadius)
+ centerLeft = maxRadius;
+ else if (centerLeft>canvas.width-maxRadius)
+ centerLeft = canvas.width-maxRadius;
+ }
+
+ function fixData(data)
+ {
+ for (var i = 0; i < data.length; ++i)
+ {
+ if (typeof(data[i].data)=='number')
+ data[i].data = [[1,data[i].data]];
+ else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined')
+ {
+ if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined')
+ data[i].label = data[i].data.label; // fix weirdness coming from flot
+ data[i].data = [[1,0]];
+
+ }
+ }
+ return data;
+ }
+
+ function combine(data)
+ {
+ data = fixData(data);
+ calcTotal(data);
+ var combined = 0;
+ var numCombined = 0;
+ var color = options.series.pie.combine.color;
+
+ var newdata = [];
+ for (var i = 0; i < data.length; ++i)
+ {
+ // make sure its a number
+ data[i].data[0][1] = parseFloat(data[i].data[0][1]);
+ if (!data[i].data[0][1])
+ data[i].data[0][1] = 0;
+
+ if (data[i].data[0][1]/total<=options.series.pie.combine.threshold)
+ {
+ combined += data[i].data[0][1];
+ numCombined++;
+ if (!color)
+ color = data[i].color;
+ }
+ else
+ {
+ newdata.push({
+ data: [[1,data[i].data[0][1]]],
+ color: data[i].color,
+ label: data[i].label,
+ angle: (data[i].data[0][1]*(Math.PI*2))/total,
+ percent: (data[i].data[0][1]/total*100)
+ });
+ }
+ }
+ if (numCombined>0)
+ newdata.push({
+ data: [[1,combined]],
+ color: color,
+ label: options.series.pie.combine.label,
+ angle: (combined*(Math.PI*2))/total,
+ percent: (combined/total*100)
+ });
+ return newdata;
+ }
+
+ function draw(plot, newCtx)
+ {
+ if (!target) return; // if no series were passed
+ ctx = newCtx;
+
+ setupPie();
+ var slices = plot.getData();
+
+ var attempts = 0;
+ while (redraw && attempts<redrawAttempts)
+ {
+ redraw = false;
+ if (attempts>0)
+ maxRadius *= shrink;
+ attempts += 1;
+ clear();
+ if (options.series.pie.tilt<=0.8)
+ drawShadow();
+ drawPie();
+ }
+ if (attempts >= redrawAttempts) {
+ clear();
+ target.prepend('<div class="error">Could not draw pie with labels contained inside canvas</div>');
+ }
+
+ if ( plot.setSeries && plot.insertLegend )
+ {
+ plot.setSeries(slices);
+ plot.insertLegend();
+ }
+
+ // we're actually done at this point, just defining internal functions at this point
+
+ function clear()
+ {
+ ctx.clearRect(0,0,canvas.width,canvas.height);
+ target.children().filter('.pieLabel, .pieLabelBackground').remove();
+ }
+
+ function drawShadow()
+ {
+ var shadowLeft = 5;
+ var shadowTop = 15;
+ var edge = 10;
+ var alpha = 0.02;
+
+ // set radius
+ if (options.series.pie.radius>1)
+ var radius = options.series.pie.radius;
+ else
+ var radius = maxRadius * options.series.pie.radius;
+
+ if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge)
+ return; // shadow would be outside canvas, so don't draw it
+
+ ctx.save();
+ ctx.translate(shadowLeft,shadowTop);
+ ctx.globalAlpha = alpha;
+ ctx.fillStyle = '#000';
+
+ // center and rotate to starting position
+ ctx.translate(centerLeft,centerTop);
+ ctx.scale(1, options.series.pie.tilt);
+
+ //radius -= edge;
+ for (var i=1; i<=edge; i++)
+ {
+ ctx.beginPath();
+ ctx.arc(0,0,radius,0,Math.PI*2,false);
+ ctx.fill();
+ radius -= i;
+ }
+
+ ctx.restore();
+ }
+
+ function drawPie()
+ {
+ startAngle = Math.PI*options.series.pie.startAngle;
+
+ // set radius
+ if (options.series.pie.radius>1)
+ var radius = options.series.pie.radius;
+ else
+ var radius = maxRadius * options.series.pie.radius;
+
+ // center and rotate to starting position
+ ctx.save();
+ ctx.translate(centerLeft,centerTop);
+ ctx.scale(1, options.series.pie.tilt);
+ //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
+
+ // draw slices
+ ctx.save();
+ var currentAngle = startAngle;
+ for (var i = 0; i < slices.length; ++i)
+ {
+ slices[i].startAngle = currentAngle;
+ drawSlice(slices[i].angle, slices[i].color, true);
+ }
+ ctx.restore();
+
+ // draw slice outlines
+ ctx.save();
+ ctx.lineWidth = options.series.pie.stroke.width;
+ currentAngle = startAngle;
+ for (var i = 0; i < slices.length; ++i)
+ drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
+ ctx.restore();
+
+ // draw donut hole
+ drawDonutHole(ctx);
+
+ // draw labels
+ if (options.series.pie.label.show)
+ drawLabels();
+
+ // restore to original state
+ ctx.restore();
+
+ function drawSlice(angle, color, fill)
+ {
+ if (angle<=0)
+ return;
+
+ if (fill)
+ ctx.fillStyle = color;
+ else
+ {
+ ctx.strokeStyle = color;
+ ctx.lineJoin = 'round';
+ }
+
+ ctx.beginPath();
+ if (Math.abs(angle - Math.PI*2) > 0.000000001)
+ ctx.moveTo(0,0); // Center of the pie
+ else if ($.browser.msie)
+ angle -= 0.0001;
+ //ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera
+ ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false);
+ ctx.closePath();
+ //ctx.rotate(angle); // This doesn't work properly in Opera
+ currentAngle += angle;
+
+ if (fill)
+ ctx.fill();
+ else
+ ctx.stroke();
+ }
+
+ function drawLabels()
+ {
+ var currentAngle = startAngle;
+
+ // set radius
+ if (options.series.pie.label.radius>1)
+ var radius = options.series.pie.label.radius;
+ else
+ var radius = maxRadius * options.series.pie.label.radius;
+
+ for (var i = 0; i < slices.length; ++i)
+ {
+ if (slices[i].percent >= options.series.pie.label.threshold*100)
+ drawLabel(slices[i], currentAngle, i);
+ currentAngle += slices[i].angle;
+ }
+
+ function drawLabel(slice, startAngle, index)
+ {
+ if (slice.data[0][1]==0)
+ return;
+
+ // format label text
+ var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
+ if (lf)
+ text = lf(slice.label, slice);
+ else
+ text = slice.label;
+ if (plf)
+ text = plf(text, slice);
+
+ var halfAngle = ((startAngle+slice.angle) + startAngle)/2;
+ var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
+ var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
+
+ var html = '<span class="pieLabel" id="pieLabel'+index+'" style="position:absolute;top:' + y + 'px;left:' + x + 'px;">' + text + "</span>";
+ target.append(html);
+ var label = target.children('#pieLabel'+index);
+ var labelTop = (y - label.height()/2);
+ var labelLeft = (x - label.width()/2);
+ label.css('top', labelTop);
+ label.css('left', labelLeft);
+
+ // check to make sure that the label is not outside the canvas
+ if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0)
+ redraw = true;
+
+ if (options.series.pie.label.background.opacity != 0) {
+ // put in the transparent background separately to avoid blended labels and label boxes
+ var c = options.series.pie.label.background.color;
+ if (c == null) {
+ c = slice.color;
+ }
+ var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;';
+ $('<div class="pieLabelBackground" style="position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').insertBefore(label).css('opacity', options.series.pie.label.background.opacity);
+ }
+ } // end individual label function
+ } // end drawLabels function
+ } // end drawPie function
+ } // end draw function
+
+ // Placed here because it needs to be accessed from multiple locations
+ function drawDonutHole(layer)
+ {
+ // draw donut hole
+ if(options.series.pie.innerRadius > 0)
+ {
+ // subtract the center
+ layer.save();
+ innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
+ layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color
+ layer.beginPath();
+ layer.fillStyle = options.series.pie.stroke.color;
+ layer.arc(0,0,innerRadius,0,Math.PI*2,false);
+ layer.fill();
+ layer.closePath();
+ layer.restore();
+
+ // add inner stroke
+ layer.save();
+ layer.beginPath();
+ layer.strokeStyle = options.series.pie.stroke.color;
+ layer.arc(0,0,innerRadius,0,Math.PI*2,false);
+ layer.stroke();
+ layer.closePath();
+ layer.restore();
+ // TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
+ }
+ }
+
+ //-- Additional Interactive related functions --
+
+ function isPointInPoly(poly, pt)
+ {
+ for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
+ ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
+ && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
+ && (c = !c);
+ return c;
+ }
+
+ function findNearbySlice(mouseX, mouseY)
+ {
+ var slices = plot.getData(),
+ options = plot.getOptions(),
+ radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
+
+ for (var i = 0; i < slices.length; ++i)
+ {
+ var s = slices[i];
+
+ if(s.pie.show)
+ {
+ ctx.save();
+ ctx.beginPath();
+ ctx.moveTo(0,0); // Center of the pie
+ //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here.
+ ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false);
+ ctx.closePath();
+ x = mouseX-centerLeft;
+ y = mouseY-centerTop;
+ if(ctx.isPointInPath)
+ {
+ if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop))
+ {
+ //alert('found slice!');
+ ctx.restore();
+ return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
+ }
+ }
+ else
+ {
+ // excanvas for IE doesn;t support isPointInPath, this is a workaround.
+ p1X = (radius * Math.cos(s.startAngle));
+ p1Y = (radius * Math.sin(s.startAngle));
+ p2X = (radius * Math.cos(s.startAngle+(s.angle/4)));
+ p2Y = (radius * Math.sin(s.startAngle+(s.angle/4)));
+ p3X = (radius * Math.cos(s.startAngle+(s.angle/2)));
+ p3Y = (radius * Math.sin(s.startAngle+(s.angle/2)));
+ p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5)));
+ p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5)));
+ p5X = (radius * Math.cos(s.startAngle+s.angle));
+ p5Y = (radius * Math.sin(s.startAngle+s.angle));
+ arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];
+ arrPoint = [x,y];
+ // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
+ if(isPointInPoly(arrPoly, arrPoint))
+ {
+ ctx.restore();
+ return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
+ }
+ }
+ ctx.restore();
+ }
+ }
+
+ return null;
+ }
+
+ function onMouseMove(e)
+ {
+ triggerClickHoverEvent('plothover', e);
+ }
+
+ function onClick(e)
+ {
+ triggerClickHoverEvent('plotclick', e);
+ }
+
+ // trigger click or hover event (they send the same parameters so we share their code)
+ function triggerClickHoverEvent(eventname, e)
+ {
+ var offset = plot.offset(),
+ canvasX = parseInt(e.pageX - offset.left),
+ canvasY = parseInt(e.pageY - offset.top),
+ item = findNearbySlice(canvasX, canvasY);
+
+ if (options.grid.autoHighlight)
+ {
+ // clear auto-highlights
+ for (var i = 0; i < highlights.length; ++i)
+ {
+ var h = highlights[i];
+ if (h.auto == eventname && !(item && h.series == item.series))
+ unhighlight(h.series);
+ }
+ }
+
+ // highlight the slice
+ if (item)
+ highlight(item.series, eventname);
+
+ // trigger any hover bind events
+ var pos = { pageX: e.pageX, pageY: e.pageY };
+ target.trigger(eventname, [ pos, item ]);
+ }
+
+ function highlight(s, auto)
+ {
+ if (typeof s == "number")
+ s = series[s];
+
+ var i = indexOfHighlight(s);
+ if (i == -1)
+ {
+ highlights.push({ series: s, auto: auto });
+ plot.triggerRedrawOverlay();
+ }
+ else if (!auto)
+ highlights[i].auto = false;
+ }
+
+ function unhighlight(s)
+ {
+ if (s == null)
+ {
+ highlights = [];
+ plot.triggerRedrawOverlay();
+ }
+
+ if (typeof s == "number")
+ s = series[s];
+
+ var i = indexOfHighlight(s);
+ if (i != -1)
+ {
+ highlights.splice(i, 1);
+ plot.triggerRedrawOverlay();
+ }
+ }
+
+ function indexOfHighlight(s)
+ {
+ for (var i = 0; i < highlights.length; ++i)
+ {
+ var h = highlights[i];
+ if (h.series == s)
+ return i;
+ }
+ return -1;
+ }
+
+ function drawOverlay(plot, octx)
+ {
+ //alert(options.series.pie.radius);
+ var options = plot.getOptions();
+ //alert(options.series.pie.radius);
+
+ var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
+
+ octx.save();
+ octx.translate(centerLeft, centerTop);
+ octx.scale(1, options.series.pie.tilt);
+
+ for (i = 0; i < highlights.length; ++i)
+ drawHighlight(highlights[i].series);
+
+ drawDonutHole(octx);
+
+ octx.restore();
+
+ function drawHighlight(series)
+ {
+ if (series.angle < 0) return;
+
+ //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
+ octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor
+
+ octx.beginPath();
+ if (Math.abs(series.angle - Math.PI*2) > 0.000000001)
+ octx.moveTo(0,0); // Center of the pie
+ octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false);
+ octx.closePath();
+ octx.fill();
+ }
+
+ }
+
+ } // end init (plugin body)
+
+ // define pie specific options and their default values
+ var options = {
+ series: {
+ pie: {
+ show: false,
+ radius: 'auto', // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
+ innerRadius:0, /* for donut */
+ startAngle: 3/2,
+ tilt: 1,
+ offset: {
+ top: 0,
+ left: 'auto'
+ },
+ stroke: {
+ color: '#FFF',
+ width: 1
+ },
+ label: {
+ show: 'auto',
+ formatter: function(label, slice){
+ return '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'<br/>'+Math.round(slice.percent)+'%</div>';
+ }, // formatter function
+ radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
+ background: {
+ color: null,
+ opacity: 0
+ },
+ threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow)
+ },
+ combine: {
+ threshold: -1, // percentage at which to combine little slices into one larger slice
+ color: null, // color to give the new slice (auto-generated if null)
+ label: 'Other' // label to give the new slice
+ },
+ highlight: {
+ //color: '#FFF', // will add this functionality once parseColor is available
+ opacity: 0.5
+ }
+ }
+ }
+ };
+
+ $.plot.plugins.push({
+ init: init,
+ options: options,
+ name: "pie",
+ version: "1.0"
+ });
+})(jQuery);
http://git-wip-us.apache.org/repos/asf/incubator-flink/blob/76d603c0/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.resize.js
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.resize.js b/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.resize.js
new file mode 100755
index 0000000..6ee972e
--- /dev/null
+++ b/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.resize.js
@@ -0,0 +1,60 @@
+/* Flot plugin for automatically redrawing plots as the placeholder resizes.
+
+Copyright (c) 2007-2013 IOLA and Ole Laursen.
+Licensed under the MIT license.
+
+It works by listening for changes on the placeholder div (through the jQuery
+resize event plugin) - if the size changes, it will redraw the plot.
+
+There are no options. If you need to disable the plugin for some plots, you
+can just fix the size of their placeholders.
+
+*/
+
+/* Inline dependency:
+ * jQuery resize event - v1.1 - 3/14/2010
+ * http://benalman.com/projects/jquery-resize-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+(function($,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 ($) {
+ var options = { }; // no options
+
+ function init(plot) {
+ function onResize() {
+ var placeholder = plot.getPlaceholder();
+
+ // somebody might have hidden us and we can't plot
+ // when we don't have the dimensions
+ if (placeholder.width() == 0 || placeholder.height() == 0)
+ return;
+
+ plot.resize();
+ plot.setupGrid();
+ plot.draw();
+ }
+
+ function bindEvents(plot, eventHolder) {
+ plot.getPlaceholder().resize(onResize);
+ }
+
+ function shutdown(plot, eventHolder) {
+ plot.getPlaceholder().unbind("resize", onResize);
+ }
+
+ plot.hooks.bindEvents.push(bindEvents);
+ plot.hooks.shutdown.push(shutdown);
+ }
+
+ $.plot.plugins.push({
+ init: init,
+ options: options,
+ name: 'resize',
+ version: '1.0'
+ });
+})(jQuery);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-flink/blob/76d603c0/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.tooltip.min.js
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.tooltip.min.js b/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.tooltip.min.js
new file mode 100755
index 0000000..bc93bf8
--- /dev/null
+++ b/flink-runtime/src/main/resources/web-docs-infoserver/js/flot/jquery.flot.tooltip.min.js
@@ -0,0 +1,12 @@
+/*
+ * jquery.flot.tooltip
+ *
+ * description: easy-to-use tooltips for Flot charts
+ * version: 0.6.2
+ * author: Krzysztof Urbas @krzysu [myviews.pl]
+ * website: https://github.com/krzysu/flot.tooltip
+ *
+ * build on 2013-09-30
+ * released under MIT License, 2012
+*/
+(function(t){var o={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},i=function(t){this.tipPosition={x:0,y:0},this.init(t)};i.prototype.init=function(o){function i(t){var o={};o.x=t.pageX,o.y=t.pageY,s.updateTooltipPosition(o)}function e(t,o,i){var e=s.getDomElement();if(i){var n;n=s.stringFormat(s.tooltipOptions.content,i),e.html(n),s.updateTooltipPosition({x:o.pageX,y:o.pageY}),e.css({left:s.tipPosition.x+s.tooltipOptions.shifts.x,top:s.tipPosition.y+s.tooltipOptions.shifts.y}).show(),"function"==typeof s.tooltipOptions.onHover&&s.tooltipOptions.onHover(i,e)}else e.hide().html("")}var s=this;o.hooks.bindEvents.push(function(o,n){s.plotOptions=o.getOptions(),s.plotOptions.tooltip!==!1&&void 0!==s.plotOptions.tooltip&&(s.tooltipOptions=s.plotOptions.tooltipOpts,s.getDomElement(),t(o.getPlaceholder()).bind("plothover",e),t(n).bind("mousemove",i))}),o.hooks.shutdown.push(function(o,s){t(o.g
etPlaceholder()).unbind("plothover",e),t(s).unbind("mousemove",i)})},i.prototype.getDomElement=function(){var o;return t("#flotTip").length>0?o=t("#flotTip"):(o=t("<div />").attr("id","flotTip"),o.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&o.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"none","white-space":"nowrap"})),o},i.prototype.updateTooltipPosition=function(o){var i=t("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,e=t("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;o.x-t(window).scrollLeft()>t(window).innerWidth()-i&&(o.x-=i),o.y-t(window).scrollTop()>t(window).innerHeight()-e&&(o.y-=e),this.tipPosition.x=o.x,this.tipPosition.y=o.y},i.prototype.stringFormat=function(t,o){var i=/%p\.{0,1}(\d{0,})/,e=/%s/,s=/%x\.{0,1}(?:\d{0,})/,n=/%y\.{0,1}(?:\d{0,})/;return"function"==typeof t&&(t=t(o.series.label,o.series.data[o.dataIndex][0],o.se
ries.data[o.dataIndex][1],o)),o.series.percent!==void 0&&(t=this.adjustValPrecision(i,t,o.series.percent)),o.series.label!==void 0&&(t=t.replace(e,o.series.label)),this.isTimeMode("xaxis",o)&&this.isXDateFormat(o)&&(t=t.replace(s,this.timestampToDate(o.series.data[o.dataIndex][0],this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",o)&&this.isYDateFormat(o)&&(t=t.replace(n,this.timestampToDate(o.series.data[o.dataIndex][1],this.tooltipOptions.yDateFormat))),"number"==typeof o.series.data[o.dataIndex][0]&&(t=this.adjustValPrecision(s,t,o.series.data[o.dataIndex][0])),"number"==typeof o.series.data[o.dataIndex][1]&&(t=this.adjustValPrecision(n,t,o.series.data[o.dataIndex][1])),o.series.xaxis.tickFormatter!==void 0&&(t=t.replace(s,o.series.xaxis.tickFormatter(o.series.data[o.dataIndex][0],o.series.xaxis))),o.series.yaxis.tickFormatter!==void 0&&(t=t.replace(n,o.series.yaxis.tickFormatter(o.series.data[o.dataIndex][1],o.series.yaxis))),t},i.prototype.isTimeMode=function(t,o){retur
n o.series[t].options.mode!==void 0&&"time"===o.series[t].options.mode},i.prototype.isXDateFormat=function(){return this.tooltipOptions.xDateFormat!==void 0&&null!==this.tooltipOptions.xDateFormat},i.prototype.isYDateFormat=function(){return this.tooltipOptions.yDateFormat!==void 0&&null!==this.tooltipOptions.yDateFormat},i.prototype.timestampToDate=function(o,i){var e=new Date(o);return t.plot.formatDate(e,i)},i.prototype.adjustValPrecision=function(t,o,i){var e,s=o.match(t);return null!==s&&""!==RegExp.$1&&(e=RegExp.$1,i=i.toFixed(e),o=o.replace(t,i)),o};var e=function(t){new i(t)};t.plot.plugins.push({init:e,options:o,name:"tooltip",version:"0.6.1"})})(jQuery);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-flink/blob/76d603c0/flink-runtime/src/main/resources/web-docs-infoserver/js/helpers.js
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/resources/web-docs-infoserver/js/helpers.js b/flink-runtime/src/main/resources/web-docs-infoserver/js/helpers.js
new file mode 100644
index 0000000..b0e935c
--- /dev/null
+++ b/flink-runtime/src/main/resources/web-docs-infoserver/js/helpers.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function formattedTimeFromTimestamp(timestamp)
+{
+ var date = new Date(timestamp);
+ return date.toLocaleString();
+}
+
+function convertTime(time) {
+ var millis= time % 1000;
+ time = parseInt(time/1000);
+ var seconds = time % 60;
+ time = parseInt(time/60);
+ var minutes = time % 60;
+ time = parseInt(time/60);
+ var hours = time % 24;
+ var out = "";
+ if(hours && hours > 0) out += hours + " " + ((hours == 1)?"hr":"hrs") + " ";
+ if(minutes && minutes > 0) out += minutes + " " + ((minutes == 1)?"min":"mins") + " ";
+ if(seconds && seconds > 0) out += seconds + " " + ((seconds == 1)?"sec":"secs") + " ";
+ if(millis&& millis> 0) out += millis+ " " + ((millis== 1)?"msec":"msecs") + " ";
+ return out.trim();
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-flink/blob/76d603c0/flink-runtime/src/main/resources/web-docs-infoserver/js/jcanvas.min.js
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/resources/web-docs-infoserver/js/jcanvas.min.js b/flink-runtime/src/main/resources/web-docs-infoserver/js/jcanvas.min.js
new file mode 100644
index 0000000..863e80c
--- /dev/null
+++ b/flink-runtime/src/main/resources/web-docs-infoserver/js/jcanvas.min.js
@@ -0,0 +1,61 @@
+/*
+ jCanvas v13.11.21
+ Copyright 2013 Caleb Evans
+ Released under the MIT license
+*/
+(function(d,Ka,sa,da,ta,A,E,f,D){function L(c){Y(this,c);return this}function J(c){c?Y(L.prototype,c):J.prefs=L.prototype=Y({},ia);return this}function K(c){return c&&c.getContext?c.getContext("2d"):f}function ja(c){c=Y({},c);c.masks=c.masks.slice(0);return c}function ea(c,b){var a;c.save();a=ja(b.transforms);b.savedTransforms.push(a)}function U(c,b,a){$(a.fillStyle)?b.fillStyle=a.fillStyle.call(c,a):b.fillStyle=a.fillStyle;$(a.strokeStyle)?b.strokeStyle=a.strokeStyle.call(c,a):b.strokeStyle=a.strokeStyle;
+b.lineWidth=a.strokeWidth;a.rounded?b.lineCap=b.lineJoin="round":(b.lineCap=a.strokeCap,b.lineJoin=a.strokeJoin,b.miterLimit=a.miterLimit);b.shadowOffsetX=a.shadowX;b.shadowOffsetY=a.shadowY;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.globalAlpha=a.opacity;b.globalCompositeOperation=a.compositing;a.imageSmoothing&&(b.webkitImageSmoothingEnabled=b.mozImageSmoothingEnabled=a.imageSmoothing)}function ua(c,b,a){a.mask&&(a.autosave&&ea(c,b),c.clip(),b.transforms.masks.push(a._args))}function X(c,
+b,a){a.closed&&b.closePath();a.shadowStroke&&0!==a.strokeWidth?(b.stroke(),b.fill(),b.shadowColor="transparent",b.shadowBlur=0,b.stroke()):(b.fill(),"transparent"!==a.fillStyle&&(b.shadowColor="transparent"),0!==a.strokeWidth&&b.stroke());a.closed||b.closePath();a._transformed&&b.restore();a.mask&&(c=P(c),ua(b,c,a))}function va(c,b,a){b._toRad=b.inDegrees?M/180:1;c.translate(b.x,b.y);c.rotate(b.rotate*b._toRad);c.translate(-b.x,-b.y);a&&(a.rotate+=b.rotate*b._toRad)}function wa(c,b,a){1!==b.scale&&
+(b.scaleX=b.scaleY=b.scale);c.translate(b.x,b.y);c.scale(b.scaleX,b.scaleY);c.translate(-b.x,-b.y);a&&(a.scaleX*=b.scaleX,a.scaleY*=b.scaleY)}function xa(c,b,a){b.translate&&(b.translateX=b.translateY=b.translate);c.translate(b.translateX,b.translateY);a&&(a.translateX+=b.translateX,a.translateY+=b.translateY)}function Q(c,b,a,e,h){a._toRad=a.inDegrees?M/180:1;a.arrowAngle*=a._toRad;a._transformed=A;b.save();h===D&&(h=e);a.fromCenter||a._centered||(a.x+=e/2,a.y+=h/2,a._centered=A);a.rotate&&va(b,
+a,{});1===a.scale&&1===a.scaleX&&1===a.scaleY||wa(b,a,{});(a.translate||a.translateX||a.translateY)&&xa(b,a,{})}function P(c){var b;fa._canvas===c&&fa._data?b=fa._data:(b=d.data(c,"jCanvas"),b||(b={canvas:c,layers:[],layer:{names:{},groups:{}},intersecting:[],lastIntersected:f,cursor:d(c).css("cursor"),drag:{},event:{type:f,x:f,y:f},events:{},transforms:ja(ma),savedTransforms:[],animating:E,animated:f,pos:0,pixelRatio:1,scaled:!1},d.data(c,"jCanvas",b)),fa._canvas=c,fa._data=b);return b}function ya(c,
+b,a){for(var e in J.events)J.events.hasOwnProperty(e)&&(a[e]||a.cursors&&a.cursors[e])&&za(c,b,a,e)}function za(c,b,a,e){e=Aa(e);J.events[e](c,b);a._event=A}function Ba(c,b,a){var e,h,g;if(a.draggable||a.cursor||a.cursors){e=["mousedown","mousemove","mouseup"];for(g=0;g<e.length;g+=1)h=e[g],za(c,b,a,h);b.events.mouseoutdrag||(c.bind("mouseout.jCanvas",function(){var a=b.drag.layer;a&&(b.drag={},a.dragcancel&&a.dragcancel.call(c[0],a),c.drawLayers())}),b.events.mouseoutdrag=A);a._event=A}}function ka(c,
+b,a,e){c=b.layer.names;e?e.name!==D&&"string"===aa(a.name)&&a.name!==e.name&&delete c[a.name]:e=a;"string"===aa(e.name)&&(c[e.name]=a)}function na(c,b,a,e){c=b.layer.groups;var h,g,d,H;a.group!==f&&(a.groups=[a.group],a.dragGroupWithLayer&&(a.dragGroups=[a.group]));e&&e.group!==D&&(e.group===f?e.groups=f:(e.groups=[e.group],e.dragGroupWithLayer&&(e.dragGroups=[e.group])));if(!e)e=a;else if(e.groups!==D&&a.groups!==f)for(g=0;g<a.groups.length;g+=1)if(h=a.groups[g],b=c[h]){for(H=0;H<b.length;H+=1)if(b[H]===
+a){d=H;b.splice(H,1);break}0===b.length&&delete c[h]}if(e.groups!==D&&e.groups!==f)for(g=0;g<e.groups.length;g+=1)h=e.groups[g],b=c[h],b||(b=c[h]=[],b.name=h),d===D&&(d=b.length),b.splice(d,0,a)}function ca(c,b,a,e){e||(e=b.cursors?b.cursors[a]:b.cursor);e&&c.css({cursor:e});b[a]&&b[a].call(c[0],b)}function O(c,b,a,e){var h=b;b._args=a;b.canvas=c;if(b.draggable||b.dragGroups)b.layer=A,b.draggable=A;b._method=e?e:b.method?d.fn[b.method]:b.type?d.fn[la[b.type]]:function(){};b.layer&&!b._layer&&(a=d(c),
+e=a.getLayers(),c=P(c),h=new L(b),h.layer=A,h._layer=A,ka(a,c,h),na(a,c,h),ya(a,c,h),Ba(a,c,h),b._event=h._event,h.index===f&&(h.index=e.length),e.splice(h.index,0,h));return h}function Ca(c){var b,a;for(a=0;a<ga.length;a+=1)b=ga[a],c[b]=c["_"+b]}function Da(c,b){var a,e;for(e=0;e<ga.length;e+=1)a=ga[e],c["_"+a]=c[a],oa[a]=A,b&&delete c[a]}function La(c,b,a){for(var e in a)a.hasOwnProperty(e)&&$(a[e])&&(a[e]=a[e].call(c,b,e));return a}function Ea(c){var b,a,e=[],h=1;c.match(/^#?\w+$/gi)&&("transparent"===
+c&&(c="rgba(0,0,0,0)"),a=Ka.head,b=a.style.color,a.style.color=c,c=d.css(a,"color"),a.style.color=b);c.match(/^rgb/gi)&&(e=c.match(/\d+/gi),c.match(/%/gi)&&(h=2.55),e[0]*=h,e[1]*=h,e[2]*=h,e[3]=e[3]!==D?ta(e[3]):1);return e}function Ma(c){var b=3,a;"array"!==aa(c.start)&&(c.start=Ea(c.start),c.end=Ea(c.end));c.now=[];if(1!==c.start[3]||1!==c.end[3])b=4;for(a=0;a<b;a+=1)c.now[a]=c.start[a]+(c.end[a]-c.start[a])*c.pos,3>a&&(c.now[a]=Na(c.now[a]));1!==c.start[3]||1!==c.end[3]?c.now="rgba("+c.now.join(",")+
+")":(c.now.slice(0,3),c.now="rgb("+c.now.join(",")+")");c.elem.nodeName?c.elem.style[c.prop]=c.now:c.elem[c.prop]=c.now}function Aa(c){void 0!==window.ontouchstart&&pa[c]&&(c=pa[c]);return c}function Oa(c){J.events[c]=function(b,a){var e,h;h=a.event;e="mouseover"===c||"mouseout"===c?"mousemove":c;a.events[e]||(b.bind(e+".jCanvas",function(a){h.x=a.offsetX;h.y=a.offsetY;h.type=e;h.event=a;b.drawLayers({resetFire:A});a.preventDefault()}),a.events[e]=A)}}function V(c,b,a){var e,h,g,d;(a=a._args)&&a._event&&
+(c=P(c),e=c.event,e.x!==f&&e.y!==f&&(g=e.x*c.pixelRatio,d=e.y*c.pixelRatio,h=b.isPointInPath(g,d)||b.isPointInStroke&&b.isPointInStroke(g,d)),b=c.transforms,a.eventX=a.mouseX=e.x,a.eventY=a.mouseY=e.y,a.event=e.event,e=c.transforms.rotate,g=a.eventX,d=a.eventY,0!==e?(a._eventX=g*R(-e)-d*T(-e),a._eventY=d*R(-e)+g*T(-e)):(a._eventX=g,a._eventY=d),a._eventX/=b.scaleX,a._eventY/=b.scaleY,h&&c.intersecting.push(a),a.intersects=h)}function Fa(c){for(;0>c;)c+=2*M;return c}function Ga(c,b,a,e,h,g,d){var f,
+z,y;a.arrowRadius&&!a.closed&&(y=Pa(d-h,g-e),y-=M,f=a.strokeWidth*R(y),z=a.strokeWidth*T(y),c=g+a.arrowRadius*R(y+a.arrowAngle/2),e=d+a.arrowRadius*T(y+a.arrowAngle/2),h=g+a.arrowRadius*R(y-a.arrowAngle/2),a=d+a.arrowRadius*T(y-a.arrowAngle/2),b.moveTo(c-f,e-z),b.lineTo(g-f,d-z),b.lineTo(h-f,a-z),b.moveTo(g-f,d-z),b.lineTo(g+f,d+z))}function ha(c,b,a,e,h,g,d,f,z,y,F){a.startArrow&&Ga(c,b,a,e,h,g,d);a.endArrow&&Ga(c,b,a,f,z,y,F)}function Ha(c,b){isNaN(Number(b.fontSize))||(b.fontSize+="px");c.font=
+b.fontStyle+" "+b.fontSize+" "+b.fontFamily}function Ia(c,b,a,e){var h,g;if(Z.text===a.text&&Z.fontStyle===a.fontStyle&&Z.fontSize===a.fontSize&&Z.fontFamily===a.fontFamily&&Z.maxWidth===a.maxWidth&&Z.lineHeight===a.lineHeight)a.width=Z.width,a.height=Z.height;else{a.width=b.measureText(e[0]).width;for(g=1;g<e.length;g+=1)h=b.measureText(e[g]).width,h>a.width&&(a.width=h);b=c.style.fontSize;c.style.fontSize=a.fontSize;a.height=ta(d.css(c,"fontSize"))*e.length*a.lineHeight;c.style.fontSize=b}}function Ja(c,
+b){var a=b.maxWidth,e=b.text.split("\n"),h=[],g,d,f,z,y;for(f=0;f<e.length;f+=1){z=e[f];y=z.split(" ");g=[];d="";if(1===y.length||c.measureText(z).width<a)g=[z];else{for(z=0;z<y.length;z+=1)c.measureText(d+y[z]).width>a&&(""!==d&&g.push(d),d=""),d+=y[z],z!==y.length-1&&(d+=" ");g.push(d)}h=h.concat(g.join("\n").replace(/( (\n))|( $)/gi,"$2").split("\n"))}return h}var ia,Y=d.extend,ba=d.inArray,aa=d.type,$=d.isFunction,Na=da.round,M=da.PI,T=da.sin,R=da.cos,Pa=da.atan2,Qa=d.event.fix,pa,qa,la,fa={},
+Z={},ra={},ma={rotate:0,scaleX:1,scaleY:1,translateX:0,translateY:0,masks:[]},ga,oa;d.fn.jCanvas=J;J.events={};ia={align:"center",arrowAngle:90,arrowRadius:0,autosave:A,baseline:"middle",bringToFront:E,ccw:E,closed:E,compositing:"source-over",concavity:0,cornerRadius:0,count:1,cropFromCenter:A,cursor:f,cursors:f,disableEvents:E,draggable:E,dragGroups:f,group:f,groups:f,data:{},each:f,end:360,fillStyle:"transparent",fireDragGroupEvents:E,fontStyle:"normal",fontSize:"12pt",fontFamily:"sans-serif",fromCenter:A,
+fn:f,height:f,imageSmoothing:A,inDegrees:A,index:f,lineHeight:1,layer:E,load:f,mask:E,maxWidth:f,miterLimit:10,name:f,opacity:1,r1:f,r2:f,radius:0,repeat:"repeat",respectAlign:E,rotate:0,rounded:E,scale:1,scaleX:1,scaleY:1,shadowBlur:0,shadowColor:"transparent",shadowStroke:!1,shadowX:0,shadowY:0,sHeight:f,sides:0,source:"",spread:0,start:0,strokeCap:"butt",strokeJoin:"miter",strokeStyle:"transparent",strokeWidth:1,sWidth:f,sx:f,sy:f,text:"",translate:0,translateX:0,translateY:0,type:f,visible:A,
+width:f,x:0,y:0};J();J.extend=function(c){J.defaults=Y(ia,c.props);J();c.name&&(d.fn[c.name]=function a(e){var h,g,d,f;for(g=0;g<this.length;g+=1)if(h=this[g],d=K(h))f=new L(e),O(h,f,e,a),U(h,d,f),c.fn.call(h,d,f);return this});return d.fn[c.name]};d.fn.getLayers=function(c){var b=this[0],a,e,h=[];if(b&&b.getContext)if(a=P(b),a=a.layers,$(c))for(e=0;e<a.length;e+=1)c.call(b,a[e])&&h.push(a[e]);else h=a;return h};d.fn.getLayer=function(c){var b=P(this[0]),a=b.layers,e=aa(c),h;if(c&&c.layer)h=c;else if("number"===
+e)0>c&&(c=a.length+c),h=a[c];else if("regexp"===e)for(b=0;b<a.length;b+=1){if("string"===aa(a[b].name)&&a[b].name.match(c)){h=a[b];break}}else h=b.layer.names[c];return h};d.fn.getLayerGroup=function(c){var b=aa(c),a,e;if("array"===b)return c;if("regexp"===b)for(a in b=P(this[0]),b=b.groups,b){if(a.match(c)){e=b[a];break}}else b=P(this[0]),e=b.layer.groups[c];return e};d.fn.getLayerIndex=function(c){var b=this.getLayers();c=this.getLayer(c);return ba(c,b)};d.fn.setLayer=function(c,b){var a,e,h,g;
+for(e=0;e<this.length;e+=1)if(a=d(this[e]),h=P(this[e]),g=d(this[e]).getLayer(c))ka(a,h,g,b),na(a,h,g,b),b.index!==D&&a.moveLayer(g,b.index),Y(g,b),ya(a,h,g),Ba(a,h,g);return this};d.fn.setLayerGroup=function(c,b){var a,e,h,g;for(e=0;e<this.length;e+=1)if(a=d(this[e]),h=a.getLayerGroup(c))for(g=0;g<h.length;g+=1)a.setLayer(h[g],b);return this};d.fn.setLayers=function(c,b){var a,e,h,g;for(e=0;e<this.length;e+=1)for(a=d(this[e]),h=a.getLayers(b),g=0;g<h.length;g+=1)a.setLayer(h[g],c);return this};d.fn.moveLayer=
+function(c,b){var a,e,h;for(e=0;e<this.length;e+=1)if(a=d(this[e]),h=a.getLayers(),a=a.getLayer(c))a.index=ba(a,h),h.splice(a.index,1),h.splice(b,0,a),0>b&&(b=h.length+b),a.index=b;return this};d.fn.removeLayer=function(c){var b,a,e,h,g;for(a=0;a<this.length;a+=1)if(b=d(this[a]),e=P(this[a]),h=b.getLayers(),g=b.getLayer(c))g.index=ba(g,h),h.splice(g.index,1),ka(b,e,g,{name:f}),na(b,e,g,{groups:f});return this};d.fn.removeLayerGroup=function(c){var b,a,e,h,g,N,H;if(c!==D)for(a=0;a<this.length;a+=1)if(b=
+d(this[a]),e=P(this[a]),h=b.getLayers(),g=b.getLayerGroup(c)){for(H=0;H<g.length;H+=1)N=g[H],N.index=ba(N,h),h.splice(N.index,1),ka(b,e,N,{name:f});delete e.layer.groups[g.name]}return this};d.fn.removeLayers=function(){var c,b;for(c=0;c<this.length;c+=1)d(this[c]),b=P(this[c]),b.layers.length=0,b.layer.names={},b.layer.groups={};return this};d.fn.addLayerToGroup=function(c,b){var a,e,h,g=[];for(e=0;e<this.length;e+=1)a=d(this[e]),h=a.getLayer(c),h.groups&&-1===ba(b,h.groups)&&(g=h.groups.slice(0),
+g.push(b),a.setLayer(h,{groups:g}));return this};d.fn.removeLayerFromGroup=function(c,b){var a,e,h,g=[],f;for(e=0;e<this.length;e+=1)a=d(this[e]),h=a.getLayer(c),f=ba(b,h.groups),-1!==f&&(g=h.groups.slice(0),g.splice(f,1),a.setLayer(h,{groups:g}));return this};d.fn.drawLayer=function(c){var b,a,e;for(b=0;b<this.length;b+=1)a=d(this[b]),K(this[b]),(e=a.getLayer(c))&&e.visible&&e._method&&(e._next=f,e._method.call(a,e));return this};d.fn.drawLayers=function(c){var b,a,e=Y({},c),h,g,N,H,z,y,F;e.index||
+(e.index=0);for(c=0;c<this.length;c+=1)if(b=d(this[c]),a=K(this[c])){H=P(this[c]);e.clear!==E&&b.clearCanvas();a=H.layers;for(N=e.index;N<a.length&&(h=a[N],h.index=N,e.resetFire&&(h._fired=E),h._event=!h.disableEvents,y=b,z=h,g=N+1,z&&z.visible&&z._method&&(z._next=g?g:f,z._method.call(y,z)),h._masks=H.transforms.masks.slice(0),h._method!==d.fn.drawImage||!h.visible);N+=1);h=H;g=z=y=void 0;y={};for(z=h.intersecting.length-1;0<=z;z-=1)if(y=h.intersecting[z],y._masks){for(g=y._masks.length-1;0<=g;g-=
+1)if(!y._masks[g].intersects){y.intersects=E;break}if(y.intersects)break}h=y;z=H.event;y=z.type;h[y]||qa[y]&&(y=qa[y]);F=H.drag;g=H.lastIntersected;g!==f&&h!==g&&g._hovered&&!g._fired&&(H.lastIntersected=f,g._fired=A,g._hovered=E,ca(b,g,"mouseout",H.cursor));h._event&&h.intersects&&(H.lastIntersected=h,!(h.mouseover||h.mouseout||h.cursor||h.cursors)||h._hovered||h._fired||(h._fired=A,h._hovered=A,ca(b,h,"mouseover")),h._fired||(h._fired=A,z.type=f,ca(b,h,y)),!h.draggable||"mousedown"!==y&&"touchstart"!==
+y||(F.layer=h));if(F.layer){h=H;var t=g=z=void 0,B=F=void 0,l=void 0,u=t=void 0;F=h.drag;g=F.layer;B=g.dragGroups||[];z=h.layers;if("mousemove"===y||"touchmove"===y){if(!F.dragging){F.dragging=A;g.bringToFront&&(z.splice(g.index,1),g.index=z.push(g));for(u=0;u<B.length;u+=1)if(t=B[u],l=h.layer.groups[t],g.groups&&l)for(t=0;t<l.length;t+=1)l[t]!==g&&(l[t]._startX=l[t].x,l[t]._startY=l[t].y,l[t]._endX=g._eventX,l[t]._endY=g._eventY,l[t].bringToFront&&(l[t].index=ba(l[t],z),z.splice(l[t].index,1),z.splice(-1,
+0,l[t]),l[t].index=z.length-2),l[t].dragstart&&g.fireDragGroupEvents&&l[t].dragstart.call(b[0],l[t]));F._startX=g._startX=g.x;F._startY=g._startY=g.y;F._endX=g._endX=g._eventX;F._endY=g._endY=g._eventY;ca(b,g,"dragstart")}g.x=g._eventX-(F._endX-F._startX);g.y=g._eventY-(F._endY-F._startY);for(u=0;u<B.length;u+=1)if(t=B[u],l=h.layer.groups[t],g.groups&&l)for(t=0;t<l.length;t+=1)l[t]!==g&&(l[t].x=g._eventX-(l[t]._endX-l[t]._startX),l[t].y=g._eventY-(l[t]._endY-l[t]._startY),l[t].drag&&g.fireDragGroupEvents&&
+l[t].drag.call(b[0],l[t]));ca(b,g,"drag")}else if("mouseup"===y||"touchend"===y){F.dragging&&(ca(b,g,"dragstop"),F.dragging=E);for(u=0;u<B.length;u+=1)if(t=B[u],l=h.layer.groups[t],g.groups&&l)for(t=0;t<l.length;t+=1)l[t]!==g&&l[t].dragstop&&g.fireDragGroupEvents&&l[t].dragstop.call(b[0],l[t]);h.drag={}}}N===a.length&&(H.intersecting.length=0,H.transforms=ja(ma),H.savedTransforms.length=0)}return this};d.fn.addLayer=function(c){var b,a;for(b=0;b<this.length;b+=1)if(a=K(this[b]))a=new L(c),a.layer=
+A,O(this[b],a,c);return this};ga=["width","height","opacity","lineHeight"];oa={};d.fn.animateLayer=function(){function c(a,b,c){return function(){Ca(c);b.animating&&b.animated!==c||a.drawLayers();g[4]&&g[4].call(a[0],c);c._animating=E;b.animating=E;b.animated=f}}function b(a,b,c){return function(e,h){c._pos!==h.pos&&(c._pos=h.pos,Ca(c),c._animating||b.animating||(c._animating=A,b.animating=A,b.animated=c),b.animating&&b.animated!==c||a.drawLayers(),g[5]&&g[5].call(a[0],e,h,c))}}var a,e,h,g=[].slice.call(arguments,
+0),N,H;"object"===aa(g[2])?(g.splice(2,0,g[2].duration||f),g.splice(3,0,g[3].easing||f),g.splice(4,0,g[4].done||g[4].complete||f),g.splice(5,0,g[5].step||f)):(g[2]===D?(g.splice(2,0,f),g.splice(3,0,f),g.splice(4,0,f)):$(g[2])&&(g.splice(2,0,f),g.splice(3,0,f)),g[3]===D?(g[3]=f,g.splice(4,0,f)):$(g[3])&&g.splice(3,0,f));for(e=0;e<this.length;e+=1)if(a=d(this[e]),h=K(this[e]))h=P(this[e]),(N=a.getLayer(g[0]))&&N._method!==d.fn.draw&&(H=Y({},g[1]),H=La(this[e],N,H),Da(H,A),Da(N),N.style=oa,d(N).animate(H,
+{duration:g[2],easing:d.easing[g[3]]?g[3]:f,complete:c(a,h,N),step:b(a,h,N)}));return this};d.fn.animateLayerGroup=function(c){var b,a,e=[].slice.call(arguments,0),h,g;for(a=0;a<this.length;a+=1)if(b=d(this[a]),h=b.getLayerGroup(c))for(g=0;g<h.length;g+=1)b.animateLayer.apply(b,[h[g]].concat(e.slice(1)));return this};d.fn.delayLayer=function(c,b){var a,e;b=b||0;for(a=0;a<this.length;a+=1)e=d(this[a]).getLayer(c),d(e).delay(b);return this};d.fn.delayLayerGroup=function(c,b){var a,e,h,g;b=b||0;for(e=
+0;e<this.length;e+=1)if(a=d(this[e]),a=a.getLayerGroup(c))for(g=0;g<a.length;g+=1)(h=a[g])&&d(h).delay(b);return this};d.fn.stopLayer=function(c,b){var a,e;for(e=0;e<this.length;e+=1)a=d(this[e]),(a=a.getLayer(c))&&d(a).stop(b);return this};d.fn.stopLayerGroup=function(c,b){var a,e,h,g;for(e=0;e<this.length;e+=1)if(a=d(this[e]),a=a.getLayerGroup(c))for(g=0;g<a.length;g+=1)(h=a[g])&&d(h).stop(b);return this};(function(c){var b;for(b=0;b<c.length;b+=1)d.fx.step[c[b]]=Ma})("color backgroundColor borderColor borderTopColor borderRightColor borderBottomColor borderLeftColor fillStyle outlineColor strokeStyle shadowColor".split(" "));
+pa={mousedown:"touchstart",mouseup:"touchend",mousemove:"touchmove"};qa={touchstart:"mousedown",touchend:"mouseup",touchmove:"mousemove"};(function(c){var b;for(b=0;b<c.length;b+=1)Oa(c[b])})("click dblclick mousedown mouseup mousemove mouseover mouseout touchstart touchmove touchend".split(" "));d.event.fix=function(c){var b,a;c=Qa.call(d.event,c);if(b=c.originalEvent)if(a=b.changedTouches,c.pageX!==D&&c.offsetX===D){if(b=d(c.currentTarget).offset())c.offsetX=c.pageX-b.left,c.offsetY=c.pageY-b.top}else a&&
+(b=d(c.currentTarget).offset())&&(c.offsetX=a[0].pageX-b.left,c.offsetY=a[0].pageY-b.top);return c};la={arc:"drawArc",bezier:"drawBezier",ellipse:"drawEllipse","function":"draw",image:"drawImage",line:"drawLine",polygon:"drawPolygon",slice:"drawSlice",quadratic:"drawQuadratic",rectangle:"drawRect",text:"drawText",vector:"drawVector"};d.fn.draw=function b(a){var e,h,g=new L(a);if(la[g.type])this[la[g.type]](g);else for(e=0;e<this.length;e+=1)if(d(this[e]),h=K(this[e]))g=new L(a),O(this[e],g,a,b),g.visible&&
+g.fn&&g.fn.call(this[e],h,g);return this};d.fn.clearCanvas=function a(e){var h,g,d=new L(e);for(h=0;h<this.length;h+=1)if(g=K(this[h]))d.width===f||d.height===f?(g.save(),g.setTransform(1,0,0,1,0,0),g.clearRect(0,0,this[h].width,this[h].height),g.restore()):(O(this[h],d,e,a),Q(this[h],g,d,d.width,d.height),g.clearRect(d.x-d.width/2,d.y-d.height/2,d.width,d.height),d._transformed&&g.restore());return this};d.fn.saveCanvas=function e(h){var g,d,f,z,y;for(g=0;g<this.length;g+=1)if(d=K(this[g]))for(z=
+P(this[g]),f=new L(h),O(this[g],f,h,e),y=0;y<f.count;y+=1)ea(d,z);return this};d.fn.restoreCanvas=function h(g){var d,f,z,y,F;for(d=0;d<this.length;d+=1)if(f=K(this[d]))for(y=P(this[d]),z=new L(g),O(this[d],z,g,h),F=0;F<z.count;F+=1){var t=f,B=y;0===B.savedTransforms.length?B.transforms=ja(ma):(t.restore(),B.transforms=B.savedTransforms.pop())}return this};d.fn.restoreCanvasOnRedraw=function(h){h=Y({},h);h.layer=A;this.restoreCanvas(h);return this};d.fn.rotateCanvas=function g(d){var f,z,y,F;for(f=
+0;f<this.length;f+=1)if(z=K(this[f]))F=P(this[f]),y=new L(d),O(this[f],y,d,g),y.autosave&&ea(z,F),va(z,y,F.transforms);return this};d.fn.scaleCanvas=function N(d){var f,y,F,t;for(f=0;f<this.length;f+=1)if(y=K(this[f]))t=P(this[f]),F=new L(d),O(this[f],F,d,N),F.autosave&&ea(y,t),wa(y,F,t.transforms);return this};d.fn.translateCanvas=function H(d){var f,F,t,B;for(f=0;f<this.length;f+=1)if(F=K(this[f]))B=P(this[f]),t=new L(d),O(this[f],t,d,H),t.autosave&&ea(F,B),xa(F,t,B.transforms);return this};d.fn.drawRect=
+function z(d){var f,t,B,l,u,C,q,v;for(f=0;f<this.length;f+=1)if(t=K(this[f]))B=new L(d),O(this[f],B,d,z),B.visible&&(U(this[f],t,B),Q(this[f],t,B,B.width,B.height),t.beginPath(),l=B.x-B.width/2,u=B.y-B.height/2,(v=B.cornerRadius)?(B.closed=A,C=B.x+B.width/2,q=B.y+B.height/2,0>C-l-2*v&&(v=(C-l)/2),0>q-u-2*v&&(v=(q-u)/2),t.moveTo(l+v,u),t.lineTo(C-v,u),t.arc(C-v,u+v,v,3*M/2,2*M,E),t.lineTo(C,q-v),t.arc(C-v,q-v,v,0,M/2,E),t.lineTo(l+v,q),t.arc(l+v,q-v,v,M/2,M,E),t.lineTo(l,u+v),t.arc(l+v,u+v,v,M,3*M/
+2,E)):t.rect(l,u,B.width,B.height),V(this[f],t,B),X(this[f],t,B));return this};d.fn.drawArc=function y(d){var f,B,l,u,C,q,v,p,k,n,m;for(f=0;f<this.length;f+=1)if(B=K(this[f]))l=new L(d),O(this[f],l,d,y),l.visible&&(U(this[f],B,l),Q(this[f],B,l,2*l.radius),l.inDegrees||360!==l.end||(l.end=2*M),l.start*=l._toRad,l.end*=l._toRad,l.start-=M/2,l.end-=M/2,B.beginPath(),B.arc(l.x,l.y,l.radius,l.start,l.end,l.ccw),k=M/180*1,l.ccw&&(k*=-1),u=l.x+l.radius*R(l.start+k),C=l.y+l.radius*T(l.start+k),q=l.x+l.radius*
+R(l.start),v=l.y+l.radius*T(l.start),p=l.x+l.radius*R(l.end+k),k=l.y+l.radius*T(l.end+k),n=l.x+l.radius*R(l.end),m=l.y+l.radius*T(l.end),ha(this[f],B,l,u,C,q,v,n,m,p,k),V(this[f],B,l),X(this[f],B,l));return this};d.fn.drawEllipse=function F(d){var f,l,u,C,q;for(f=0;f<this.length;f+=1)if(l=K(this[f]))u=new L(d),O(this[f],u,d,F),u.visible&&(U(this[f],l,u),Q(this[f],l,u,u.width,u.height),C=4/3*u.width,q=u.height,l.beginPath(),l.moveTo(u.x,u.y-q/2),l.bezierCurveTo(u.x-C/2,u.y-q/2,u.x-C/2,u.y+q/2,u.x,
+u.y+q/2),l.bezierCurveTo(u.x+C/2,u.y+q/2,u.x+C/2,u.y-q/2,u.x,u.y-q/2),V(this[f],l,u),u.closed=A,X(this[f],l,u));return this};d.fn.drawPolygon=function t(d){var f,u,C,q,v,p,k,n,m,x;for(f=0;f<this.length;f+=1)if(u=K(this[f]))if(C=new L(d),O(this[f],C,d,t),C.visible){U(this[f],u,C);Q(this[f],u,C,2*C.radius);v=2*M/C.sides;p=v/2;q=p+M/2;k=C.radius*R(p);u.beginPath();for(x=0;x<C.sides;x+=1)n=C.x+C.radius*R(q),m=C.y+C.radius*T(q),u.lineTo(n,m),C.concavity&&(n=C.x+(k+-k*C.concavity)*R(q+p),m=C.y+(k+-k*C.concavity)*
+T(q+p),u.lineTo(n,m)),q+=v;V(this[f],u,C);C.closed=A;X(this[f],u,C)}return this};d.fn.drawSlice=function B(f){var u,C,q,v,p;for(u=0;u<this.length;u+=1)if(d(this[u]),C=K(this[u]))q=new L(f),O(this[u],q,f,B),q.visible&&(U(this[u],C,q),Q(this[u],C,q,2*q.radius),q.start*=q._toRad,q.end*=q._toRad,q.start-=M/2,q.end-=M/2,q.start=Fa(q.start),q.end=Fa(q.end),q.end<q.start&&(q.end+=2*M),v=(q.start+q.end)/2,p=q.radius*q.spread*R(v),v=q.radius*q.spread*T(v),q.x+=p,q.y+=v,C.beginPath(),C.arc(q.x,q.y,q.radius,
+q.start,q.end,q.ccw),C.lineTo(q.x,q.y),V(this[u],C,q),q.closed=A,X(this[u],C,q));return this};d.fn.drawLine=function l(d){var f,q,v,p,k,n;for(f=0;f<this.length;f+=1)if(q=K(this[f]))if(v=new L(d),O(this[f],v,d,l),v.visible){U(this[f],q,v);Q(this[f],q,v,0);p=1;for(q.beginPath();A;)if(k=v["x"+p],n=v["y"+p],k!==D&&n!==D)q.lineTo(k+v.x,n+v.y),p+=1;else break;p-=1;ha(this[f],q,v,v.x2+v.x,v.y2+v.y,v.x1+v.x,v.y1+v.y,v["x"+(p-1)]+v.x,v["y"+(p-1)]+v.y,v["x"+p]+v.x,v["y"+p]+v.y);V(this[f],q,v);X(this[f],q,v)}return this};
+d.fn.drawQuadratic=function u(f){var d,v,p,k,n,m,x,w;for(d=0;d<this.length;d+=1)if(v=K(this[d]))if(p=new L(f),O(this[d],p,f,u),p.visible){U(this[d],v,p);Q(this[d],v,p,0);k=2;v.beginPath();for(v.moveTo(p.x1+p.x,p.y1+p.y);A;)if(n=p["x"+k],m=p["y"+k],x=p["cx"+(k-1)],w=p["cy"+(k-1)],n!==D&&m!==D&&x!==D&&w!==D)v.quadraticCurveTo(x+p.x,w+p.y,n+p.x,m+p.y),k+=1;else break;k-=1;ha(this[d],v,p,p.cx1+p.x,p.cy1+p.y,p.x1+p.x,p.y1+p.y,p["cx"+(k-1)]+p.x,p["cy"+(k-1)]+p.y,p["x"+k]+p.x,p["y"+k]+p.y);V(this[d],v,p);
+X(this[d],v,p)}return this};d.fn.drawBezier=function C(d){var f,p,k,n,m,x,w,s,I,S,W;for(f=0;f<this.length;f+=1)if(p=K(this[f]))if(k=new L(d),O(this[f],k,d,C),k.visible){U(this[f],p,k);Q(this[f],p,k,0);n=2;m=1;p.beginPath();for(p.moveTo(k.x1+k.x,k.y1+k.y);A;)if(x=k["x"+n],w=k["y"+n],s=k["cx"+m],I=k["cy"+m],S=k["cx"+(m+1)],W=k["cy"+(m+1)],x!==D&&w!==D&&s!==D&&I!==D&&S!==D&&W!==D)p.bezierCurveTo(s+k.x,I+k.y,S+k.x,W+k.y,x+k.x,w+k.y),n+=1,m+=2;else break;n-=1;m-=2;ha(this[f],p,k,k.cx1+k.x,k.cy1+k.y,k.x1+
+k.x,k.y1+k.y,k["cx"+(m+1)]+k.x,k["cy"+(m+1)]+k.y,k["x"+n]+k.x,k["y"+n]+k.y);V(this[f],p,k);X(this[f],p,k)}return this};d.fn.drawVector=function q(f){var d,k,n,m,x,w,s,I,S,W,G,E;for(d=0;d<this.length;d+=1)if(k=K(this[d]))if(n=new L(f),O(this[d],n,f,q),n.visible){U(this[d],k,n);Q(this[d],k,n,0);m=1;k.beginPath();S=G=s=n.x;W=E=I=n.y;for(k.moveTo(n.x,n.y);A;)if(x=n["a"+m],w=n["l"+m],x!==D&&w!==D)x*=n._toRad,x-=M/2,S=G,W=E,G+=w*R(x),E+=w*T(x),1===m&&(s=G,I=E),k.lineTo(G,E),m+=1;else break;ha(this[d],k,
+n,s,I,n.x,n.y,S,W,G,E);V(this[d],k,n);X(this[d],k,n)}return this};d.fn.drawText=function v(p){var k,n,m,x,w,s,I;for(k=0;k<this.length;k+=1)if(d(this[k]),n=K(this[k]))if(m=new L(p),O(this[k],m,p,v),m.visible){U(this[k],n,m);n.textBaseline=m.baseline;n.textAlign=m.align;Ha(n,m);x=m.maxWidth!==f?Ja(n,m):m.text.toString().split("\n");Ia(this[k],n,m,x);p&&m.layer&&(p.width=m.width,p.height=m.height);Q(this[k],n,m,m.width,m.height);s=m.x;"left"===m.align?m.respectAlign?m.x+=m.width/2:s-=m.width/2:"right"===
+m.align&&(m.respectAlign?m.x-=m.width/2:s+=m.width/2);for(w=0;w<x.length;w+=1)n.shadowColor=m.shadowColor,I=m.y+w*m.height/x.length-(x.length-1)*m.height/x.length/2,n.fillText(x[w],s,I),"transparent"!==m.fillStyle&&(n.shadowColor="transparent"),n.strokeText(x[w],s,I);m._event&&(n.beginPath(),n.rect(m.x-m.width/2,m.y-m.height/2,m.width,m.height),V(this[k],n,m),n.closePath());m._transformed&&n.restore()}Z=m;return this};d.fn.measureText=function(d){var f,k;f=this.getLayer(d);if(!f||f&&!f._layer)f=new L(d);
+if(d=K(this[0]))Ha(d,f),k=Ja(d,f),Ia(this[0],d,f,k);return f};d.fn.drawImage=function p(k){function n(k,p,n,s,r,w){return function(){U(m[p],n,r);r.width===f&&r.sWidth===f&&(r.width=r.sWidth=G.width);r.height===f&&r.sHeight===f&&(r.height=r.sHeight=G.height);w&&(w.width=r.width,w.height=r.height);r.sWidth!==f&&r.sHeight!==f&&r.sx!==f&&r.sy!==f?(r.width===f&&(r.width=r.sWidth),r.height===f&&(r.height=r.sHeight),r.cropFromCenter||(r.sx+=r.sWidth/2,r.sy+=r.sHeight/2),0>r.sy-r.sHeight/2&&(r.sy=r.sHeight/
+2),r.sy+r.sHeight/2>G.height&&(r.sy=G.height-r.sHeight/2),0>r.sx-r.sWidth/2&&(r.sx=r.sWidth/2),r.sx+r.sWidth/2>G.width&&(r.sx=G.width-r.sWidth/2),Q(m[p],n,r,r.width,r.height),n.drawImage(G,r.sx-r.sWidth/2,r.sy-r.sHeight/2,r.sWidth,r.sHeight,r.x-r.width/2,r.y-r.height/2,r.width,r.height)):(Q(m[p],n,r,r.width,r.height),n.drawImage(G,r.x-r.width/2,r.y-r.height/2,r.width,r.height));n.beginPath();n.rect(r.x-r.width/2,r.y-r.height/2,r.width,r.height);V(m[p],n,r);n.closePath();r._transformed&&n.restore();
+ua(n,s,r);r.load&&r.load.call(k,w);r.layer&&(r._args._masks=s.transforms.masks.slice(0),r._next&&d(k).drawLayers({clear:E,resetFire:A,index:r._next}))}}var m=this,x,w,s,I,S,W,G,M,J;for(w=0;w<m.length;w+=1)if(x=m[w],s=K(m[w]))I=P(m[w]),S=new L(k),W=O(m[w],S,k,p),S.visible&&(J=S.source,M=J.getContext,J.src||M?G=J:J&&(ra[J]!==D?G=ra[J]:(G=new sa,G.src=J,ra[J]=G)),G&&(G.complete||M?n(x,w,s,I,S,W)():(d(G).bind("load",n(x,w,s,I,S,W)),G.src=G.src)));return m};d.fn.createPattern=function(p){function k(){s=
+m.createPattern(w,x.repeat);x.load&&x.load.call(n[0],s)}var n=this,m,x,w,s,I;(m=K(n[0]))?(x=new L(p),I=x.source,$(I)?(w=d("<canvas />")[0],w.width=x.width,w.height=x.height,p=K(w),I.call(w,p),k()):(p=I.getContext,I.src||p?w=I:(w=new sa,w.src=I),w.complete||p?k():(d(w).bind("load",k),w.src=w.src))):s=f;return s};d.fn.createGradient=function(d){var k,n=[],m,x,w,s,I,A,E;d=new L(d);if(k=K(this[0])){d.x1=d.x1||0;d.y1=d.y1||0;d.x2=d.x2||0;d.y2=d.y2||0;k=d.r1!==f||d.r2!==f?k.createRadialGradient(d.x1,d.y1,
+d.r1,d.x2,d.y2,d.r2):k.createLinearGradient(d.x1,d.y1,d.x2,d.y2);for(s=1;d["c"+s]!==D;s+=1)d["s"+s]!==D?n.push(d["s"+s]):n.push(f);m=n.length;n[0]===f&&(n[0]=0);n[m-1]===f&&(n[m-1]=1);for(s=0;s<m;s+=1){if(n[s]!==f){A=1;E=0;x=n[s];for(I=s+1;I<m;I+=1)if(n[I]!==f){w=n[I];break}else A+=1;x>w&&(n[I]=n[s])}else n[s]===f&&(E+=1,n[s]=x+(w-x)/A*E);k.addColorStop(n[s],d["c"+(s+1)])}}else k=f;return k};d.fn.setPixels=function k(d){var m,x,w,s,A,E,D,G,J;for(x=0;x<this.length;x+=1)if(m=this[x],w=K(m)){s=new L(d);
+O(m,s,d,k);Q(this[x],w,s,s.width,s.height);if(s.width===f||s.height===f)s.width=m.width,s.height=m.height,s.x=s.width/2,s.y=s.height/2;if(0!==s.width&&0!==s.height){E=w.getImageData(s.x-s.width/2,s.y-s.height/2,s.width,s.height);D=E.data;J=D.length;if(s.each)for(G=0;G<J;G+=4)A={r:D[G],g:D[G+1],b:D[G+2],a:D[G+3]},s.each.call(m,A,s),D[G]=A.r,D[G+1]=A.g,D[G+2]=A.b,D[G+3]=A.a;w.putImageData(E,s.x-s.width/2,s.y-s.height/2);w.restore()}}return this};d.fn.getCanvasImage=function(d,n){var m=this[0];n===D&&
+(n=1);return m&&m.toDataURL?m.toDataURL("image/"+d,n):f};d.fn.detectPixelRatio=function(f){var n,m,x,w,s,D,E;for(m=0;m<this.length;m+=1)n=this[m],d(this[m]),x=K(n),E=P(this[m]),E.scaled||(w=window.devicePixelRatio||1,s=x.webkitBackingStorePixelRatio||x.mozBackingStorePixelRatio||x.msBackingStorePixelRatio||x.oBackingStorePixelRatio||x.backingStorePixelRatio||1,w/=s,1!==w&&(s=n.width,D=n.height,n.width=s*w,n.height=D*w,n.style.width=s+"px",n.style.height=D+"px",x.scale(w,w)),E.pixelRatio=w,E.scaled=
+A,f&&f.call(n,w));return this};d.support.canvas=d("<canvas />")[0].getContext;J.defaults=ia;J.transformShape=Q;J.detectEvents=V;J.closePath=X;J.getTouchEventName=Aa;d.jCanvas=J})(jQuery,document,Image,Math,parseFloat,!0,!1,null);
http://git-wip-us.apache.org/repos/asf/incubator-flink/blob/76d603c0/flink-runtime/src/main/resources/web-docs-infoserver/js/jobmanagerFrontend.js
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/resources/web-docs-infoserver/js/jobmanagerFrontend.js b/flink-runtime/src/main/resources/web-docs-infoserver/js/jobmanagerFrontend.js
new file mode 100644
index 0000000..27e33dc
--- /dev/null
+++ b/flink-runtime/src/main/resources/web-docs-infoserver/js/jobmanagerFrontend.js
@@ -0,0 +1,471 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var jsonGlobal;
+var widthProgressbar = 120;
+
+// For coloring the dependency graph
+var colors = [ "#37485D", "#D9AADC", "#4F7C61", "#8F9C6A", "#BC8E88" ];
+
+var timestamp = 0;
+
+var recentjobs = new Array();
+
+/*
+ * Initializes global job table
+ */
+function init() {
+ $.ajax({ url : "jobsInfo", type : "GET", cache: false, success : function(json) {
+
+ // If no job running, poll for new jobs
+ if(json == "")
+ setTimeout(function() {init()}, 2000);
+
+ jsonGlobal = json
+ // Fill Table
+ fillTable("#jobs", json)
+
+ }, dataType : "json",
+ });
+}
+
+// Init once on page load
+$(init());
+
+/*
+ * Pools for updates on currently running jobs
+ */
+function poll(jobId) {
+ $.ajax({ url : "jobsInfo?get=updates&job="+jobId, type : "GET", cache: false, success : function(json) {
+
+ // Call init of no more jobs are running
+
+ $.each(json.recentjobs, function(j, job) {
+ if(!$.inArray(job.jobid, recentjobs)) {
+ init();
+ }
+ });
+
+ updateTable(json);
+ }, dataType : "json",
+ });
+};
+
+/*
+ * Polls the job history on page load
+ */
+(function pollArchive() {
+ $.ajax({ url : "jobsInfo?get=archive", cache: false, type : "GET",
+ success : function(json) {
+
+ // Fill Table
+ fillTableArchive("#jobsArchive", json)
+
+ }, dataType : "json",
+ });
+})();
+
+/*
+ * Polls the number of taskmanagers on page load
+ */
+(function pollTaskmanagers() {
+ $.ajax({ url : "jobsInfo?get=taskmanagers", cache: false, type : "GET",
+ success : function(json) {
+ $("#stat-taskmanagers").html(json.taskmanagers);
+ $("#stat-slots").html(json.slots);
+ }, dataType : "json",
+ });
+})();
+
+/*
+ * Toggle ExecutionVectors
+ */
+$(document).on("click", ".opensub", function() {
+ var id = $(this).data("open");
+ $("#" + id).toggle();
+ drawDependencies();
+});
+
+/**
+ * Cancels a job
+ */
+$(document).on("click", ".cancel", function() {
+ var id = $(this).attr("job");
+ $.ajax({ url : "jobsInfo?get=cancel&job=" + id, cache: false, type : "GET",
+ success : function(json) {
+ }
+ });
+});
+
+/*
+ * Draw graph on left side beside table
+ */
+function drawDependencies() {
+ $.each(jsonGlobal, function(i, job) {
+ $("#dependencies" + job.jobid).clearCanvas();
+ $("#dependencies" + job.jobid).attr("height", 10);
+ $("#dependencies" + job.jobid).attr("height", ($("#" + job.jobid).height()-$("#sum").height()-14));
+
+ edgeCount = -1;
+ $.each(job.groupvertices, function(j, groupvertex) {
+ $.each(groupvertex.backwardEdges, function(k, edge) {
+ var y1 = ($("#" + edge.groupvertexid).offset().top - $("#dependencies"+ job.jobid).offset().top) + 15;
+ var y2 = ($("#" + groupvertex.groupvertexid).offset().top - $("#dependencies" + job.jobid).offset().top) + 15;
+ var cy1 = y1 + (y2 - y1) / 2;
+ var cx1 = 0;
+ edgeCount++;
+
+ var strokeWidth = 2;
+ if (edge.channelType == "NETWORK")
+ var strokeWidth = 3;
+
+ $("#dependencies" + job.jobid).drawQuadratic({
+ strokeStyle : colors[edgeCount % 5],
+ strokeWidth : strokeWidth,
+ rounded : true,
+ endArrow : true,
+ arrowRadius : 10,
+ arrowAngle : 40,
+ x1 : 95,
+ y1 : y1, // Start point
+ cx1 : cx1,
+ cy1 : cy1, // Control point
+ x2 : 95,
+ y2 : y2
+ // End point
+ });
+ });
+ });
+ });
+
+}
+
+/*
+ * Creates and fills the global running jobs table
+ */
+function fillTable(table, json) {
+ $(table).html("");
+
+ $.each(json, function(i, job) {
+ $("#rJpH").hide();
+ var countGroups = 0;
+ var countTasks = 0;
+ var countStarting = 0;
+ var countRunning = 0;
+ var countFinished = 0;
+ var countCanceled = 0;
+ var countFailed = 0;
+ recentjobs.push(job.jobid);
+ poll(job.jobid);
+ if(parseInt(job.time) > timestamp)
+ timestamp = parseInt(job.time);
+ $(table).append(
+ "<h2 id=\""+job.jobid+"_title\">"+ job.jobname
+ + " ("+ formattedTimeFromTimestamp(job.time) + ")"
+ +"</h2>"
+ +"<a id=\""+job.jobid+"_cancel\" class=\"cancel btn btn-warning\" href=\"#\" job=\""+job.jobid+"\" style=\"margin-bottom: 0.5cm\">cancel</a><br />");
+ var jobtable;
+ jobtable = "<div class=\"table-responsive\">";
+ jobtable += "<table class=\"table table-bordered table-hover table-striped\" id=\""+job.jobid+"\" jobname=\""+job.jobname+"\">\
+ <tr>\
+ <th>Name</th>\
+ <th>Tasks</th>\
+ <th>Starting</th>\
+ <th>Running</th>\
+ <th>Finished</th>\
+ <th>Canceled</th>\
+ <th>Failed</th>\
+ </tr>";
+
+ $.each(job.groupvertices, function(j, groupvertex) {
+ countGroups++;
+ countTasks += groupvertex.numberofgroupmembers;
+ starting = (groupvertex.CREATED + groupvertex.SCHEDULED + groupvertex.DEPLOYING);
+ countStarting += starting;
+ countRunning += groupvertex.RUNNING;
+ countFinished += groupvertex.FINISHED;
+ countCanceled += groupvertex.CANCELING + groupvertex.CANCELED;
+ countFailed += groupvertex.FAILED;
+ jobtable += "<tr>\
+ <td id=\""+groupvertex.groupvertexid+"\">\
+ <span class=\"opensub\" data-open=\"_"+groupvertex.groupvertexid+"\">"
+ + groupvertex.groupvertexname
+ + "</span>\
+ </td>\
+ <td class=\"nummembers\">"+ groupvertex.numberofgroupmembers+ "</td>";
+ jobtable += progressBar(groupvertex.numberofgroupmembers, starting, 'starting');
+ jobtable += progressBar(groupvertex.numberofgroupmembers, groupvertex.RUNNING, 'running');
+ jobtable += progressBar(groupvertex.numberofgroupmembers, (groupvertex.FINISHED), 'success finished');
+ jobtable += progressBar(groupvertex.numberofgroupmembers, (groupvertex.CANCELING + groupvertex.CANCELED), 'warning canceled');
+ jobtable += progressBar(groupvertex.numberofgroupmembers, groupvertex.FAILED, 'danger failed');
+ jobtable += "</tr><tr>\
+ <td colspan=8 id=\"_"+groupvertex.groupvertexid+"\" style=\"display:none\">\
+ <div class =\"table-responsive\">\
+ <table class=\"table table-bordered table-hover table-striped tablesorter\">\
+ <tr>\
+ <th>Name</th>\
+ <th>status</th>\
+ <th>instancename</th>\
+ <th>instancetype</th>\
+ </tr>";
+ $.each(groupvertex.groupmembers, function(k, vertex) {
+ jobtable += "<tr id="+vertex.vertexid+" lastupdate=\""+job.time+"\">\
+ <td>"+ vertex.vertexname + "</td>\
+ <td class=\"status\">"+ vertex.vertexstatus + "</td>\
+ <td>"+ vertex.vertexinstancename + "</td>\
+ <td>"+ vertex.vertexinstancetype + "</td>\
+ </tr>";
+ });
+ jobtable += "</table></div>\
+ </td></tr>";
+ });
+
+ jobtable += "<tr id=\"sum\">\
+ <td colspan=\"2\" align=\"center\">Sum</td>\
+ <td class=\"nummebembers\">"+ countTasks + "</td>";
+ jobtable += progressBar(countTasks, countStarting, 'starting');
+ jobtable += progressBar(countTasks, countRunning, 'running');
+ jobtable += progressBar(countTasks, countFinished, 'success finished');
+ jobtable += progressBar(countTasks, countCanceled, 'warning canceled');
+ jobtable += progressBar(countTasks, countFailed, 'danger failed');
+ jobtable += "</tr>";
+
+ jobtable += "</table></div>"
+ $(table).append(jobtable);
+ $("#" + job.jobid).prepend(
+ "<tr><td width=\"100\" rowspan=" + (countGroups * 2 + 2)+ " style=\"overflow:hidden\">\
+ <canvas id=\"dependencies" + job.jobid+ "\" height=\"10\" width=\"100\"></canvas>\
+ </td></tr>");
+ });
+ drawDependencies(json);
+
+}
+
+/*
+ * Generates the progress bars
+ */
+function progressBar(maximum, input, classVal) {
+ if (input != 0) {
+ return "<td class=\""+classVal+"\" val=\""+input+"\"><div class=\"progress\"><div class=\"progress-bar progress-bar-success\" role=\"progressbar\""
+ + "aria-valuemin=\"0\" aria-valuemax=\""+widthProgressbar+"\" style=\"width:"
+ + (20 + 80*input/maximum) + "%;\">"
+ + input
+ + "</div></div></td>";
+ } else {
+ return "<td class=\""+classVal+"\" val=\""+input+"\">"+input+"</td>";
+ }
+}
+
+
+/*
+ * Generates the progress bar without the class val
+ */
+
+function progressBar2(maximum, input) {
+ if (input != 0) {
+ return "<div class=\"progress\"><div class=\"progress-bar progress-bar-success\" role=\"progressbar\""
+ + "aria-valuemin=\"0\" aria-valuemax=\""+widthProgressbar+"\" style=\"width:"
+ + (20 + 80*input/maximum) + "%;\">"
+ + input
+ + "</div></div>";
+ }
+}
+
+/*
+ * Returns the new width for a progress bar
+ */
+function newWidth(maximum, val) {
+ return (20 + 80*val/maximum);
+}
+
+
+/*
+ * Updates the global running job table with newest events
+ */
+function updateTable(json) {
+ var pollfinished = false;
+ $.each(json.vertexevents , function(i, event) {
+
+ if(parseInt($("#"+event.vertexid).attr("lastupdate")) < event.timestamp)
+ {
+ // not very nice
+ var oldstatus = ""+$("#"+event.vertexid).children(".status").html();
+ if (oldstatus == "CREATED" || oldstatus == "SCHEDULED" || oldstatus == "DEPLOYING")
+ oldstatus = "starting";
+ else if(oldstatus == "CANCELING")
+ oldstatus = "canceled";
+
+ var newstate = event.newstate;
+ if(newstate == "CREATED" || newstate == "SCHEDULED" || newstate == "DEPLOYING")
+ newstate = "starting";
+ else if(newstate == "CANCELING")
+ newstate = "canceled";
+
+ // update detailed state
+ $("#"+event.vertexid).children(".status").html(event.newstate);
+ // update timestamp
+ $("#"+event.vertexid).attr("lastupdate", event.timestamp);
+
+ var nummembers = parseInt($("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children(".nummembers").html());
+ var summembers = parseInt($("#sum").children(".nummebembers").html());
+
+
+ if(oldstatus.toLowerCase() != newstate.toLowerCase()) {
+
+ // adjust groupvertex
+ var oldcount = parseInt($("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+oldstatus.toLowerCase()).attr("val"));
+ var oldcount2 = parseInt($("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+newstate.toLowerCase()).attr("val"));
+ $("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+oldstatus.toLowerCase()).attr("val", oldcount-1);
+ $("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+newstate.toLowerCase()).attr("val", oldcount2+1);
+
+ //adjust progressbars nummembers
+ if (oldcount == 1) {
+ $("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+oldstatus.toLowerCase()).children().first().remove();
+ $("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+oldstatus.toLowerCase()).html("0");
+
+ } else if (oldcount > 1) {
+ $("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+oldstatus.toLowerCase()).first().children().first().children().first().css("width", newWidth(nummembers, (oldcount-1))+"%").html(oldcount-1);
+ }
+
+ if (oldcount2 == 0) {
+ $("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+newstate.toLowerCase()).html(progressBar2(nummembers, 1, newstate.toLowerCase()));
+ } else if (oldcount2 > 0) {
+ $("#"+event.vertexid).parent().parent().parent().parent().parent().prev().children("."+newstate.toLowerCase()).first().children().first().children().first().css("width", newWidth(nummembers, (oldcount2+1))+"%").html(oldcount2+1);
+ }
+ // adjust sum
+ oldcount = parseInt($("#sum").children("."+oldstatus.toLowerCase()).attr("val"));
+ oldcount2 = parseInt($("#sum").children("."+newstate.toLowerCase()).attr("val"));
+ $("#sum").children("."+oldstatus.toLowerCase()).attr("val", oldcount-1);
+ $("#sum").children("."+newstate.toLowerCase()).attr("val", oldcount2+1);
+
+ //adjust progressbars summembers
+ if (oldcount == 1) {
+ $("#sum").children("."+oldstatus.toLowerCase()).children().first().remove();
+ $("#sum").children("."+oldstatus.toLowerCase()).html("0");
+ } else if (oldcount > 1) {
+ $("#sum").children("."+oldstatus.toLowerCase()).first().children().first().children().first().css("width", newWidth(summembers, (oldcount-1))+"%").html(oldcount-1);
+ }
+
+ if (oldcount2 == 0) {
+ $("#sum").children("."+newstate.toLowerCase()).first().html(progressBar2(summembers, 1, newstate.toLowerCase()));
+ } else if (oldcount2 > 0) {
+ $("#sum").children("."+newstate.toLowerCase()).first().children().first().children().first().css("width", newWidth(summembers, (oldcount2+1))+"%").html(oldcount2+1);
+ }
+ }
+ }
+ });
+
+ // handle jobevents
+ $.each(json.jobevents , function(i, event) {
+ console.log(event.newstate);
+
+ if(event.newstate == "FINISHED" || event.newstate == "FAILED" || event.newstate == "CANCELED") {
+ // stop polling
+ pollfinished = true;
+
+ // delete table
+ var jobname = $("#"+json.jobid).attr("jobname");
+ $("#"+json.jobid).remove();
+ $("#"+json.jobid+"_title").remove();
+ $("#"+json.jobid+"_cancel").remove();
+
+ // remove from internal list
+ for(var i in recentjobs){
+ if(recentjobs[i]==json.jobid){
+ recentjobs.splice(i,1);
+ break;
+ }
+ }
+
+ //display message if all jobs are done
+ if(recentjobs.length == 0) {
+ $("#rJpH").show();
+ }
+
+ // add to history
+ setTimeout(function() {
+ var jobjson = {};
+ jobjson.jobid = json.jobid;
+ jobjson.jobname = jobname;
+ jobjson.time = event.timestamp;
+ jobjson.status = event.newstate;
+ _fillTableArchive("#jobsArchive", jobjson, true);
+ }, 8000);
+ }
+ });
+
+ if(!pollfinished)
+ setTimeout(function() {poll(json.jobid)}, 2000);
+ else if(recentjobs.length == 0) {
+ // wait long enough for job to be completely removed on server side before new init
+ setTimeout(init, 5000);
+ }
+}
+
+var archive_finished = 0;
+var archive_failed = 0;
+var archive_canceled = 0;
+
+/*
+ * Creates job history table
+ */
+function fillTableArchive(table, json) {
+ $(table).html("");
+
+ $("#jobs-finished").html(archive_finished);
+ $("#jobs-failed").html(archive_failed);
+ $("#jobs-canceled").html(archive_canceled);
+
+ $.each(json, function(i, job) {
+ _fillTableArchive(table, job, false)
+ });
+}
+
+/*
+ * Adds one row to job history table
+ */
+function _fillTableArchive(table, job, prepend) {
+
+ // no duplicates
+ if($("#"+job.jobid+"_archive").length > 0) {
+ return false;
+ }
+
+ if(prepend)
+ $(table).prepend(
+ "<li id=\""+job.jobid+"_archive\"><a href=\"analyze.html?job=" + job.jobid + "\">"
+ + job.jobname + " ("
+ + formattedTimeFromTimestamp(parseInt(job.time))
+ + ")</a></li>");
+ else
+ $(table).append(
+ "<li><a href=\"analyze.html?job=" + job.jobid + "\">"
+ + job.jobname + " ("
+ + formattedTimeFromTimestamp(parseInt(job.time))
+ + ")</a></li>");
+ if (job.status == "FINISHED")
+ archive_finished++;
+ if (job.status == "FAILED")
+ archive_failed++;
+ if (job.status == "CANCELED")
+ archive_canceled++;
+
+ $("#jobs-finished").html(archive_finished);
+ $("#jobs-failed").html(archive_failed);
+ $("#jobs-canceled").html(archive_canceled);
+}