]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/dojo/openils/vandelay/TreeDndSource.js
Match Set Tree editor improvements/cleanup
[working/Evergreen.git] / Open-ILS / web / js / dojo / openils / vandelay / TreeDndSource.js
1 dojo.provide("openils.vandelay.TreeDndSource");
2 dojo.require("dijit._tree.dndSource");
3
4 /* This class specifically serves the eg/vandelay/match_set interface
5  * for editing Vandelay Match Set trees.  It should probably  have a more
6  * specific name that reflects that.
7  */
8 dojo.declare(
9     "openils.vandelay.TreeDndSource", dijit._tree.dndSource, {
10         "_is_replaceable": function(spoint, dpoint, disroot) {
11             /* An OP can replace anything, but non-OPs can only replace other
12              * non-OPs, EXCEPT when the dest is the root node (this allows
13              * for simple "trees" with only a single non-OP node.
14              */
15             if (disroot)
16                 return true;
17             else if (spoint.bool_op())
18                 return true;
19             else if (!dpoint.bool_op())
20                 return true;
21             return false;
22         },
23         "constructor": function() {
24             /* Given a tree object, there seems to be no way to access its
25              * dndController, which seems to be the only thing that knows
26              * about a tree's selected nodes.  So we register instances
27              * in a global variable in order to find them later. :-(
28              */
29             if (!window._tree_dnd_controllers)
30                 window._tree_dnd_controllers = [];
31
32             window._tree_dnd_controllers.push(this);
33         },
34         "checkItemAcceptance": function(target, source, position) {
35             if (!source._ready || source == this) return;
36
37             if (this.tree.model.replace_mode) {
38                 var ditem = dijit.getEnclosingWidget(target).item;
39                 return (
40                     position == "over" && this._is_replaceable(
41                         source.getAllNodes()[0].match_point,
42                         this.tree.model.store.getValue(ditem, "match_point"),
43                         ditem === this.tree.model.root
44                     )
45                 );
46             } else {
47                 return (
48                     position != "over" ||
49                     this.tree.model.mayHaveChildren(
50                         dijit.getEnclosingWidget(target).item
51                     )
52                 );
53             }
54             /* code in match_set.js makes sure that source._ready gets set true
55              * only when we want the item to be draggable */
56         },
57         "itemCreator": function(nodes, somethingelse) {
58             var default_items = this.inherited(arguments);
59             for (var i = 0; i < default_items.length; i++)
60                 default_items[i].match_point = nodes[i].match_point;
61             return default_items;
62         },
63         "onDndDrop": function(source, nodes, copy) {
64             if (
65                 !this.tree.model.replace_mode ||
66                 this.containerState != "Over" ||
67                 this.dropPosition == "Before" ||
68                 this.dropPosition == "After" ||
69                 source == this
70             ) {
71                 return this.inherited(arguments);
72             }
73
74             /* This method only comes into play for our "replace mode" */
75
76             var target_widget = dijit.getEnclosingWidget(this.targetAnchor);
77             var new_params = this.itemCreator(nodes, this.targetAnchor)[0];
78
79             /* Here, we morph target_widget.item into the new item */
80
81             var store = this.tree.model.store;
82             var item = target_widget.item;
83             for (var k in new_params) {
84                 if (k == "id") continue;    /* can't use this / don't need it */
85                 store.setValue(item, k, new_params[k]);
86             }
87             if (this.tree.model.root === item) {    /* replacing root node */
88                 if (!new_params.match_point.bool_op()) {
89                     /* If we're here, we've replaced the root node with
90                      * something that isn't a bool op, so we need to nuke
91                      * any children that the item has.
92                      */
93                     store.setValue(item, "children", []);
94                 }
95             }
96             if (typeof(window.render_vmsp_label) == "function") {
97                 store.setValue(
98                     item,
99                     "name",
100                     window.render_vmsp_label(new_params.match_point)
101                 );
102             }
103
104             /* just because this is at the end of the default implementation: */
105             this.onDndCancel();
106         }
107     }
108 );