X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph-utils.js;h=2ba6ab5c9951e37808951c4a26e70649b4dc7074;hb=7f02898088f43f0bd97e6b9f7f54ee3b0cf630a6;hp=b5521c4912d2270f9ce074d84c7e994770110c27;hpb=004b5c90b03ee12be0ac0e653ec4006970ee6740;p=dygraphs.git diff --git a/dygraph-utils.js b/dygraph-utils.js index b5521c4..2ba6ab5 100644 --- a/dygraph-utils.js +++ b/dygraph-utils.js @@ -172,36 +172,59 @@ Dygraph.hsvToRGB = function (hue, saturation, value) { // The following functions are from quirksmode.org with a modification for Safari from // http://blog.firetree.net/2005/07/04/javascript-find-position/ // http://www.quirksmode.org/js/findpos.html +// ... and modifications to support scrolling divs. -/** @private */ +/** + * Find the x-coordinate of the supplied object relative to the left side + * of the page. + * @private + */ Dygraph.findPosX = function(obj) { var curleft = 0; - if(obj.offsetParent) - while(1) - { - curleft += obj.offsetLeft; - if(!obj.offsetParent) + if(obj.offsetParent) { + var copyObj = obj; + while(1) { + curleft += copyObj.offsetLeft; + if(!copyObj.offsetParent) { break; - obj = obj.offsetParent; + } + copyObj = copyObj.offsetParent; } - else if(obj.x) + } else if(obj.x) { curleft += obj.x; + } + // This handles the case where the object is inside a scrolled div. + while(obj && obj != document.body) { + curleft -= obj.scrollLeft; + obj = obj.parentNode; + } return curleft; }; -/** @private */ +/** + * Find the y-coordinate of the supplied object relative to the top of the + * page. + * @private + */ Dygraph.findPosY = function(obj) { var curtop = 0; - if(obj.offsetParent) - while(1) - { - curtop += obj.offsetTop; - if(!obj.offsetParent) + if(obj.offsetParent) { + var copyObj = obj; + while(1) { + curtop += copyObj.offsetTop; + if(!copyObj.offsetParent) { break; - obj = obj.offsetParent; + } + copyObj = copyObj.offsetParent; } - else if(obj.y) + } else if(obj.y) { curtop += obj.y; + } + // This handles the case where the object is inside a scrolled div. + while(obj && obj != document.body) { + curtop -= obj.scrollTop; + obj = obj.parentNode; + } return curtop; }; @@ -530,3 +553,108 @@ Dygraph.createCanvas = function() { return canvas; }; + +/** + * @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. + * @return { Boolean } true if the graph needs new points else false. + */ +Dygraph.isPixelChangingOptionList = function(labels, attrs) { + // A whitelist of options that do not change pixel positions. + var pixelSafeOptions = { + 'annotationClickHandler': true, + 'annotationDblClickHandler': true, + 'annotationMouseOutHandler': true, + 'annotationMouseOverHandler': true, + 'axisLabelColor': true, + 'axisLineColor': true, + 'axisLineWidth': true, + 'clickCallback': true, + 'colorSaturation': true, + 'colorValue': true, + 'colors': true, + 'connectSeparatedPoints': true, + 'digitsAfterDecimal': true, + 'drawCallback': true, + 'drawPoints': true, + 'drawXGrid': true, + 'drawYGrid': true, + 'fillAlpha': true, + 'gridLineColor': true, + 'gridLineWidth': true, + 'hideOverlayOnMouseOut': true, + 'highlightCallback': true, + 'highlightCircleSize': true, + 'interactionModel': true, + 'isZoomedIgnoreProgrammaticZoom': true, + 'labelsDiv': true, + 'labelsDivStyles': true, + 'labelsDivWidth': true, + 'labelsKMB': true, + 'labelsKMG2': true, + 'labelsSeparateLines': true, + 'labelsShowZeroValues': true, + 'legend': true, + 'maxNumberWidth': true, + 'panEdgeFraction': true, + 'pixelsPerYLabel': true, + 'pointClickCallback': true, + 'pointSize': true, + 'showLabelsOnHighlight': true, + 'showRoller': true, + 'sigFigs': true, + 'strokeWidth': true, + 'underlayCallback': true, + 'unhighlightCallback': true, + 'xAxisLabelFormatter': true, + 'xTicker': true, + 'xValueFormatter': true, + 'yAxisLabelFormatter': true, + 'yValueFormatter': true, + 'zoomCallback': true + }; + + // Assume that we do not require new points. + // This will change to true if we actually do need new points. + var requiresNewPoints = false; + + // Create a dictionary of series names for faster lookup. + // If there are no labels, then the dictionary stays empty. + var seriesNamesDictionary = { }; + if (labels) { + for (var i = 1; i < labels.length; i++) { + seriesNamesDictionary[labels[i]] = true; + } + } + + // Iterate through the list of updated options. + for (property in attrs) { + // Break early if we already know we need new points from a previous option. + if (requiresNewPoints) { + break; + } + if (attrs.hasOwnProperty(property)) { + // Find out of this field is actually a series specific options list. + 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]) { + // Break early if we already know we need new points from a previous option. + if (requiresNewPoints) { + break; + } + if (attrs[property].hasOwnProperty(subProperty) && !pixelSafeOptions[subProperty]) { + requiresNewPoints = true; + } + } + // If this was not a series specific option list, check if its a pixel changing property. + } else if (!pixelSafeOptions[property]) { + requiresNewPoints = true; + } + } + } + + return requiresNewPoints; +};