// --- check whether everything is ok before we return
// NOTE(konigsberg): isIE is never defined in this object. Bug of some sort.
- if (!this.isIE && !(DygraphCanvasRenderer.isSupported(this.element)))
+ if (!this.isIE && !(Dygraph.isCanvasSupported(this.element)))
throw "Canvas is not supported.";
// internal state
};
/**
- * Checks whether the browser supports the <canvas> tag.
- * @private
- */
-DygraphCanvasRenderer.isSupported = function(canvasName) {
- var canvas = null;
- try {
- if (typeof(canvasName) == 'undefined' || canvasName === null) {
- canvas = document.createElement("canvas");
- } else {
- canvas = canvasName;
- }
- canvas.getContext("2d");
- }
- catch (e) {
- var ie = navigator.appVersion.match(/MSIE (\d\.\d)/);
- var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
- if ((!ie) || (ie[1] < 6) || (opera))
- return false;
- return true;
- }
- return true;
-};
-
-/**
* This method is responsible for drawing everything on the chart, including
* lines, error bars, fills and axes.
* It is called immediately after clear() on every frame, including during pans
* context.
*/
Dygraph.Interaction.movePan = function(event, g, context) {
- context.dragEndX = g.dragGetX_(event, context);
- context.dragEndY = g.dragGetY_(event, context);
+ context.dragEndX = Dygraph.dragGetX_(event, context);
+ context.dragEndY = Dygraph.dragGetY_(event, context);
var minDate = context.initialLeftmostDate -
(context.dragEndX - context.dragStartX) * context.xUnitsPerPixel;
* context.
*/
Dygraph.Interaction.endPan = function(event, g, context) {
- context.dragEndX = g.dragGetX_(event, context);
- context.dragEndY = g.dragGetY_(event, context);
+ context.dragEndX = Dygraph.dragGetX_(event, context);
+ context.dragEndY = Dygraph.dragGetY_(event, context);
var regionWidth = Math.abs(context.dragEndX - context.dragStartX);
var regionHeight = Math.abs(context.dragEndY - context.dragStartY);
*/
Dygraph.Interaction.moveZoom = function(event, g, context) {
context.zoomMoved = true;
- context.dragEndX = g.dragGetX_(event, context);
- context.dragEndY = g.dragGetY_(event, context);
+ context.dragEndX = Dygraph.dragGetX_(event, context);
+ context.dragEndY = Dygraph.dragGetY_(event, context);
var xDelta = Math.abs(context.dragStartX - context.dragEndX);
var yDelta = Math.abs(context.dragStartY - context.dragEndY);
*/
Dygraph.Interaction.endZoom = function(event, g, context) {
context.isZooming = false;
- context.dragEndX = g.dragGetX_(event, context);
- context.dragEndY = g.dragGetY_(event, context);
+ context.dragEndX = Dygraph.dragGetX_(event, context);
+ context.dragEndY = Dygraph.dragGetY_(event, context);
var regionWidth = Math.abs(context.dragEndX - context.dragStartX);
var regionHeight = Math.abs(context.dragEndY - context.dragStartY);
},
mouseup: function(event, g, context) {
// TODO(danvk): this logic is repeated in Dygraph.Interaction.endZoom
- context.dragEndX = g.dragGetX_(event, context);
- context.dragEndY = g.dragGetY_(event, context);
+ context.dragEndX = Dygraph.dragGetX_(event, context);
+ context.dragEndY = Dygraph.dragGetY_(event, context);
var regionWidth = Math.abs(context.dragEndX - context.dragStartX);
var regionHeight = Math.abs(context.dragEndY - context.dragStartY);
--- /dev/null
+// This file contains typedefs and externs that are needed by the Closure Compiler.
+
+/**
+ * @typedef {{
+ * px: number,
+ * py: number,
+ * isZooming: boolean,
+ * isPanning: boolean,
+ * is2DPan: boolean,
+ * cancelNextDblclick: boolean,
+ * initializeMouseDown:
+ * function(!Event, !Dygraph, !DygraphInteractionContext)
+ * }}
+ */
+var DygraphInteractionContext;
+
/**
* Add an event handler. This smooths a difference between IE and the rest of
* the world.
- * @param { !Element } elem The element to add the event to.
- * @param { string } type The type of the event, e.g. 'click' or 'mousemove'.
- * @param { function(Event):(boolean|undefined) } fn The function to call
+ * @param {!Node} elem The element to add the event to.
+ * @param {string} type The type of the event, e.g. 'click' or 'mousemove'.
+ * @param {function(Event):(boolean|undefined)} fn The function to call
* on the event. The function takes one parameter: the event object.
* @private
*/
* Add an event handler. This event handler is kept until the graph is
* destroyed with a call to graph.destroy().
*
- * @param { !Element } elem The element to add the event to.
- * @param { string } type The type of the event, e.g. 'click' or 'mousemove'.
- * @param { function(Event):(boolean|undefined) } fn The function to call
+ * @param {!Node} elem The element to add the event to.
+ * @param {string} type The type of the event, e.g. 'click' or 'mousemove'.
+ * @param {function(Event):(boolean|undefined)} fn The function to call
* on the event. The function takes one parameter: the event object.
* @private
*/
/**
* Remove an event handler. This smooths a difference between IE and the rest
* of the world.
- * @param {!Element} elem The element to add the event to.
+ * @param {!Node} elem The element to remove the event from.
* @param {string} type The type of the event, e.g. 'click' or 'mousemove'.
* @param {function(Event):(boolean|undefined)} fn The function to call
* on the event. The function takes one parameter: the event object.
* browser actions, e.g. highlighting text on a double-click.
* Based on the article at
* http://www.switchonthecode.com/tutorials/javascript-tutorial-the-scroll-wheel
- * @param { !Event } e The event whose normal behavior should be canceled.
+ * @param {!Event} e The event whose normal behavior should be canceled.
* @private
*/
Dygraph.cancelEvent = function(e) {
};
/**
+ * Converts page the x-coordinate of the event to pixel x-coordinates on the
+ * canvas (i.e. DOM Coords).
+ * @param {!Event} e Drag event.
+ * @param {!DygraphInteractionContext} context Interaction context object.
+ * @return {number} The amount by which the drag has moved to the right.
+ */
+Dygraph.dragGetX_ = function(e, context) {
+ return Dygraph.pageX(e) - context.px;
+};
+
+/**
+ * Converts page the y-coordinate of the event to pixel y-coordinates on the
+ * canvas (i.e. DOM Coords).
+ * @param {!Event} e Drag event.
+ * @param {!DygraphInteractionContext} context Interaction context object.
+ * @return {number} The amount by which the drag has moved down.
+ */
+Dygraph.dragGetY_ = function(e, context) {
+ return Dygraph.pageY(e) - context.py;
+};
+
+/**
* This returns true unless the parameter is 0, null, undefined or NaN.
* TODO(danvk): rename this function to something like 'isNonZeroNan'.
*
};
/**
- * @param { {x:?number,y:?number,yval:?number} } p The point to consider, valid
+ * @param {{x:?number,y:?number,yval:?number}} p The point to consider, valid
* points are {x, y} objects
- * @param { boolean } allowNaNY Treat point with y=NaN as valid
- * @return { boolean } Whether the point has numeric x and y.
+ * @param {boolean=} opt_allowNaNY Treat point with y=NaN as valid
+ * @return {boolean} Whether the point has numeric x and y.
* @private
*/
-Dygraph.isValidPoint = function(p, allowNaNY) {
+Dygraph.isValidPoint = function(p, opt_allowNaNY) {
if (!p) return false; // null or undefined object
if (p.yval === null) return false; // missing point
if (p.x === null || p.x === undefined) return false;
if (p.y === null || p.y === undefined) return false;
- if (isNaN(p.x) || (!allowNaNY && isNaN(p.y))) return false;
+ if (isNaN(p.x) || (!opt_allowNaNY && isNaN(p.y))) return false;
return true;
};
};
/**
- * @param {Object} o
+ * @param {*} o
* @return {boolean}
* @private
*/
b: parseInt(bits[3], 10)
};
};
+
+/**
+ * Checks whether the browser supports the <canvas> tag.
+ * @param {HTMLCanvasElement=} opt_canvasElement Pass a canvas element as an
+ * optimization if you have one.
+ * @return {boolean} Whether the browser supports canvas.
+ */
+Dygraph.isCanvasSupported = function(opt_canvasElement) {
+ var canvas;
+ try {
+ canvas = opt_canvasElement || document.createElement("canvas");
+ canvas.getContext("2d");
+ }
+ catch (e) {
+ var ie = navigator.appVersion.match(/MSIE (\d\.\d)/);
+ var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
+ if ((!ie) || (ie[1] < 6) || (opera))
+ return false;
+ return true;
+ }
+ return true;
+};
+
+/**
+ * Parses the value as a floating point number. This is like the parseFloat()
+ * built-in, but with a few differences:
+ * - the empty string is parsed as null, rather than NaN.
+ * - if the string cannot be parsed at all, an error is logged.
+ * If the string can't be parsed, this method returns null.
+ * @param {string} x The string to be parsed
+ * @param {number=} opt_line_no The line number from which the string comes.
+ * @param {string=} opt_line The text of the line from which the string comes.
+ */
+Dygraph.parseFloat_ = function(x, opt_line_no, opt_line) {
+ var val = parseFloat(x);
+ if (!isNaN(val)) return val;
+
+ // Try to figure out what happeend.
+ // If the value is the empty string, parse it as null.
+ if (/^ *$/.test(x)) return null;
+
+ // If it was actually "NaN", return it as NaN.
+ if (/^ *nan *$/i.test(x)) return NaN;
+
+ // Looks like a parsing error.
+ var msg = "Unable to parse '" + x + "' as a number";
+ if (opt_line !== undefined && opt_line_no !== undefined) {
+ msg += " on line " + (1+(opt_line_no||0)) + " ('" + opt_line + "') of CSV.";
+ }
+ Dygraph.error(msg);
+
+ return null;
+};
};
/**
- * @private
- * Converts page the x-coordinate of the event to pixel x-coordinates on the
- * canvas (i.e. DOM Coords).
- */
-Dygraph.prototype.dragGetX_ = function(e, context) {
- return Dygraph.pageX(e) - context.px;
-};
-
-/**
- * @private
- * Converts page the y-coordinate of the event to pixel y-coordinates on the
- * canvas (i.e. DOM Coords).
- */
-Dygraph.prototype.dragGetY_ = function(e, context) {
- return Dygraph.pageY(e) - context.py;
-};
-
-/**
* Set up all the mouse handlers needed to capture dragging behavior for zoom
* events.
* @private
var canvasPos = Dygraph.findPos(g.canvas_);
contextB.px = canvasPos.x;
contextB.py = canvasPos.y;
- contextB.dragStartX = g.dragGetX_(event, contextB);
- contextB.dragStartY = g.dragGetY_(event, contextB);
+ contextB.dragStartX = Dygraph.dragGetX_(event, contextB);
+ contextB.dragStartY = Dygraph.dragGetY_(event, contextB);
contextB.cancelNextDblclick = false;
contextB.tarp.cover();
}
};
/**
- * Parses the value as a floating point number. This is like the parseFloat()
- * built-in, but with a few differences:
- * - the empty string is parsed as null, rather than NaN.
- * - if the string cannot be parsed at all, an error is logged.
- * If the string can't be parsed, this method returns null.
- * @param {String} x The string to be parsed
- * @param {Number} opt_line_no The line number from which the string comes.
- * @param {String} opt_line The text of the line from which the string comes.
- * @private
- */
-
-// Parse the x as a float or return null if it's not a number.
-Dygraph.prototype.parseFloat_ = function(x, opt_line_no, opt_line) {
- var val = parseFloat(x);
- if (!isNaN(val)) return val;
-
- // Try to figure out what happeend.
- // If the value is the empty string, parse it as null.
- if (/^ *$/.test(x)) return null;
-
- // If it was actually "NaN", return it as NaN.
- if (/^ *nan *$/i.test(x)) return NaN;
-
- // Looks like a parsing error.
- var msg = "Unable to parse '" + x + "' as a number";
- if (opt_line !== null && opt_line_no !== null) {
- msg += " on line " + (1+opt_line_no) + " ('" + opt_line + "') of CSV.";
- }
- Dygraph.error(msg);
-
- return null;
-};
-
-/**
* @private
* Parses a string in a special csv format. We expect a csv file where each
* line is a date point, and the first field in each line is the date string.
(1 + i) + " ('" + line + "') which is not of this form.");
fields[j] = [0, 0];
} else {
- fields[j] = [this.parseFloat_(vals[0], i, line),
- this.parseFloat_(vals[1], i, line)];
+ fields[j] = [Dygraph.parseFloat_(vals[0], i, line),
+ Dygraph.parseFloat_(vals[1], i, line)];
}
}
} else if (this.getBooleanOption("errorBars")) {
(inFields.length - 1) + "): '" + line + "'");
}
for (j = 1; j < inFields.length; j += 2) {
- fields[(j + 1) / 2] = [this.parseFloat_(inFields[j], i, line),
- this.parseFloat_(inFields[j + 1], i, line)];
+ fields[(j + 1) / 2] = [Dygraph.parseFloat_(inFields[j], i, line),
+ Dygraph.parseFloat_(inFields[j + 1], i, line)];
}
} else if (this.getBooleanOption("customBars")) {
// Bars are a low;center;high tuple
} else {
vals = val.split(";");
if (vals.length == 3) {
- fields[j] = [ this.parseFloat_(vals[0], i, line),
- this.parseFloat_(vals[1], i, line),
- this.parseFloat_(vals[2], i, line) ];
+ fields[j] = [ Dygraph.parseFloat_(vals[0], i, line),
+ Dygraph.parseFloat_(vals[1], i, line),
+ Dygraph.parseFloat_(vals[2], i, line) ];
} else {
Dygraph.warn('When using customBars, values must be either blank ' +
'or "low;center;high" tuples (got "' + val +
} else {
// Values are just numbers
for (j = 1; j < inFields.length; j++) {
- fields[j] = this.parseFloat_(inFields[j], i, line);
+ fields[j] = Dygraph.parseFloat_(inFields[j], i, line);
}
}
if (ret.length > 0 && fields[0] < ret[ret.length - 1][0]) {