Changeset 507

Show
Ignore:
Timestamp:
01/15/06 08:23:50 (3 years ago)
Author:
therve@gmail.com
Message:

Add doc, extract sortables to a new file.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • mochikit/branches/scriptaculous/MochiKit/DragAndDrop.js

    r502 r507  
    2323 
    2424DragAndDrop.Droppables = { 
     25    /*** 
     26 
     27    Manage all droppables. Shouldn't be used, use the Droppable object instead. 
     28 
     29    ***/ 
    2530    drops: [], 
    2631 
     
    102107 
    103108DragAndDrop.Droppable.prototype = { 
    104     __init__: function (element, options) { 
     109    /*** 
     110 
     111    A droppable object. Simple use is to create giving an element: 
     112 
     113        new DragAndDrop.Droppable('myelement'); 
     114 
     115    Generally you'll want to define the 'onDrop' function and maybe the 
     116    'accept' option to filter draggables. 
     117 
     118    ***/ 
     119    __init__: function (element, /* optional */options) { 
    105120        this.element = MochiKit.DOM.getElement(element); 
    106121        this.options = MochiKit.Base.update({ 
     
    120135                }); 
    121136            } else { 
    122                 this.options._containers.push(MochiKit.DOM.getElement(containment)); 
     137                this.options._containers.push( 
     138                    MochiKit.DOM.getElement(containment)); 
    123139            } 
    124140        } 
     
    159175    deactivate: function () { 
    160176        if (this.options.hoverclass) { 
    161             MochiKit.DOM.removeElementClass(this.element, this.options.hoverclass); 
     177            MochiKit.DOM.removeElementClass(this.element, 
     178                                            this.options.hoverclass); 
    162179        } 
    163180        DragAndDrop.Droppables.last_active = null; 
     
    173190 
    174191DragAndDrop.Draggables = { 
     192    /*** 
     193 
     194    Manage draggables elements. Not intended to direct use. 
     195 
     196    ***/ 
    175197    drags: [], 
     198 
    176199    observers: [], 
    177200 
     
    288311 
    289312DragAndDrop.Draggable.prototype = { 
    290     __init__: function (element, options) { 
     313    /*** 
     314 
     315    A draggable object. Simple instantiate : 
     316 
     317        new DragAndDrop.Draggable('myelement'); 
     318 
     319    ***/ 
     320    __init__: function (element, /* optional */options) { 
    291321        options = MochiKit.Base.update({ 
    292322            handle: false, 
     
    523553}; 
    524554 
    525 SortableObserver = function (element, observer) { 
    526     this.__init__(element, observer); 
    527 }; 
    528  
    529 SortableObserver.prototype = { 
    530     __init__: function (element, observer) { 
    531         this.element = MochiKit.DOM.getElement(element); 
    532         this.observer = observer; 
    533         this.lastValue = Sortable.serialize(this.element); 
    534     }, 
    535  
    536     onStart: function () { 
    537         this.lastValue = Sortable.serialize(this.element); 
    538     }, 
    539  
    540     onEnd: function () { 
    541         Sortable.unmark(); 
    542         if (this.lastValue != Sortable.serialize(this.element)) { 
    543             this.observer(this.element) 
    544         } 
    545     } 
    546 }; 
    547  
    548 var Sortable = { 
    549     sortables: new Array(), 
    550  
    551     options: function (element){ 
    552         element = MochiKit.DOM.getElement(element); 
    553         var result; 
    554         MochiKit.Iter.forEach(this.sortables, function (s) { 
    555             if (s.element == element) { 
    556                 result = s; 
    557                 throw MochiKit.Iter.StopIteration; 
    558             } 
    559         }); 
    560         return result; 
    561     }, 
    562  
    563     destroy: function (element){ 
    564         element = MochiKit.DOM.getElement(element); 
    565         MochiKit.Iter.forEach(MochiKit.Iter.ifilter(function (s) { 
    566                 return s.element == element; 
    567             }, this.sortables), function (s) { 
    568                 DragAndDrop.Draggables.removeObserver(s.element); 
    569                 MochiKit.Iter.forEach(s.droppables, function (d) { 
    570                     DragAndDrop.Droppables.remove(d); 
    571                 }); 
    572             s.draggables.invoke('destroy'); 
    573         }); 
    574         this.sortables = MochiKit.Base.filter(function (s) { 
    575             return s.element != element; 
    576         }, this.sortables); 
    577     }, 
    578  
    579     create: function (element, options) { 
    580         element = MochiKit.DOM.getElement(element); 
    581         options = MochiKit.Base.update({ 
    582             element: element, 
    583             tag: 'li',  // assumes li children, override with tag: 'tagname' 
    584             dropOnEmpty: false, 
    585             tree: false,  // fixme: unimplemented 
    586             overlap: 'vertical',  // one of 'vertical', 'horizontal' 
    587             constraint: 'vertical',  // one of 'vertical', 'horizontal', false 
    588             // also takes array of elements (or ids); or false 
    589             containment: element, 
    590             handle: false,  // or a CSS class 
    591             only: false, 
    592             hoverclass: null, 
    593             ghosting: false, 
    594             format: null, 
    595             onChange: MochiKit.Base.emptyFunction, 
    596             onUpdate: MochiKit.Base.emptyFunction 
    597         }, options); 
    598  
    599         // clear any old sortable with same element 
    600         this.destroy(element); 
    601  
    602         // build options for the draggables 
    603         var options_for_draggable = { 
    604             revert: true, 
    605             ghosting: options.ghosting, 
    606             constraint: options.constraint, 
    607             handle: options.handle 
    608         }; 
    609  
    610         if (options.starteffect) { 
    611             options_for_draggable.starteffect = options.starteffect; 
    612         } 
    613  
    614         if (options.reverteffect) { 
    615             options_for_draggable.reverteffect = options.reverteffect; 
    616         } else if (options.ghosting) { 
    617             options_for_draggable.reverteffect = function (element) { 
    618                 element.style.top = 0; 
    619                 element.style.left = 0; 
    620             }; 
    621         } 
    622  
    623         if (options.endeffect) { 
    624             options_for_draggable.endeffect = options.endeffect; 
    625         } 
    626  
    627         if (options.zindex) { 
    628             options_for_draggable.zindex = options.zindex; 
    629         } 
    630  
    631         // build options for the droppables 
    632         var options_for_droppable = { 
    633             overlap: options.overlap, 
    634             containment: options.containment, 
    635             hoverclass: options.hoverclass, 
    636             onHover: Sortable.onHover, 
    637             greedy: !options.dropOnEmpty 
    638         } 
    639  
    640         // fix for gecko engine 
    641         MochiKit.DOM.cleanWhitespace(element); 
    642  
    643         options.draggables = []; 
    644         options.droppables = []; 
    645  
    646         // make it so 
    647  
    648         // drop on empty handling 
    649         if (options.dropOnEmpty) { 
    650             new DragAndDrop.Droppable(element, 
    651             {containment: options.containment, 
    652              onHover: Sortable.onEmptyHover, 
    653              greedy: false}); 
    654             options.droppables.push(element); 
    655         } 
    656         MochiKit.Iter.forEach((this.findElements(element, options) || []), 
    657         function (e) { 
    658             // handles are per-draggable 
    659             var handle = options.handle ? 
    660                 MochiKit.DOM.getElementsByTagAndClassName(null, 
    661                     options.handle, e)[0] : e; 
    662             options.draggables.push( 
    663                 new DragAndDrop.Draggable(e, 
    664                     MochiKit.Base.update(options_for_draggable, 
    665                                          {handle: handle}))); 
    666             new DragAndDrop.Droppable(e, options_for_droppable); 
    667             options.droppables.push(e); 
    668         }); 
    669  
    670         // keep reference 
    671         this.sortables.push(options); 
    672  
    673         // for onupdate 
    674         DragAndDrop.Draggables.addObserver( 
    675             new SortableObserver(element, options.onUpdate)); 
    676     }, 
    677  
    678     // return all suitable-for-sortable elements in a guaranteed order 
    679     findElements: function (element, options) { 
    680         if (!element.hasChildNodes()) { 
    681             return null; 
    682         } 
    683         var elements = []; 
    684         MochiKit.Iter.forEach(element.childNodes, function (e) { 
    685             if (e.tagName && 
    686                 e.tagName.toUpperCase() == options.tag.toUpperCase() && 
    687                (!options.only || 
    688                 (MochiKit.DOM.hasElementClass(e, options.only)))) { 
    689                 elements.push(e); 
    690             } 
    691             if (options.tree) { 
    692                 var grandchildren = this.findElements(e, options); 
    693                 if (grandchildren) { 
    694                     elements.push(grandchildren); 
    695                 } 
    696             } 
    697         }); 
    698  
    699         return (elements.length > 0 ? MochiKit.Iter.flatten(elements) : null); 
    700     }, 
    701  
    702     onHover: function (element, dropon, overlap) { 
    703         if (overlap > 0.5) { 
    704             Sortable.mark(dropon, 'before'); 
    705             if (dropon.previousSibling != element) { 
    706                 var oldParentNode = element.parentNode; 
    707                 element.style.visibility = 'hidden';  // fix gecko rendering 
    708                 dropon.parentNode.insertBefore(element, dropon); 
    709                 if (dropon.parentNode != oldParentNode) { 
    710                     Sortable.options(oldParentNode).onChange(element); 
    711                 } 
    712                 Sortable.options(dropon.parentNode).onChange(element); 
    713             } 
    714         } else { 
    715             Sortable.mark(dropon, 'after'); 
    716             var nextElement = dropon.nextSibling || null; 
    717             if (nextElement != element) { 
    718                 var oldParentNode = element.parentNode; 
    719                 element.style.visibility = 'hidden';  // fix gecko rendering 
    720                 dropon.parentNode.insertBefore(element, nextElement); 
    721                 if (dropon.parentNode != oldParentNode) { 
    722                     Sortable.options(oldParentNode).onChange(element); 
    723                 } 
    724                 Sortable.options(dropon.parentNode).onChange(element); 
    725             } 
    726         } 
    727     }, 
    728  
    729     onEmptyHover: function (element, dropon) { 
    730         if (element.parentNode != dropon) { 
    731             var oldParentNode = element.parentNode; 
    732             dropon.appendChild(element); 
    733             Sortable.options(oldParentNode).onChange(element); 
    734             Sortable.options(dropon).onChange(element); 
    735         } 
    736     }, 
    737  
    738     unmark: function () { 
    739         if (Sortable._marker) { 
    740             MochiKit.DOM.hideElement(Sortable._marker); 
    741         } 
    742     }, 
    743  
    744     mark: function (dropon, position) { 
    745         // mark on ghosting only 
    746         var sortable = Sortable.options(dropon.parentNode); 
    747         if (sortable && !sortable.ghosting) { 
    748             return; 
    749         } 
    750  
    751         if (!Sortable._marker) { 
    752             Sortable._marker = MochiKit.DOM.getElement('dropmarker') || 
    753                                document.createElement('DIV'); 
    754             MochiKit.DOM.hideElement(Sortable._marker); 
    755             MochiKit.DOM.addElementClass(Sortable._marker, 'dropmarker'); 
    756             Sortable._marker.style.position = 'absolute'; 
    757             document.getElementsByTagName('body').item(0).appendChild( 
    758                 Sortable._marker); 
    759         } 
    760         var offsets = MochiKit.Position.cumulativeOffset(dropon); 
    761         Sortable._marker.style.left = offsets[0] + 'px'; 
    762         Sortable._marker.style.top = offsets[1] + 'px'; 
    763  
    764         if (position == 'after') { 
    765             if (sortable.overlap == 'horizontal') { 
    766                 Sortable._marker.style.left = (offsets[0] + 
    767                                                dropon.clientWidth) + 'px'; 
    768             } else { 
    769                 Sortable._marker.style.top = (offsets[1] + 
    770                                               dropon.clientHeight) + 'px'; 
    771             } 
    772         } 
    773         MochiKit.DOM.showElement(Sortable._marker); 
    774     }, 
    775  
    776     serialize: function (element, options) { 
    777         element = MochiKit.DOM.getElement(element); 
    778         var sortableOptions = this.options(element); 
    779         options = MochiKit.Base.update( 
    780         { 
    781             tag: sortableOptions.tag, 
    782             only: sortableOptions.only, 
    783             name: element.id, 
    784             format: sortableOptions.format || /^[^_]*_(.*)$/ 
    785         }, options || {}); 
    786         return MochiKit.Base.map(function (item) { 
    787           return (encodeURIComponent(options.name) + '[]=' + 
    788                   encodeURIComponent(item.id.match(options.format) ? 
    789                     item.id.match(options.format)[1] : '')); 
    790         }, MochiKit.DOM.getElement( 
    791             this.findElements(element, options) || [])).join('&'); 
    792     } 
    793 }; 
    794