--- /dev/null
+dojo.require("dojo.data.ItemFileWriteStore");
+dojo.require("dijit.Tree");
+dojo.require("dijit.form.Button");
+dojo.require("dojo.dnd.Source");
+dojo.require("dijit._tree.dndSource");
+//dojo.require("openils.vandelay.TreeDndSource");
+dojo.require("openils.vandelay.TreeStoreModel");
+dojo.require("openils.User");
+dojo.require("openils.Util");
+dojo.require("openils.PermaCrud");
+dojo.require("openils.widget.ProgressDialog");
+
+var node_editor;
+var _crads;
+
+function _find_crad_by_name(name) {
+ for (var i = 0; i < _crads.length; i++) {
+ if (_crads[i].name() == name)
+ return _crads[i];
+ }
+ return null;
+}
+
+function NodeEditor() {
+ var self = this;
+
+ var _svf_select_template = null;
+ var _factories_by_type = {
+ "svf": function() {
+ if (!_svf_select_template) {
+ _svf_select_template = dojo.create(
+ "select", {"fmfield": "svf"}
+ );
+ for (var i=0; i<_crads.length; i++) {
+ dojo.create(
+ "option", {
+ "value": _crads[i].name(),
+ "innerHTML": _crads[i].label()
+ }, _svf_select_template
+ );
+ }
+ }
+
+ var select = dojo.clone(_svf_select_template);
+ dojo.attr(select, "id", "svf-select");
+ var label = dojo.create(
+ "label", {
+ "for": "svf-select", "innerHTML": "Single-Value-Field:"
+ }
+ );
+
+ var tr = dojo.create("tr");
+ dojo.place(label, dojo.create("td", null, tr));
+ dojo.place(select, dojo.create("td", null, tr));
+
+ return [tr];
+ },
+ "tag": function() {
+ var rows = [dojo.create("tr"), dojo.create("tr")];
+ dojo.create(
+ "label", {
+ "for": "tag-input", "innerHTML": "Tag:"
+ }, dojo.create("td", null, rows[0])
+ );
+ dojo.create(
+ "input", {
+ "id": "tag-input",
+ "type": "text",
+ "size": 4,
+ "maxlength": 3,
+ "fmfield": "tag"
+ }, dojo.create("td", null, rows[0])
+ );
+ dojo.create(
+ "label", {
+ "for": "subfield-input", "innerHTML": "Subfield: \u2021"
+ }, dojo.create("td", null, rows[1])
+ );
+ dojo.create(
+ "input", {
+ "id": "subfield-input",
+ "type": "text",
+ "size": 2,
+ "maxlength": 1,
+ "fmfield": "subfield"
+ }, dojo.create("td", null, rows[1])
+ );
+ return rows;
+ },
+ "bool_op": function() {
+ var tr = dojo.create("tr");
+ dojo.create(
+ "label",
+ {"for": "operator-select", "innerHTML": "Operator:"},
+ dojo.create("td", null, tr)
+ );
+ var select = dojo.create(
+ "select", {"fmfield": "bool_op", "id": "operator-select"},
+ dojo.create("td", null, tr)
+ );
+ dojo.create("option", {"value": "AND", "innerHTML": "AND"}, select);
+ dojo.create("option", {"value": "OR", "innerHTML": "OR"}, select);
+
+ return [tr];
+ }
+ };
+
+ function _simple_value_getter(control) {
+ if (typeof control.selectedIndex != "undefined")
+ return control.options[control.selectedIndex].value;
+ else if (dojo.attr(control, "type") == "checkbox")
+ return control.checked;
+ else
+ return control.value;
+ };
+
+ this._init = function(dnd_source, node_editor_container) {
+ this.dnd_source = dnd_source;
+ this.node_editor_container = dojo.byId(node_editor_container);
+ };
+
+ this.clear = function() {
+ this.dnd_source.selectAll().deleteSelectedNodes();
+ dojo.empty(this.node_editor_container);
+ };
+
+ this.update_draggable = function(draggable) {
+ var s = "";
+// draggable.data = {"match_point": new vmsp()};
+ var had_op = false;
+ dojo.query("[fmfield]", this.node_editor_container).forEach(
+ function(control) {
+ var used_svf = null;
+ var field = dojo.attr(control, "fmfield");
+ var value = _simple_value_getter(control);
+// draggable.data.match_point[field](value);
+
+ if (field == "subfield")
+ s += " \u2021";
+ if (field == "svf")
+ used_svf = value;
+ if (field == "quality")
+ return;
+ if (field == "bool_op")
+ had_op = true;
+ if (field == "negate") {
+ if (value) {
+ if (had_op)
+ s = "<strong>N</strong>" + s;
+ else
+ s = "<strong>NOT</strong> " + s;
+ }
+ } else {
+ s += value;
+ }
+
+ if (used_svf !== null) {
+ var our_crad = _find_crad_by_name(used_svf);
+ /* XXX i18n, use fmtted strings */
+ s += " / " + our_crad.label() + "<br /><em>" +
+ (our_crad.description() || "") + "</em><br />";
+ }
+ }
+ );
+ dojo.attr(draggable, "innerHTML", s);
+ };
+
+ this._add_consistent_controls = function(tgt) {
+ if (!this._consistent_controls) {
+ var trs = dojo.query("[consistent-controls]");
+ this._consistent_controls = [];
+ for (var i = 0; i < trs.length; i++)
+ this._consistent_controls[i] = dojo.clone(trs[i]);
+ dojo.empty(trs[0].parentNode);
+ }
+
+ this._consistent_controls.forEach(
+ function(node) { dojo.place(dojo.clone(node), tgt); }
+ );
+ };
+
+ this.add = function(type) {
+ this.clear();
+
+ /* a representation, not the editing widgets, but will also carry
+ * the fieldmapper object when dragged to the tree */
+ var draggable = dojo.create(
+ "li", {
+ "innerHTML": "Define your match point and drag me<br/>" +
+ "to the tree on the right"
+ }
+ );
+
+ /* these are the editing widgets */
+ var table = dojo.create("table", {"className": "node-editor"});
+
+ var nodes = _factories_by_type[type]();
+ for (var i = 0; i < nodes.length; i++) dojo.place(nodes[i], table);
+
+ this._add_consistent_controls(table);
+
+ dojo.create(
+ "input", {
+ "type": "submit", "value": "Ok",
+ "onclick": function() { self.update_draggable(draggable); }
+ }, dojo.create(
+ "td", {"colspan": 2, "align": "center"},
+ dojo.create("tr", null, table)
+ )
+ );
+
+ dojo.place(table, this.node_editor_container, "only");
+ /* XXX around here attach other data structures to the node */
+ this.dnd_source.insertNodes(false, [draggable]);
+ };
+
+ this._init.apply(this, arguments);
+}
+
+function init_test() {
+ progress_dialog.show(true);
+
+ /* XXX No-one should have hundreds of these or anything, but theoretically
+ * this could be problematic with a big enough list of crad objects. */
+ _crads = new openils.PermaCrud().retrieveAll(
+ "crad", {"order_by": {"crad": "label"}}
+ );
+
+ var store = new dojo.data.ItemFileWriteStore({
+ "data": {
+ "identifier": "id", "label": "name", "items": [
+ {
+ "id": "root", "name": "AND",
+ "children": [
+ {"_reference": "leaf0"}, {"_reference": "leaf1"}
+ ]
+ },
+ {"id": "leaf0", "name": "nonsense test"},
+ {"id": "leaf1", "name": "more nonsense"}
+ ]
+ }
+ });
+
+ var treeModel = new openils.vandelay.TreeStoreModel({
+ store: store, "query": {"id": "root"}
+ });
+
+ var tree = new dijit.Tree(
+ {
+ "model": treeModel,
+ "dndController": dijit._tree.dndSource,
+ "dragThreshold": 8,
+ "betweenThreshold": 5,
+ "persist": false
+ }, "treeOne"
+ );
+
+ node_editor = new NodeEditor(mysrc, "node-editor-container");
+
+ dojo.connect(
+ mysrc, "onDndDrop", null,
+ function(source, nodes, copy, target) {
+ if (source == this) {
+ var model = target.tree.model;
+ model.getRoot(
+ function(root) {
+ model.getSimpleTree(
+ root, function(results) { alert(js2JSON(results)); }
+ );
+ }
+ );
+ node_editor.clear(); /* because otherwise this acts like a copy! */
+ } else {
+ alert("XXX [mysrc] nodes length is " + nodes.length); /* XXX DEBUG */
+ }
+ }
+ );
+ progress_dialog.hide();
+}
+
+openils.Util.addOnLoad(init_test);
--- /dev/null
+[% WRAPPER 'default/base.tt2' %]
+[% ctx.page_title = 'Vandelay Match Set Points' %]
+<style type="text/css">
+ .outer { clear: both; }
+ #vmsp-buttons button { padding: 0 1.5em; }
+ .node-editor { margin-bottom: 2em; }
+ .node-editor td { padding: 0.5ex; }
+ label[title] { border-bottom: 1px dashed #666; }
+ li { background-color: #ddd; }
+</style>
+<h1>[% ctx.page_title %]</h1>
+<table class="hidden">
+ <tr consistent-controls="1">
+ <td>
+ <label for="quality-input"
+ title="A relative number representing the impact of this expression on the quality of the overall record match">
+ Quality:
+ </label>
+ </td>
+ <td>
+ <input id="quality-input" type="text" value="1"
+ size="4" maxlength="3" fmfield="quality" />
+ </td>
+ </tr>
+ <tr consistent-controls="1">
+ <td>
+ <label for="negate-input">Negate?</label>
+ </td>
+ <td>
+ <input id="negate-input" type="checkbox" fmfield="negate" />
+ </td>
+ </tr>
+</table>
+<div class="outer">
+ <div><!-- XXX TODO: consider a read-only display here of the query as built
+ so far from the treet --></div>
+ <div id="vmsp-buttons">
+ <button onclick="node_editor.add('svf');">New Single-Value-Field</button>
+ <button onclick="node_editor.add('tag');">New MARC Tag and Subfield</button>
+ <button onclick="node_editor.add('bool_op');">New Boolean Operator</button>
+ </div>
+</div>
+<div class="outer" style="margin-top: 2ex;">
+ <div style="float: left; width: 49%">
+ <div>
+ <form id="node-editor-container" onsubmit="return false;"></form>
+ </div>
+ <ul dojoType="dojo.dnd.Source" jsId="mysrc"></ul>
+ </div>
+
+ <div style="float: right; width: 50%">
+ <div><big>Your Expression</big></div>
+ <div id="treeOne"></div>
+ </div>
+</div>
+<div jsId="progress_dialog" dojoType="openils.widget.ProgressDialog"></div>
+<script type="text/javascript"
+ src="[% ctx.media_prefix %]/js/ui/default/vandelay/treetest.js"></script>
+[% END %]