Don't clear overlay on mouseup if not zooming.
[dygraphs.git] / experimental / palette / palette.js
CommitLineData
20590000
RK
1// Copyright (c) 2011 Google, Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21/**
22 * @fileoverview Dygraphs options palette.
23 *
24 * @author konigsberg@google.com (Robert Konigsberg)
25 */
26"use strict";
27
28function Palette() {
29 this.model = {};
30 this.onchange = function() {};
31 this.filterBar = null;
32}
33
909bae9b 34Palette.createChild = function(type, parentElement, className) {
59a80f4a
RK
35 var element = document.createElement(type);
36 parentElement.appendChild(element);
909bae9b
RK
37 if (className) {
38 element.className = className;
39 }
59a80f4a
RK
40 return element;
41};
42
20590000
RK
43Palette.prototype.create = function(document, parentElement) {
44 var palette = this;
20590000 45
909bae9b 46 var table = Palette.createChild("div", parentElement, "palette");
59a80f4a 47 table.width="300px";
20590000 48
59a80f4a 49 this.tooltip = new Tooltip();
20590000 50
909bae9b 51 var row = Palette.createChild("div", table, "header");
59a80f4a 52 row.style.visibility = "visible";
59a80f4a 53
21285cf9 54 Palette.createChild("span", row).textContent = "Filter:";
59a80f4a 55 this.filterBar = Palette.createChild("input", Palette.createChild("span", row));
2d9dee16 56 this.filterBar.type = "search";
20590000
RK
57 this.filterBar.onkeyup = function() {
58 palette.filter(palette.filterBar.value)
59 };
2d9dee16 60 this.filterBar.onclick = this.filterBar.onkeyup;
d95dc014 61 var go = Palette.createChild("button", Palette.createChild("span", row));
21285cf9 62 go.textContent = "Redraw"
20590000
RK
63 go.onclick = function() {
64 palette.onchange();
65 };
66
ce50b6e8 67 // CURRENTLY HIDDEN.
d95dc014 68 var tmp = Palette.createChild("button", Palette.createChild("span", row));
21285cf9 69 tmp.textContent = "Copy"
d95dc014
RK
70 tmp.onclick = function() {
71 var textarea = new TextArea();
ce50b6e8 72 textarea.show("header", "Now is the time for all good men\nto come to the aid of their country");
d95dc014 73 };
ce50b6e8 74 tmp.style.display = "none";
d95dc014 75
20590000
RK
76 for (var opt in opts) {
77 try {
78 if (opts.hasOwnProperty(opt)) {
79 var type = opts[opt].type;
80 var isFunction = type.indexOf("function(") == 0;
59a80f4a
RK
81 var row = Palette.createChild("div", table);
82 row.onmouseover = function(source, title, type, body, e) {
83 return function(e) {
84 palette.tooltip.show(source, e, title, type, body);
85 };
86 } (row, opt, type, Dygraph.OPTIONS_REFERENCE[opt].description);
87 row.onmouseout = function() { palette.tooltip.hide(); };
88
909bae9b 89 var div = Palette.createChild("span", row, "name");
21285cf9 90 div.textContent = opt;
59a80f4a 91
909bae9b 92 var value = Palette.createChild("span", row, "option");
20590000
RK
93
94 if (isFunction) {
59a80f4a 95 var input = Palette.createChild("button", value);
20590000
RK
96 input.onclick = function(opt, palette) {
97 return function(event) {
98 var entry = palette.model[opt];
99 var inputValue = entry.functionString;
100 if (inputValue == null || inputValue.length == 0) {
d95dc014 101 inputValue = opts[opt].type + "{\n\n}";
20590000 102 }
d95dc014 103 var textarea = new TextArea();
909bae9b 104 textarea.show(opt, inputValue);
d95dc014 105 textarea.okCallback = function(value) {
20590000
RK
106 if (value != inputValue) {
107 entry.functionString = value;
21285cf9 108 entry.input.textContent = value ? "defined" : "not defined";
20590000
RK
109 palette.onchange();
110 }
111 }
112 }
113 }(opt, this);
114 } else {
21285cf9
RK
115 var input = Palette.createChild("input", value, "textInput");
116 if (type == "boolean") {
117 input.size = "5";
118 input.maxlength = "5";
119 }
20590000
RK
120 input.onkeypress = function(event) {
121 var keycode = event.which;
122 if (keycode == 13 || keycode == 8) {
123 palette.onchange();
124 }
125 }
126
127 input.type="text";
128 }
129 this.model[opt] = { input: input, row: row };
130 }
131 } catch(err) {
132 throw "For option " + opt + ":" + err;
133 }
134 }
135 this.filter("");
136}
137
138// TODO: replace semicolon parsing with comma parsing, and supporting quotes.
139Palette.parseStringArray = function(value) {
140 if (value == null || value.length == 0) {
141 return null;
142 }
143 return value.split(";");
144}
145
146Palette.parseBooleanArray = function(value) {
147 if (value == null || value.length == 0) {
148 return null;
149 }
150 return value.split(',').map(function(x) { return x.trim() == "true"; });
151}
152
153Palette.parseFloatArray = function(value) {
154 if (value == null || value.length == 0) {
155 return null;
156 }
157 return value.split(',').map(function(x) { return parseFloat(x); });
158}
159
160Palette.parseIntArray = function(value) {
161 if (value == null || value.length == 0) {
162 return null;
163 }
164 return value.split(',').map(function(x) { return parseInt(x); });
165}
166
167Palette.prototype.read = function() {
168 var results = {};
169 for (var opt in this.model) {
170 if (this.model.hasOwnProperty(opt)) {
171 var type = opts[opt].type;
172 var isFunction = type.indexOf("function(") == 0;
173 var input = this.model[opt].input;
174 var value = isFunction ? this.model[opt].functionString : input.value;
175 if (value && value.length != 0) {
176 if (type == "boolean") {
177 results[opt] = value == "true";
178 } else if (type == "int") {
179 results[opt] = parseInt(value);
180 } else if (type == "float") {
181 results[opt] = parseFloat(value);
182 } else if (type == "array<string>") {
183 results[opt] = Palette.parseStringArray(value);
184 } else if (type == "array<float>") {
185 results[opt] = Palette.parseFloatArray(value);
186 } else if (type == "array<boolean>") {
187 results[opt] = Palette.parseBooleanArray(value);
188 } else if (type == "array<Date>") {
189 results[opt] = Palette.parseIntArray(value);
190 } else if (isFunction) {
191 var localVariable = null;
192 eval("localVariable = " + value);
193 results[opt] = localVariable;
194 } else {
195 results[opt] = value;
196 }
197 }
198 }
199 }
200 return results;
201}
202
203/**
204 * Write to input elements.
205 */
206Palette.prototype.write = function(hash) {
207 var results = {};
208 for (var opt in this.model) {
209 // && hash.hasOwnProperty(opt)
210 if (this.model.hasOwnProperty(opt)) {
211 var input = this.model[opt].input;
212 var type = opts[opt].type;
213 var value = hash[opt];
214 if (type == "array<string>") {
215 if (value) {
216 input.value = value.join("; ");
217 }
218 } else if (type.indexOf("array") == 0) {
219 if (value) {
220 input.value = value.join(", ");
221 }
222 } else if (type.indexOf("function(") == 0) {
21285cf9 223 input.textContent = value ? "defined" : "not defined";
20590000
RK
224 this.model[opt].functionString = value ? value.toString() : null;
225 } else {
226 if (value) {
227 input.value = value;
228 }
229 }
230 }
231 }
232}
233
234Palette.prototype.filter = function(pattern) {
235 pattern = pattern.toLowerCase();
59a80f4a 236 var even = true;
20590000
RK
237 for (var opt in this.model) {
238 if (this.model.hasOwnProperty(opt)) {
239 var row = this.model[opt].row;
59a80f4a
RK
240 var matches = opt.toLowerCase().indexOf(pattern) >= 0;
241 row.style.display = matches ? "block" : "none";
242 if (matches) {
243 row.className = even ? "even" : "odd";
244 even = !even;
245 }
20590000
RK
246 }
247 }
248}