]>
git.wh0rd.org - tt-rss.git/blob - lib/dojo/dnd/Container.js.uncompressed.js
1 define("dojo/dnd/Container", ["../main", "../Evented", "./common", "../parser"], function(dojo
, Evented
) {
11 "Over" - mouse over a container
12 Container item states:
14 "Over" - mouse over a container item
18 dojo.declare("dojo.dnd.__ContainerArgs", [], {
21 // a creator function, which takes a data item, and returns an object like that:
22 // {node: newNode, data: usedData, type: arrayOfStrings}
26 // don't start the drag operation, if clicked on form elements
29 // dropParent: Node||String
30 // node or node's id to use as the parent node for dropped items
31 // (must be underneath the 'node' parameter in the DOM)
34 // _skipStartup: Boolean
35 // skip startup(), which collects children, for deferred initialization
36 // (this is used in the markup mode)
40 dojo.dnd.Item = function(){
42 // Represents (one of) the source node(s) being dragged.
43 // Contains (at least) the "type" and "data" attributes.
45 // Type(s) of this item, by default this is ["text"]
47 // Logical representation of the object being dragged.
48 // If the drag object's type is "text" then data is a String,
49 // if it's another type then data could be a different Object,
50 // perhaps a name/value hash.
57 dojo
.declare("dojo.dnd.Container", Evented
, {
59 // a Container object, which knows when mouse hovers over it,
60 // and over which element it hovers
62 // object attributes (for markup)
67 // The DOM node the mouse is currently hovered over
70 // map: Hash<String, dojo.dnd.Item>
71 // Map from an item's id (which is also the DOMNode's id) to
72 // the dojo.dnd.Item itself.
76 constructor: function(node
, params
){
78 // a constructor of the Container
80 // node or node's id to build the container on
81 // params: dojo.dnd.__ContainerArgs
82 // a dictionary of parameters
83 this.node
= dojo
.byId(node
);
84 if(!params
){ params
= {}; }
85 this.creator
= params
.creator
|| null;
86 this.skipForm
= params
.skipForm
;
87 this.parent
= params
.dropParent
&& dojo
.byId(params
.dropParent
);
89 // class-specific variables
94 this.containerState
= "";
95 dojo
.addClass(this.node
, "dojoDndContainer");
98 if(!(params
&& params
._skipStartup
)){
104 dojo
.connect(this.node
, "onmouseover", this, "onMouseOver"),
105 dojo
.connect(this.node
, "onmouseout", this, "onMouseOut"),
106 // cancel text selection and text dragging
107 dojo
.connect(this.node
, "ondragstart", this, "onSelectStart"),
108 dojo
.connect(this.node
, "onselectstart", this, "onSelectStart")
112 // object attributes (for markup)
115 // creator function, dummy at the moment
118 // abstract access to the map
119 getItem: function(/*String*/ key
){
121 // returns a data item by its key (id)
122 return this.map
[key
]; // dojo.dnd.Item
124 setItem: function(/*String*/ key
, /*dojo.dnd.Item*/ data
){
126 // associates a data item with its key (id)
127 this.map
[key
] = data
;
129 delItem: function(/*String*/ key
){
131 // removes a data item from the map by its key (id)
132 delete this.map
[key
];
134 forInItems: function(/*Function*/ f
, /*Object?*/ o
){
136 // iterates over a data map skipping members that
137 // are present in the empty object (IE and/or 3rd-party libraries).
138 o
= o
|| dojo
.global
;
139 var m
= this.map
, e
= dojo
.dnd
._empty
;
141 if(i
in e
){ continue; }
142 f
.call(o
, m
[i
], i
, this);
146 clearItems: function(){
148 // removes all data items from the map
153 getAllNodes: function(){
155 // returns a list (an array) of all valid child nodes
156 return dojo
.query("> .dojoDndItem", this.parent
); // NodeList
160 // sync up the node list with the data map
162 this.getAllNodes().forEach(function(node
){
164 var item
= this.getItem(node
.id
);
170 node
.id
= dojo
.dnd
.getUniqueId();
172 var type
= node
.getAttribute("dndType"),
173 data
= node
.getAttribute("dndData");
175 data
: data
|| node
.innerHTML
,
176 type
: type
? type
.split(/\s*,\s*/) : ["text"]
182 insertNodes: function(data
, before
, anchor
){
184 // inserts an array of new nodes before/after an anchor node
186 // a list of data items, which should be processed by the creator function
188 // insert before the anchor, if true, and after the anchor otherwise
190 // the anchor node to be used as a point of insertion
191 if(!this.parent
.firstChild
){
195 anchor
= this.parent
.firstChild
;
199 anchor
= anchor
.nextSibling
;
203 for(var i
= 0; i
< data
.length
; ++i
){
204 var t
= this._normalizedCreator(data
[i
]);
205 this.setItem(t
.node
.id
, {data
: t
.data
, type
: t
.type
});
206 this.parent
.insertBefore(t
.node
, anchor
);
209 for(var i
= 0; i
< data
.length
; ++i
){
210 var t
= this._normalizedCreator(data
[i
]);
211 this.setItem(t
.node
.id
, {data
: t
.data
, type
: t
.type
});
212 this.parent
.appendChild(t
.node
);
219 // prepares this object to be garbage-collected
220 dojo
.forEach(this.events
, dojo
.disconnect
);
222 this.node
= this.parent
= this.current
= null;
226 markupFactory: function(params
, node
, ctor
){
227 params
._skipStartup
= true;
228 return new ctor(node
, params
);
232 // collects valid child items and populate the map
234 // set up the real parent node
236 // use the standard algorithm, if not assigned
237 this.parent
= this.node
;
238 if(this.parent
.tagName
.toLowerCase() == "table"){
239 var c
= this.parent
.getElementsByTagName("tbody");
240 if(c
&& c
.length
){ this.parent
= c
[0]; }
243 this.defaultCreator
= dojo
.dnd
._defaultCreator(this.parent
);
245 // process specially marked children
250 onMouseOver: function(e
){
252 // event processor for onmouseover
255 var n
= e
.relatedTarget
;
257 if(n
== this.node
){ break; }
265 this._changeState("Container", "Over");
268 n
= this._getChildByEvent(e
);
269 if(this.current
== n
){ return; }
270 if(this.current
){ this._removeItemClass(this.current
, "Over"); }
271 if(n
){ this._addItemClass(n
, "Over"); }
274 onMouseOut: function(e
){
276 // event processor for onmouseout
279 for(var n
= e
.relatedTarget
; n
;){
280 if(n
== this.node
){ return; }
288 this._removeItemClass(this.current
, "Over");
291 this._changeState("Container", "");
294 onSelectStart: function(e
){
296 // event processor for onselectevent and ondragevent
299 if(!this.skipForm
|| !dojo
.dnd
.isFormElement(e
)){
305 onOverEvent: function(){
307 // this function is called once, when mouse is over our container
309 onOutEvent: function(){
311 // this function is called once, when mouse is out of our container
313 _changeState: function(type
, newState
){
315 // changes a named state to new state value
317 // a name of the state to change
320 var prefix
= "dojoDnd" + type
;
321 var state
= type
.toLowerCase() + "State";
322 //dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
323 dojo
.replaceClass(this.node
, prefix
+ newState
, prefix
+ this[state
]);
324 this[state
] = newState
;
326 _addItemClass: function(node
, type
){
328 // adds a class with prefix "dojoDndItem"
332 // a variable suffix for a class name
333 dojo
.addClass(node
, "dojoDndItem" + type
);
335 _removeItemClass: function(node
, type
){
337 // removes a class with prefix "dojoDndItem"
341 // a variable suffix for a class name
342 dojo
.removeClass(node
, "dojoDndItem" + type
);
344 _getChildByEvent: function(e
){
346 // gets a child, which is under the mouse at the moment, or null
351 for(var parent
= node
.parentNode
; parent
; node
= parent
, parent
= node
.parentNode
){
352 if(parent
== this.parent
&& dojo
.hasClass(node
, "dojoDndItem")){ return node
; }
357 _normalizedCreator: function(/*dojo.dnd.Item*/ item
, /*String*/ hint
){
359 // adds all necessary data to the output of the user-supplied creator function
360 var t
= (this.creator
|| this.defaultCreator
).call(this, item
, hint
);
361 if(!dojo
.isArray(t
.type
)){ t
.type
= ["text"]; }
362 if(!t
.node
.id
){ t
.node
.id
= dojo
.dnd
.getUniqueId(); }
363 dojo
.addClass(t
.node
, "dojoDndItem");
368 dojo
.dnd
._createNode = function(tag
){
370 // returns a function, which creates an element of given tag
371 // (SPAN by default) and sets its innerHTML to given text
373 // a tag name or empty for SPAN
374 if(!tag
){ return dojo
.dnd
._createSpan
; }
375 return function(text
){ // Function
376 return dojo
.create(tag
, {innerHTML
: text
}); // Node
380 dojo
.dnd
._createTrTd = function(text
){
382 // creates a TR/TD structure with given text as an innerHTML of TD
385 var tr
= dojo
.create("tr");
386 dojo
.create("td", {innerHTML
: text
}, tr
);
390 dojo
.dnd
._createSpan = function(text
){
392 // creates a SPAN element with given text as its innerHTML
395 return dojo
.create("span", {innerHTML
: text
}); // Node
398 // dojo.dnd._defaultCreatorNodes: Object
399 // a dictionary that maps container tag names to child tag names
400 dojo
.dnd
._defaultCreatorNodes
= {ul
: "li", ol
: "li", div
: "div", p
: "div"};
402 dojo
.dnd
._defaultCreator = function(node
){
404 // takes a parent node, and returns an appropriate creator function
407 var tag
= node
.tagName
.toLowerCase();
408 var c
= tag
== "tbody" || tag
== "thead" ? dojo
.dnd
._createTrTd
:
409 dojo
.dnd
._createNode(dojo
.dnd
._defaultCreatorNodes
[tag
]);
410 return function(item
, hint
){ // Function
411 var isObj
= item
&& dojo
.isObject(item
), data
, type
, n
;
412 if(isObj
&& item
.tagName
&& item
.nodeType
&& item
.getAttribute
){
413 // process a DOM node
414 data
= item
.getAttribute("dndData") || item
.innerHTML
;
415 type
= item
.getAttribute("dndType");
416 type
= type
? type
.split(/\s*,\s*/) : ["text"];
417 n
= item
; // this node is going to be moved rather than copied
419 // process a DnD item object or a string
420 data
= (isObj
&& item
.data
) ? item
.data
: item
;
421 type
= (isObj
&& item
.type
) ? item
.type
: ["text"];
422 n
= (hint
== "avatar" ? dojo
.dnd
._createSpan
: c
)(String(data
));
425 n
.id
= dojo
.dnd
.getUniqueId();
427 return {node
: n
, data
: data
, type
: type
};
431 return dojo
.dnd
.Container
;