Changeset 7899
- Timestamp:
- 04/01/07 22:30:43 (22 months ago)
- Location:
- trunk/src/dnd2
- Files:
-
- 6 modified
-
avatar.js (modified) (3 diffs)
-
container.js (modified) (7 diffs)
-
manager.js (modified) (10 diffs)
-
move.js (modified) (5 diffs)
-
selector.js (modified) (16 diffs)
-
source.js (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/dnd2/avatar.js
r7896 r7899 6 6 7 7 dojo.dnd2.Avatar = function(manager){ 8 // summary: an object, which represents transferred DnD items visually 9 // manager: Object: a DnD manager object 8 10 this.manager = manager; 9 11 this.construct(); 12 // calculate various offsets 13 this.offX = dojo.dnd2._getOffset(this.node, "left"); 14 this.offY = dojo.dnd2._getOffset(this.node, "top"); 10 15 }; 11 16 12 17 dojo.dnd2._getOffset = function(node, side){ 18 // summary: calculates an offset for a content box 19 // node: Node: a node 20 // side: String: a side of a box ("left", "right", "top", or "bottom") 13 21 var h = dojo.html; 14 return h.getMarginExtent(node, side) + h.getBorderExtent(node, side) + h.getPaddingExtent(node, side); 22 return h.getMarginExtent(node, side) + h.getBorderExtent(node, side) + h.getPaddingExtent(node, side); // Number 15 23 }; 16 24 17 25 dojo.extend(dojo.dnd2.Avatar, { 18 26 construct: function(){ 27 // summary: a constructor function; 28 // it is separate so it can be (dynamically) overwritten in case of need 19 29 var h = dojo.html; 20 30 var a = dojo.doc().createElement("table"); … … 43 53 a.appendChild(b); 44 54 this.node = a; 45 // calculate various offsets46 this.offX = dojo.dnd2._getOffset(a, "left");47 this.offY = dojo.dnd2._getOffset(a, "top");48 55 }, 49 56 destroy: function(){ 57 // summary: a desctructor for the avatar, called to remove all references so it can be garbage-collected 50 58 this.node.parentNode.removeChild(this.node); 51 59 this.node = false; 52 60 }, 53 61 update: function(){ 62 // summary: updates the avatar to reflect the current DnD state 54 63 dojo.html[(this.manager.canDropFlag ? "add" : "remove") + "Class"](this.node, "dojoDndAvatarCanDrop"); 55 64 // replace text … … 64 73 }, 65 74 _generateText: function(){ 75 // summary: generates a proper text to reflect copying or moving of items 66 76 return (this.manager.copy ? "copy" : "mov") + "ing " + this.manager.nodes.length + " item" + (this.manager.nodes.length != 1 ? "s" : ""); 67 77 } -
trunk/src/dnd2/container.js
r7896 r7899 16 16 17 17 dojo.declare("dojo.dnd2.Container", null, 18 // summary: a Container object, which knows when mouse hovers over it, 19 // and know over which element it hovers 18 20 function(node, params){ 19 // general variables 21 // summary: a constructor of the Container 22 // node: Node: node or node's id to build the container on 23 // params: Object: a dict of parameters, recognized parameters are: 24 // filter: Function: a filter function, which is used to filter out children of the container 25 // creator: Function: a creator function, which takes a data item, and returns an object like that: 26 // {node: newNode, data: usedData, types: arrayOfStrings} 20 27 this.node = dojo.byId(node); 21 28 this.nodeFilter = (params && params.filter) ? params.filter : function(n){ return n.nodeType == 1; }; … … 49 56 dojo.event.connect(this.node, "onmouseout", this, "onMouseOut"); 50 57 // cancel text selection and text dragging 51 dojo.event.connect(this.node, "ondragstart", this, "cancelEvent");52 dojo.event.connect(this.node, "onselectstart", this, "cancelEvent");58 dojo.event.connect(this.node, "ondragstart", dojo.event.browser, "stopEvent"); 59 dojo.event.connect(this.node, "onselectstart", dojo.event.browser, "stopEvent"); 53 60 }, 54 61 { 55 62 // mouse events 56 63 onMouseOver: function(e){ 64 // summary: event processor for onmouseover 65 // e: Event: mouse event 57 66 if(!dojo.dom.isDescendantOf(e.relatedTarget, this.node)){ 58 this. changeState("Container", "Over");67 this._changeState("Container", "Over"); 59 68 this.onOverEvent(); 60 69 } 61 var node = this. getChildByEvent(e);70 var node = this._getChildByEvent(e); 62 71 if(this.current == node){ return; } 63 if(this.current){ this. removeItemClass(this.current, "Over"); }64 if(node){ this. addItemClass(node, "Over"); }72 if(this.current){ this._removeItemClass(this.current, "Over"); } 73 if(node){ this._addItemClass(node, "Over"); } 65 74 this.current = node; 66 75 }, 67 76 onMouseOut: function(e){ 77 // summary: event processor for onmouseout 78 // e: Event: mouse event 68 79 if(dojo.dom.isDescendantOf(e.relatedTarget, this.node)){ return; } 69 80 if(this.current){ 70 this. removeItemClass(this.current, "Over");81 this._removeItemClass(this.current, "Over"); 71 82 this.current = null; 72 83 } 73 this. changeState("Container", "");84 this._changeState("Container", ""); 74 85 this.onOutEvent(); 75 86 }, 76 87 // methods 77 88 getAllNodes: function(){ 89 // summary: returns a list (an array) of all valid child nodes 78 90 var t = []; 79 91 var c = this.node.tagName.toLowerCase() == "table" ? this.parent.getElementsByTagName("tr") : this.node.childNodes; … … 84 96 } 85 97 } 86 return t; 98 return t; // Array 87 99 }, 88 100 insertNodes: function(data, before, anchor){ 101 // summary: inserts an array of new nodes before/after an anchor node 102 // data: Array: a list of data items, which should be processed by the creator function 103 // before: Boolean: insert before the anchor, if true, and after the anchot otherwise 104 // anchor: Node: the anchor node to be used as a point of insertion 89 105 if(!this.parent.firstChild){ 90 106 anchor = null; … … 111 127 } 112 128 } 113 return this; 129 return this; // self 114 130 }, 115 131 // utilities 116 onOverEvent: function(){}, 117 onOutEvent: function(){}, 118 cancelEvent: function(e){ dojo.event.browser.stopEvent(e); }, 119 changeState: function(type, newState){ 132 onOverEvent: function(){ 133 // summary: this function is called once, when mouse is over our container 134 }, 135 onOutEvent: function(){ 136 // summary: this function is called once, when mouse is out of our container 137 }, 138 _changeState: function(type, newState){ 139 // summary: changes a named state to new state value 140 // type: String: a name of the state to change 141 // newState: String: new state 120 142 var prefix = "dojoDnd" + type; 121 143 var state = type.toLowerCase() + "State"; … … 123 145 this[state] = newState; 124 146 }, 125 addItemClass: function(node, type){ dojo.html.addClass(node, "dojoDndItem" + type); }, 126 removeItemClass: function(node, type){ dojo.html.removeClass(node, "dojoDndItem" + type); }, 127 getChildByEvent: function(e){ 147 _addItemClass: function(node, type){ 148 // summary: adds a class with prefix "dojoDndItem" 149 // node: Node: a node 150 // type: String: a variable suffix for a class name 151 dojo.html.addClass(node, "dojoDndItem" + type); 152 }, 153 _removeItemClass: function(node, type){ 154 // summary: removes a class with prefix "dojoDndItem" 155 // node: Node: a node 156 // type: String: a variable suffix for a class name 157 dojo.html.removeClass(node, "dojoDndItem" + type); 158 }, 159 _getChildByEvent: function(e){ 160 // summary: gets a child, which is under the mouse at the moment 161 // e: Event: a mouse event 128 162 var node = e.target; 129 163 if(node == this.node){ return null; } … … 133 167 parent = node.parentNode; 134 168 } 135 return (parent && this.nodeFilter(node)) ? node : null; 169 return (parent && this.nodeFilter(node)) ? node : null; // Node 136 170 } 137 171 }); 138 172 139 173 dojo.dnd2._createNode = function(tag){ 174 // summary: returns a function, which creates an element of given tag 175 // (SPAN by default) and sets its innerHTML to given text 176 // tag: String: a tag name or empty for SPAN 140 177 if(!tag){ return dojo.dnd2._createSpan; } 141 return function(text){ 178 return function(text){ // Function 142 179 var n = dojo.doc().createElement(tag); 143 180 n.innerHTML = text; … … 147 184 148 185 dojo.dnd2._createTrTd = function(text){ 186 // summary: creates a TR/TD structure with given text as an innerHTML of TD 187 // text: String: a text for TD 149 188 var tr = dojo.doc().createElement("tr"); 150 189 var td = dojo.doc().createElement("td"); 151 190 td.innerHTML = text; 152 191 tr.appendChild(td); 153 return tr; 192 return tr; // Node 154 193 }; 155 194 156 195 dojo.dnd2._createSpan = function(text){ 196 // summary: creates a SPAN element with given text as its innerHTML 197 // text: String: a text for SPAN 157 198 var n = dojo.doc().createElement("span"); 158 199 n.innerHTML = text; 159 return n; 160 }; 161 200 return n; // Node 201 }; 202 203 // dojo.dnd2._defaultCreatorNodes: Object: a dicitionary, which maps container tag names to child tag names 162 204 dojo.dnd2._defaultCreatorNodes = {ul: "li", ol: "li", div: "div", p: "div"}; 205 163 206 dojo.dnd2._defaultCreator = function(node){ 207 // summary: takes a container node, and returns an appropriate creator function 208 // node: Node: a container node 164 209 var tag = node.tagName.toLowerCase(); 165 210 var c = tag == "table" ? dojo.dnd2._createTrTd : dojo.dnd2._createNode(dojo.dnd2._defaultCreatorNodes[tag]); 166 211 var r = dojo.lang.repr ? dojo.lang.repr : function(o){ return o + ""; }; 167 return function(data, hint){ 212 return function(data, hint){ // Function 168 213 var t = r(data); 169 214 var n = (hint == "avatar" ? dojo.dnd2._createSpan : c)(t); -
trunk/src/dnd2/manager.js
r7896 r7899 7 7 8 8 dojo.dnd2.Manager = function(){ 9 // summary: the manager of DnD operations (usually a singleton) 9 10 this.avatar = null; 10 11 11 this.source = null; 12 12 this.nodes = []; 13 13 this.copy = true; 14 15 14 this.target = null; 16 15 this.canDropFlag = false; … … 20 19 // methods 21 20 overSource: function(source){ 21 // summary: called when a source detected a mouse-over conditiion 22 // source: Object: the reporter 22 23 if(this.avatar){ 23 24 this.target = (source && source.targetState != "Disabled") ? source : null; … … 27 28 }, 28 29 outSource: function(source){ 30 // summary: called when a source detected a mouse-out conditiion 31 // source: Object: the reporter 29 32 if(this.avatar){ 30 33 if(this.target == source){ … … 39 42 }, 40 43 startDrag: function(source, nodes, copy){ 44 // summary: called to initiate the DnD operation 45 // source: Object: the source which provides items 46 // nodes: Array: the list of transferred items 47 // copy: Boolean: copy items, if true, move items otherwise 41 48 this.source = source; 42 49 this.nodes = nodes; … … 52 59 }, 53 60 canDrop: function(flag){ 61 // summary: called to notify if the current target can accept items 54 62 var canDropFlag = this.target && flag; 55 63 if(this.canDropFlag != canDropFlag){ … … 59 67 }, 60 68 stopDrag: function(){ 69 // summary: stop the DnD in progress 61 70 dojo.html.removeClass(dojo.body(), "dojoDndCopy"); 62 71 dojo.html.removeClass(dojo.body(), "dojoDndMove"); … … 70 79 this.nodes = []; 71 80 }, 72 makeAvatar: function(){ return new dojo.dnd2.Avatar(this); }, 73 updateAvatar: function(){ this.avatar.update(); }, 81 makeAvatar: function(){ 82 // summary: makes the avatar, it is separate to be overwritten dynamically, if needed 83 return new dojo.dnd2.Avatar(this); 84 }, 85 updateAvatar: function(){ 86 // summary: updates the avatar, it is separate to be overwritten dynamically, if needed 87 this.avatar.update(); 88 }, 74 89 // mouse event processors 75 90 onMouseMove: function(e){ 91 // summary: event processor for onmousemove 92 // e: Event: mouse event 76 93 var a = this.avatar; 77 94 if(a){ … … 79 96 s.left = (e.pageX + 10 + a.offX) + "px"; 80 97 s.top = (e.pageY + 10 + a.offY) + "px"; 81 if(this.copy != e.ctrlKey){ this. setCopyStatus(e.ctrlKey); }98 if(this.copy != e.ctrlKey){ this._setCopyStatus(e.ctrlKey); } 82 99 } 83 100 }, 84 101 onMouseUp: function(e){ 102 // summary: event processor for onmouseup 103 // e: Event: mouse event 85 104 if(this.avatar){ 86 105 if(this.target && this.canDropFlag){ … … 94 113 // keyboard event processors 95 114 onKeyDown: function(e){ 96 if(this.avatar && e.keyCode == dojo.event.browser.keys.KEY_CTRL && !this.copy){ this.setCopyStatus(true); } 115 // summary: event processor for onkeydown, watching for CTRL for copy/move status 116 // e: Event: keyboard event 117 if(this.avatar && e.keyCode == dojo.event.browser.keys.KEY_CTRL && !this.copy){ this._setCopyStatus(true); } 97 118 }, 98 119 onKeyUp: function(e){ 99 if(this.avatar && e.keyCode == dojo.event.browser.keys.KEY_CTRL && this.copy){ this.setCopyStatus(false); } 120 // summary: event processor for onkeyup, watching for CTRL for copy/move status 121 // e: Event: keyboard event 122 if(this.avatar && e.keyCode == dojo.event.browser.keys.KEY_CTRL && this.copy){ this._setCopyStatus(false); } 100 123 }, 101 124 // utilities 102 setCopyStatus: function(copy){ 125 _setCopyStatus: function(copy){ 126 // summary: changes the copy status 127 // copy: Boolean: the copy status 103 128 this.copy = copy; 104 this.source. markDndStatus(this.copy);129 this.source._markDndStatus(this.copy); 105 130 this.updateAvatar(); 106 131 dojo.html.replaceClass(dojo.body(), "dojoDnd" + (this.copy ? "Copy" : "Move"), "dojoDnd" + (this.copy ? "Move" : "Copy")); … … 108 133 }); 109 134 135 // summary: the manager singleton variable, can be overwritten, if needed 110 136 dojo.dnd2._manager = null; 111 137 112 138 dojo.dnd2.manager = function(){ 139 // summary: returns the current DnD manager, creates one if it is not created yet 113 140 if(!dojo.dnd2._manager){ 114 141 dojo.dnd2._manager = new dojo.dnd2.Manager(); 115 142 } 116 return dojo.dnd2._manager; 143 return dojo.dnd2._manager; // Object 117 144 }; -
trunk/src/dnd2/move.js
r7896 r7899 5 5 6 6 dojo.dnd2.Mover = function(node, e){ 7 // summary: an object, which makes a node follow the mouse 8 // node: Node: a node (or node's id) to be moved 9 // e: Event: a mouse event, which started the move; 10 // only pageX and pageY properties are used 7 11 this.node = dojo.byId(node); 8 12 this.mouseX = e.pageX; … … 10 14 var h = dojo.html; 11 15 this.nodePos = h.abs(this.node, true, h.boxSizing.MARGIN_BOX); 16 dojo.event.connectOnce(dojo.doc(), "onmousemove", this, "_makeAbsolute"); 12 17 dojo.event.connect(dojo.doc(), "onmousemove", this, "onMouseMove"); 13 dojo.event.connect(dojo.doc(), "onmouseup", this, " onMouseUp");18 dojo.event.connect(dojo.doc(), "onmouseup", this, "destroy"); 14 19 // cancel text selection and text dragging 15 20 dojo.event.connect(dojo.doc(), "ondragstart", dojo.event.browser, "stopEvent"); … … 20 25 // mouse event processors 21 26 onMouseMove: function(e){ 27 // summary: event processor for onmousemove 28 // e: Event: mouse event 22 29 var s = this.node.style; 23 s.position = "absolute"; // enforcing the absolute mode24 30 s.left = (e.pageX - this.mouseX + this.nodePos.x) + "px"; 25 31 s.top = (e.pageY - this.mouseY + this.nodePos.y) + "px"; 26 32 }, 27 onMouseUp: function(e){ 28 this.cancel(); 33 // utilities 34 _makeAbsolute: function(){ 35 // summary: makes the node absolute; it is meant to be called only once 36 this.node.style.position = "absolute"; // enforcing the absolute mode 29 37 }, 30 // utilities 31 cancel: function(){ 38 destroy: function(){ 39 // summary: stops the move, deletes all references, so the object can be garbage-collected 40 dojo.event.disconnect(dojo.doc(), "onmousemove", this, "_makeAbsolute"); 32 41 dojo.event.disconnect(dojo.doc(), "onmousemove", this, "onMouseMove"); 33 42 dojo.event.disconnect(dojo.doc(), "onmouseup", this, "onMouseUp"); … … 38 47 }); 39 48 40 dojo.dnd2.move = function(node, e){ return new dojo.dnd2.Mover(node, e); };41 42 49 dojo.dnd2.Moveable = function(node, handle){ 50 // summary: an object, which makes a node moveable 51 // node: Node: a node (or node's id) to be moved 52 // handle: Node: a node (or node's id), which is used as a mouse handle; 53 // if omitted, the node itself is used as a handle 43 54 if(!handle){ handle = node; } 44 55 this.node = dojo.byId(node); … … 54 65 // mouse event processors 55 66 onMouseDown: function(e){ 56 dojo.dnd2.move(this.node, e); 67 // summary: event processor for onmousedown, creates a Mover for the node 68 // e: Event: mouse event 69 new dojo.dnd2.Mover(this.node, e); 57 70 dojo.event.browser.stopEvent(e); 58 71 }, 59 72 // utilities 60 cancel: function(){ 73 destroy: function(){ 74 // summary: stops watching for possible move, deletes all references, so the object can be garbage-collected 61 75 dojo.event.disconnect(this.handle, "onmousedown", this, "onMouseDown"); 62 76 dojo.event.disconnect(this.handle, "ondragstart", dojo.event.browser, "stopEvent"); -
trunk/src/dnd2/selector.js
r7896 r7899 14 14 */ 15 15 16 dojo.declare("dojo.dnd2.Selector", dojo.dnd2.Container, 16 dojo.declare("dojo.dnd2.Selector", dojo.dnd2.Container, 17 // summary: a Selector object, which knows how to select its children 17 18 function(node, params){ 18 // general variables 19 // summary: a constructor of the Selector 20 // node: Node: node or node's id to build the selector on 21 // params: Object: a dict of parameters, recognized parameters are: 22 // singular: Boolean: allows selection of only one element, if true 23 // the rest of parameters are passed to the container 19 24 this.singular = params && params.singular; 20 25 // class-specific variables … … 29 34 // mouse events 30 35 onMouseDown: function(e){ 36 // summary: event processor for onmousedown 37 // e: Event: mouse event 31 38 if(!this.current){ return; } 32 39 if(!this.singular && !e.ctrlKey && !e.shiftKey && (this.current.id in this.selection)){ 33 40 this.simpleSelection = true; 34 this.cancelEvent(e);41 dojo.event.browser.stopEvent(e); 35 42 return; 36 43 } … … 41 48 if(!(i in empty)){ 42 49 var n = dojo.byId(i); 43 this. removeItemClass(n, "Selected");50 this._removeItemClass(n, "Selected"); 44 51 } 45 52 } … … 54 61 } 55 62 this.anchor = c[i]; 56 this. addItemClass(this.anchor, "Anchor");63 this._addItemClass(this.anchor, "Anchor"); 57 64 } 58 65 this.selection[this.anchor.id] = 1; … … 68 75 if(!this.nodeFilter(n)){ continue; } 69 76 if(n == this.anchor || n == this.current){ break; } 70 this. addItemClass(n, "Selected");77 this._addItemClass(n, "Selected"); 71 78 this.selection[n.id] = 1; 72 79 } 73 this. addItemClass(this.current, "Selected");80 this._addItemClass(this.current, "Selected"); 74 81 this.selection[this.current.id] = 1; 75 82 } … … 78 85 if(this.anchor == this.current){ 79 86 if(e.ctrlKey){ 80 this. removeItemClass(this.anchor, "Anchor");87 this._removeItemClass(this.anchor, "Anchor"); 81 88 this.anchor = null; 82 89 this.selection = {}; … … 84 91 }else{ 85 92 if(this.anchor){ 86 this. removeItemClass(this.anchor, "Anchor");93 this._removeItemClass(this.anchor, "Anchor"); 87 94 } 88 95 this.anchor = this.current; 89 this. addItemClass(this.anchor, "Anchor");96 this._addItemClass(this.anchor, "Anchor"); 90 97 this.selection = {}; 91 98 this.selection[this.current.id] = 1; … … 94 101 if(e.ctrlKey){ 95 102 if(this.anchor == this.current){ 96 this. removeItemClass(this.anchor, "Anchor");103 this._removeItemClass(this.anchor, "Anchor"); 97 104 delete this.selection[this.anchor.id]; 98 105 this.anchor = null; 99 106 }else{ 100 107 if(this.current.id in this.selection){ 101 this. removeItemClass(this.current, "Selected");108 this._removeItemClass(this.current, "Selected"); 102 109 delete this.selection[this.current.id]; 103 110 }else{ … … 106 113 } 107 114 this.anchor = this.current; 108 this. addItemClass(this.current, "Anchor");115 this._addItemClass(this.current, "Anchor"); 109 116 this.selection[this.current.id] = 1; 110 117 } … …