X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph-utils.js;h=3d77148654e82d9e391008e17245b1845bd528d3;hb=769e8bc7b8799385e2677b26a5c0a72e839f44ca;hp=bf488efd02eb59467a13ee0399fd0473bc0d5220;hpb=920208fbb3565a1f9075d49a7be486819bdd1174;p=dygraphs.git diff --git a/dygraph-utils.js b/dygraph-utils.js index bf488ef..3d77148 100644 --- a/dygraph-utils.js +++ b/dygraph-utils.js @@ -11,6 +11,8 @@ * search) and generic DOM-manipulation functions. */ +"use strict"; + Dygraph.LOG_SCALE = 10; Dygraph.LN_TEN = Math.log(Dygraph.LOG_SCALE); @@ -25,7 +27,12 @@ Dygraph.INFO = 2; Dygraph.WARNING = 3; Dygraph.ERROR = 3; -// TODO(danvk): any way I can get the line numbers to be this.warn call? +// Set this to log stack traces on warnings, etc. +// This requires stacktrace.js, which is up to you to provide. +// A copy can be found in the dygraphs repo, or at +// https://github.com/eriwen/javascript-stacktrace +Dygraph.LOG_STACK_TRACES = false; + /** * @private * Log an error on the JS console at the given severity. @@ -33,6 +40,24 @@ Dygraph.ERROR = 3; * @param { String } The message to log. */ Dygraph.log = function(severity, message) { + var st; + if (typeof(printStackTrace) != 'undefined') { + // Remove uninteresting bits: logging functions and paths. + var st = printStackTrace({guess:false}); + while (st[0].indexOf("stacktrace") != -1) { + st.splice(0, 1); + } + + st.splice(0, 2); + for (var i = 0; i < st.length; i++) { + st[i] = st[i].replace(/\([^)]*\/(.*)\)/, '@$1') + .replace(/\@.*\/([^\/]*)/, '@$1') + .replace('[object Object].', ''); + } + var top_msg = st.splice(0, 1)[0]; + message += ' (' + top_msg.replace(/^.*@ ?/, '') + ')'; + } + if (typeof(console) != 'undefined') { switch (severity) { case Dygraph.DEBUG: @@ -49,6 +74,10 @@ Dygraph.log = function(severity, message) { break; } } + + if (Dygraph.LOG_STACK_TRACES) { + console.log(st.join('\n')); + } }; /** @private */ @@ -436,6 +465,11 @@ Dygraph.binarySearch = function(val, arry, abs, low, high) { Dygraph.dateParser = function(dateStr) { var dateStrSlashed; var d; + + // Let the system try the format first. + d = Dygraph.dateStrToMillis(dateStr); + if (d && !isNaN(d)) return d; + if (dateStr.search("-") != -1) { // e.g. '2009-7-12' or '2009-07-12' dateStrSlashed = dateStr.replace("-", "/", "g"); while (dateStrSlashed.search("-") != -1) { @@ -579,7 +613,7 @@ Dygraph.clone = function(o) { Dygraph.createCanvas = function() { var canvas = document.createElement("canvas"); - isIE = (/MSIE/.test(navigator.userAgent) && !window.opera); + var isIE = (/MSIE/.test(navigator.userAgent) && !window.opera); if (isIE && (typeof(G_vmlCanvasManager) != 'undefined')) { canvas = G_vmlCanvasManager.initElement(canvas); } @@ -589,6 +623,52 @@ Dygraph.createCanvas = function() { /** * @private + * Checks whether the user is on an Android browser. + * Android does not fully support the tag, e.g. w/r/t/ clipping. + */ +Dygraph.isAndroid = function() { + return /Android/.test(navigator.userAgent); +}; + +/** + * @private + * Call a function N times at a given interval, then call a cleanup function + * once. repeat_fn is called once immediately, then (times - 1) times + * asynchronously. If times=1, then cleanup_fn() is also called synchronously. + * @param repeat_fn {Function} Called repeatedly -- takes the number of calls + * (from 0 to times-1) as an argument. + * @param times {number} The number of times to call repeat_fn + * @param every_ms {number} Milliseconds between calls + * @param cleanup_fn {Function} A function to call after all repeat_fn calls. + * @private + */ +Dygraph.repeatAndCleanup = function(repeat_fn, times, every_ms, cleanup_fn) { + var count = 0; + var start_time = new Date().getTime(); + repeat_fn(count); + if (times == 1) { + cleanup_fn(); + return; + } + + (function loop() { + if (count >= times) return; + var target_time = start_time + (1 + count) * every_ms; + setTimeout(function() { + count++; + repeat_fn(count) + if (count >= times - 1) { + cleanup_fn(); + } else { + loop(); + } + }, target_time - new Date().getTime()); + // TODO(danvk): adjust every_ms to produce evenly-timed function calls. + })(); +}; + +/** + * @private * This function will scan the option list and determine if they * require us to recalculate the pixel positions of each point. * @param { List } a list of options to check. @@ -605,10 +685,6 @@ Dygraph.isPixelChangingOptionList = function(labels, attrs) { 'axisLineColor': true, 'axisLineWidth': true, 'clickCallback': true, - 'colorSaturation': true, - 'colorValue': true, - 'colors': true, - 'connectSeparatedPoints': true, 'digitsAfterDecimal': true, 'drawCallback': true, 'drawPoints': true, @@ -665,7 +741,7 @@ Dygraph.isPixelChangingOptionList = function(labels, attrs) { } // Iterate through the list of updated options. - for (property in attrs) { + for (var property in attrs) { // Break early if we already know we need new points from a previous option. if (requiresNewPoints) { break; @@ -675,7 +751,7 @@ Dygraph.isPixelChangingOptionList = function(labels, attrs) { if (seriesNamesDictionary[property]) { // This property value is a list of options for this series. // If any of these sub properties are not pixel safe, set the flag. - for (subProperty in attrs[property]) { + for (var subProperty in attrs[property]) { // Break early if we already know we need new points from a previous option. if (requiresNewPoints) { break;