}
if (typeof(window.console) != 'undefined') {
+ // In older versions of Firefox, only console.log is defined.
+ var console = window.console;
+ var log = function(console, method, msg) {
+ if (method && typeof(method) == 'function') {
+ method.call(console, msg);
+ } else {
+ console.log(msg);
+ }
+ };
+
switch (severity) {
case Dygraph.DEBUG:
- window.console.debug('dygraphs: ' + message);
+ log(console, console.debug, 'dygraphs: ' + message);
break;
case Dygraph.INFO:
- window.console.info('dygraphs: ' + message);
+ log(console, console.info, 'dygraphs: ' + message);
break;
case Dygraph.WARNING:
- window.console.warn('dygraphs: ' + message);
+ log(console, console.warn, 'dygraphs: ' + message);
break;
case Dygraph.ERROR:
- window.console.error('dygraphs: ' + message);
+ log(console, console.error, 'dygraphs: ' + message);
break;
}
}
/**
* @param {string} message
- * @private
*/
Dygraph.error = function(message) {
Dygraph.log(Dygraph.ERROR, message);
* on the event. The function takes one parameter: the event object.
* @private
*/
-Dygraph.prototype.addEvent = function addEvent(elem, type, fn) {
+Dygraph.prototype.addAndTrackEvent = function(elem, type, fn) {
Dygraph.addEvent(elem, type, fn);
this.registeredEvents_.push({ elem : elem, type : type, fn : fn });
};
* on the event. The function takes one parameter: the event object.
* @private
*/
-Dygraph.removeEvent = function addEvent(elem, type, fn) {
+Dygraph.removeEvent = function(elem, type, fn) {
if (elem.removeEventListener) {
elem.removeEventListener(type, fn, false);
} else {
}
};
+Dygraph.prototype.removeTrackedEvents_ = function() {
+ if (this.registeredEvents_) {
+ for (var idx = 0; idx < this.registeredEvents_.length; idx++) {
+ var reg = this.registeredEvents_[idx];
+ Dygraph.removeEvent(reg.elem, reg.type, reg.fn);
+ }
+ }
+
+ this.registeredEvents_ = [];
+};
+
/**
* Cancels further processing of an event. This is useful to prevent default
* browser actions, e.g. highlighting text on a double-click.
if(obj.offsetParent) {
var copyObj = obj;
while(1) {
+ // NOTE: the if statement here is for IE8.
+ var borderLeft = "0";
+ if (window.getComputedStyle) {
+ borderLeft = window.getComputedStyle(copyObj, null).borderLeft || "0";
+ }
+ curleft += parseInt(borderLeft, 10) ;
curleft += copyObj.offsetLeft;
if(!copyObj.offsetParent) {
break;
if(obj.offsetParent) {
var copyObj = obj;
while(1) {
+ // NOTE: the if statement here is for IE8.
+ var borderTop = "0";
+ if (window.getComputedStyle) {
+ borderTop = window.getComputedStyle(copyObj, null).borderTop || "0";
+ }
+ curtop += parseInt(borderTop, 10) ;
curtop += copyObj.offsetTop;
if(!copyObj.offsetParent) {
break;
* @param {!Object} self
* @param {!Object} o
* @return {!Object}
- * @private
*/
Dygraph.update = function(self, o) {
if (typeof(o) != 'undefined' && o !== null) {
};
/**
- * Returns a new iterator over array, between indexes start and
+ * Returns a new iterator over array, between indexes start and
* start + length, and only returns entries that pass the accept function
*
* @param {!Array} array the array to iterate over.
* This function will scan the option list and determine if they
* require us to recalculate the pixel positions of each point.
* @param {!Array.<string>} labels a list of options to check.
- * @param {!Object} attrs
+ * @param {!Object} attrs
* @return {boolean} true if the graph needs new points else false.
* @private
*/
/**
* Compares two arrays to see if they are equal. If either parameter is not an
- * array it will return false. Does a shallow compare
+ * array it will return false. Does a shallow compare
* Dygraph.compareArrays([[1,2], [3, 4]], [[1,2], [3,4]]) === false.
* @param {!Array.<T>} array1 first array
* @param {!Array.<T>} array2 second array
delta = delta || Math.PI * 2 / sides;
ctx.beginPath();
- var first = true;
var initialAngle = rotationRadians;
var angle = initialAngle;
var computeCoordinates = function() {
var x = cx + (Math.sin(angle) * radius);
var y = cy + (-Math.cos(angle) * radius);
- return [x, y];
+ return [x, y];
};
var initialCoordinates = computeCoordinates();
* };
* window.addEventListener('mouseup', mouseUpHandler);
* };
- *
+ *
* @constructor
*/
Dygraph.IFrameTarp = function() {
return null;
};
+
+/**
+ * Is one node contained by another?
+ * @param {Node} containee The contained node.
+ * @param {Node} container The container node.
+ * @return {boolean} Whether containee is inside (or equal to) container.
+ * @private
+ */
+Dygraph.isNodeContainedBy = function(containee, container) {
+ if (container === null || containee === null) {
+ return false;
+ }
+ var containeeNode = /** @type {Node} */ (containee);
+ while (containeeNode && containeeNode !== container) {
+ containeeNode = containeeNode.parentNode;
+ }
+ return (containeeNode === container);
+};
+
+
+// This masks some numeric issues in older versions of Firefox,
+// where 1.0/Math.pow(10,2) != Math.pow(10,-2).
+/** @type {function(number,number):number} */
+Dygraph.pow = function(base, exp) {
+ if (exp < 0) {
+ return 1.0 / Math.pow(base, -exp);
+ }
+ return Math.pow(base, exp);
+};
+
+// For Dygraph.setDateSameTZ, below.
+Dygraph.dateSetters = {
+ ms: Date.prototype.setMilliseconds,
+ s: Date.prototype.setSeconds,
+ m: Date.prototype.setMinutes,
+ h: Date.prototype.setHours
+};
+
+/**
+ * This is like calling d.setSeconds(), d.setMinutes(), etc, except that it
+ * adjusts for time zone changes to keep the date/time parts consistent.
+ *
+ * For example, d.getSeconds(), d.getMinutes() and d.getHours() will all be
+ * the same before/after you call setDateSameTZ(d, {ms: 0}). The same is not
+ * true if you call d.setMilliseconds(0).
+ *
+ * @type {function(!Date, Object.<number>)}
+ */
+Dygraph.setDateSameTZ = function(d, parts) {
+ var tz = d.getTimezoneOffset();
+ for (var k in parts) {
+ if (!parts.hasOwnProperty(k)) continue;
+ var setter = Dygraph.dateSetters[k];
+ if (!setter) throw "Invalid setter: " + k;
+ setter.call(d, parts[k]);
+ if (d.getTimezoneOffset() != tz) {
+ d.setTime(d.getTime() + (tz - d.getTimezoneOffset()) * 60 * 1000);
+ }
+ }
+};