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