From: Robert Konigsberg Date: Fri, 4 Jan 2013 03:35:56 +0000 (-0500) Subject: Merge branch 'master' of github.com:kberg/dygraphs X-Git-Tag: v1.0.0~131^2~2 X-Git-Url: https://adrianiainlam.tk/git/?a=commitdiff_plain;h=014a0f3441223be74be72ee47da276010931774f;hp=901b2ebbe25c116c93550cfca91b0704d751d997;p=dygraphs.git Merge branch 'master' of github.com:kberg/dygraphs Conflicts: auto_tests/tests/axis_labels.js --- diff --git a/auto_tests/tests/axis_labels.js b/auto_tests/tests/axis_labels.js index 56ddf3d..d2c819c 100644 --- a/auto_tests/tests/axis_labels.js +++ b/auto_tests/tests/axis_labels.js @@ -569,72 +569,48 @@ AxisLabelsTestCase.prototype.testIncludeZero = function() { AxisLabelsTestCase.prototype.testAxisLabelFontSize = function() { var graph = document.getElementById("graph"); var g = new Dygraph(graph, AxisLabelsTestCase.simpleData, {}); - var assertSize = function(className, size) { - var sizePx = size + "px"; - var labels = graph.getElementsByClassName(className); - assertTrue(labels.length > 0); - - // window.getComputedStyle is apparently compatible with all browsers - // (IE first became compatible with IE9.) - // If this test fails on earlier browsers, then enable something like this, - // because the font size is set by the parent div. - // if (!window.getComputedStyle) { - // fontSize = label.parentElement.style.fontSize; - // } - for (var idx = 0; idx < labels.length; idx++) { - var label = labels[idx]; - var fontSize = window.getComputedStyle(label).fontSize; - assertEquals(sizePx, fontSize); - } - } // Be sure we're dealing with a 14-point default. assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize); - assertSize("dygraph-axis-label-x", 14); - assertSize("dygraph-axis-label-y", 14); + Util.assertFontSizes(graph, "dygraph-axis-label-x", 14); + Util.assertFontSizes(graph, "dygraph-axis-label-y", 14); g.updateOptions({ axisLabelFontSize : 8}); - assertSize("dygraph-axis-label-x", 8); - assertSize("dygraph-axis-label-y", 8); - -/* - Enable these tests when https://code.google.com/p/dygraphs/issues/detail?id=126 - is fixed. + Util.assertFontSizes(graph, "dygraph-axis-label-x", 8); + Util.assertFontSizes(graph, "dygraph-axis-label-y", 8); g.updateOptions({ axisLabelFontSize : null, - axes : { + axes : { x : { axisLabelFontSize : 5 }, - } - }); + } + }); - assertSize("dygraph-axis-label-x", 5); - assertSize("dygraph-axis-label-y", 14); + Util.assertFontSizes(graph, "dygraph-axis-label-x", 5); + Util.assertFontSizes(graph, "dygraph-axis-label-y", 14); g.updateOptions({ - axisLabelFontSize : null, - axes : { - y : { axisLabelFontSize : 3 }, - } - }); + axes : { + y : { axisLabelFontSize : 20 }, + } + }); - assertSize("dygraph-axis-label-x", 5); - assertSize("dygraph-axis-label-y", 3); + Util.assertFontSizes(graph, "dygraph-axis-label-x", 5); + Util.assertFontSizes(graph, "dygraph-axis-label-y", 20); g.updateOptions({ - series : { + series : { Y2 : { axis : "y2" } // copy y2 series to y2 axis. - }, - axes : { - y2 : { axisLabelFontSize : 8 }, - } - }); - - assertSize("dygraph-axis-label-x", 5); - assertSize("dygraph-axis-label-y", 3); - assertSize("dygraph-axis-label-y2", 8); -*/ + }, + axes : { + y2 : { axisLabelFontSize : 12 }, + } + }); + + Util.assertFontSizes(graph, "dygraph-axis-label-x", 5); + Util.assertFontSizes(graph, "dygraph-axis-label-y1", 20); + Util.assertFontSizes(graph, "dygraph-axis-label-y2", 12); } AxisLabelsTestCase.prototype.testAxisLabelFontSizeNull = function() { diff --git a/dygraph-options.js b/dygraph-options.js index f059ff9..81f7667 100644 --- a/dygraph-options.js +++ b/dygraph-options.js @@ -11,7 +11,8 @@ * dygraph_ - the graph. * global_ - global attributes (common among all graphs, AIUI) * user - attributes set by the user - * axes_ - array of axis index to { series : [ series names ] , options : { axis-specific options. } + * yAxes_ - array of axis index to { series : [ series names ] , options : { axis-specific options. } + * xAxis_ - { options : { axis-specific options. } * series_ - { seriesName -> { idx, yAxis, options }} * labels_ - used as mapping from index to series name. */ @@ -28,7 +29,8 @@ */ var DygraphOptions = function(dygraph) { this.dygraph_ = dygraph; - this.axes_ = []; + this.yAxes_ = []; + this.xAxis_ = {}; this.series_ = {}; // Once these two objects are initialized, you can call get(); @@ -92,7 +94,8 @@ DygraphOptions.axisToIndex_ = function(axis) { DygraphOptions.prototype.reparseSeries = function() { this.labels = this.get("labels").slice(1); - this.axes_ = [ { series : [], options : {}} ]; // Always one axis at least. + this.yAxes_ = [ { series : [], options : {}} ]; // Always one axis at least. + this.xAxis_ = { options : {} }; this.series_ = {}; // Traditionally, per-series options were specified right up there with the options. For instance @@ -131,12 +134,12 @@ DygraphOptions.prototype.reparseSeries = function() { var axis = optionsForSeries["axis"]; if (typeof(axis) == 'object') { yAxis = ++axisId; - this.axes_[yAxis] = { series : [ seriesName ], options : axis }; + this.yAxes_[yAxis] = { series : [ seriesName ], options : axis }; } // Associate series without axis options with axis 0. if (!axis) { // undefined - this.axes_[0].series.push(seriesName); + this.yAxes_[0].series.push(seriesName); } this.series_[seriesName] = { idx: idx, yAxis: yAxis, options : optionsForSeries }; @@ -157,7 +160,7 @@ DygraphOptions.prototype.reparseSeries = function() { } var yAxis = this.series_[axis].yAxis; this.series_[seriesName].yAxis = yAxis; - this.axes_[yAxis].series.push(seriesName); + this.yAxes_[yAxis].series.push(seriesName); } } } else { @@ -171,20 +174,20 @@ DygraphOptions.prototype.reparseSeries = function() { yAxis: yAxis, options : optionsForSeries }; - if (!this.axes_[yAxis]) { - this.axes_[yAxis] = { series : [ seriesName ], options : {} }; + if (!this.yAxes_[yAxis]) { + this.yAxes_[yAxis] = { series : [ seriesName ], options : {} }; } else { - this.axes_[yAxis].series.push(seriesName); + this.yAxes_[yAxis].series.push(seriesName); } } } - // This doesn't support reading from the 'x' axis, only 'y' and 'y2. var axis_opts = this.user_["axes"] || {}; - Dygraph.update(this.axes_[0].options, axis_opts["y"] || {}); - if (this.axes_.length > 1) { - Dygraph.update(this.axes_[1].options, axis_opts["y2"] || {}); + Dygraph.update(this.yAxes_[0].options, axis_opts["y"] || {}); + if (this.yAxes_.length > 1) { + Dygraph.update(this.yAxes_[1].options, axis_opts["y2"] || {}); } + Dygraph.update(this.xAxis_.options, axis_opts["x"] || {}); }; /** @@ -223,19 +226,35 @@ DygraphOptions.prototype.getGlobalDefault_ = function(name) { * * @param {String} name the name of the option. * @param {String|number} axis the axis to search. Can be the string representation - * ("y", "y2") or the axis number (0, 1). + * ("x", "y", "y2") or the y-axis number (0, 1). (x-axis can't be specified by number.') */ DygraphOptions.prototype.getForAxis = function(name, axis) { - var axisIdx = 0; + var axisIdx; + var axisString; + + // Since axis can be a number or a string, straighten everything out here. if (typeof(axis) == 'number') { axisIdx = axis; + axisString = axisIdx == 0 ? "y" : "y2"; } else { - // TODO(konigsberg): Accept only valid axis strings? - axisIdx = (axis == "y2") ? 1 : 0; + if (axis == "y1") { axis = "y"; } // Standardize on 'y'. Is this bad? I think so. + if (axis == "y") { + axisIdx = 0; + } else if (axis == "y2") { + axisIdx = 1; + } else if (axis == "x") { + axisIdx = -1; // simply a placeholder for below. + } else { + throw "Unknown axis " + axis; + } + axisString = axis; } + + var userAxis = (axisIdx == -1) ? this.xAxis_ : this.yAxes_[axisIdx]; + // Search the user-specified axis option first. - if (this.axes_[axisIdx]) { - var axisOptions = this.axes_[axisIdx].options; + if (userAxis) { // This condition could be removed if we always set up this.yAxes_ for y2. + var axisOptions = userAxis.options; if (axisOptions.hasOwnProperty(name)) { return axisOptions[name]; } @@ -248,7 +267,6 @@ DygraphOptions.prototype.getForAxis = function(name, axis) { } // Default axis options third. - var axisString = axis == 0 ? "y" : "y2"; var defaultAxisOptions = Dygraph.DEFAULT_ATTRS.axes[axisString]; if (defaultAxisOptions.hasOwnProperty(name)) { return defaultAxisOptions[name]; @@ -294,7 +312,7 @@ DygraphOptions.prototype.getForSeries = function(name, series) { * @return {Number} the number of axes. */ DygraphOptions.prototype.numAxes = function() { - return this.axes_.length; + return this.yAxes_.length; }; /** @@ -307,15 +325,16 @@ DygraphOptions.prototype.axisForSeries = function(seriesName) { /** * Returns the options for the specified axis. */ +// TODO(konigsberg): this is y-axis specific. Support the x axis. DygraphOptions.prototype.axisOptions = function(yAxis) { - return this.axes_[yAxis].options; + return this.yAxes_[yAxis].options; }; /** * Return the series associated with an axis. */ DygraphOptions.prototype.seriesForAxis = function(yAxis) { - return this.axes_[yAxis].series; + return this.yAxes_[yAxis].series; }; /** diff --git a/dygraph.js b/dygraph.js index 1ac7d43..4c8c65d 100644 --- a/dygraph.js +++ b/dygraph.js @@ -598,6 +598,9 @@ Dygraph.prototype.getOption = function(name, opt_seriesName) { return this.attr_(name, opt_seriesName); }; +Dygraph.prototype.getOptionForAxis = function(name, axis) { + return this.attributes_.getForAxis(name, axis); +} /** * @private * @param String} axis The name of the axis (i.e. 'x', 'y' or 'y2') diff --git a/experimental/palette/multi-palette.js b/experimental/palette/multi-palette.js index 2307030..ee01a4c 100644 --- a/experimental/palette/multi-palette.js +++ b/experimental/palette/multi-palette.js @@ -130,49 +130,62 @@ MultiPalette.prototype.activate = function(key) { MultiPalette.prototype.showHash = function() { var hash = this.read(); var textarea = new TextArea(); - textarea.cancel.style.display = "none"; - - /* - * JSON.stringify isn't built to be nice to functions. The following fixes - * this. - * - * First, val.toString only does part of the work, turning it into - * "function () {\n alert(\"p-click!\");\n}", - * - * {start,end}Marker make the surrounding quotes easy to find, and then - * remove them. It also converts the instances of \n and \" so the - * result looks like: - * function () { - * alert("p-click!"); - * }", - */ - var startMarker = "<~%!<"; - var endMarker = ">!%~>"; - var replacer = function(key, val) { - if (typeof val === 'function') { - return startMarker + val.toString() + endMarker; - } - return val; - } - var text = JSON.stringify(hash, replacer, 2); - while(true) { - var start = text.indexOf(startMarker); - var end = text.indexOf(endMarker); - if (start == -1) { - break; - } - var substring = text.substring(start + startMarker.length, end); - while(substring.indexOf("\\n") >= 0) { - substring = substring.replace("\\n", "\n"); + + var hashToString = function(hash) { + /* + * JSON.stringify isn't built to be nice to functions. The following fixes + * this. + * + * First, val.toString only does part of the work, turning it into + * "function () {\n alert(\"p-click!\");\n}", + * + * {start,end}Marker make the surrounding quotes easy to find, and then + * remove them. It also converts the instances of \n and \" so the + * result looks like: + * function () { + * alert("p-click!"); + * }", + */ + var startMarker = "<~%!<"; + var endMarker = ">!%~>"; + var replacer = function(key, val) { + if (typeof val === 'function') { + return startMarker + val.toString() + endMarker; + } + return val; } - while(substring.indexOf("\\\"") >= 0) { - substring = substring.replace("\\\"", "\""); + var text = JSON.stringify(hash, replacer, 2); + while(true) { + var start = text.indexOf(startMarker); + var end = text.indexOf(endMarker); + if (start == -1) { + break; + } + var substring = text.substring(start + startMarker.length, end); + while(substring.indexOf("\\n") >= 0) { + substring = substring.replace("\\n", "\n"); + } + while(substring.indexOf("\\\"") >= 0) { + substring = substring.replace("\\\"", "\""); + } + text = text.substring(0, start - 1) + + substring + + text.substring(end + endMarker.length + 1); } - text = text.substring(0, start - 1) - + substring - + text.substring(end + endMarker.length + 1); + return text; } + + var text = hashToString(hash); + var self = this; textarea.show("options", text); + textarea.okCallback = function(value) { + if (value != text) { + var newHash; + eval("newHash = " + value + ";"); + self.write(newHash); + self.onchange(); + } + }; } /** diff --git a/experimental/palette/options.js b/experimental/palette/options.js index 7d15670..bb74957 100644 --- a/experimental/palette/options.js +++ b/experimental/palette/options.js @@ -59,13 +59,17 @@ var opts = { avoidMinZero : { type : "boolean" }, + axis : { + type : "string", + scope : [ "series" ] + }, axisLabelColor : { type : "string", // scope : [ "x", "y", "y2" ] }, axisLabelFontSize : { type : "int", - // scope : [ "x", "y", "y2" ] + scope : [ "global", "x", "y", "y2" ] }, axisLabelFormatter : { type : "function(numberOrDate, granularity, opts, dygraph)", diff --git a/experimental/palette/palette.js b/experimental/palette/palette.js index d98ab15..514463f 100644 --- a/experimental/palette/palette.js +++ b/experimental/palette/palette.js @@ -215,6 +215,9 @@ Palette.prototype.read = function() { * Write to input elements. */ Palette.prototype.write = function(hash) { + if (!hash) { + return; + } var results = {}; for (var opt in this.model) { if (this.model.hasOwnProperty(opt)) { diff --git a/plugins/axes.js b/plugins/axes.js index 1f9c256..40b826c 100644 --- a/plugins/axes.js +++ b/plugins/axes.js @@ -52,7 +52,7 @@ axes.prototype.layout = function(e) { if (g.getOption('xAxisHeight')) { h = g.getOption('xAxisHeight'); } else { - h = g.getOption('axisLabelFontSize') + 2 * g.getOption('axisTickSize'); + h = g.getOptionForAxis('axisLabelFontSize', 'x') + 2 * g.getOption('axisTickSize'); } var x_axis_rect = e.reserveSpaceBottom(h); } @@ -101,18 +101,34 @@ axes.prototype.willDrawChart = function(e) { var label, x, y, tick, i; - var labelStyle = { - position: "absolute", - fontSize: g.getOption('axisLabelFontSize') + "px", - zIndex: 10, - color: g.getOption('axisLabelColor'), - width: g.getOption('axisLabelWidth') + "px", - // height: this.attr_('axisLabelFontSize') + 2 + "px", - lineHeight: "normal", // Something other than "normal" line-height screws up label positioning. - overflow: "hidden" + var makeLabelStyle = function(axis) { + return { + position: "absolute", + fontSize: g.getOptionForAxis('axisLabelFontSize', axis) + "px", + zIndex: 10, + color: g.getOption('axisLabelColor'), + width: g.getOption('axisLabelWidth') + "px", + // height: g.getOptionForAxis('axisLabelFontSize', 'x') + 2 + "px", + lineHeight: "normal", // Something other than "normal" line-height screws up label positioning. + overflow: "hidden" + }; + } + + var labelStyles = { + x : makeLabelStyle('x'), + y : makeLabelStyle('y'), + y2 : makeLabelStyle('y2'), }; + var makeDiv = function(txt, axis, prec_axis) { + /* + * This seems to be called with the following three sets of axis/perc_axis: + * x: undefined + * y: y1 + * y: y2 + */ var div = document.createElement("div"); + var labelStyle = labelStyles[prec_axis == 'y2' ? 'y2' : axis]; for (var name in labelStyle) { if (labelStyle.hasOwnProperty(name)) { div.style[name] = labelStyle[name]; @@ -149,6 +165,7 @@ axes.prototype.willDrawChart = function(e) { sgn = -1; prec_axis = 'y2'; } + var fontSize = g.getOptionForAxis('axisLabelFontSize', prec_axis); y = area.y + tick[1] * area.h; /* Tick marks are currently clipped, so don't bother drawing them. @@ -160,10 +177,10 @@ axes.prototype.willDrawChart = function(e) { */ label = makeDiv(tick[2], 'y', num_axes == 2 ? prec_axis : null); - var top = (y - g.getOption('axisLabelFontSize') / 2); + var top = (y - fontSize / 2); if (top < 0) top = 0; - if (top + g.getOption('axisLabelFontSize') + 3 > canvasHeight) { + if (top + fontSize + 3 > canvasHeight) { label.style.bottom = "0px"; } else { label.style.top = top + "px"; @@ -185,7 +202,8 @@ axes.prototype.willDrawChart = function(e) { // tick on the x-axis. Shift the bottom tick up a little bit to // compensate if necessary. var bottomTick = this.ylabels_[0]; - var fontSize = g.getOption('axisLabelFontSize'); + // Interested in the y2 axis also? + var fontSize = g.getOptionForAxis('axisLabelFontSize', "y"); var bottom = parseInt(bottomTick.style.top, 10) + fontSize; if (bottom > canvasHeight - fontSize) { bottomTick.style.top = (parseInt(bottomTick.style.top, 10) -