r8877@llin: dpavlin | 2005-11-14 18:40:33 +0100
[webpac2] / web / iwf / iwfgui.js
index 884cac3..be3e5d2 100644 (file)
@@ -1,51 +1,65 @@
-// -----------------------------------------------------------------------------\r
-// IWF - Interactive Website Framework.  Javascript library for creating\r
-// responsive thin client interfaces.\r
-//\r
-// Copyright (C) 2005 Brock Weaver brockweaver@gmail.com\r
-//\r
-//     This library is free software; you can redistribute it and/or modify\r
-// it under the terms of the GNU Lesser General Public License as published\r
-// by the Free Software Foundation; either version 2.1 of the License, or\r
-// (at your option) any later version.\r
-//\r
-//     This library is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
-// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public\r
-// License for more details.\r
+// --------------------------------------------------------------------------\r
+/// IWF - Interactive Website Framework.  Javascript library for creating\r
+/// responsive thin client interfaces.\r
+///\r
+/// Copyright (C) 2005 Brock Weaver brockweaver@users.sourceforge.net\r
+///\r
+///     This library is free software; you can redistribute it and/or modify\r
+/// it under the terms of the GNU Lesser General Public License as published\r
+/// by the Free Software Foundation; either version 2.1 of the License, or\r
+/// (at your option) any later version.\r
+///\r
+///     This library is distributed in the hope that it will be useful, but\r
+/// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+/// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public\r
+/// License for more details.\r
+///\r
+///    You should have received a copy of the GNU Lesser General Public License\r
+/// along with this library; if not, write to the Free Software Foundation,\r
+/// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+///\r
+/// Brock Weaver\r
+/// brockweaver@users.sourceforge.net\r
+/// 1605 NW Maple Pl\r
+/// Ankeny, IA 50021\r
+///\r
+//! http://iwf.sourceforge.net/\r
+// --------------------------------------------------------------------------\r
+//! NOTE: To minimize file size, strip all fluffy comments (except the LGPL, of course!)\r
+//! using the following regex (global flag and multiline on):\r
+//!            ^\t*//([^/!].*|$)\r
 //\r
-//    You should have received a copy of the GNU Lesser General Public License\r
-// along with this library; if not, write to the Free Software Foundation,\r
-// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+// This reduces file size by about 30%, give or take.\r
 //\r
-// Brock Weaver\r
-// brockweaver@gmail.com\r
-// 1605 NW Maple Pl\r
-// Ankeny, IA 50021\r
-// -----------------------------------------------------------------------------\r
+//!  To rip out only logging statements (commented or uncommented):\r
+//!            ^/{0,2}iwfLog.*\r
+// --------------------------------------------------------------------------\r
 \r
 // --------------------------------------------------------------------------\r
-// iwfgui.js\r
+//! iwfgui.js\r
 //\r
 // GUI inspection and manipulation functions\r
 //\r
-// Dependencies:\r
-// iwfcore.js\r
+//! Dependencies:\r
+//! iwfcore.js\r
 //\r
-// Brock Weaver - brockweaver@sourceforge.net - iwf.sourceforge.net\r
-// v 0.1 - 2005-06-05\r
-// Initial release.\r
+//! Brock Weaver - brockweaver@users.sourceforge.net\r
+//! v 0.2 - 2005-11-14\r
+//! core bug patch\r
+// --------------------------------------------------------------------------\r
+//! v 0.1 - 2005-06-05\r
+//! Initial release.\r
 // --------------------------------------------------------------------------\r
 // Issues:\r
 //  Timeouts have hiccups sometimes when they begin to overlap\r
-//  Not tested on Safari -- I need an iMac!\r
+//  Not tested on Safari -- I need a Mac!\r
 //  _iwfMoveTo() has some calculation problems with certain motionType values\r
 // --------------------------------------------------------------------------\r
 \r
 // -----------------------------------\r
 // Dependency Check\r
 if (!window.iwfGetById){\r
-       alert("IWF Dependency Error: you must set a reference to the iwfcore.js file *before* iwfgui.js! I.E.:\n\n<script type='text/javascript' src='iwfcore.js'></script>\n<script type='text/javascript' src='iwfgui.js'></script>");\r
+       iwfLog("IWF Dependency Error: you must set a reference to the iwfcore.js file *before* iwfgui.js! I.E.:\n\n<script type='text/javascript' src='iwfcore.js'></script>\n<script type='text/javascript' src='iwfgui.js'></script>", true);\r
 }\r
 // -----------------------------------\r
 \r
@@ -339,12 +353,12 @@ function _iwfClearTimeout(id, name, category, forceful){
 \r
 }\r
 \r
-// BROCK\r
 function iwfDelay(ms, fpOrString){\r
+       // note this inner function creates a closure...\r
        function _iwfDelayExpired(){\r
                if (localIsString){\r
                        // passed a string. eval it.\r
-iwfLog("_iwfDelayExpired: calling string of:\n" + localFpOrString, true);\r
+//iwfLog("_iwfDelayExpired: calling string of:\n" + localFpOrString, true);\r
                        eval(localFpOrString);\r
                } else {\r
                        // they passed a function pointer.\r
@@ -526,11 +540,13 @@ function iwfSetY(id, newy){
 \r
 function iwfZIndex(id, z){\r
        var el = iwfGetById(id);\r
+       if (!el) return 0;\r
+\r
        if (iwfExists(el)){\r
                if (iwfExists(z)){\r
                        el.style.zIndex = z;\r
                }\r
-               return parseInt(el.style.zIndex);\r
+               return iwfToInt(el.style.zIndex, true);\r
        }\r
        return 0;\r
 }\r
@@ -599,7 +615,7 @@ function _iwfMoveTo(id1, xOrig, yOrig, xDest, yDest, ticksLeft, totalTicks, moti
                var elX = iwfX1(el);\r
                var elY = iwfY1(el);\r
 \r
-               // hack for floating point anomolies -- stops animation when element is "close enough"\r
+               //! hack for floating point anomolies -- stops animation when element is "close enough"\r
                var epsilon = 0.001;\r
 \r
                var xDone = false;\r
@@ -625,7 +641,7 @@ function _iwfMoveTo(id1, xOrig, yOrig, xDest, yDest, ticksLeft, totalTicks, moti
                }\r
 \r
                if (ticksLeft <= 0 || (xDone && yDone)){\r
-                       // time is up. / motion is done\r
+                       //! time is up / motion is "close enough"\r
 //iwfLog("_iwfMoveTo time is up / motion is done.");\r
                        iwfX1(el, xDest);\r
                        iwfY1(el, yDest);\r
@@ -871,6 +887,36 @@ function iwfYScroll(id) {
 // Begin: Size\r
 // -----------------------------------\r
 \r
+function iwfClientHeight(){\r
+  var vHeight = 0;\r
+       if(document.compatMode == 'CSS1Compat' && document.documentElement && document.documentElement.clientHeight) {\r
+               vHeight = document.documentElement.clientHeight;\r
+       } else if(document.body && document.body.clientHeight) {\r
+               vHeight = document.body.clientHeight;\r
+       } else if(iwfExists(window.innerWidth,window.innerHeight,document.width)) {\r
+               vHeight = window.innerHeight;\r
+               if(document.width>window.innerWidth) {\r
+                       vHeight -= 16;\r
+               }\r
+       }\r
+  return vHeight;\r
+}\r
+\r
+function iwfClientWidth(){\r
+       var vWidth = 0;\r
+       if(document.compatMode == 'CSS1Compat' && document.documentElement && document.documentElement.clientWidth) {\r
+               vWidth = document.documentElement.clientWidth;\r
+       } else if(document.body && document.body.clientWidth) {\r
+               vWidth = document.body.clientWidth;\r
+       } else if(iwfExists(window.innerWidth,window.innerHeight,document.height)) {\r
+               vWidth = window.innerWidth;\r
+               if(document.height>window.innerHeight) {\r
+                       vWidth -= 16;\r
+               }\r
+       }\r
+       return vWidth;\r
+}\r
+\r
 function iwfWidth(id, neww){\r
 \r
 \r
@@ -904,23 +950,6 @@ function iwfWidth(id, neww){
 \r
 \r
 \r
-//     var el = iwfGetById(id);\r
-//     var w = 0;\r
-//     if (iwfExists(el)){\r
-//             if(iwfExists(el.style, el.offsetWidth) && iwfIsString(el.style.width)) {\r
-//                     if(neww) iwfDetermineWidth(el, neww);\r
-//                     w = el.offsetWidth;\r
-//             }\r
-//             else if(iwfExists(el.style) && iwfExists(el.style.pixelWidth)) {\r
-//                     if(neww) el.style.pixelWidth = neww;\r
-//                     w = el.style.pixelWidth;\r
-//             }\r
-//             else if(iwfExists(el.clip) && iwfExists(el.clip.right)) {\r
-//                     if(neww) e.clip.right = neww;\r
-//                     w = el.clip.right;\r
-//             }\r
-//     }\r
-//     return w;\r
 }\r
 \r
 function iwfHeight(id, newh){\r
@@ -953,8 +982,7 @@ function iwfY2(id, y2){
        if (iwfExists(el)) {\r
                var y1 = iwfY(el);\r
                if (iwfExists(y2)){\r
-                       var h = iwfHeight(el);\r
-                       iwfHeight(el, y1 + h);\r
+                       iwfHeight(el, y2 - y1);\r
                }\r
                return y1 + iwfHeight(el);\r
        }\r
@@ -964,10 +992,9 @@ function iwfY2(id, y2){
 function iwfX2(id, x2){\r
        var el = iwfGetById(id);\r
        if (iwfExists(el)) {\r
-               var x1 = iwfX(id);\r
+               var x1 = iwfX(el);\r
                if (iwfExists(x2)){\r
-                       var w = iwfWidth(id);\r
-                       iwfWidth(id, x1 + h);\r
+                       iwfWidth(el, x2 - x1);\r
                }\r
                return x1 + iwfWidth(el);\r
        }\r
@@ -987,10 +1014,10 @@ function iwfDetermineWidth(el,neww){
 \r
        } else if(iwfExists(el.currentStyle,document.compatMode)){\r
                if(document.compatMode=='CSS1Compat'){\r
-                       padl = parseInt(el.currentStyle.paddingLeft);\r
-                       padr = parseInt(el.currentStyle.paddingRight);\r
-                       bdrl = parseInt(el.currentStyle.borderLeftWidth);\r
-                       bdrr = parseInt(el.currentStyle.borderRightWidth);\r
+                       padl = iwfToInt(el.currentStyle.paddingLeft, true);\r
+                       padr = iwfToInt(el.currentStyle.paddingRight, true);\r
+                       bdrl = iwfToInt(el.currentStyle.borderLeftWidth, true);\r
+                       bdrr = iwfToInt(el.currentStyle.borderRightWidth, true);\r
                }\r
        } else if(iwfExists(el.offsetWidth,el.style.width)){\r
                el.style.width = neww + 'px';\r
@@ -1016,10 +1043,10 @@ function iwfDetermineHeight(el,newh){
                badb = iwfDetermineStyle(el,'border-bottom-height');\r
        } else if(iwfExists(el.currentStyle,document.compatMode)){\r
                if(document.compatMode=='CSS1Compat'){\r
-                       padt = parseInt(el.currentStyle.paddingTop);\r
-                       padb = parseInt(el.currentStyle.paddingBottom);\r
-                       bdrt = parseInt(el.currentStyle.borderTopHeight);\r
-                       bdrb = parseInt(el.currentStyle.borderBottomHeight);\r
+                       padt = iwfToInt(el.currentStyle.paddingTop, true);\r
+                       padb = iwfToInt(el.currentStyle.paddingBottom, true);\r
+                       bdrt = iwfToInt(el.currentStyle.borderTopHeight, true);\r
+                       bdrb = iwfToInt(el.currentStyle.borderBottomHeight, true);\r
                }\r
        } else if(iwfExists(el.offsetHeight, el.style.height)){\r
                el.style.height = newh + 'px';\r
@@ -1037,6 +1064,41 @@ function iwfDetermineHeight(el,newh){
        else el.style.height = h2 + 'px';\r
 }\r
 \r
+function iwfOverlaps(id1, id2) {\r
+       var el1 = iwfGetById(id1);\r
+       var el2 = iwfGetById(id2);\r
+\r
+       if (!el1 || !el2) return false;\r
+\r
+       var x1a = iwfX(el1);\r
+       var x1b = iwfX2(el1);\r
+       var y1a = iwfY(el1);\r
+       var y1b = iwfY2(el1);\r
+\r
+       var x2a = iwfX(el2);\r
+       var x2b = iwfX2(el2);\r
+       var y2a = iwfY(el2);\r
+       var y2b = iwfY2(el2);\r
+\r
+       if(x1a > x2b || x1b < x2a || y1a > y2b || y1b < y2a) {\r
+               return false;\r
+       } else {\r
+               return true;\r
+       }\r
+\r
+}\r
+\r
+function iwfXCenter(id) {\r
+       var el = iwfGetById(id);\r
+       if (!el) return 0;\r
+       return iwfX(el) + iwfWidth(el) / 2;\r
+}\r
+\r
+function iwfYCenter(id) {\r
+       var el = iwfGetById(id);\r
+       if (!el) return 0;\r
+       return iwfY(el) + iwfHeight(el) / 2;\r
+}\r
 \r
 // -----------------------------------\r
 // End: Size\r
@@ -1046,21 +1108,73 @@ function iwfDetermineHeight(el,newh){
 // Begin: Event\r
 // -----------------------------------\r
 \r
-function iwfAddEvent(id,eventName,callback) {\r
+function iwfAddEvent(id, eventName,callback) {\r
        var el = iwfGetById(id);\r
        if (!el) return;\r
-       if (el.attachEvent) {\r
+\r
+       var txt = callback;\r
+       if (iwfIsString(callback)){\r
+               callback = function() { eval(txt);};\r
+       }\r
+\r
+       if (el.addEventListener) {\r
+               el.addEventListener(eventName.substr(2), callback, false);\r
+       } else if (el.attachEvent) {\r
+//iwfLog('attaching event ' + eventName + ' to element ' + el.id + ' with the callback:\n' + callback, true);\r
                el.attachEvent(eventName, callback);\r
        } else {\r
-               el[eventName] = callback;\r
+               iwfLog("Couldn't add event " + eventName + " to element " + el.id + " because neither addEventListener nor attachEvent are implemented.", true);\r
        }\r
 }\r
 \r
 function iwfRemoveEvent(id, eventName, callback){\r
        var el = iwfGetById(id);\r
        if (!el) return;\r
-       if (el.detachEvent) el.detachEvent(eventName, callback);\r
-       else eval('el.' + eventName + ' = null;');\r
+       if (el.removeEventListener) {\r
+               el.removeEventListener(eventName.substr(2), callback, false);\r
+       } else if (el.detachEvent) {\r
+               el.detachEvent(eventName, callback);\r
+       } else {\r
+               iwfLog("Couldn't remove event " + eventName + " from element " + el.id + " because neither removeEventListener nor detachEvent are implemented.", true);\r
+       }\r
+}\r
+\r
+function iwfCallAttribute(id, eventName, evt){\r
+       var el = iwfGetById(id);\r
+       if (!el) return false;\r
+\r
+       var val = iwfAttribute(el, eventName);\r
+//iwfLog("calling attribute " + eventName + "=" + val, true);\r
+       if (val){\r
+               eval(val);\r
+       }\r
+\r
+       return;\r
+\r
+\r
+\r
+\r
+       if (el.fireEvent){\r
+iwfLog("firing event " + eventName + " on el " + el.id);\r
+               el.fireEvent(eventName, evt);\r
+       } else if (el.dispatchEvent){\r
+               // chop off the "on" at the beginning...\r
+//             eventName = eventName.substr(2);\r
+//             iwfLog(eventName, true);\r
+               var newEvent = null;\r
+               if (document.createEvent){\r
+                       newEvent = document.createEvent("Events");\r
+               } else {\r
+                       newEvent = document.createEventObject();\r
+               }\r
+               newEvent.initEvent(eventName, true, true); //, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);\r
+iwfLog("dispatching event " + eventName + " on el " + el.id);\r
+               if (!el.dispatchEvent(newEvent)){\r
+iwfLog("Could not el.dispatchEvent failed!", true);\r
+               }\r
+       } else {\r
+iwfLog("Could not el.fireEvent or el.dispatchEvent!", true);\r
+       }\r
 }\r
 \r
 function iwfEvent(ev) {\r
@@ -1076,6 +1190,9 @@ function iwfEvent(ev) {
        if(evt.target) this.target = evt.target;\r
        else if(evt.srcElement) this.target = evt.srcElement;\r
 \r
+       this.X = iwfX(evt.target);\r
+       this.Y = iwfY(evt.target);\r
+\r
        if(iwfExists(evt.clientX,evt.clientY)) {\r
                this.X = evt.clientX + iwfXScroll();\r
                this.Y = evt.clientY + iwfYScroll();\r
@@ -1158,84 +1275,419 @@ function iwfMapRollovers(){
 // Begin: Drag-N-Drop\r
 // -----------------------------------\r
 \r
-var iwfDragger = {el:null, inUse:false};\r
+var iwfDragger = {el:null, curTarget:null, targets:new Array()};\r
 var iwfHiZ = 2;\r
 \r
-function iwfEnableDrag(id, startCallback, dragCallback, endCallback) {\r
+var iwfResizer = {elSrc:null, elTgt:null};\r
+\r
+function iwfResize(resizeId, targetId){\r
+       var resizer = iwfGetById(resizeId);\r
+       if (!resizer) return;\r
+\r
+       var target = iwfGetById(targetId);\r
+       if (!target) return;\r
+\r
+       iwfResizer.elSrc = resizer;\r
+       iwfResizer.elTgt = target;\r
+\r
+\r
+       // set the drag start / move / stop\r
+       iwfAttribute(resizer, 'iwfdragbegin', 'iwfResizeStart()');\r
+       iwfAttribute(resizer, 'iwfdragmove', 'iwfResizeMove()');\r
+       iwfAttribute(resizer, 'iwfdragend', 'iwfResizeEnd()');\r
+\r
+       iwfDrag(resizer);\r
+\r
+}\r
+\r
+function iwfResizeStart(){\r
+\r
+}\r
+\r
+function iwfResizeMove(resizeId, targetId){\r
+       // elSrc should have already been moved to its new location.\r
+       // make elTgt fit to it.\r
+       var tgtX = iwfX(iwfResizer.elTgt);\r
+       var tgtY = iwfY(iwfResizer.elTgt);\r
+\r
+       var srcX2 = iwfX2(iwfResizer.elSrc);\r
+       if (srcX2 - 100 < tgtX){\r
+               srcX2 = tgtX + 100;\r
+       }\r
+\r
+       var srcY2 = iwfY2(iwfResizer.elSrc);\r
+       if (srcY2 - 50 < tgtY){\r
+               srcY2 = tgtY + 50;\r
+       }\r
+//iwfLog("srcX2:" + srcX2 + "\tsrcY2:" + srcY2);\r
+//     iwfX1(iwfResizer.elSrc, srcX2 - iwfWidth(iwfResizer.elSrc));\r
+//     iwfY1(iwfResizer.elSrc, srcY2 - iwfHeight(iwfResizer.elSrc));\r
+\r
+//     iwfX2(iwfResizer.elTgt, srcX2);\r
+//     iwfY2(iwfResizer.elTgt, srcY2);\r
+\r
+       // if container exists, make it occupy all but titlebar space...\r
+       if (iwfResizer.elTgt){\r
+               var elContainer = iwfGetById(iwfResizer.elTgt.id + 'Container');\r
+               if (elContainer){\r
+                       iwfHeight(elContainer, iwfHeight(iwfResizer.elTgt) - iwfHeight(iwfResizer.elTgt.id + 'TitleBar') - 2);\r
+               }\r
+       }\r
+\r
+\r
+}\r
+\r
+function iwfResizeEnd(){\r
+\r
+iwfLog(iwfElementToString(iwfResizer.elSrc), true);\r
+\r
+       iwfResizer.elSrc = null;\r
+       iwfResizer.elTgt = null;\r
+}\r
+\r
+function iwfDrag(id) {\r
+\r
        var el = iwfGetById(id);\r
        if (!el) return;\r
-       el.iwfDraggable = true;\r
-       el.iwfOnDragStart = startCallback;\r
-       el.iwfOnDrag = dragCallback;\r
-       el.iwfOnDragEnd = endCallback;\r
-       iwfAddEvent(el, 'onmousedown', iwfDragMouseDown);\r
-       if (!iwfDragger.inUse) {\r
-               iwfDragger.inUse = true;\r
-               iwfAddEvent(document, 'onmousemove', iwfDragMouseMove);\r
+\r
+//iwfLog(iwfElementToString(el), true);\r
+       if (!iwfDragger.el) {\r
+               el.iwfDragTarget = true;\r
+               iwfAddEvent(el, 'onmousedown', iwfDragMouseDown);\r
+               // BROCK: sync issues here in IE when there is no container.\r
+               // HACK: force a container always? hmmmm...\r
+//             iwfFireEvent(el, 'onmousedown');\r
        }\r
 }\r
 function iwfDragMouseDown(ev){\r
+\r
        var evt = new iwfEvent(ev);\r
        var el = evt.target;\r
-       while(el && !el.iwfDraggable) {\r
-               el = iwfParent(el);\r
+       while(el && !el.iwfDragTarget) {\r
+               el = iwfGetParent(el);\r
        }\r
        if (el) {\r
+\r
+               iwfDragger.el = el;\r
+\r
+               iwfAddEvent(document, 'onmousemove', iwfDragMouseMove);\r
+               iwfAddEvent(document, 'onmouseup', iwfDragMouseUp);\r
+\r
+\r
+\r
                if (ev && ev.preventDefault) ev.preventDefault();\r
                else if (window.event) window.event.returnValue = false;\r
-               el.iwfDragX = evt.X;\r
-               el.iwfDragY = evt.Y;\r
+               else if (iwfExists(ev.cancelBubble)) ev.cancelBubble = true;\r
+\r
+               el.iwfDragOrigX = iwfX(el);\r
+               el.iwfDragOrigY = iwfY(el);\r
+               el.iwfDragOffsetX = evt.X - iwfX(el);\r
+               el.iwfDragOffsetY = evt.Y - iwfY(el);\r
+\r
 \r
                iwfZIndex(el, iwfHiZ++);\r
 \r
-               iwfDragger.el = el;\r
-               iwfAddEvent(document, 'onmouseup', iwfDragMouseUp, false);\r
-               if (el.iwfOnDragStart) {\r
-                       el.iwfOnDragStart(el, evt.X, evt.Y);\r
-               }\r
+               iwfCallAttribute(el, 'iwfdragbegin');\r
        }\r
 }\r
 \r
 function iwfDragMouseMove(ev){\r
        var evt = new iwfEvent(ev);\r
+\r
        if (iwfDragger.el) {\r
-               if (ev && ev.preventDefault) ev.preventDefault();\r
+               if (evt && evt.preventDefault) evt.preventDefault();\r
                else if (window.event) window.event.returnValue = false;\r
+               else if (iwfExists(ev.cancelBubble)) ev.cancelBubble = true;\r
+\r
                var el = iwfDragger.el;\r
-               var dx = evt.X - el.iwfDragX;\r
-               var dy = evt.Y - el.iwfDragY;\r
-               el.iwfDragX = evt.X;\r
-               el.iwfDragY = evt.Y;\r
 \r
-               if (el.iwfOnDrag) {\r
-                       el.iwfOnDrag(el, dx, dy);\r
-               } else {\r
-                       iwfX(el, iwfX(el) + dx);\r
-                       iwfY(el, iwfY(el) + dy);\r
+\r
+               var newX = evt.X - el.iwfDragOffsetX;\r
+               if (newX > iwfClientWidth() - iwfWidth(el)){\r
+                                       newX = iwfClientWidth() - iwfWidth(el);\r
+               }\r
+               if (newX < 0) {\r
+                       newX = 0;\r
                }\r
+\r
+               var newY = evt.Y - el.iwfDragOffsetY;\r
+               if (newY > iwfClientHeight() - iwfHeight(el)){\r
+                       newY = iwfClientHeight() - iwfHeight(el);\r
+               }\r
+               if (newY < 0) {\r
+                       newY = 0;\r
+               }\r
+\r
+\r
+               iwfX(el, newX);\r
+               iwfY(el, newY);\r
+\r
+               // and hilite any drop targets...\r
+               for(var i=0;i<iwfDragger.targets.length;i++){\r
+                       if (!iwfDragger.curTarget && iwfOverlaps(iwfDragger.targets[i], iwfDragger.el)) {\r
+                               iwfDragOver(iwfDragger.targets[i]);\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               iwfCallAttribute(el, 'iwfdragmove');\r
+\r
        }\r
 }\r
+\r
 function iwfDragMouseUp(ev) {\r
        if (iwfDragger.el) {\r
                if (ev && ev.preventDefault) ev.preventDefault();\r
                else if (window.event) window.event.returnValue = false;\r
-               iwfRemoveEvent(document, 'onmouseup', iwfDragMouseUp, false);\r
-               if (iwfDragger.el.iwfOnDragEnd) {\r
-                       var evt = new iwfEvent(ev);\r
-                       iwfDragger.el.iwfOnDragEnd(iwfDragger.el, evt.X, evt.Y);\r
-               }\r
+               else if (iwfExists(ev.cancelBubble)) ev.cancelBubble = true;\r
+\r
+               var evt = new iwfEvent(ev);\r
+               iwfRemoveEvent(document, 'onmousedown', iwfDragMouseDown);\r
+               iwfRemoveEvent(document, 'onmousemove', iwfDragMouseMove);\r
+               iwfRemoveEvent(document, 'onmouseup', iwfDragMouseUp);\r
+\r
+               iwfCallAttribute(iwfDragger.el, 'iwfdragend');\r
+\r
+               iwfDragDrop();\r
+               iwfDragger.el.iwfDragTarget = false;\r
                iwfDragger.el = null;\r
        }\r
 }\r
 \r
+function iwfDragOver(idTarget) {\r
+       var tgt = iwfGetById(idTarget);\r
+       if (!tgt) return;\r
+\r
+       if (!iwfDragger.el) return;\r
+\r
+       if (iwfDragger.curTarget) return;\r
+\r
+\r
+       iwfDragger.curTarget = tgt.id;\r
+\r
+\r
+       tgt.iwfBackgroundColor = tgt.style.backgroundColor;\r
+       tgt.style.backgroundColor = '#efefef';\r
+\r
+       iwfDragger.el.iwfBorder = iwfDragger.el.style.border;\r
+       iwfDragger.el.style.border = '3px solid blue';\r
+\r
+}\r
+\r
+function iwfDragOut() {\r
+\r
+       var tgt = iwfGetById(iwfDragger.curTarget);\r
+       if (!tgt) return;\r
+\r
+       iwfDragger.curTarget = null;\r
+\r
+\r
+       if (!iwfDragger.el) return;\r
+\r
+\r
+\r
+       iwfDragger.el.style.border = iwfDragger.el.iwfBorder;\r
+       tgt.style.backgroundColor = tgt.iwfBackgroundColor;\r
+\r
+\r
+}\r
+\r
+function iwfDragDrop() {\r
+\r
+       var tgt = iwfGetById(iwfDragger.curTarget);\r
+\r
+       iwfDragOut(iwfDragger.curTarget);\r
+\r
+\r
+\r
+       if (!iwfDragger.el) return;\r
+\r
+       var src = iwfGetById(iwfDragger.el);\r
+\r
+       if (src) {\r
+               if (!tgt) {\r
+                       if (iwfDragger.targets.length > 0) {\r
+                               // targets exist, but none were dropped on. return to original x/y\r
+                               iwfMoveTo(tgt, iwfAttribute(iwfDragger.el, 'iwfDragOrigX'), iwfAttribute(iwfDragger.el, 'iwfDragOrigY'), 30);\r
+                       }\r
+               } else {\r
+                       // target found. dock to it.\r
+                       iwfDockTo(tgt, src, "tl", "tl", 30);\r
+               }\r
+       }\r
+}\r
+\r
+function iwfMapDropTargets(node) {\r
+\r
+       if (!node || !node.childNodes) {\r
+iwfLog('No childNodes found for ' + iwfElementToString(node), true);\r
+               return;\r
+       }\r
+\r
+       for(var i=0; i<node.childNodes.length;i++){\r
+iwfLog('child=' + iwfElementToString(node.childNodes[i]), true);\r
+               if (iwfAttribute(node.childNodes[i], 'iwfDropTarget') == 'true'){\r
+                       iwfDragger.targets.push(iwfAttribute(node.childNodes[i], 'id'));\r
+               }\r
+               iwfMapDropTargets(node.childNodes[i]);\r
+       }\r
+\r
+\r
+}\r
+\r
+function iwfMapDraggables(node){\r
+       if (!node) {\r
+iwfLog("when mapping windows, node not found");\r
+               return;\r
+       } else if (!node.childNodes){\r
+iwfLog("No childNodes found for " + iwfElementToString(node.childNodes[i]));\r
+               return;\r
+       }\r
+\r
+       for(var i=0; i<node.childNodes.length;i++){\r
+               if (iwfAttribute(node.childNodes[i], 'iwfDraggable') == 'true'){\r
+iwfLog("Found draggable to map: " + iwfElementToString(node.childNodes[i]));\r
+                       iwfMakeDraggable(node.childNodes[i]);\r
+               }\r
+       }\r
+}\r
+\r
+function iwfMakeDraggable(id){\r
+       var el = iwfGetById(id);\r
+       if (!el) return;\r
+\r
+       if (iwfAttribute(el, 'iwfDraggableMapped') == 'true'){\r
+               // element has already been mapped for dragging. escape.\r
+               return;\r
+       }\r
+\r
+       // mark it as being mapped as a drag target\r
+       iwfAttribute(el, 'iwfDraggableMapped', 'true');\r
+       iwfAttribute(el, 'iwfDragTarget', 'true');\r
+\r
+       // make sure window is absolutely positioned and overflow is okay\r
+       el.style.position = 'absolute';\r
+       el.style.overflow = 'hidden';\r
+       el.style.cursor = 'move';\r
+\r
+       iwfAddEvent(el, 'onmousedown', 'iwfDrag("' + el.id + '");');\r
+\r
+}\r
+\r
+function iwfMapWindows(node){\r
+       if (!node) {\r
+iwfLog("when mapping windows, node not found");\r
+               return;\r
+       } else if (!node.childNodes){\r
+iwfLog("No childNodes found for " + iwfElementToString(node.childNodes[i]));\r
+               return;\r
+       }\r
+\r
+       for(var i=0; i<node.childNodes.length;i++){\r
+               if (iwfAttribute(node.childNodes[i], 'iwfWindow') == 'true'){\r
+iwfLog("Found window to map: " + iwfElementToString(node.childNodes[i]));\r
+                       iwfGetOrCreateWindow(node.childNodes[i]);\r
+               }\r
+       }\r
+}\r
+\r
+function iwfGetOrCreateWindow(id){\r
+       var el = iwfGetById(id);\r
+       if (!el) return null;\r
+\r
+       if (iwfAttribute(el, 'iwfWindowCreated') == 'true'){\r
+               // window has already been created. escape.\r
+               return;\r
+       }\r
+\r
+       // make sure window is absolutely positioned and overflow is okay\r
+       el.style.position = 'absolute';\r
+       el.style.overflow = 'hidden';\r
+\r
+       // create a title bar\r
+       var elTitle = iwfGetOrCreateById(el.id + 'TitleBar', 'div');\r
+       if (!elTitle) return;\r
+\r
+       elTitle.style.backgroundColor = 'navy';\r
+       elTitle.style.color = 'white';\r
+       elTitle.style.cursor = 'move';\r
+       elTitle.innerHTML = "&nbsp;" + iwfAttribute(el, 'iwfWindowTitle');\r
+\r
+       // dragging title bar should move the window\r
+       iwfAddEvent(elTitle, 'onmousedown',  'iwfDrag("' + el.id + '");');\r
+\r
+\r
+       // create the container which will contain all other html specified in the div\r
+       var elContainer = iwfGetOrCreateById(el.id + 'Container', 'div');\r
+       if (!elContainer) return;\r
+\r
+       elContainer.style.width='100%';\r
+       elContainer.style.height='90%';\r
+       elContainer.style.overflow='scroll';\r
+\r
+       // transfer window contents into the new container\r
+       elContainer.innerHTML = el.innerHTML;\r
+       // clear the window\r
+       el.innerHTML = '';\r
+\r
+\r
+       // create the resizer which will handle resizing\r
+       var elResizer = iwfGetOrCreateById(el.id + 'Resizer', 'div');\r
+       if (!elResizer) return;\r
+\r
+\r
+       elResizer.innerHTML = "<table border='0' cellspacing='0' cellpadding='0' width='100%' height='3px' ><tr ><td width='95%' style='cursor:s-resize'>&nbsp;</td><td style='cursor:se-resize'>&nbsp;</td></tr></table>";\r
+//     elResizer.innerHTML = '<span style="width:90%;background-color:red;color:white;cursor:s-resize;padding-right:30px;">blah</span><span style="width:20px;color:black;background-color:gray;cursor:se-resize">*</span>';\r
+\r
+\r
+\r
+       // set style properties on resizer\r
+//     iwfX(elResizer, iwfX(el) + 20);\r
+//     iwfY(elResizer, iwfY(el) + 20);\r
+//     iwfZIndex(elResizer, 9999999);\r
+//     iwfHeight(elResizer, 15);\r
+//     iwfWidth(elResizer, 15);\r
+//     elTitle.style.cursor = 'move';\r
+//     elResizer.style.position = 'absolute';\r
+//     elResizer.style.borderStyle = 'solid';\r
+//     elResizer.style.borderColor = 'black';\r
+//     elResizer.style.borderWidth = '1px';\r
+//     elResizer.backgroundColor = 'white';\r
+//     elResizer.style.overflow = 'hidden';\r
+//     elResizer.style.textAlign = 'center';\r
+//     elResizer.style.cursor = 'se-resize';\r
+//     elResizer.innerHTML = '-';\r
+\r
+       // dragging the resizer should resize the window\r
+       iwfAddEvent(elResizer, 'onmousedown', 'iwfResize("' + elResizer.id + '","' + el.id + '");');\r
+\r
+\r
+       // add title bar to window\r
+       iwfAddChild(el, elTitle, true);\r
+\r
+       // add container to window\r
+       iwfAddChild(el, elContainer);\r
+\r
+       // add resizer to window\r
+       iwfAddChild(el, elResizer);\r
+\r
+//     iwfX(elResizer, iwfX2(el) - 15);\r
+//     iwfY(elResizer, iwfY2(el) - 15);\r
+\r
+iwfLog(iwfElementToString(elResizer),true);\r
+\r
+       // align resizer to bottom right of window\r
+       iwfResize(elResizer, el);\r
+\r
+\r
+\r
+       // add the flag saying we've created the window\r
+       iwfAttribute(el, 'iwfWindowCreated', 'true');\r
+\r
+\r
+}\r
+\r
 // -----------------------------------\r
 // End: Drag-N-Drop\r
 // -----------------------------------\r
 \r
-// -----------------------------------\r
-// Begin: Initializers\r
-// -----------------------------------\r
-iwfMapRollovers();\r
-// -----------------------------------\r
-// End: Initializers\r
-// -----------------------------------\r