OSDN Git Service

git-svn-id: https://svn.sourceforge.jp/svnroot/nucleus-jp/plugin@1020 1ca29b6e-896d...
[nucleus-jp/nucleus-plugins.git] / NP_TrackBack / branches / DOM-branch / trackback / js / rico / ricoDragDrop.js
1 /**
2   *
3   *  Copyright 2005 Sabre Airline Solutions
4   *
5   *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6   *  file except in compliance with the License. You may obtain a copy of the License at
7   *
8   *         http://www.apache.org/licenses/LICENSE-2.0
9   *
10   *  Unless required by applicable law or agreed to in writing, software distributed under the
11   *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12   *  either express or implied. See the License for the specific language governing permissions
13   *  and limitations under the License.
14   **/
15 //-------------------- ricoDragAndDrop.js
16 Rico.DragAndDrop = Class.create();
17
18 Rico.DragAndDrop.prototype = {
19
20    initialize: function() {
21       this.dropZones                = new Array();
22       this.draggables               = new Array();
23       this.currentDragObjects       = new Array();
24       this.dragElement              = null;
25       this.lastSelectedDraggable    = null;
26       this.currentDragObjectVisible = false;
27       this.interestedInMotionEvents = false;
28       this._mouseDown = this._mouseDownHandler.bindAsEventListener(this);
29       this._mouseMove = this._mouseMoveHandler.bindAsEventListener(this);
30       this._mouseUp = this._mouseUpHandler.bindAsEventListener(this);
31    },
32
33    registerDropZone: function(aDropZone) {
34       this.dropZones[ this.dropZones.length ] = aDropZone;
35    },
36
37    deregisterDropZone: function(aDropZone) {
38       var newDropZones = new Array();
39       var j = 0;
40       for ( var i = 0 ; i < this.dropZones.length ; i++ ) {
41          if ( this.dropZones[i] != aDropZone )
42             newDropZones[j++] = this.dropZones[i];
43       }
44
45       this.dropZones = newDropZones;
46    },
47
48    clearDropZones: function() {
49       this.dropZones = new Array();
50    },
51
52    registerDraggable: function( aDraggable ) {
53       this.draggables[ this.draggables.length ] = aDraggable;
54       this._addMouseDownHandler( aDraggable );
55    },
56
57    clearSelection: function() {
58       for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
59          this.currentDragObjects[i].deselect();
60       this.currentDragObjects = new Array();
61       this.lastSelectedDraggable = null;
62    },
63
64    hasSelection: function() {
65       return this.currentDragObjects.length > 0;
66    },
67
68    setStartDragFromElement: function( e, mouseDownElement ) {
69       this.origPos = RicoUtil.toDocumentPosition(mouseDownElement);
70       this.startx = e.screenX - this.origPos.x
71       this.starty = e.screenY - this.origPos.y
72       //this.startComponentX = e.layerX ? e.layerX : e.offsetX;
73       //this.startComponentY = e.layerY ? e.layerY : e.offsetY;
74       //this.adjustedForDraggableSize = false;
75
76       this.interestedInMotionEvents = this.hasSelection();
77       this._terminateEvent(e);
78    },
79
80    updateSelection: function( draggable, extendSelection ) {
81       if ( ! extendSelection )
82          this.clearSelection();
83
84       if ( draggable.isSelected() ) {
85          this.currentDragObjects.removeItem(draggable);
86          draggable.deselect();
87          if ( draggable == this.lastSelectedDraggable )
88             this.lastSelectedDraggable = null;
89       }
90       else {
91          this.currentDragObjects[ this.currentDragObjects.length ] = draggable;
92          draggable.select();
93          this.lastSelectedDraggable = draggable;
94       }
95    },
96
97    _mouseDownHandler: function(e) {
98       if ( arguments.length == 0 )
99          e = event;
100
101       // if not button 1 ignore it...
102       var nsEvent = e.which != undefined;
103       if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
104          return;
105
106       var eventTarget      = e.target ? e.target : e.srcElement;
107       var draggableObject  = eventTarget.draggable;
108
109       var candidate = eventTarget;
110       while (draggableObject == null && candidate.parentNode) {
111          candidate = candidate.parentNode;
112          draggableObject = candidate.draggable;
113       }
114    
115       if ( draggableObject == null )
116          return;
117
118       this.updateSelection( draggableObject, e.ctrlKey );
119
120       // clear the drop zones postion cache...
121       if ( this.hasSelection() )
122          for ( var i = 0 ; i < this.dropZones.length ; i++ )
123             this.dropZones[i].clearPositionCache();
124
125       this.setStartDragFromElement( e, draggableObject.getMouseDownHTMLElement() );
126    },
127
128
129    _mouseMoveHandler: function(e) {
130       var nsEvent = e.which != undefined;
131       if ( !this.interestedInMotionEvents ) {
132          //this._terminateEvent(e);
133          return;
134       }
135
136       if ( ! this.hasSelection() )
137          return;
138
139       if ( ! this.currentDragObjectVisible )
140          this._startDrag(e);
141
142       if ( !this.activatedDropZones )
143          this._activateRegisteredDropZones();
144
145       //if ( !this.adjustedForDraggableSize )
146       //   this._adjustForDraggableSize(e);
147
148       this._updateDraggableLocation(e);
149       this._updateDropZonesHover(e);
150
151       this._terminateEvent(e);
152    },
153
154    _makeDraggableObjectVisible: function(e)
155    {
156       if ( !this.hasSelection() )
157          return;
158
159       var dragElement;
160       if ( this.currentDragObjects.length > 1 )
161          dragElement = this.currentDragObjects[0].getMultiObjectDragGUI(this.currentDragObjects);
162       else
163          dragElement = this.currentDragObjects[0].getSingleObjectDragGUI();
164
165       // go ahead and absolute position it...
166       if ( RicoUtil.getElementsComputedStyle(dragElement, "position")  != "absolute" )
167 /*      if (Element.getStyle(dragElement,'position')=='absolute')*/
168          dragElement.style.position = "absolute";
169
170       // need to parent him into the document...
171       if ( dragElement.parentNode == null || dragElement.parentNode.nodeType == 11 )
172          document.body.appendChild(dragElement);
173
174       this.dragElement = dragElement;
175       this._updateDraggableLocation(e);
176
177       this.currentDragObjectVisible = true;
178    },
179
180    /**
181    _adjustForDraggableSize: function(e) {
182       var dragElementWidth  = this.dragElement.offsetWidth;
183       var dragElementHeight = this.dragElement.offsetHeight;
184       if ( this.startComponentX > dragElementWidth )
185          this.startx -= this.startComponentX - dragElementWidth + 2;
186       if ( e.offsetY ) {
187          if ( this.startComponentY > dragElementHeight )
188             this.starty -= this.startComponentY - dragElementHeight + 2;
189       }
190       this.adjustedForDraggableSize = true;
191    },
192    **/
193
194    _leftOffset: function(e) {
195            return e.offsetX ? document.body.scrollLeft : 0
196         },
197
198    _topOffset: function(e) {
199            return e.offsetY ? document.body.scrollTop:0
200         },
201
202                 
203    _updateDraggableLocation: function(e) {
204       var dragObjectStyle = this.dragElement.style;
205       dragObjectStyle.left = (e.screenX + this._leftOffset(e) - this.startx) + "px"
206       dragObjectStyle.top  = (e.screenY + this._topOffset(e) - this.starty) + "px";
207    },
208
209    _updateDropZonesHover: function(e) {
210       var n = this.dropZones.length;
211       for ( var i = 0 ; i < n ; i++ ) {
212          if ( ! this._mousePointInDropZone( e, this.dropZones[i] ) )
213             this.dropZones[i].hideHover();
214       }
215
216       for ( var i = 0 ; i < n ; i++ ) {
217          if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
218             if ( this.dropZones[i].canAccept(this.currentDragObjects) )
219                this.dropZones[i].showHover();
220          }
221       }
222    },
223
224    _startDrag: function(e) {
225       for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
226          this.currentDragObjects[i].startDrag();
227
228       this._makeDraggableObjectVisible(e);
229    },
230
231    _mouseUpHandler: function(e) {
232       if ( ! this.hasSelection() )
233          return;
234
235       var nsEvent = e.which != undefined;
236       if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
237          return;
238
239       this.interestedInMotionEvents = false;
240
241       if ( this.dragElement == null ) {
242          this._terminateEvent(e);
243          return;
244       }
245
246       if ( this._placeDraggableInDropZone(e) )
247          this._completeDropOperation(e);
248       else {
249          this._terminateEvent(e);
250          Rico.animate(new Rico.Effect.Position( this.dragElement, this.origPos.x, this.origPos.y),
251                       {duration: 200,
252                        steps: 20,
253                        onFinish : this._doCancelDragProcessing.bind(this) } );
254       }
255
256      Event.stopObserving(document.body, "mousemove", this._mouseMove);
257      Event.stopObserving(document.body, "mouseup",  this._mouseUp);
258    },
259
260    _retTrue: function () {
261       return true;
262    },
263
264    _completeDropOperation: function(e) {
265       if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
266          if ( this.dragElement.parentNode != null )
267             this.dragElement.parentNode.removeChild(this.dragElement);
268       }
269
270       this._deactivateRegisteredDropZones();
271       this._endDrag();
272       this.clearSelection();
273       this.dragElement = null;
274       this.currentDragObjectVisible = false;
275       this._terminateEvent(e);
276    },
277
278    _doCancelDragProcessing: function() {
279       this._cancelDrag();
280
281         if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() && this.dragElement)
282            if ( this.dragElement.parentNode != null )
283               this.dragElement.parentNode.removeChild(this.dragElement);
284
285
286       this._deactivateRegisteredDropZones();
287       this.dragElement = null;
288       this.currentDragObjectVisible = false;
289    },
290
291    _placeDraggableInDropZone: function(e) {
292       var foundDropZone = false;
293       var n = this.dropZones.length;
294       for ( var i = 0 ; i < n ; i++ ) {
295          if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
296             if ( this.dropZones[i].canAccept(this.currentDragObjects) ) {
297                this.dropZones[i].hideHover();
298                this.dropZones[i].accept(this.currentDragObjects);
299                foundDropZone = true;
300                break;
301             }
302          }
303       }
304
305       return foundDropZone;
306    },
307
308    _cancelDrag: function() {
309       for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
310          this.currentDragObjects[i].cancelDrag();
311    },
312
313    _endDrag: function() {
314       for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
315          this.currentDragObjects[i].endDrag();
316    },
317
318    _mousePointInDropZone: function( e, dropZone ) {
319
320       var absoluteRect = dropZone.getAbsoluteRect();
321
322       return e.clientX  > absoluteRect.left + this._leftOffset(e) &&
323              e.clientX  < absoluteRect.right + this._leftOffset(e) &&
324              e.clientY  > absoluteRect.top + this._topOffset(e)   &&
325              e.clientY  < absoluteRect.bottom + this._topOffset(e);
326    },
327
328    _addMouseDownHandler: function( aDraggable )
329    {
330        htmlElement  = aDraggable.getMouseDownHTMLElement();
331       if ( htmlElement  != null ) { 
332          htmlElement.draggable = aDraggable;
333          Event.observe(htmlElement , "mousedown", this._onmousedown.bindAsEventListener(this));
334          Event.observe(htmlElement, "mousedown", this._mouseDown);
335       }
336    },
337
338    _activateRegisteredDropZones: function() {
339       var n = this.dropZones.length;
340       for ( var i = 0 ; i < n ; i++ ) {
341          var dropZone = this.dropZones[i];
342          if ( dropZone.canAccept(this.currentDragObjects) )
343             dropZone.activate();
344       }
345
346       this.activatedDropZones = true;
347    },
348
349    _deactivateRegisteredDropZones: function() {
350       var n = this.dropZones.length;
351       for ( var i = 0 ; i < n ; i++ )
352          this.dropZones[i].deactivate();
353       this.activatedDropZones = false;
354    },
355
356    _onmousedown: function () {
357      Event.observe(document.body, "mousemove", this._mouseMove);
358      Event.observe(document.body, "mouseup",  this._mouseUp);
359    },
360
361    _terminateEvent: function(e) {
362       if ( e.stopPropagation != undefined )
363          e.stopPropagation();
364       else if ( e.cancelBubble != undefined )
365          e.cancelBubble = true;
366
367       if ( e.preventDefault != undefined )
368          e.preventDefault();
369       else
370          e.returnValue = false;
371    },
372
373
374            initializeEventHandlers: function() {
375               if ( typeof document.implementation != "undefined" &&
376                  document.implementation.hasFeature("HTML",   "1.0") &&
377                  document.implementation.hasFeature("Events", "2.0") &&
378                  document.implementation.hasFeature("CSS",    "2.0") ) {
379                  document.addEventListener("mouseup",   this._mouseUpHandler.bindAsEventListener(this),  false);
380                  document.addEventListener("mousemove", this._mouseMoveHandler.bindAsEventListener(this), false);
381               }
382               else {
383                  document.attachEvent( "onmouseup",   this._mouseUpHandler.bindAsEventListener(this) );
384                  document.attachEvent( "onmousemove", this._mouseMoveHandler.bindAsEventListener(this) );
385               }
386            }
387         }
388
389         var dndMgr = new Rico.DragAndDrop();
390         dndMgr.initializeEventHandlers();
391
392
393 //-------------------- ricoDraggable.js
394 Rico.Draggable = Class.create();
395
396 Rico.Draggable.prototype = {
397
398    initialize: function( type, htmlElement ) {
399       this.type          = type;
400       this.htmlElement   = $(htmlElement);
401       this.selected      = false;
402    },
403
404    /**
405     *   Returns the HTML element that should have a mouse down event
406     *   added to it in order to initiate a drag operation
407     *
408     **/
409    getMouseDownHTMLElement: function() {
410       return this.htmlElement;
411    },
412
413    select: function() {
414       this.selected = true;
415
416       if ( this.showingSelected )
417          return;
418
419       var htmlElement = this.getMouseDownHTMLElement();
420
421       var color = Rico.Color.createColorFromBackground(htmlElement);
422       color.isBright() ? color.darken(0.033) : color.brighten(0.033);
423
424       this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color");
425 //      this.saveBackground = Element.getStyle(htmlElement,'backgroundColor') || Element.getStyle(htmlElement,'background-color')
426       htmlElement.style.backgroundColor = color.asHex();
427       this.showingSelected = true;
428    },
429
430    deselect: function() {
431       this.selected = false;
432       if ( !this.showingSelected )
433          return;
434
435       var htmlElement = this.getMouseDownHTMLElement();
436
437       htmlElement.style.backgroundColor = this.saveBackground;
438       this.showingSelected = false;
439    },
440
441    isSelected: function() {
442       return this.selected;
443    },
444
445    startDrag: function() {
446    },
447
448    cancelDrag: function() {
449    },
450
451    endDrag: function() {
452    },
453
454    getSingleObjectDragGUI: function() {
455       return this.htmlElement;
456    },
457
458    getMultiObjectDragGUI: function( draggables ) {
459       return this.htmlElement;
460    },
461
462    getDroppedGUI: function() {
463       return this.htmlElement;
464    },
465
466    toString: function() {
467       return this.type + ":" + this.htmlElement + ":";
468    }
469
470 }
471
472
473 //-------------------- ricoDropzone.js
474 Rico.Dropzone = Class.create();
475
476 Rico.Dropzone.prototype = {
477
478    initialize: function( htmlElement ) {
479       this.htmlElement  = $(htmlElement);
480       this.absoluteRect = null;
481    },
482
483    getHTMLElement: function() {
484       return this.htmlElement;
485    },
486
487    clearPositionCache: function() {
488       this.absoluteRect = null;
489    },
490
491    getAbsoluteRect: function() {
492       if ( this.absoluteRect == null ) {
493          var htmlElement = this.getHTMLElement();
494          var pos = RicoUtil.toViewportPosition(htmlElement);
495
496          this.absoluteRect = {
497             top:    pos.y,
498             left:   pos.x,
499             bottom: pos.y + htmlElement.offsetHeight,
500             right:  pos.x + htmlElement.offsetWidth
501          };
502       }
503       return this.absoluteRect;
504    },
505
506    activate: function() {
507       var htmlElement = this.getHTMLElement();
508       if (htmlElement == null  || this.showingActive)
509          return;
510
511       this.showingActive = true;
512       this.saveBackgroundColor = htmlElement.style.backgroundColor;
513
514       var fallbackColor = "#ffea84";
515       var currentColor = Rico.Color.createColorFromBackground(htmlElement);
516       if ( currentColor == null )
517          htmlElement.style.backgroundColor = fallbackColor;
518       else {
519          currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2);
520          htmlElement.style.backgroundColor = currentColor.asHex();
521       }
522    },
523
524    deactivate: function() {
525       var htmlElement = this.getHTMLElement();
526       if (htmlElement == null || !this.showingActive)
527          return;
528
529       htmlElement.style.backgroundColor = this.saveBackgroundColor;
530       this.showingActive = false;
531       this.saveBackgroundColor = null;
532    },
533
534    showHover: function() {
535       var htmlElement = this.getHTMLElement();
536       if ( htmlElement == null || this.showingHover )
537          return;
538
539       this.saveBorderWidth = htmlElement.style.borderWidth;
540       this.saveBorderStyle = htmlElement.style.borderStyle;
541       this.saveBorderColor = htmlElement.style.borderColor;
542
543       this.showingHover = true;
544       htmlElement.style.borderWidth = "1px";
545       htmlElement.style.borderStyle = "solid";
546       //htmlElement.style.borderColor = "#ff9900";
547       htmlElement.style.borderColor = "#ffff00";
548    },
549
550    hideHover: function() {
551       var htmlElement = this.getHTMLElement();
552       if ( htmlElement == null || !this.showingHover )
553          return;
554
555       htmlElement.style.borderWidth = this.saveBorderWidth;
556       htmlElement.style.borderStyle = this.saveBorderStyle;
557       htmlElement.style.borderColor = this.saveBorderColor;
558       this.showingHover = false;
559    },
560
561    canAccept: function(draggableObjects) {
562       return true;
563    },
564
565    accept: function(draggableObjects) {
566       var htmlElement = this.getHTMLElement();
567       if ( htmlElement == null )
568          return;
569
570       n = draggableObjects.length;
571       for ( var i = 0 ; i < n ; i++ )
572       {
573          var theGUI = draggableObjects[i].getDroppedGUI();
574 /*         if (Element.getStyle(theGUI,'position')=='absolute')*/
575          if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" )
576          {
577             theGUI.style.position = "static";
578             theGUI.style.top = "";
579             theGUI.style.top = "";
580          }
581          htmlElement.appendChild(theGUI);
582       }
583    }
584 }
585
586 RicoUtil = Object.extend(RicoUtil, {
587    getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) {
588       if ( arguments.length == 2 )
589          mozillaEquivalentCSS = cssProperty;
590
591       var el = $(htmlElement);
592       if ( el.currentStyle )
593          return el.currentStyle[cssProperty];
594       else
595          return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS);
596    },
597
598    createXmlDocument : function() {
599       if (document.implementation && document.implementation.createDocument) {
600          var doc = document.implementation.createDocument("", "", null);
601
602          if (doc.readyState == null) {
603             doc.readyState = 1;
604             doc.addEventListener("load", function () {
605                doc.readyState = 4;
606                if (typeof doc.onreadystatechange == "function")
607                   doc.onreadystatechange();
608             }, false);
609          }
610
611          return doc;
612       }
613
614       if (window.ActiveXObject)
615           return Try.these(
616             function() { return new ActiveXObject('MSXML2.DomDocument')   },
617             function() { return new ActiveXObject('Microsoft.DomDocument')},
618             function() { return new ActiveXObject('MSXML.DomDocument')    },
619             function() { return new ActiveXObject('MSXML3.DomDocument')   }
620           ) || false;
621
622       return null;
623    },
624
625    getContentAsString: function( parentNode ) {
626       return parentNode.xml != undefined ? 
627          this._getContentAsStringIE(parentNode) :
628          this._getContentAsStringMozilla(parentNode);
629    },
630
631   _getContentAsStringIE: function(parentNode) {
632      var contentStr = "";
633      for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
634          var n = parentNode.childNodes[i];
635          if (n.nodeType == 4) {
636              contentStr += n.nodeValue;
637          }
638          else {
639            contentStr += n.xml;
640        }
641      }
642      return contentStr;
643   },
644
645   _getContentAsStringMozilla: function(parentNode) {
646      var xmlSerializer = new XMLSerializer();
647      var contentStr = "";
648      for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
649           var n = parentNode.childNodes[i];
650           if (n.nodeType == 4) { // CDATA node
651               contentStr += n.nodeValue;
652           }
653           else {
654             contentStr += xmlSerializer.serializeToString(n);
655         }
656      }
657      return contentStr;
658   },
659
660    toViewportPosition: function(element) {
661       return this._toAbsolute(element,true);
662    },
663
664    toDocumentPosition: function(element) {
665       return this._toAbsolute(element,false);
666    },
667
668    /**
669     *  Compute the elements position in terms of the window viewport
670     *  so that it can be compared to the position of the mouse (dnd)
671     *  This is additions of all the offsetTop,offsetLeft values up the
672     *  offsetParent hierarchy, ...taking into account any scrollTop,
673     *  scrollLeft values along the way...
674     *
675     * IE has a bug reporting a correct offsetLeft of elements within a
676     * a relatively positioned parent!!!
677     **/
678    _toAbsolute: function(element,accountForDocScroll) {
679
680       if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 )
681          return this._toAbsoluteMozilla(element,accountForDocScroll);
682
683       var x = 0;
684       var y = 0;
685       var parent = element;
686       while ( parent ) {
687
688          var borderXOffset = 0;
689          var borderYOffset = 0;
690          if ( parent != element ) {
691             var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" ));
692             var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" ));
693             borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset;
694             borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset;
695          }
696
697          x += parent.offsetLeft - parent.scrollLeft + borderXOffset;
698          y += parent.offsetTop - parent.scrollTop + borderYOffset;
699          parent = parent.offsetParent;
700       }
701
702       if ( accountForDocScroll ) {
703          x -= this.docScrollLeft();
704          y -= this.docScrollTop();
705       }
706
707       return { x:x, y:y };
708    },
709
710    /**
711     *  Mozilla did not report all of the parents up the hierarchy via the
712     *  offsetParent property that IE did.  So for the calculation of the
713     *  offsets we use the offsetParent property, but for the calculation of
714     *  the scrollTop/scrollLeft adjustments we navigate up via the parentNode
715     *  property instead so as to get the scroll offsets...
716     *
717     **/
718    _toAbsoluteMozilla: function(element,accountForDocScroll) {
719       var x = 0;
720       var y = 0;
721       var parent = element;
722       while ( parent ) {
723          x += parent.offsetLeft;
724          y += parent.offsetTop;
725          parent = parent.offsetParent;
726       }
727
728       parent = element;
729       while ( parent &&
730               parent != document.body &&
731               parent != document.documentElement ) {
732          if ( parent.scrollLeft  )
733             x -= parent.scrollLeft;
734          if ( parent.scrollTop )
735             y -= parent.scrollTop;
736          parent = parent.parentNode;
737       }
738
739       if ( accountForDocScroll ) {
740          x -= this.docScrollLeft();
741          y -= this.docScrollTop();
742       }
743
744       return { x:x, y:y };
745    },
746
747    docScrollLeft: function() {
748       if ( window.pageXOffset )
749          return window.pageXOffset;
750       else if ( document.documentElement && document.documentElement.scrollLeft )
751          return document.documentElement.scrollLeft;
752       else if ( document.body )
753          return document.body.scrollLeft;
754       else
755          return 0;
756    },
757
758    docScrollTop: function() {
759       if ( window.pageYOffset )
760          return window.pageYOffset;
761       else if ( document.documentElement && document.documentElement.scrollTop )
762          return document.documentElement.scrollTop;
763       else if ( document.body )
764          return document.body.scrollTop;
765       else
766          return 0;
767    }
768 });
769
770 Rico.includeLoaded('ricoDragDrop.js');