5a2891c76b8d85c9dfbf7cafff8ffd037fe6e4fe
1 // Copyright (c) 2011 Google, Inc.
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:
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
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
22 * @fileoverview Dygraphs options palette.
24 * @author konigsberg@google.com (Robert Konigsberg)
30 this.onchange
= function() {};
31 this.filterBar
= null;
34 Palette
.createChild
= function(type
, parentElement
) {
35 var element
= document
.createElement(type
);
36 parentElement
.appendChild(element
);
40 function Tooltip(parent
) {
42 parent
= document
.getElementsByTagName("body")[0];
44 this.elem
= Palette
.createChild("div", parent
);
45 this.title
= Palette
.createChild("div", this.elem
);
46 this.elem
.className
= "tooltip";
47 this.title
.className
= "title";
48 this.type
= Palette
.createChild("div", this.elem
);
49 this.type
.className
= "type";
50 this.body
= Palette
.createChild("div", this.elem
);
51 this.body
.className
= "body";
55 Tooltip
.prototype.show
= function(source
, event
, title
, type
, body
) {
56 this.title
.innerHTML
= title
;
57 this.body
.innerHTML
= body
;
58 this.type
.innerText
= type
; // innerText for arrays.
60 var getTopLeft
= function(element
) {
61 var x
= element
.offsetLeft
;
62 var y
= element
.offsetTop
;
63 element
= element
.offsetParent
;
65 while(element
!= null) {
66 x
= parseInt(x
) + parseInt(element
.offsetLeft
);
67 y
= parseInt(y
) + parseInt(element
.offsetTop
);
68 element
= element
.offsetParent
;
73 this.elem
.style
.height
= source
.style
.height
;
74 this.elem
.style
.width
= "280";
75 var topLeft
= getTopLeft(source
);
76 this.elem
.style
.top
= parseInt(topLeft
[0] + source
.offsetHeight
) + 'px';
77 this.elem
.style
.left
= parseInt(topLeft
[1] + 10) + 'px';
78 this.elem
.style
.visibility
= "visible";
81 Tooltip
.prototype.hide
= function() {
82 this.elem
.style
.visibility
= "hidden";
85 Palette
.prototype.create
= function(document
, parentElement
) {
88 var table
= Palette
.createChild("div", parentElement
);
89 table
.className
= "palette";
92 this.tooltip
= new Tooltip();
94 var row
= Palette
.createChild("div", table
);
95 row
.style
.visibility
= "visible";
96 row
.className
= "header";
98 Palette
.createChild("span", row
).innerText
= "Filter:";
99 this.filterBar
= Palette
.createChild("input", Palette
.createChild("span", row
));
100 this.filterBar
.type
= "search";
101 this.filterBar
.onkeyup
= function() {
102 palette
.filter(palette
.filterBar
.value
)
104 this.filterBar
.onclick
= this.filterBar
.onkeyup
;
105 var go
= document
.createElement("button");
106 Palette
.createChild("span", row
).appendChild(go
);
107 go
.innerText
= "Redraw"
108 go
.onclick
= function() {
112 for (var opt
in opts
) {
114 if (opts
.hasOwnProperty(opt
)) {
115 var type
= opts
[opt
].type
;
116 var isFunction
= type
.indexOf("function(") == 0;
117 var row
= Palette
.createChild("div", table
);
118 row
.onmouseover
= function(source
, title
, type
, body
, e
) {
120 palette
.tooltip
.show(source
, e
, title
, type
, body
);
122 } (row
, opt
, type
, Dygraph
.OPTIONS_REFERENCE
[opt
].description
);
123 row
.onmouseout
= function() { palette
.tooltip
.hide(); };
125 var div
= Palette
.createChild("span", row
);
127 div
.className
= "name";
129 var value
= Palette
.createChild("span", row
);
130 value
.className
= "option";
133 var input
= Palette
.createChild("button", value
);
134 input
.onclick
= function(opt
, palette
) {
135 return function(event
) {
136 var entry
= palette
.model
[opt
];
137 var inputValue
= entry
.functionString
;
138 if (inputValue
== null || inputValue
.length
== 0) {
139 inputValue
= opts
[opt
].type
+ "{ }";
141 var value
= prompt("enter function", inputValue
);
143 if (value
.length
== 0) {
146 if (value
!= inputValue
) {
147 entry
.functionString
= value
;
148 entry
.input
.innerText
= value
? "defined" : "not defined";
155 var input
= Palette
.createChild("input", value
);
156 input
.onkeypress
= function(event
) {
157 var keycode
= event
.which
;
158 if (keycode
== 13 || keycode
== 8) {
165 this.model
[opt
] = { input
: input
, row
: row
};
168 throw "For option " + opt
+ ":" + err
;
174 // TODO: replace semicolon parsing with comma parsing, and supporting quotes.
175 Palette
.parseStringArray
= function(value
) {
176 if (value
== null || value
.length
== 0) {
179 return value
.split(";");
182 Palette
.parseBooleanArray
= function(value
) {
183 if (value
== null || value
.length
== 0) {
186 return value
.split(',').map(function(x
) { return x
.trim() == "true"; });
189 Palette
.parseFloatArray
= function(value
) {
190 if (value
== null || value
.length
== 0) {
193 return value
.split(',').map(function(x
) { return parseFloat(x
); });
196 Palette
.parseIntArray
= function(value
) {
197 if (value
== null || value
.length
== 0) {
200 return value
.split(',').map(function(x
) { return parseInt(x
); });
203 Palette
.prototype.read
= function() {
205 for (var opt
in this.model
) {
206 if (this.model
.hasOwnProperty(opt
)) {
207 var type
= opts
[opt
].type
;
208 var isFunction
= type
.indexOf("function(") == 0;
209 var input
= this.model
[opt
].input
;
210 var value
= isFunction
? this.model
[opt
].functionString
: input
.value
;
211 if (value
&& value
.length
!= 0) {
212 if (type
== "boolean") {
213 results
[opt
] = value
== "true";
214 } else if (type
== "int") {
215 results
[opt
] = parseInt(value
);
216 } else if (type
== "float") {
217 results
[opt
] = parseFloat(value
);
218 } else if (type
== "array<string>") {
219 results
[opt
] = Palette
.parseStringArray(value
);
220 } else if (type
== "array<float>") {
221 results
[opt
] = Palette
.parseFloatArray(value
);
222 } else if (type
== "array<boolean>") {
223 results
[opt
] = Palette
.parseBooleanArray(value
);
224 } else if (type
== "array<Date>") {
225 results
[opt
] = Palette
.parseIntArray(value
);
226 } else if (isFunction
) {
227 var localVariable
= null;
228 eval("localVariable = " + value
);
229 results
[opt
] = localVariable
;
231 results
[opt
] = value
;
240 * Write to input elements.
242 Palette
.prototype.write
= function(hash
) {
244 for (var opt
in this.model
) {
245 // && hash.hasOwnProperty(opt)
246 if (this.model
.hasOwnProperty(opt
)) {
247 var input
= this.model
[opt
].input
;
248 var type
= opts
[opt
].type
;
249 var value
= hash
[opt
];
250 if (type
== "array<string>") {
252 input
.value
= value
.join("; ");
254 } else if (type
.indexOf("array") == 0) {
256 input
.value
= value
.join(", ");
258 } else if (type
.indexOf("function(") == 0) {
259 input
.innerText
= value
? "defined" : "not defined";
260 this.model
[opt
].functionString
= value
? value
.toString() : null;
270 Palette
.prototype.filter
= function(pattern
) {
271 pattern
= pattern
.toLowerCase();
273 for (var opt
in this.model
) {
274 if (this.model
.hasOwnProperty(opt
)) {
275 var row
= this.model
[opt
].row
;
276 var matches
= opt
.toLowerCase().indexOf(pattern
) >= 0;
277 row
.style
.display
= matches
? "block" : "none";
279 row
.className
= even
? "even" : "odd";