*/
dojo.declare(
"openils.vandelay.TreeDndSource", dijit._tree.dndSource, {
+ "_is_replaceable": function(src_item, target_item) {
+ /* An OP can replace anything, but non-OPs can only replace other
+ * non-OPs
+ */
+ console.log("src item: " + src_item + " target item: " + target_item);
+ return true; /* XXX TODO FINISHME */
+ },
"constructor": function() {
/* Given a tree object, there seems to be no way to access its
* dndController, which seems to be the only thing that knows
window._tree_dnd_controllers.push(this);
},
"checkItemAcceptance": function(target, source, position) {
- return (
- source._ready && (
+ if (!source._ready || source == this) return;
+
+ if (this.tree.model._replace_mode) {
+ return (
+ position == "over" && this._is_replaceable(
+ source.getAllNodes()[0].match_point,
+ dijit.getEnclosingWidget(target).item.match_point
+ )
+ );
+ } else {
+ return (
position != "over" ||
this.tree.model.mayHaveChildren(
dijit.getEnclosingWidget(target).item
)
- )
- );
+ );
+ }
/* code in match_set.js makes sure that source._ready gets set true
* only when we want the item to be draggable */
},
- "itemCreator": function(nodes) {
+ "itemCreator": function(nodes, somethingelse) {
+ console.log("gew: " + dijit.getEnclosingWidget(somethingelse).item.name);
+ console.log("dojo.dnd.manager.copy: " + dojo.dnd.manager.copy);
var default_items = this.inherited(arguments);
for (var i = 0; i < default_items.length; i++)
default_items[i].match_point = nodes[i].match_point;
dojo.require("dijit.Tree");
dojo.require("dijit.form.Button");
dojo.require("dojo.data.ItemFileWriteStore");
-//dojo.require("openils.vandelay.DndSource");
dojo.require("dojo.dnd.Source");
dojo.require("openils.vandelay.TreeDndSource");
dojo.require("openils.vandelay.TreeStoreModel");
this.clear = function() {
this.dnd_source.selectAll().deleteSelectedNodes();
dojo.empty(this.node_editor_container);
+ this.dnd_source._ready = false;
};
- this.update_draggable = function(draggable) {
- var s = "";
- draggable.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.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;
- }
+ this.build_vmsp = function() {
+ var match_point = new vmsp();
+ var controls = dojo.query("[fmfield]", this.node_editor_container);
+ for (var i = 0; i < controls.length; i++) {
+ var field = dojo.attr(controls[i], "fmfield");
+ var value = _simple_value_getter(controls[i]);
+ match_point[field](value);
+ }
+ return match_point;
+ };
- 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 />";
- }
- }
+ this.update_draggable = function(draggable) {
+ draggable.match_point = this.build_vmsp();
+ dojo.attr(
+ draggable, "innerHTML", render_vmsp_label(draggable.match_point)
);
- dojo.attr(draggable, "innerHTML", s);
this.dnd_source._ready = true;
};
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.dnd_source._ready = false;
};
this._init.apply(this, arguments);
/* XXX replace later with code that will suit this function's purpose
* as well as that of update_draggable. */
-function display_name_from_point(point) {
+function render_vmsp_label(point) {
/* quick and dirty */
if (point.bool_op()) {
- return (point.negate() == "t" ? "N" : "") + point.bool_op();
+ return (openils.Util.isTrue(point.negate()) ? "N" : "") +
+ point.bool_op();
} else if (point.svf()) {
- return (point.negate() == "t" ? "NOT " : "") + point.svf();
+ return (openils.Util.isTrue(point.negate()) ? "NOT " : "") +
+ point.svf() + " / " + _find_crad_by_name(point.svf()).label();
} else {
- return (point.negate() == "t" ? "NOT " : "") + point.tag() +
- "\u2021" + point.subfield();
+ return (openils.Util.isTrue(point.negate()) ? "NOT " : "") +
+ point.tag() + " \u2021" + point.subfield();
}
}
-function delete_selected_from_tree() {
+function replace_mode() {
+ tree.model._replace_mode ^= 1;
+ dojo.attr(
+ "replacer", "innerHTML",
+ localeStrings[
+ (tree.model._replace_mode ? "EXIT" : "ENTER") + "_REPLACE_MODE"
+ ]
+ );
+}
+
+function delete_selected_in_tree() {
/* relies on the fact that we only have one tree that would have
* registered a dnd controller. */
_tree_dnd_controllers[0].getSelectedItems().forEach(
function(item) {
- tree.model.store.deleteItem(item);
+ if (item === tree.model.root)
+ alert(localeStrings.LEAVE_ROOT_ALONE);
+ else
+ tree.model.store.deleteItem(item);
}
);
}
point.children([]);
var item = {
"id": (root ? "root" : refgen),
- "name": display_name_from_point(point),
+ "name": render_vmsp_label(point),
"match_point": point.clone(),
"children": []
};
dojo.byId("vms-mtype").innerHTML = match_set.mtype();
}
-function init_test() {
+function my_init() {
progress_dialog.show(true);
dojo.requireLocalization("openils.vandelay", "match_set");
[openils.User.authtoken, CGI.param("match_set")]
);
-// {
-// "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 store = new dojo.data.ItemFileWriteStore({
"data": {
"identifier": "id",
}
});
- var treeModel = new openils.vandelay.TreeStoreModel({
- store: store, "query": {"id": "root"}
+ var tree_model = new openils.vandelay.TreeStoreModel({
+ "store": store, "query": {"id": "root"}
});
var src = new dojo.dnd.Source("src-here");
tree = new dijit.Tree(
{
- "model": treeModel,
+ "model": tree_model,
"dndController": openils.vandelay.TreeDndSource,
"dragThreshold": 8,
"betweenThreshold": 5,
dojo.connect(
src, "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)); }
- );
- }
- );
+ /* XXX because of the... interesting... characteristics of DnD
+ * design in dojo/dijit (at least as of 1.3), this callback will
+ * fire both for our working node dndSource and for the tree!
+ */
+ if (source == this)
node_editor.clear(); /* because otherwise this acts like a copy! */
- } else {
- alert("XXX [src] nodes length is " + nodes.length); /* XXX DEBUG */
- }
}
);
progress_dialog.hide();
}
-openils.Util.addOnLoad(init_test);
+openils.Util.addOnLoad(my_init);
[% ctx.page_title = 'Vandelay Match Set Editor' %]
<style type="text/css">
h1 { margin: 1ex 0; }
- .outer { clear: both; }
- #vmsp-buttons button { margin: 0 0.5em; }
+ .outer { clear: both; margin-bottom: 1ex; }
+ button { margin: 0 0.5em; }
#tree-here { margin-bottom: 1.5em; }
#vms-table { padding-bottom: 2ex; }
#vms-table th { text-align: right; }
#vms-table td { padding-left: 1em; }
#src-pane { float: left; width: 49%; }
#tree-pane { float: right; width: 50%; }
+ #submit-row { clear: both; text-align: center; padding-top: 1.5ex; }
+ #submit-row hr { margin: 1ex 0; }
.node-editor { margin-bottom: 1.5ex; }
.node-editor td { padding: 0.5ex; }
li { background-color: #ddd; }
<div><!-- XXX TODO: consider a read-only display here of the query as built
so far from the treet --></div>
<div id="vmsp-buttons">
- New
+ Add new
<button onclick="node_editor.add('svf');">Single-Value-Field</button>
<button onclick="node_editor.add('tag');">MARC Tag and Subfield</button>
<button onclick="node_editor.add('bool_op');">Boolean Operator</button>
</div>
<div class="outer" style="margin-top: 2ex;">
<div id="src-pane">
+ <div><big>Working Match Point</big></div>
<div>
<form id="node-editor-container" onsubmit="return false;"></form>
</div>
<div id="tree-pane">
<div><big>Your Expression</big></div>
<div id="tree-here"></div>
- <button id="deleter" onclick="delete_selected_from_tree()">
- Deleted Selected Node
- </button>
+ <div>
+ <button id="deleter" onclick="delete_selected_in_tree()">
+ Delete Selected Node
+ </button>
+ <button id="replacer" onclick="replace_mode()">
+ Enter Replace Mode
+ </button>
+ </div>
</div>
</div>
+<div id="submit-row">
+ <hr />
+ <button onclick="save_tree()">Save Changes</button>
+</div>
<div jsId="progress_dialog" dojoType="openils.widget.ProgressDialog"></div>
<script type="text/javascript"
src="[% ctx.media_prefix %]/js/ui/default/vandelay/match_set.js"></script>