Be array<int> friendly.
[dygraphs.git] / experimental / palette / palette.js
index f242545..9e4139f 100644 (file)
  */
 "use strict";
 
-function Palette() {
+/**
+ * scope is either "global", "series", "x", "y" or "y2".
+ */
+function Palette(scope) {
+  // Contains pair of "input" (the input object) and "row" (the parent row)
+  // Also contains functionString.
   this.model = {};
+  // This is meant to be overridden by a palette host.
   this.onchange = function() {};
-  this.filterBar = null;
+  this.scope = scope;
+  this.root = null;
 }
 
-Palette.prototype.create = function(document, parentElement) {
+Palette.createChild = function(type, parentElement, className) {
+  var element = document.createElement(type);
+  parentElement.appendChild(element);
+  if (className) {
+    element.className = className;
+  }
+  return element;
+};
+
+Palette.prototype.create = function(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 table = Palette.createChild("div", parentElement[0], "palette");
+  this.root = table;
+  table.width="300px";
 
-  var row = createChild("tr", table);
-  row.style.display = "block";
+  this.tooltip = new Tooltip();
 
-  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();
+  // Build the header
+  var header = Palette.createChild("div", table, "header");
+  header.style.visibility = "visible";
+
+  // CURRENTLY HIDDEN.
+  var tmp = Palette.createChild("button", Palette.createChild("span", header));
+  tmp.textContent = "Copy"
+  tmp.onclick = function() {
+    var textarea = new TextArea();
+    textarea.show("header", "Now is the time for all good men\nto come to the aid of their country");
   };
+  tmp.style.display = "none";
 
+  // One row per option.
   for (var opt in opts) {
     try {
       if (opts.hasOwnProperty(opt)) {
         var type = opts[opt].type;
+
+        var scope = opts[opt].scope || [ "global" ]; // Scope can be empty, infer "global" only.
+        var valid = scope[0] == "*" || $.inArray(this.scope, scope) >= 0;
+        if (!valid) {
+          continue;
+        }
+
         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";
+        var row = Palette.createChild("div", table);
+        row.onmouseover = function(source, title, type, body) {
+          return function() {
+            palette.tooltip.show(source, title, type, body);
+          };
+        } (row, opt, type, Dygraph.OPTIONS_REFERENCE[opt].description);
+        row.onmouseout = function() { palette.tooltip.hide(); };
+
+        var div = Palette.createChild("span", row, "name");
+        div.textContent = opt;
+
+        var value = Palette.createChild("span", row, "option");
 
         if (isFunction) {
-           var input = createChild("button", createChild("td", row));
+           var input = Palette.createChild("button", value);
            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 + "{ }";
+                 inputValue = opts[opt].type + "{\n\n}";
                }
-               var value = prompt("enter function", inputValue);
-               if (value != null) {
-                 if (value.length == 0) {
-                   value = null;
-                 }
+                    var textarea = new TextArea();
+                    textarea.show(opt, inputValue);
+                    textarea.okCallback = function(value) {
                  if (value != inputValue) {
                    entry.functionString = value;
-                   entry.input.innerText = value ? "defined" : "not defined";
+                   entry.input.textContent = value ? "defined" : "not defined";
                    palette.onchange();
                  }
                }
              }
            }(opt, this);
+        } else if (type == "boolean") {
+           var input = Palette.createChild("button", value);
+           input.onclick = function(e) {
+             var btn = e.target;
+             if (btn.value == "none") {
+               Palette.populateBooleanButton(btn, "true");
+             } else if (btn.value == "true") {
+               Palette.populateBooleanButton(btn, "false");
+             } else {
+               Palette.populateBooleanButton(btn, "none");
+             }
+             palette.onchange();
+           };
         } else {
-          var input = createChild("input", createChild("td", row));
+          var input = Palette.createChild("input", value, "textInput");
+          input.type="text";
           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 };
       }
@@ -151,7 +186,13 @@ Palette.prototype.read = function() {
       var value = isFunction ? this.model[opt].functionString : input.value;
       if (value && value.length != 0) {
         if (type == "boolean") {
-          results[opt] = value == "true";
+          if (value == "false") {
+            results[opt] = false;
+          }
+          if (value == "true") {
+            results[opt] = true;
+          }
+          // Ignore value == "none"
         } else if (type == "int") {
           results[opt] = parseInt(value);
         } else if (type == "float") {
@@ -162,6 +203,8 @@ Palette.prototype.read = function() {
           results[opt] = Palette.parseFloatArray(value);
         } else if (type == "array<boolean>") {
           results[opt] = Palette.parseBooleanArray(value);
+        } else if (type == "array<int>") {
+          results[opt] = Palette.parseIntArray(value);
         } else if (type == "array<Date>") {
           results[opt] = Palette.parseIntArray(value);
         } else if (isFunction) {
@@ -183,12 +226,14 @@ Palette.prototype.read = function() {
 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 (type == "boolean") {
+        var text = value == true ? "true" : (value == false ? "false" : "none");
+        Palette.populateBooleanButton(input, text);
+      } else if (type == "array<string>") {
         if (value) {
           input.value = value.join("; ");
         }
@@ -197,10 +242,10 @@ Palette.prototype.write = function(hash) {
           input.value = value.join(", ");
         }
       } else if (type.indexOf("function(") == 0) {
-        input.innerText = value ? "defined" : "not defined";
+        input.textContent = value ? "defined" : "not defined";
         this.model[opt].functionString = value ? value.toString() : null;
       } else {
-        if (value) {
+        if (value != undefined) {
           input.value = value;
         }
       }
@@ -208,12 +253,23 @@ Palette.prototype.write = function(hash) {
   }
 }
 
+Palette.populateBooleanButton = function(button, value) {
+  button.innerHTML = value;
+  button.value = value;
+}
+
 Palette.prototype.filter = function(pattern) {
   pattern = pattern.toLowerCase();
+  var even = true;
   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";
+      var matches = opt.toLowerCase().indexOf(pattern) >= 0;
+      row.style.display = matches ? "block" : "none";
+      if (matches) {
+        row.className = even ? "even" : "odd";
+        even = !even;
+      }
     }
   }
 }