--- /dev/null
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9">
+ <title>Palette Demo</title>
+ <!--[if IE]>
+ <script type="text/javascript" src="../../excanvas.js"></script>
+ <![endif]-->
+ <script type="text/javascript" src="../../dygraph-dev.js"></script>
+ <script type="text/javascript" src="options.js"></script>
+ <script type="text/javascript" src="palette.js"></script>
+ <script type="text/javascript" src="index.js"></script>
+ <link rel="stylesheet" type="text/css" href="palette.css" />
+ <style>
+ </style>
+ </head>
+ <body>
+ <h2>Palette</h2>
+ <div style="font-size:smaller;"><p>To configure this chart, tweak the values on the right.
+ Enter applies changes, and the filter bar on the top reduces selections</p></div>
+ <table>
+ <tr>
+ <td valign="top">
+ <div id="graph"></div>
+ <div id="status" style="width:200px; font-size:0.8em; padding-top:5px;"></div>
+ Other messages:
+ <div id="messages"></div>
+ </td>
+ <td valign="top"><div class="palette" id="optionsPalette"></div></td>
+ </tr>
+ </table>
+ </body>
+ <script type="text/javascript">start();</script>
+</html>
--- /dev/null
+// Copyright (c) 2012 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/**
+ * @fileoverview Javascript to run index.html.
+ *
+ * @author konigsberg@google.com (Robert Konigsberg)
+ */
+
+"use strict";
+
+function draw(element, options) {
+ try {
+ element.innerHTML = "";
+ element.removeAttribute("style");
+ var g = new Dygraph(
+ element,
+ function() {
+ var zp = function(x) { if (x < 10) return "0"+x; else return x; };
+ var r = "date,parabola,line,another line,sine wave\n";
+ for (var i=1; i<=31; i++) {
+ r += "201110" + zp(i);
+ r += "," + 10*(i*(31-i));
+ r += "," + 10*(8*i);
+ r += "," + 10*(250 - 8*i);
+ r += "," + 10*(125 + 125 * Math.sin(0.3*i));
+ r += "\n";
+ }
+ return r;
+ }, options
+ );
+
+ // These don't work yet.
+ g.updateOptions({
+ labelsDiv: 'status',
+ });
+ } catch(err) {
+ addMessage(err);
+ throw(err);
+ } finally {
+ }
+}
+
+function addMessage(text) {
+ var messages = document.getElementById("messages");
+ messages.innerText = messages.innerText + text + "\n";
+}
+
+function start() {
+ var options = {
+ colors: [
+ "rgb(51,204,204)",
+ "rgb(255,100,100)",
+ "#00DD55",
+ "rgba(50,50,200,0.4)"
+ ],
+ labelsSeparateLines: true,
+ labelsKMB: true,
+ legend: 'always',
+ width: 640,
+ height: 480,
+ title: 'Interesting Shapes',
+ xlabel: 'Date',
+ ylabel: 'Count',
+ axisLineColor: 'white',
+ drawXGrid: false,
+ pointClickCallback: function() { alert("p-click!"); },
+ };
+
+ var redraw = function() {
+ draw(document.getElementById("graph"), palette.read());
+ }
+
+ var palette = new Palette();
+ palette.create(document, document.getElementById("optionsPalette"));
+ palette.write(options);
+ palette.onchange = redraw;
+ palette.filterBar.focus();
+ redraw();
+
+ for (var opt in Dygraph.OPTIONS_REFERENCE) {
+ if (!(opt in opts)) {
+ var entry = Dygraph.OPTIONS_REFERENCE[opt];
+ console.warn("missing option: " + opt + " of type " + entry.type);
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2011 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/**
+ * @fileoverview List of options and their types, used for the palette.
+ *
+ * @author konigsberg@google.com (Robert Konigsberg)
+ */
+
+"use strict";
+
+var opts = {
+ animatedZooms: { type: "boolean" },
+ annotationClickHandler : {type: "function(annotation, point, dygraph, event)"},
+ annotationDblClickHandler : {type: "function(annotation, point, dygraph, event)"},
+ annotationMouseOutHandler : {type: "function(annotation, point, dygraph, event)"},
+ annotationMouseOverHandler : {type: "function(annotation, point, dygraph, event)"},
+ avoidMinZero: { type: "boolean" },
+ axisLabelColor: { type: "string" },
+ axisLabelFontSize: {type: "int" },
+ axisLabelWidth: {type: "int" },
+ axisLineColor: {type: "string" },
+ axisLineWidth: {type: "int" },
+ axisTickSize: {type: "int" },
+ clickCallback : {type: "function(e, x, points)"},
+ colorSaturation: { type: "float" },
+ colors: { type: "array<string>" },
+ colorValue: { type: "float" },
+ connectSeparatedPoints: { type: "boolean" },
+ customBars: { type: "boolean" },
+ dateWindow: { type: "array<Date>"},
+ delimiter: { type: "string" },
+ digitsAfterDecimal: { type: "int"},
+ displayAnnotations: { type: "boolean" },
+ drawCallback : {type: "function(dygraph, is_initial)"},
+ drawPoints: { type: "boolean" },
+ drawXAxis: {type: "boolean" },
+ drawXGrid: {type: "boolean" },
+ drawYAxis: {type: "boolean" },
+ drawYGrid: {type: "boolean" },
+ errorBars: { type: "boolean" },
+ fillAlpha: { type: "float" },
+ fillGraph: { type: "boolean" },
+ fractions: { type: "boolean" },
+ gridLineColor: { type: "string" },
+ gridLineWidth: { type: "int" },
+ height: {type: "int"},
+ hideOverlayOnMouseOut: { type: "boolean" },
+ highlightCallback : {type: "function(event, x, points,row)"},
+ highlightCircleSize: { type: "int" },
+ includeZero: { type: "boolean" },
+ isZoomedIgnoreProgrammaticZoom: {type: "boolean" },
+ labelsDivWidth: {type: "integer"},
+ labels: {type: "array<string>" },
+ labelsKMB: {type: "boolean" },
+ labelsKMG2: {type: "boolean"},
+ labelsSeparateLines: {type: "boolean"},
+ labelsShowZeroValues: {type: "boolean"},
+ legend: {type: "string"},
+ logscale: { type: "boolean" },
+ maxNumberWidth: {type: "int"},
+ panEdgeFraction: { type: "float" },
+ pixelsPerLabel: { type: "int" },
+ pixelsPerXLabel: { type: "int" },
+ pixelsPerYLabel: { type: "int" },
+ pointClickCallback : {type: "function(e, point)"},
+ pointSize: { type: "integer" },
+ rangeSelectorHeight: { type: "int" },
+ rangeSelectorPlotFillColor: { type: "int" },
+ rangeSelectorPlotStrokeColor: { type: "int" },
+ rightGap: {type: "boolean"},
+ rollPeriod: {type: "int"},
+ showLabelsOnHighlight: { type: "boolean" },
+ showRangeSelector: { type: "boolean" },
+ showRoller: {type: "boolean" },
+ sigFigs: {type: "int"},
+ sigma: { type: "float" },
+ stackedGraph: { type: "boolean" },
+ stepPlot: { type: "boolean" },
+ strokeWidth: { type: "integer" },
+ timingName: { type: "string" },
+ title: {type: "string"},
+ titleHeight: {type: "integer"},
+ underlayCallback : {type: "function(canvas, area, dygraph)"},
+ unhighlightCallback : {type: "function(event)"},
+ valueRange: {type: "array<float>"},
+ visibility: {type: "array<boolean>"},
+ width: {type: "int"},
+ wilsonInterval: { type: "boolean" },
+ xAxisHeight: {type: "int"},
+ xAxisLabelWidth: {type: "int"},
+ xLabelHeight: {type: "int"},
+ xlabel : {type: "string" },
+ xValueParser : {type: "function(str)"},
+ yAxisLabelWidth: {type: "int"},
+ yLabelWidth: {type: "int"},
+ ylabel : {type: "string" },
+ zoomCallback : {type: "function(minDate, maxDate, yRanges)"},
+};
--- /dev/null
+.palette {
+ border-style: solid;
+ border-width: 1px;
+ font-size:smaller;
+}
--- /dev/null
+// Copyright (c) 2011 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/**
+ * @fileoverview Dygraphs options palette.
+ *
+ * @author konigsberg@google.com (Robert Konigsberg)
+ */
+"use strict";
+
+function Palette() {
+ this.model = {};
+ this.onchange = function() {};
+ this.filterBar = null;
+}
+
+Palette.prototype.create = function(document, parentElement) {
+ var palette = this;
+ var createChild = function(type, parentElement) {
+ var element = document.createElement(type);
+ parentElement.appendChild(element);
+ return element;
+ };
+
+ var table = createChild("table", parentElement);
+ table.class = "palette";
+
+ var row = createChild("tr", table);
+ row.style.display = "block";
+
+ createChild("td", row).innerText = "Filter:";
+ this.filterBar = createChild("input", createChild("td", row));
+ this.filterBar.onkeyup = function() {
+ palette.filter(palette.filterBar.value)
+ };
+ var go = document.createElement("button");
+ createChild("td", row).appendChild(go);
+ go.innerText = "Redraw"
+ go.onclick = function() {
+ palette.onchange();
+ };
+
+ for (var opt in opts) {
+ try {
+ if (opts.hasOwnProperty(opt)) {
+ var type = opts[opt].type;
+ var isFunction = type.indexOf("function(") == 0;
+ var row = createChild("tr", table);
+ var div = createChild("div", createChild("td", row));
+ var a = createChild("a", div);
+ a.innerText = opt;
+ a.href = "http://dygraphs.com/options.html#" + opt;
+ a.title = Dygraph.OPTIONS_REFERENCE[opt].description;
+ a.target="_blank";
+
+ if (isFunction) {
+ var input = createChild("button", createChild("td", row));
+ input.onclick = function(opt, palette) {
+ return function(event) {
+ var entry = palette.model[opt];
+ var inputValue = entry.functionString;
+ if (inputValue == null || inputValue.length == 0) {
+ inputValue = type + "{ }";
+ }
+ var value = prompt("enter function", inputValue);
+ if (value != null) {
+ if (value.length == 0) {
+ value = null;
+ }
+ if (value != inputValue) {
+ entry.functionString = value;
+ entry.input.innerText = value ? "defined" : "not defined";
+ palette.onchange();
+ }
+ }
+ }
+ }(opt, this);
+ } else {
+ var input = createChild("input", createChild("td", row));
+ input.onkeypress = function(event) {
+ var keycode = event.which;
+ if (keycode == 13 || keycode == 8) {
+ palette.onchange();
+ }
+ }
+
+ input.type="text";
+ }
+ this.model[opt] = { input: input, row: row };
+ }
+ } catch(err) {
+ throw "For option " + opt + ":" + err;
+ }
+ }
+ this.filter("");
+}
+
+// TODO: replace semicolon parsing with comma parsing, and supporting quotes.
+Palette.parseStringArray = function(value) {
+ if (value == null || value.length == 0) {
+ return null;
+ }
+ return value.split(";");
+}
+
+Palette.parseBooleanArray = function(value) {
+ if (value == null || value.length == 0) {
+ return null;
+ }
+ return value.split(',').map(function(x) { return x.trim() == "true"; });
+}
+
+Palette.parseFloatArray = function(value) {
+ if (value == null || value.length == 0) {
+ return null;
+ }
+ return value.split(',').map(function(x) { return parseFloat(x); });
+}
+
+Palette.parseIntArray = function(value) {
+ if (value == null || value.length == 0) {
+ return null;
+ }
+ return value.split(',').map(function(x) { return parseInt(x); });
+}
+
+Palette.prototype.read = function() {
+ var results = {};
+ for (var opt in this.model) {
+ if (this.model.hasOwnProperty(opt)) {
+ var type = opts[opt].type;
+ var isFunction = type.indexOf("function(") == 0;
+ var input = this.model[opt].input;
+ var value = isFunction ? this.model[opt].functionString : input.value;
+ if (value && value.length != 0) {
+ if (type == "boolean") {
+ results[opt] = value == "true";
+ } else if (type == "int") {
+ results[opt] = parseInt(value);
+ } else if (type == "float") {
+ results[opt] = parseFloat(value);
+ } else if (type == "array<string>") {
+ results[opt] = Palette.parseStringArray(value);
+ } else if (type == "array<float>") {
+ results[opt] = Palette.parseFloatArray(value);
+ } else if (type == "array<boolean>") {
+ results[opt] = Palette.parseBooleanArray(value);
+ } else if (type == "array<Date>") {
+ results[opt] = Palette.parseIntArray(value);
+ } else if (isFunction) {
+ var localVariable = null;
+ eval("localVariable = " + value);
+ results[opt] = localVariable;
+ } else {
+ results[opt] = value;
+ }
+ }
+ }
+ }
+ return results;
+}
+
+/**
+ * Write to input elements.
+ */
+Palette.prototype.write = function(hash) {
+ var results = {};
+ for (var opt in this.model) {
+ // && hash.hasOwnProperty(opt)
+ if (this.model.hasOwnProperty(opt)) {
+ var input = this.model[opt].input;
+ var type = opts[opt].type;
+ var value = hash[opt];
+ if (type == "array<string>") {
+ if (value) {
+ input.value = value.join("; ");
+ }
+ } else if (type.indexOf("array") == 0) {
+ if (value) {
+ input.value = value.join(", ");
+ }
+ } else if (type.indexOf("function(") == 0) {
+ input.innerText = value ? "defined" : "not defined";
+ this.model[opt].functionString = value ? value.toString() : null;
+ } else {
+ if (value) {
+ input.value = value;
+ }
+ }
+ }
+ }
+}
+
+Palette.prototype.filter = function(pattern) {
+ pattern = pattern.toLowerCase();
+ for (var opt in this.model) {
+ if (this.model.hasOwnProperty(opt)) {
+ var row = this.model[opt].row;
+ row.style.display = (opt.toLowerCase().indexOf(pattern) >= 0) ? "block" : "none";
+ }
+ }
+}