r9065@llin: dpavlin | 2005-11-23 01:15:39 +0100
[webpac2] / web / iwf / iwfgui.js
1 // --------------------------------------------------------------------------\r
2 /// IWF - Interactive Website Framework.  Javascript library for creating\r
3 /// responsive thin client interfaces.\r
4 ///\r
5 /// Copyright (C) 2005 Brock Weaver brockweaver@users.sourceforge.net\r
6 ///\r
7 ///     This library is free software; you can redistribute it and/or modify\r
8 /// it under the terms of the GNU Lesser General Public License as published\r
9 /// by the Free Software Foundation; either version 2.1 of the License, or\r
10 /// (at your option) any later version.\r
11 ///\r
12 ///     This library is distributed in the hope that it will be useful, but\r
13 /// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
14 /// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public\r
15 /// License for more details.\r
16 ///\r
17 ///    You should have received a copy of the GNU Lesser General Public License\r
18 /// along with this library; if not, write to the Free Software Foundation,\r
19 /// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
20 ///\r
21 /// Brock Weaver\r
22 /// brockweaver@users.sourceforge.net\r
23 /// 1605 NW Maple Pl\r
24 /// Ankeny, IA 50021\r
25 ///\r
26 //! http://iwf.sourceforge.net/\r
27 // --------------------------------------------------------------------------\r
28 //! NOTE: To minimize file size, strip all fluffy comments (except the LGPL, of course!)\r
29 //! using the following regex (global flag and multiline on):\r
30 //!            ^\t*//([^/!].*|$)\r
31 //\r
32 // This reduces file size by about 30%, give or take.\r
33 //\r
34 //!  To rip out only logging statements (commented or uncommented):\r
35 //!            ^/{0,2}iwfLog.*\r
36 // --------------------------------------------------------------------------\r
37 \r
38 // --------------------------------------------------------------------------\r
39 //! iwfgui.js\r
40 //\r
41 // GUI inspection and manipulation functions\r
42 //\r
43 //! Dependencies:\r
44 //! iwfcore.js\r
45 //\r
46 //! Brock Weaver - brockweaver@users.sourceforge.net\r
47 //! v 0.2 - 2005-11-14\r
48 //! core bug patch\r
49 // --------------------------------------------------------------------------\r
50 //! v 0.1 - 2005-06-05\r
51 //! Initial release.\r
52 // --------------------------------------------------------------------------\r
53 // Issues:\r
54 //  Timeouts have hiccups sometimes when they begin to overlap\r
55 //  Not tested on Safari -- I need a Mac!\r
56 //  _iwfMoveTo() has some calculation problems with certain motionType values\r
57 // --------------------------------------------------------------------------\r
58 \r
59 // -----------------------------------\r
60 // Dependency Check\r
61 if (!window.iwfGetById){\r
62         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
63 }\r
64 // -----------------------------------\r
65 \r
66 \r
67 \r
68 // -----------------------------------\r
69 // Begin: Visibility\r
70 // -----------------------------------\r
71 \r
72 function iwfShow(id, reserveSpace){\r
73         var el = iwfGetById(id);\r
74         if (reserveSpace){\r
75                 if (iwfExists(el) && iwfExists(el.style) && iwfExists(el.style.visibility)) el.style.visibility = 'visible';\r
76         } else {\r
77                 if (iwfExists(el) && iwfExists(el.style) && iwfExists(el.style.display)) el.style.display = 'inline';\r
78         }\r
79 }\r
80 \r
81 function iwfHide(id, reserveSpace){\r
82         var el = iwfGetById(id);\r
83         if (reserveSpace){\r
84                 if (el && iwfExists(el.style) && iwfExists(el.style.visibility)) el.style.visibility = 'hidden';\r
85         } else {\r
86                 if (el && iwfExists(el.style) && iwfExists(el.style.display)) el.style.display = 'none';\r
87         }\r
88 }\r
89 \r
90 function iwfHideDelay(id, ms, reserveSpace){\r
91         var el = iwfGetById(id);\r
92         if (!el) return;\r
93 \r
94         // wipeout any other re-visibling timeouts we have (nice spelling, eh?)\r
95         _iwfClearTimeout(el, "hidedelay", "visible", true);\r
96 \r
97         if (ms < 1){\r
98                 iwfHide(el, reserveSpace);\r
99         } else {\r
100                 _iwfSetTimeout(el, "hidedelay", "visible", "iwfHideDelay('" + el.id + "', 0, " + reserveSpace + ")", ms);\r
101         }\r
102 }\r
103 \r
104 function iwfShowDelay(id, ms, reserveSpace){\r
105         var el = iwfGetById(id);\r
106         if (!el) return;\r
107 \r
108         // wipeout any other re-visibling timeouts we have (nice spelling, eh?)\r
109         _iwfClearTimeout(el, "showdelay", "visible", true);\r
110 \r
111         if (ms < 1){\r
112                 iwfShow(el, reserveSpace);\r
113         } else {\r
114                 _iwfSetTimeout(el, "showdelay", "visible", "iwfShowDelay('" + el.id + "', 0, " + reserveSpace + ")", ms);\r
115         }\r
116 }\r
117 \r
118 function iwfShowGently(id, pct, reserveSpace){\r
119 \r
120         var el = iwfGetById(id);\r
121         if (!el) return;\r
122 \r
123         // wipeout any other re-visibling timeouts we have (nice spelling, eh?)\r
124         _iwfClearTimeout(el, "showgently", "visible", true);\r
125 \r
126         var opacity = iwfOpacity(el);\r
127         if (iwfIsHidden(el)){\r
128                 // set opacity to 0\r
129                 iwfOpacity(el, 0, false, false);\r
130 \r
131                 // show it\r
132                 iwfShow(el, reserveSpace);\r
133         }\r
134 \r
135         // adjust opacity up by the given percentage\r
136         opacity = iwfOpacity(el, pct, true);\r
137 \r
138         if (opacity < 100) {\r
139                 // set a timeout\r
140                 _iwfSetTimeout(el, "showgently", "visible", "iwfShowGently('" + el.id + "'," + pct + ", " + reserveSpace + ")", 50);\r
141         }\r
142 }\r
143 \r
144 function iwfHideGently(id, pct, reserveSpace){\r
145         var el = iwfGetById(id);\r
146         if (!el) return;\r
147 \r
148         if (iwfIsHidden(el)) return;\r
149 \r
150         // wipeout any other re-visibling timeouts we have (nice spelling, eh?)\r
151         _iwfClearTimeout(el, "hidegently", "visible", true);\r
152 \r
153         var opacity = iwfOpacity(el);\r
154         if (opacity <= 0){\r
155 \r
156                 // hide it\r
157                 iwfHide(el, reserveSpace);\r
158 \r
159                 // set opacity back to fully opaque, so when they iwfShow() it,\r
160                 // the element isn't fully transparent and looks like iwfShow() didn't work\r
161                 iwfOpacity(el, 100, false, true);\r
162 \r
163 \r
164         } else {\r
165                 // make it less opaque...\r
166                 iwfOpacity(el, -pct, true);\r
167 \r
168                 // set our timeout\r
169                 _iwfSetTimeout(el, "hidegently", "visible", "iwfHideGently('" + el.id + "'," + pct + ", " + reserveSpace + ")", 50);\r
170         }\r
171 }\r
172 \r
173 function iwfHideGentlyDelay(id, pct, ms, reserveSpace){\r
174         var el = iwfGetById(id);\r
175         if (!el) return;\r
176 \r
177         if (iwfIsHidden(el)) return;\r
178 \r
179         // wipeout any other re-visibling timeouts we have (nice spelling, eh?)\r
180         _iwfClearTimeout(el, "hidegentlydelay", "visible", true);\r
181 \r
182 \r
183         if (ms < 1){\r
184                 iwfHideGently(el, pct, reserveSpace);\r
185         } else {\r
186                 _iwfSetTimeout(el, "hidegentlydelay", "visible", "iwfHideGentlyDelay('" + el.id + "'," + pct + ", 0, " + reserveSpace + ")", ms);\r
187         }\r
188 \r
189 }\r
190 \r
191 function iwfShowGentlyDelay(id, pct, ms, reserveSpace){\r
192         var el = iwfGetById(id);\r
193         if (!el) return;\r
194 \r
195 \r
196         // wipeout any other re-visibling timeouts we have (nice spelling, eh?)\r
197         _iwfClearTimeout(el, "showgentlydelay", "visible", true);\r
198 \r
199         if (ms < 1){\r
200                 iwfShowGently(el, pct, reserveSpace);\r
201         } else {\r
202                 _iwfSetTimeout(el, "showgentlydelay", "visible", "iwfShowGentlyDelay('" + el.id + "'," + pct + ", 0, " + reserveSpace + ")", ms);\r
203         }\r
204 }\r
205 \r
206 function iwfOpacity(id, pct, relative, keepHiddenIfAlreadyHidden){\r
207         var el = iwfGetById(id);\r
208         if (el){\r
209                 if (iwfExists(pct) && pct != null){\r
210                         // set opacity\r
211                         var newPct = iwfToFloat(pct, true);\r
212                         if (relative){\r
213                                 // lookup current opacity\r
214                                 newPct = iwfOpacity(id, null, false);\r
215 \r
216                                 // modify pct by that much\r
217                                 newPct += pct;\r
218                         }\r
219 \r
220                         if (newPct < 0){\r
221                                 newPct = 0;\r
222                         } else if (newPct > 100){\r
223                                 newPct = 100;\r
224                         }\r
225 \r
226                         if (iwfExists(el.style.opacity)) el.style.opacity = newPct/100;\r
227                         else if (iwfExists(el.style.filter)) el.style.filter = "alpha(opacity=" + newPct + ")";\r
228                         else if (iwfExists(el.style.mozOpacity)) el.style.mozOpacity = newPct/100;\r
229 \r
230                         // also display it if opacity > 0 and !keepHidden\r
231                         if (newPct > 0 && !keepHiddenIfAlreadyHidden){\r
232                                 if (iwfIsHidden(id)){\r
233                                         iwfShow(id);\r
234                                 }\r
235                         }\r
236 \r
237                         return newPct;\r
238 \r
239                 } else {\r
240                         // get current opacity\r
241                         var val = null;\r
242                         if (iwfExists(el.style.opacity)){\r
243                                 if (el.style.opacity == ''){\r
244                                         val = 100;\r
245                                 } else {\r
246                                         val = iwfToFloat(el.style.opacity, 2, true) * 100;\r
247                                 }\r
248                         } else if (iwfExists(el.style.filter)) {\r
249                                 if (el.style.filter){\r
250                                         if (el.style.filter.indexOf("opacity") == 0){\r
251                                                 val = 100;\r
252                                         } else {\r
253                                                 val = iwfToFloat(el.style.filter, 2, true);\r
254                                         }\r
255                                 } else {\r
256                                         val = 100;\r
257                                 }\r
258                         } else if (iwfExists(el.style.mozOpacity)) {\r
259                                 if (el.style.mozOpacity == ''){\r
260                                         val = 100;\r
261                                 } else {\r
262                                         val = iwfToFloat(el.style.mozOpacity, 2, true) * 100;\r
263                                 }\r
264                         }\r
265 \r
266                         return val;\r
267                 }\r
268         }\r
269 }\r
270 \r
271 function iwfIsShown(id){\r
272         return !iwfIsHidden(id);\r
273 }\r
274 \r
275 function iwfIsHidden(id){\r
276         var el = iwfGetById(id);\r
277 //      if (!el) return false;\r
278 \r
279         var hidden = false;\r
280         if (iwfExists(el.style) && iwfExists(el.style.visibility)) {\r
281                 hidden = el.style.visibility == 'hidden';\r
282         }\r
283         if (iwfExists(el.style) && iwfExists(el.style.display)) {\r
284                 hidden = hidden || el.style.display == 'none';\r
285         }\r
286         return hidden;\r
287 }\r
288 \r
289 function iwfToggle(id, reserveSpace){\r
290         if (iwfIsHidden(id)) iwfShow(id, reserveSpace);\r
291         else iwfHide(id, reserveSpace);\r
292 }\r
293 \r
294 \r
295 \r
296 // -----------------------------------\r
297 // End: Visibility\r
298 // -----------------------------------\r
299 \r
300 // -----------------------------------\r
301 // Begin: Timers\r
302 // -----------------------------------\r
303 \r
304 function _iwfSetTimeout(id, name, category, fn, ms){\r
305         var el = iwfGetById(id);\r
306         if (!el) return;\r
307 \r
308         var att = iwfAttribute(el, 'iwfTimeoutCategory' + category);\r
309         if (!att){\r
310                 // that attribute doesn't exist yet, or is null\r
311         } else if (att != name){\r
312                 // attribute exists but doesn't match our name.\r
313                 // clear out the existing one, since the category matches.\r
314                 _iwfClearTimeout(el.id, att, category);\r
315         } else {\r
316                 // attribute matches our name.\r
317         }\r
318 \r
319         iwfAttribute(el, 'iwfTimeoutCategory' + category, name);\r
320 //iwfLog('setting timeout for ' + name + ' to ' + fn);\r
321         var timeoutid = setTimeout(fn, ms);\r
322         iwfAttribute(el, 'iwfTimeoutId' + category, timeoutid);\r
323         return true;\r
324 }\r
325 \r
326 function _iwfCheckTimeout(id, name, category){\r
327 //return true;\r
328 \r
329         var el = iwfGetById(id);\r
330         if (!el) return false;\r
331 \r
332         var att = iwfAttribute(el, 'iwfTimeoutCategory' + category);\r
333         if (!att || att == name){\r
334                 return true;\r
335         } else {\r
336                 return false;\r
337         }\r
338 \r
339 }\r
340 \r
341 function _iwfClearTimeout(id, name, category, forceful){\r
342         var el = iwfGetById(id);\r
343         if (!el) return;\r
344 \r
345         var att = iwfAttribute(el, 'iwfTimeoutCategory' + category);\r
346 \r
347         if (att == name || forceful){\r
348 //              iwfLog('clearing timeout for ' + att);\r
349                 clearTimeout(iwfAttribute(el, 'iwfTimeoutId' + category));\r
350                 iwfRemoveAttribute(el, 'iwfTimeoutId' + category);\r
351                 iwfRemoveAttribute(el, 'iwfTimeoutCategory' + category);\r
352         }\r
353 \r
354 }\r
355 \r
356 function iwfDelay(ms, fpOrString){\r
357         // note this inner function creates a closure...\r
358         function _iwfDelayExpired(){\r
359                 if (localIsString){\r
360                         // passed a string. eval it.\r
361 //iwfLog("_iwfDelayExpired: calling string of:\n" + localFpOrString, true);\r
362                         eval(localFpOrString);\r
363                 } else {\r
364                         // they passed a function pointer.\r
365                         // call it, passing any args we were given.\r
366                         if (!localArgs || localArgs.length == 0){\r
367                                 localFpOrString();\r
368                         } else if (localArgs.length == 1){\r
369                                 localFpOrString(localArgs[0]);\r
370                         } else {\r
371                                 var s = 'localFpOrString(';\r
372                                 for(var i=0;i<localArgs.length;i++){\r
373                                         if (i > 0){\r
374                                                 s += ', ';\r
375                                         }\r
376                                         if(localArgs[i] == null){\r
377                                                 s += 'null';\r
378                                         } else if(iwfIsString(localArgs[i])){\r
379                                                 s += '"' + localArgs[i].replace(/"/gi, '\\"') + '"';\r
380                                         } else {\r
381                                                 s += localArgs[i];\r
382                                         }\r
383                                 }\r
384                                 s += ')';\r
385 //iwfLog("_iwfDelayExpired: calling fp of:\n" + s, true);\r
386                                 eval(s);\r
387                         }\r
388                 }\r
389                 delete localFpOrString;\r
390                 delete localIsString;\r
391                 delete localArgs;\r
392         }\r
393 \r
394         var localFpOrString = fpOrString;\r
395         var localIsString = iwfIsString(fpOrString);\r
396         var localArgs = null;\r
397 \r
398         if (!iwfIsString(fpOrString)){\r
399                 if (arguments && arguments.length > 0){\r
400                         localArgs = new Array();\r
401                         for(var i=2;i<arguments.length;i++){\r
402 //iwfLog('args[' + i + '] = ' + arguments[i], true);\r
403                                 localArgs.push(arguments[i]);\r
404                         }\r
405                 }\r
406         }\r
407         setTimeout(_iwfDelayExpired, ms);\r
408 }\r
409 \r
410 // -----------------------------------\r
411 // End: Timers\r
412 // -----------------------------------\r
413 \r
414 \r
415 // -----------------------------------\r
416 // Begin: Positioning\r
417 // -----------------------------------\r
418 \r
419 function iwfX1(id, newx){\r
420         return iwfX(id, newx);\r
421 }\r
422 \r
423 \r
424 function iwfFocusSelect(id, promptmsg){\r
425         var el = iwfGetById(id);\r
426         if (promptmsg){\r
427                 alert(promptmsg);\r
428         }\r
429         if (!iwfIsHidden(id)){\r
430                 try {\r
431                         el.focus();\r
432                         el.select();\r
433                 } catch(e) { }\r
434         }\r
435         return false;\r
436 }\r
437 \r
438 function iwfFocus(id, promptmsg){\r
439         var el = iwfGetById(id);\r
440         if (promptmsg){\r
441                 alert(promptmsg);\r
442         }\r
443         if (!iwfIsHidden(id)){\r
444                 try {\r
445                         el.focus();\r
446                 } catch(e) { }\r
447         }\r
448         return false;\r
449 }\r
450 \r
451 \r
452 \r
453 function iwfX(id, newx){\r
454         var absx = 0;\r
455 \r
456         if (iwfIsNumber(newx)) {\r
457                 absx = iwfSetX(id, newx);\r
458         } else {\r
459                 var el = iwfGetById(id);\r
460                 if (!el) return 0;\r
461                 if (iwfIsString(el.style.left) && el.style.left.length > 0){\r
462                         absx = iwfToInt(el.style.left, true);\r
463                         if (isNaN(absx)) {\r
464                                 absx = 0;\r
465                         }\r
466                 } else if (iwfExists(el.style.pixelLeft) && el.style.pixelLeft) {\r
467                         absx = el.style.pixelLeft;\r
468                 } else {\r
469                         while (el) {\r
470                                 if (iwfExists(el.offsetLeft)) absx += el.offsetLeft;\r
471                                 el = iwfGetParent(el, true);\r
472                         }\r
473                 }\r
474         }\r
475 \r
476         return absx;\r
477 }\r
478 \r
479 function iwfSetX(id, newx){\r
480         var el = iwfGetById(id);\r
481         if (!el) return;\r
482         if(iwfExists(el.style) && iwfIsString(el.style.left)) {\r
483                 el.style.left = newx + 'px';\r
484         }\r
485         else if(iwfExists(el.style) && iwfExists(el.style.pixelLeft)) {\r
486                 el.style.pixelLeft = newx;\r
487         }\r
488         else if(iwfExists(el.left)) {\r
489                 el.left = newx;\r
490         }\r
491         return newx;\r
492 }\r
493 \r
494 function iwfY1(id, newy){\r
495         var el = iwfGetById(id);\r
496         return iwfY(el, newy);\r
497 }\r
498 \r
499 function iwfY(id, newy){\r
500         var absy = 0;\r
501 \r
502         if (iwfIsNumber(newy)) {\r
503                 absy = iwfSetY(id, newy);\r
504         } else {\r
505                 var el = iwfGetById(id);\r
506                 if (!el) return 0;\r
507 \r
508                 if (iwfIsString(el.style.top) && el.style.top.length > 0){\r
509                         absy = iwfToInt(el.style.top, true);\r
510                         if (isNaN(absy)) {\r
511                                 absy = 0;\r
512                         }\r
513                 } else if (iwfExists(el.style.pixelTop) && el.style.pixelTop) {\r
514                         absy = el.style.pixelTop;\r
515                 } else {\r
516                         while (el) {\r
517                                 if (iwfExists(el.offsetTop)) absy += el.offsetTop;\r
518                                 el = iwfGetParent(el, true);\r
519                         }\r
520                 }\r
521         }\r
522 \r
523         return absy;\r
524 }\r
525 \r
526 function iwfSetY(id, newy){\r
527         var el = iwfGetById(id);\r
528         if (!el) return;\r
529         if (iwfExists(el.style)){\r
530                 if (iwfIsString(el.style.top)) {\r
531                         el.style.top = newy + 'px';\r
532                 } else if(iwfExists(el.style.pixelTop)) {\r
533                         el.style.pixelTop = newy;\r
534                 } else if(iwfExists(el.top)) {\r
535                         el.top = newy;\r
536                 }\r
537         }\r
538         return newy;\r
539 }\r
540 \r
541 function iwfZIndex(id, z){\r
542         var el = iwfGetById(id);\r
543         if (!el) return 0;\r
544 \r
545         if (iwfExists(el)){\r
546                 if (iwfExists(z)){\r
547                         el.style.zIndex = z;\r
548                 }\r
549                 return iwfToInt(el.style.zIndex, true);\r
550         }\r
551         return 0;\r
552 }\r
553 \r
554 function iwfMoveTo(id1, xDest, yDest, totalTicks, motionType){\r
555 \r
556         var el = iwfGetById(id1);\r
557 \r
558         if (el){\r
559                 var origX = iwfX1(el);\r
560                 var origY = iwfY1(el);\r
561 \r
562                 // wipeout any other repositioning timeouts we have...\r
563                 _iwfClearTimeout(el, "moveto", "position", true);\r
564 \r
565                 // move any elements we have docked to us\r
566                 _iwfMoveDockedItems(el, xDest, yDest, totalTicks, motionType);\r
567 \r
568                 if (!totalTicks){\r
569                         // do it immediately.\r
570                         iwfX1(id1, xDest);\r
571                         iwfY1(id1, yDest);\r
572                 } else {\r
573                         // animate the movement\r
574                         _iwfMoveTo(id1, origX, origY, xDest, yDest, totalTicks, totalTicks, motionType);\r
575                 }\r
576         }\r
577 \r
578 }\r
579 \r
580 function _iwfMoveDockedItems(id, xDest, yDest, totalTicks, motionType){\r
581         var elMaster = iwfGetById(id);\r
582         if (elMaster){\r
583                 var dockers = iwfAttribute(elMaster, 'iwfDockers');\r
584 //iwfLog("Dockers for " + iwfAttribute(elMaster, 'id') + ":\n" + dockers, true);\r
585                 if (dockers && dockers.length > 0){\r
586                         // there is one or more items docked to us\r
587                         // tell them to move with us!\r
588                         dockers = dockers.split(",");\r
589                         for(var i=0;i<dockers.length;i++){\r
590                                 var elSlave = iwfGetById(dockers[i]);\r
591                                 if (elSlave){\r
592 //iwfLog("found element '" + dockers[i] + "' which is docked to element " + iwfAttribute(elMaster, 'id'), true);\r
593                                         var xOffset = iwfX(elMaster) - iwfX(elSlave);\r
594                                         var yOffset = iwfY(elMaster) - iwfY(elSlave);\r
595                                         var xEnd = xDest - xOffset;\r
596                                         var yEnd = yDest - yOffset;\r
597                                         iwfMoveTo(elSlave, xEnd, yEnd, totalTicks, motionType);\r
598                                 }\r
599                         }\r
600                 }\r
601         }\r
602 }\r
603 \r
604 function _iwfMoveTo(id1, xOrig, yOrig, xDest, yDest, ticksLeft, totalTicks, motionType){\r
605 //iwfLog("_iwfMoveTo(" + id1 + ", " + xOrig + ", " + yOrig + ", " + xDest + ", " + yDest + ", " + ticksLeft + ", " + totalTicks + ", '" + motionType + "')");\r
606         var el = iwfGetById(id1);\r
607         if (!el){\r
608 //iwfLog("could not locate el with id of " + id1);\r
609         } else {\r
610                 el_id = iwfAttribute(el, 'id');\r
611 \r
612                 _iwfClearTimeout(el, "moveto", "position", true);\r
613 \r
614 \r
615                 var elX = iwfX1(el);\r
616                 var elY = iwfY1(el);\r
617 \r
618                 //! hack for floating point anomolies -- stops animation when element is "close enough"\r
619                 var epsilon = 0.001;\r
620 \r
621                 var xDone = false;\r
622                 if (elX > xDest){\r
623                         if (xDest + epsilon > elX){\r
624                                 xDone = true;\r
625                         }\r
626                 } else {\r
627                         if (xDest - epsilon < elX){\r
628                                 xDone = true;\r
629                         }\r
630                 }\r
631 \r
632                 var yDone = false;\r
633                 if (elY > yDest){\r
634                         if (yDest + epsilon > elY){\r
635                                 yDone = true;\r
636                         }\r
637                 } else {\r
638                         if (yDest - epsilon < elY){\r
639                                 yDone = true;\r
640                         }\r
641                 }\r
642 \r
643                 if (ticksLeft <= 0 || (xDone && yDone)){\r
644                         //! time is up / motion is "close enough"\r
645 //iwfLog("_iwfMoveTo time is up / motion is done.");\r
646                         iwfX1(el, xDest);\r
647                         iwfY1(el, yDest);\r
648 \r
649                 } else {\r
650 \r
651                         var pctLeft = ticksLeft / totalTicks;\r
652 \r
653                         var xTotal = xDest - xOrig;\r
654                         var yTotal = yDest - yOrig;\r
655 \r
656                         var xCur, yCur, rt;\r
657 \r
658                         switch(motionType){\r
659                                 case 'd':\r
660                                 case 'dec':\r
661                                 default:\r
662                                         rt = pctLeft * pctLeft * pctLeft * pctLeft * pctLeft * pctLeft;\r
663                                         xCur = xOrig + (xTotal - (rt * xTotal));\r
664                                         yCur = yOrig + (yTotal - (rt * yTotal));\r
665                                         break;\r
666                                 case 'a':\r
667                                 case 'acc':\r
668                                         pctLeft = 1 - pctLeft;\r
669                                         rt = pctLeft * pctLeft * pctLeft * pctLeft;\r
670                                         xCur = xOrig + (rt * xTotal);\r
671                                         yCur = yOrig + (rt * yTotal);\r
672                                         break;\r
673                                 case 'b':\r
674                                 case 'both':\r
675                                         if (pctDone > 0.75){\r
676                                                 // over 3/4 done -- decelerate\r
677                                                 rt = pctLeft * pctLeft * pctLeft * pctLeft;\r
678                                                 xCur = xOrig + (xTotal - (rt * xTotal));\r
679                                                 yCur = yOrig + (yTotal - (rt * yTotal));\r
680 \r
681                                         } else if (pctDone < 0.25){\r
682                                                 // not 1/4 done yet -- accelerate\r
683                                                 pctLeft = 1 - pctLeft;\r
684                                                 rt = pctLeft * pctLeft * pctLeft * pctLeft; // * pctDone * pctDone;\r
685                                                 xCur = xOrig + (rt * xTotal);\r
686                                                 yCur = yOrig + (rt * yTotal);\r
687 \r
688                                         } else {\r
689                                                 // between 1/4 and 3/5 done -- linear\r
690                                                 xCur = xOrig + (pctLeft * xTotal);\r
691                                                 yCur = yOrig + (pctLeft * yTotal);\r
692                                         }\r
693                                         break;\r
694                                 case 'lin':\r
695                                 case 'linear':\r
696                                 case 'l':\r
697                                         // use linear motion\r
698                                         xCur = xOrig + (pctLeft * xTotal);\r
699                                         yCur = yOrig + (pctLeft * yTotal);\r
700                                         break;\r
701                         }\r
702 \r
703                         iwfX1(el, xCur);\r
704                         iwfY1(el, yCur);\r
705 \r
706 \r
707                         ticksLeft--;\r
708 \r
709                         var fn = "_iwfMoveTo('" + el_id + "', " + xOrig + ", " + yOrig + ", " + xDest + ", " + yDest + ", " + ticksLeft + ", " + totalTicks + ", '" + motionType + "')";\r
710 //iwfLog("timeout set to call: " + fn);\r
711                         _iwfSetTimeout(el, "moveto", "position", fn, 50);\r
712                 }\r
713         }\r
714 }\r
715 \r
716 function iwfUnDockFrom(id1, id2){\r
717         var elSlave = iwfGetById(id1);\r
718 \r
719         if (elSlave){\r
720                 var slaveId = iwfAttribute(elSlave, 'id');\r
721                 // determine who elSlave is docked to\r
722                 var dockedTo = iwfAttribute(elSlave, 'iwfDockedTo');\r
723                 if (dockedTo){\r
724                         // elSlave says he's docked to the guy with id of dockedTo.\r
725                         // grab that guy.\r
726                         var elMaster = iwfGetById(dockedTo);\r
727 //iwfLog("dockedTo:" + iwfAttribute(elMaster, 'id'), true);\r
728                         if (elMaster){\r
729                                 // elMaster is the guy elSlave is docked to.\r
730                                 // tell elMaster to remove elSlave from his docker list\r
731 \r
732                                 var dockers = iwfAttribute(elMaster, 'iwfDockers');\r
733 //iwfLog("undocking items from " + iwfAttribute(elMaster, 'id') + ":\n" + dockers, true);\r
734                                 if (dockers && dockers.length > 0){\r
735                                         var arrDockers = dockers.split(",");\r
736                                         if (arrDockers.length == 0){\r
737                                                 arrDockers.push(dockers);\r
738                                         }\r
739 //iwfLog('arrDockers=' + arrDockers + '\nlength=' + arrDockers.length, true);\r
740                                         for(var i=0;i<arrDockers.length;i++){\r
741 //iwfLog("undocking is checking " + arrDockers[i] + " against " + slaveId, true);\r
742                                                 if (arrDockers[i] == slaveId){\r
743                                                         // undock elSlave from elMaster\r
744                                                         arrDockers.splice(i, 1);\r
745 \r
746                                                         var output = arrDockers.join(",");\r
747 //iwfLog("writing iwfDockers=" + output);\r
748 \r
749                                                         // write this back to elMaster\r
750                                                         iwfAttribute(elMaster, 'iwfDockers', output);\r
751                                                         break;\r
752                                                 }\r
753                                         }\r
754                                 }\r
755                         }\r
756                         // tell elSlave he's no longer docked to elMaster.\r
757                         iwfAttribute(elSlave, 'iwfDockedTo', null);\r
758                 }\r
759         }\r
760 }\r
761 \r
762 function iwfAlignTo(id1, id2, anchor1, anchor2, totalTicks, motionType){\r
763         var elMover = iwfGetById(id1);\r
764         var elStays = iwfGetById(id2);\r
765 \r
766         if (elMover && elStays){\r
767 \r
768                 var newX = iwfX(elStays);\r
769                 var newY = iwfY(elStays);\r
770 \r
771                 var anc = ((anchor1 +'  ').substr(0,2) + (anchor2 + '  ').substr(0,2)).toLowerCase();\r
772 iwfLog("anchor encoding: " + anc);\r
773                 if (anc.charAt(0) == 'b'){\r
774                         newY -= iwfHeight(elMover);\r
775                 } else if (anc.charAt(0) == 'c'){\r
776                         newY -= iwfHeight(elMover) / 2;\r
777                 }\r
778 \r
779                 var moverWidth;\r
780                 var staysWidth;\r
781                 if (anc.charAt(1) == 'r'){\r
782                         moverWidth = iwfWidth(elMover);\r
783                         newX -= moverWidth;\r
784                 } else if (anc.charAt(1) == 'c'){\r
785                         moverWidth = iwfWidth(elMover);\r
786                         newX -= moverWidth / 2;\r
787                 }\r
788                 if (anc.charAt(2) == 'b'){\r
789                         newY += iwfHeight(elStays);\r
790                 } else if (anc.charAt(2) == 'c'){\r
791                         newY += iwfHeight(elStays) / 2;\r
792                 }\r
793                 if (anc.charAt(3) == 'r'){\r
794                         staysWidth = iwfWidth(elStays);\r
795                         newX += staysWidth;\r
796                 } else if (anc.charAt(3) == 'c'){\r
797                         staysWidth = iwfWidth(elStays);\r
798                         newX += staysWidth / 2;\r
799                 }\r
800 \r
801 iwfLog(iwfAttribute(elMover, 'id') + ' width:' + moverWidth + '\n' + iwfAttribute(elStays, 'id') + ' width:' + staysWidth);\r
802 \r
803                 // move to those alignment points\r
804                 iwfMoveTo(elMover, newX, newY, totalTicks, totalTicks, motionType);\r
805         }\r
806 }\r
807 \r
808 function iwfDockTo(id1, id2, anchor1, anchor2, totalTicks, motionType){\r
809         var elSlave = iwfGetById(id1);\r
810         var elMaster = iwfGetById(id2);\r
811 \r
812         if (elSlave && elMaster){\r
813 \r
814                 // dock elSlave to elMaster...\r
815 \r
816                 // pull all items currently docked to elMaster\r
817                 var dockers = iwfAttribute(elMaster,'iwfDockers');\r
818                 // append elSlave to that list\r
819                 if(!dockers){\r
820                         dockers = iwfAttribute(elSlave, 'id');\r
821                 } else {\r
822                         var arrDockers = dockers.split(",");\r
823                         if (arrDockers.length == 0){\r
824                                 arrDockers = new Array(dockers);\r
825                         }\r
826 \r
827                         var slaveId = iwfAttribute(elSlave, 'id');\r
828                         var found = false;\r
829                         for(var i=0;i<arrDockers.length;i++){\r
830                                 if (arrDockers[i] == slaveId){\r
831                                         found = true;\r
832                                 }\r
833                         }\r
834                         if (!found){\r
835                                 // elSlave is not in elMaster's list of dockers yet.  add him.\r
836                                 dockers += "," + iwfAttribute(elSlave, 'id');\r
837                         }\r
838                 }\r
839 \r
840                 // write list back to elMaster\r
841                 iwfAttribute(elMaster, 'iwfDockers', dockers);\r
842 \r
843                 // have elSlave remember who he's docked to\r
844                 iwfAttribute(elSlave, 'iwfDockedTo', iwfAttribute(elMaster, 'id'));\r
845 \r
846 \r
847 //iwfLog("dockers for " + iwfAttribute(elMaster, 'id') + " = " + dockers, true);\r
848 \r
849 \r
850                 iwfAlignTo(elSlave, elMaster, anchor1, anchor2, totalTicks, motionType);\r
851 \r
852         }\r
853 \r
854 \r
855 }\r
856 \r
857 function iwfXScroll(id) {\r
858         var scrollx=0;\r
859         var el = iwfGetById(id);\r
860         if (!el){\r
861                 if(document.documentElement && document.documentElement.scrollLeft) scrollx=document.documentElement.scrollLeft;\r
862                 else if(document.body && iwfExists(document.body.scrollLeft)) scrollx=document.body.scrollLeft;\r
863         } else {\r
864                 if (iwfIsNumber(el.scrollLeft)) scrollx = el.scrollLeft;\r
865         }\r
866         return scrollx;\r
867 }\r
868 function iwfYScroll(id) {\r
869         var scrolly=0;\r
870         var el = iwfGetById(id);\r
871         if (!el){\r
872                 if(document.documentElement && document.documentElement.scrollTop) scrolly=document.documentElement.scrollTop;\r
873                 else if(document.body && iwfExists(document.body.scrollTop)) scrolly=document.body.scrollTop;\r
874         } else {\r
875                 if (iwfIsNumber(el.scrollTop)) scrolly = el.scrollTop;\r
876         }\r
877         return scrolly;\r
878 }\r
879 \r
880 \r
881 \r
882 // -----------------------------------\r
883 // End: Positioning\r
884 // -----------------------------------\r
885 \r
886 // -----------------------------------\r
887 // Begin: Size\r
888 // -----------------------------------\r
889 \r
890 function iwfClientHeight(){\r
891   var vHeight = 0;\r
892         if(document.compatMode == 'CSS1Compat' && document.documentElement && document.documentElement.clientHeight) {\r
893                 vHeight = document.documentElement.clientHeight;\r
894         } else if(document.body && document.body.clientHeight) {\r
895                 vHeight = document.body.clientHeight;\r
896         } else if(iwfExists(window.innerWidth,window.innerHeight,document.width)) {\r
897                 vHeight = window.innerHeight;\r
898                 if(document.width>window.innerWidth) {\r
899                         vHeight -= 16;\r
900                 }\r
901         }\r
902   return vHeight;\r
903 }\r
904 \r
905 function iwfClientWidth(){\r
906         var vWidth = 0;\r
907         if(document.compatMode == 'CSS1Compat' && document.documentElement && document.documentElement.clientWidth) {\r
908                 vWidth = document.documentElement.clientWidth;\r
909         } else if(document.body && document.body.clientWidth) {\r
910                 vWidth = document.body.clientWidth;\r
911         } else if(iwfExists(window.innerWidth,window.innerHeight,document.height)) {\r
912                 vWidth = window.innerWidth;\r
913                 if(document.height>window.innerHeight) {\r
914                         vWidth -= 16;\r
915                 }\r
916         }\r
917         return vWidth;\r
918 }\r
919 \r
920 function iwfWidth(id, neww){\r
921 \r
922 \r
923 \r
924         var el = iwfGetById(id);\r
925         if (!el) return 0;\r
926         var w = 0;\r
927         if (iwfExists(el)){\r
928                 if (iwfExists(el.style)){\r
929                         if (iwfExists(el.offsetWidth) && iwfIsString(el.style.width)){\r
930                                 if (neww) iwfDetermineWidth(el, neww);\r
931                                 w = el.offsetWidth;\r
932                         } else if (iwfExists(el.style.pixelWidth)) {\r
933                                 if(neww) el.style.pixelWidth = neww;\r
934                                 w = el.style.pixelWidth;\r
935                         } else {\r
936                                 w = -1;\r
937                         }\r
938                 } else if (iwfExists(el.clip) && iwfExists(el.clip.right)) {\r
939                         if(newh) e.clip.right = neww;\r
940                         w = el.clip.right;\r
941                 } else {\r
942                         w = -2;\r
943                 }\r
944 \r
945 //iwfLog('width of ' + iwfAttribute(el, 'id') + ' = ' + w, true);\r
946 \r
947         }\r
948 \r
949         return w;\r
950 \r
951 \r
952 \r
953 }\r
954 \r
955 function iwfHeight(id, newh){\r
956         var el = iwfGetById(id);\r
957         if (!el) return 0;\r
958         var h = 0;\r
959         if (iwfExists(el)){\r
960                 if (iwfExists(el.style)){\r
961                         if (iwfExists(el.offsetHeight) && iwfIsString(el.style.height)){\r
962                                 if (newh) iwfDetermineHeight(el, newh);\r
963                                 h = el.offsetHeight;\r
964                         } else if (iwfExists(el.style.pixelHeight)) {\r
965                                 if(newh) el.style.pixelHeight = newh;\r
966                                 h = el.style.pixelHeight;\r
967                         } else {\r
968                                 h = -1;\r
969                         }\r
970                 } else if (iwfExists(el.clip) && iwfExists(el.clip.bottom)) {\r
971                         if(newh) e.clip.bottom = newh;\r
972                         h = el.clip.bottom;\r
973                 } else {\r
974                         h = -2;\r
975                 }\r
976         }\r
977         return h;\r
978 }\r
979 \r
980 function iwfY2(id, y2){\r
981         var el = iwfGetById(id);\r
982         if (iwfExists(el)) {\r
983                 var y1 = iwfY(el);\r
984                 if (iwfExists(y2)){\r
985                         iwfHeight(el, y2 - y1);\r
986                 }\r
987                 return y1 + iwfHeight(el);\r
988         }\r
989         return 0;\r
990 }\r
991 \r
992 function iwfX2(id, x2){\r
993         var el = iwfGetById(id);\r
994         if (iwfExists(el)) {\r
995                 var x1 = iwfX(el);\r
996                 if (iwfExists(x2)){\r
997                         iwfWidth(el, x2 - x1);\r
998                 }\r
999                 return x1 + iwfWidth(el);\r
1000         }\r
1001         return 0;\r
1002 }\r
1003 \r
1004 function iwfDetermineStyle(el,prop){\r
1005         return parseInt(document.defaultView.getComputedStyle(el,'').getPropertyValue(prop),10);\r
1006 }\r
1007 function iwfDetermineWidth(el,neww){\r
1008         var padl=0, padr=0, bdrl=0, bdrr=0;\r
1009         if (iwfExists(document.defaultView) && iwfExists(document.defaultView.getComputedStyle)){\r
1010                 padl = iwfDetermineStyle(el,'padding-left');\r
1011                 padr = iwfDetermineStyle(el,'padding-right');\r
1012                 bdrl = iwfDetermineStyle(el,'border-left-width');\r
1013                 bdrr = iwfDetermineStyle(el,'border-right-width');\r
1014 \r
1015         } else if(iwfExists(el.currentStyle,document.compatMode)){\r
1016                 if(document.compatMode=='CSS1Compat'){\r
1017                         padl = iwfToInt(el.currentStyle.paddingLeft, true);\r
1018                         padr = iwfToInt(el.currentStyle.paddingRight, true);\r
1019                         bdrl = iwfToInt(el.currentStyle.borderLeftWidth, true);\r
1020                         bdrr = iwfToInt(el.currentStyle.borderRightWidth, true);\r
1021                 }\r
1022         } else if(iwfExists(el.offsetWidth,el.style.width)){\r
1023                 el.style.width = neww + 'px';\r
1024                 padl=el.offsetWidth - neww;\r
1025         }\r
1026 \r
1027         if(isNaN(padl)) padl=0;\r
1028         if(isNaN(padr)) padr=0;\r
1029         if(isNaN(bdrl)) bdrl=0;\r
1030         if(isNaN(bdrr)) bdrr=0;\r
1031 \r
1032         var w2 = neww - padl - padr - bdrl - bdrr;\r
1033         if (isNaN(w2) || w2 < 0) return;\r
1034         else el.style.width = w2 + 'px';\r
1035 }\r
1036 \r
1037 function iwfDetermineHeight(el,newh){\r
1038         var padt=0, padb=0, bdrt=0, bdrb=0;\r
1039         if(iwfExists(document.defaultView) && iwfExists(document.defaultView.getComputedStyle)){\r
1040                 padt = iwfDetermineStyle(el,'padding-top');\r
1041                 padb = iwfDetermineStyle(el,'padding-bottom');\r
1042                 badt = iwfDetermineStyle(el,'border-top-height');\r
1043                 badb = iwfDetermineStyle(el,'border-bottom-height');\r
1044         } else if(iwfExists(el.currentStyle,document.compatMode)){\r
1045                 if(document.compatMode=='CSS1Compat'){\r
1046                         padt = iwfToInt(el.currentStyle.paddingTop, true);\r
1047                         padb = iwfToInt(el.currentStyle.paddingBottom, true);\r
1048                         bdrt = iwfToInt(el.currentStyle.borderTopHeight, true);\r
1049                         bdrb = iwfToInt(el.currentStyle.borderBottomHeight, true);\r
1050                 }\r
1051         } else if(iwfExists(el.offsetHeight, el.style.height)){\r
1052                 el.style.height = newh + 'px';\r
1053                 padt = el.offsetHeight - newh;\r
1054         }\r
1055 \r
1056         if(isNaN(padt)) padt=0;\r
1057         if(isNaN(padb)) padb=0;\r
1058         if(isNaN(bdrt)) bdrt=0;\r
1059         if(isNaN(bdrb)) bdrb=0;\r
1060 \r
1061         var h2 = newh - padt - padb - bdrt - bdrb;\r
1062 \r
1063         if(isNaN(h2) || h2 < 0) return;\r
1064         else el.style.height = h2 + 'px';\r
1065 }\r
1066 \r
1067 function iwfOverlaps(id1, id2) {\r
1068         var el1 = iwfGetById(id1);\r
1069         var el2 = iwfGetById(id2);\r
1070 \r
1071         if (!el1 || !el2) return false;\r
1072 \r
1073         var x1a = iwfX(el1);\r
1074         var x1b = iwfX2(el1);\r
1075         var y1a = iwfY(el1);\r
1076         var y1b = iwfY2(el1);\r
1077 \r
1078         var x2a = iwfX(el2);\r
1079         var x2b = iwfX2(el2);\r
1080         var y2a = iwfY(el2);\r
1081         var y2b = iwfY2(el2);\r
1082 \r
1083         if(x1a > x2b || x1b < x2a || y1a > y2b || y1b < y2a) {\r
1084                 return false;\r
1085         } else {\r
1086                 return true;\r
1087         }\r
1088 \r
1089 }\r
1090 \r
1091 function iwfXCenter(id) {\r
1092         var el = iwfGetById(id);\r
1093         if (!el) return 0;\r
1094         return iwfX(el) + iwfWidth(el) / 2;\r
1095 }\r
1096 \r
1097 function iwfYCenter(id) {\r
1098         var el = iwfGetById(id);\r
1099         if (!el) return 0;\r
1100         return iwfY(el) + iwfHeight(el) / 2;\r
1101 }\r
1102 \r
1103 // -----------------------------------\r
1104 // End: Size\r
1105 // -----------------------------------\r
1106 \r
1107 // -----------------------------------\r
1108 // Begin: Event\r
1109 // -----------------------------------\r
1110 \r
1111 function iwfAddEvent(id, eventName,callback) {\r
1112         var el = iwfGetById(id);\r
1113         if (!el) return;\r
1114 \r
1115         var txt = callback;\r
1116         if (iwfIsString(callback)){\r
1117                 callback = function() { eval(txt);};\r
1118         }\r
1119 \r
1120         if (el.addEventListener) {\r
1121                 el.addEventListener(eventName.substr(2), callback, false);\r
1122         } else if (el.attachEvent) {\r
1123 //iwfLog('attaching event ' + eventName + ' to element ' + el.id + ' with the callback:\n' + callback, true);\r
1124                 el.attachEvent(eventName, callback);\r
1125         } else {\r
1126                 iwfLog("Couldn't add event " + eventName + " to element " + el.id + " because neither addEventListener nor attachEvent are implemented.", true);\r
1127         }\r
1128 }\r
1129 \r
1130 function iwfRemoveEvent(id, eventName, callback){\r
1131         var el = iwfGetById(id);\r
1132         if (!el) return;\r
1133         if (el.removeEventListener) {\r
1134                 el.removeEventListener(eventName.substr(2), callback, false);\r
1135         } else if (el.detachEvent) {\r
1136                 el.detachEvent(eventName, callback);\r
1137         } else {\r
1138                 iwfLog("Couldn't remove event " + eventName + " from element " + el.id + " because neither removeEventListener nor detachEvent are implemented.", true);\r
1139         }\r
1140 }\r
1141 \r
1142 function iwfCallAttribute(id, eventName, evt){\r
1143         var el = iwfGetById(id);\r
1144         if (!el) return false;\r
1145 \r
1146         var val = iwfAttribute(el, eventName);\r
1147 //iwfLog("calling attribute " + eventName + "=" + val, true);\r
1148         if (val){\r
1149                 eval(val);\r
1150         }\r
1151 \r
1152         return;\r
1153 \r
1154 \r
1155 \r
1156 \r
1157         if (el.fireEvent){\r
1158 iwfLog("firing event " + eventName + " on el " + el.id);\r
1159                 el.fireEvent(eventName, evt);\r
1160         } else if (el.dispatchEvent){\r
1161                 // chop off the "on" at the beginning...\r
1162 //              eventName = eventName.substr(2);\r
1163 //              iwfLog(eventName, true);\r
1164                 var newEvent = null;\r
1165                 if (document.createEvent){\r
1166                         newEvent = document.createEvent("Events");\r
1167                 } else {\r
1168                         newEvent = document.createEventObject();\r
1169                 }\r
1170                 newEvent.initEvent(eventName, true, true); //, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);\r
1171 iwfLog("dispatching event " + eventName + " on el " + el.id);\r
1172                 if (!el.dispatchEvent(newEvent)){\r
1173 iwfLog("Could not el.dispatchEvent failed!", true);\r
1174                 }\r
1175         } else {\r
1176 iwfLog("Could not el.fireEvent or el.dispatchEvent!", true);\r
1177         }\r
1178 }\r
1179 \r
1180 function iwfEvent(ev) {\r
1181         this.keyCode = 0;\r
1182         this.target = null;\r
1183         this.type = '';\r
1184         this.X = 0;\r
1185         this.Y = 0;\r
1186         var evt = ev || window.event;\r
1187         if(!evt) return;\r
1188 \r
1189         if(evt.type) this.type = evt.type;\r
1190         if(evt.target) this.target = evt.target;\r
1191         else if(evt.srcElement) this.target = evt.srcElement;\r
1192 \r
1193         this.X = iwfX(evt.target);\r
1194         this.Y = iwfY(evt.target);\r
1195 \r
1196         if(iwfExists(evt.clientX,evt.clientY)) {\r
1197                 this.X = evt.clientX + iwfXScroll();\r
1198                 this.Y = evt.clientY + iwfYScroll();\r
1199         } else if (iwfExists(evt.offsetX, evt.offsetY)){\r
1200                 this.X = evt.offsetX;\r
1201                 this.Y = evt.offsetY;\r
1202         }\r
1203 \r
1204         if (evt.keyCode) { this.keyCode = evt.keyCode; }\r
1205         else if (iwfExists(evt.which)) { this.keyCode = evt.which; }\r
1206 \r
1207         return this;\r
1208 }\r
1209 \r
1210 // -----------------------------------\r
1211 // End: Event\r
1212 // -----------------------------------\r
1213 \r
1214 \r
1215 // -----------------------------------\r
1216 // Begin: Image\r
1217 // -----------------------------------\r
1218 function iwfRollover(id, overurl){\r
1219         var el = iwfGetById(id);\r
1220         if (!el) return;\r
1221         var rollover = null;\r
1222         if (overurl){\r
1223                 rollover = overurl;\r
1224         } else {\r
1225                 iwfAttribute(el, "rolloversrc");\r
1226         }\r
1227         if (!rollover) return;\r
1228         el.iwfOrigSrc = el.src;\r
1229         el.iwfRolloverImg = new Image();\r
1230         el.iwfRolloverImg.src = rollover;\r
1231         iwfAddEvent(el, 'onmouseover', iwfDoRollover);\r
1232         iwfAddEvent(el, 'onmouseout', iwfDoRollover);\r
1233 }\r
1234 \r
1235 function iwfDoRollover(ev){\r
1236         var evt = new iwfEvent(ev);\r
1237         var el = evt.target;\r
1238         if (el.src == el.iwfOrigSrc){\r
1239                 iwfSwapImage(el, el.iwfRolloverImg);\r
1240         } else {\r
1241                 iwfSwapImage(el, el.iwfOrigSrc);\r
1242         }\r
1243 }\r
1244 \r
1245 function iwfPreloadImage(id, newimg){\r
1246         var el = iwfGetById(id);\r
1247         if (!el) return;\r
1248         /* todo: preload images here */\r
1249 }\r
1250 \r
1251 function iwfSwapImage(id, newimg){\r
1252         var el = iwfGetById(id);\r
1253         if (!el) return;\r
1254         if (iwfIsString(newimg)){\r
1255                 el.src = newimg;\r
1256         } else {\r
1257                 el.src = newimg.src;\r
1258         }\r
1259 }\r
1260 \r
1261 // preload images and attach event handlers for rollovers\r
1262 function iwfMapRollovers(){\r
1263         var nodes = iwfGetByTagName('img');\r
1264         for(var i=0;i<nodes.length;i++){\r
1265                 iwfRollover(nodes[i]);\r
1266         }\r
1267 }\r
1268 \r
1269 // -----------------------------------\r
1270 // End: Image\r
1271 // -----------------------------------\r
1272 \r
1273 \r
1274 // -----------------------------------\r
1275 // Begin: Drag-N-Drop\r
1276 // -----------------------------------\r
1277 \r
1278 var iwfDragger = {el:null, curTarget:null, targets:new Array()};\r
1279 var iwfHiZ = 2;\r
1280 \r
1281 var iwfResizer = {elSrc:null, elTgt:null};\r
1282 \r
1283 function iwfResize(resizeId, targetId){\r
1284         var resizer = iwfGetById(resizeId);\r
1285         if (!resizer) return;\r
1286 \r
1287         var target = iwfGetById(targetId);\r
1288         if (!target) return;\r
1289 \r
1290         iwfResizer.elSrc = resizer;\r
1291         iwfResizer.elTgt = target;\r
1292 \r
1293 \r
1294         // set the drag start / move / stop\r
1295         iwfAttribute(resizer, 'iwfdragbegin', 'iwfResizeStart()');\r
1296         iwfAttribute(resizer, 'iwfdragmove', 'iwfResizeMove()');\r
1297         iwfAttribute(resizer, 'iwfdragend', 'iwfResizeEnd()');\r
1298 \r
1299         iwfDrag(resizer);\r
1300 \r
1301 }\r
1302 \r
1303 function iwfResizeStart(){\r
1304 \r
1305 }\r
1306 \r
1307 function iwfResizeMove(resizeId, targetId){\r
1308         // elSrc should have already been moved to its new location.\r
1309         // make elTgt fit to it.\r
1310         var tgtX = iwfX(iwfResizer.elTgt);\r
1311         var tgtY = iwfY(iwfResizer.elTgt);\r
1312 \r
1313         var srcX2 = iwfX2(iwfResizer.elSrc);\r
1314         if (srcX2 - 100 < tgtX){\r
1315                 srcX2 = tgtX + 100;\r
1316         }\r
1317 \r
1318         var srcY2 = iwfY2(iwfResizer.elSrc);\r
1319         if (srcY2 - 50 < tgtY){\r
1320                 srcY2 = tgtY + 50;\r
1321         }\r
1322 //iwfLog("srcX2:" + srcX2 + "\tsrcY2:" + srcY2);\r
1323 //      iwfX1(iwfResizer.elSrc, srcX2 - iwfWidth(iwfResizer.elSrc));\r
1324 //      iwfY1(iwfResizer.elSrc, srcY2 - iwfHeight(iwfResizer.elSrc));\r
1325 \r
1326 //      iwfX2(iwfResizer.elTgt, srcX2);\r
1327 //      iwfY2(iwfResizer.elTgt, srcY2);\r
1328 \r
1329         // if container exists, make it occupy all but titlebar space...\r
1330         if (iwfResizer.elTgt){\r
1331                 var elContainer = iwfGetById(iwfResizer.elTgt.id + 'Container');\r
1332                 if (elContainer){\r
1333                         iwfHeight(elContainer, iwfHeight(iwfResizer.elTgt) - iwfHeight(iwfResizer.elTgt.id + 'TitleBar') - 2);\r
1334                 }\r
1335         }\r
1336 \r
1337 \r
1338 }\r
1339 \r
1340 function iwfResizeEnd(){\r
1341 \r
1342 iwfLog(iwfElementToString(iwfResizer.elSrc), true);\r
1343 \r
1344         iwfResizer.elSrc = null;\r
1345         iwfResizer.elTgt = null;\r
1346 }\r
1347 \r
1348 function iwfDrag(id) {\r
1349 \r
1350         var el = iwfGetById(id);\r
1351         if (!el) return;\r
1352 \r
1353 //iwfLog(iwfElementToString(el), true);\r
1354         if (!iwfDragger.el) {\r
1355                 el.iwfDragTarget = true;\r
1356                 iwfAddEvent(el, 'onmousedown', iwfDragMouseDown);\r
1357                 // BROCK: sync issues here in IE when there is no container.\r
1358                 // HACK: force a container always? hmmmm...\r
1359 //              iwfFireEvent(el, 'onmousedown');\r
1360         }\r
1361 }\r
1362 function iwfDragMouseDown(ev){\r
1363 \r
1364         var evt = new iwfEvent(ev);\r
1365         var el = evt.target;\r
1366         while(el && !el.iwfDragTarget) {\r
1367                 el = iwfGetParent(el);\r
1368         }\r
1369         if (el) {\r
1370 \r
1371                 iwfDragger.el = el;\r
1372 \r
1373                 iwfAddEvent(document, 'onmousemove', iwfDragMouseMove);\r
1374                 iwfAddEvent(document, 'onmouseup', iwfDragMouseUp);\r
1375 \r
1376 \r
1377 \r
1378                 if (ev && ev.preventDefault) ev.preventDefault();\r
1379                 else if (window.event) window.event.returnValue = false;\r
1380                 else if (iwfExists(ev.cancelBubble)) ev.cancelBubble = true;\r
1381 \r
1382                 el.iwfDragOrigX = iwfX(el);\r
1383                 el.iwfDragOrigY = iwfY(el);\r
1384                 el.iwfDragOffsetX = evt.X - iwfX(el);\r
1385                 el.iwfDragOffsetY = evt.Y - iwfY(el);\r
1386 \r
1387 \r
1388                 iwfZIndex(el, iwfHiZ++);\r
1389 \r
1390                 iwfCallAttribute(el, 'iwfdragbegin');\r
1391         }\r
1392 }\r
1393 \r
1394 function iwfDragMouseMove(ev){\r
1395         var evt = new iwfEvent(ev);\r
1396 \r
1397         if (iwfDragger.el) {\r
1398                 if (evt && evt.preventDefault) evt.preventDefault();\r
1399                 else if (window.event) window.event.returnValue = false;\r
1400                 else if (iwfExists(ev.cancelBubble)) ev.cancelBubble = true;\r
1401 \r
1402                 var el = iwfDragger.el;\r
1403 \r
1404 \r
1405                 var newX = evt.X - el.iwfDragOffsetX;\r
1406                 if (newX > iwfClientWidth() - iwfWidth(el)){\r
1407                                         newX = iwfClientWidth() - iwfWidth(el);\r
1408                 }\r
1409                 if (newX < 0) {\r
1410                         newX = 0;\r
1411                 }\r
1412 \r
1413                 var newY = evt.Y - el.iwfDragOffsetY;\r
1414                 if (newY > iwfClientHeight() - iwfHeight(el)){\r
1415                         newY = iwfClientHeight() - iwfHeight(el);\r
1416                 }\r
1417                 if (newY < 0) {\r
1418                         newY = 0;\r
1419                 }\r
1420 \r
1421 \r
1422                 iwfX(el, newX);\r
1423                 iwfY(el, newY);\r
1424 \r
1425                 // and hilite any drop targets...\r
1426                 for(var i=0;i<iwfDragger.targets.length;i++){\r
1427                         if (!iwfDragger.curTarget && iwfOverlaps(iwfDragger.targets[i], iwfDragger.el)) {\r
1428                                 iwfDragOver(iwfDragger.targets[i]);\r
1429                                 break;\r
1430                         }\r
1431                 }\r
1432 \r
1433                 iwfCallAttribute(el, 'iwfdragmove');\r
1434 \r
1435         }\r
1436 }\r
1437 \r
1438 function iwfDragMouseUp(ev) {\r
1439         if (iwfDragger.el) {\r
1440                 if (ev && ev.preventDefault) ev.preventDefault();\r
1441                 else if (window.event) window.event.returnValue = false;\r
1442                 else if (iwfExists(ev.cancelBubble)) ev.cancelBubble = true;\r
1443 \r
1444                 var evt = new iwfEvent(ev);\r
1445                 iwfRemoveEvent(document, 'onmousedown', iwfDragMouseDown);\r
1446                 iwfRemoveEvent(document, 'onmousemove', iwfDragMouseMove);\r
1447                 iwfRemoveEvent(document, 'onmouseup', iwfDragMouseUp);\r
1448 \r
1449                 iwfCallAttribute(iwfDragger.el, 'iwfdragend');\r
1450 \r
1451                 iwfDragDrop();\r
1452                 iwfDragger.el.iwfDragTarget = false;\r
1453                 iwfDragger.el = null;\r
1454         }\r
1455 }\r
1456 \r
1457 function iwfDragOver(idTarget) {\r
1458         var tgt = iwfGetById(idTarget);\r
1459         if (!tgt) return;\r
1460 \r
1461         if (!iwfDragger.el) return;\r
1462 \r
1463         if (iwfDragger.curTarget) return;\r
1464 \r
1465 \r
1466         iwfDragger.curTarget = tgt.id;\r
1467 \r
1468 \r
1469         tgt.iwfBackgroundColor = tgt.style.backgroundColor;\r
1470         tgt.style.backgroundColor = '#efefef';\r
1471 \r
1472         iwfDragger.el.iwfBorder = iwfDragger.el.style.border;\r
1473         iwfDragger.el.style.border = '3px solid blue';\r
1474 \r
1475 }\r
1476 \r
1477 function iwfDragOut() {\r
1478 \r
1479         var tgt = iwfGetById(iwfDragger.curTarget);\r
1480         if (!tgt) return;\r
1481 \r
1482         iwfDragger.curTarget = null;\r
1483 \r
1484 \r
1485         if (!iwfDragger.el) return;\r
1486 \r
1487 \r
1488 \r
1489         iwfDragger.el.style.border = iwfDragger.el.iwfBorder;\r
1490         tgt.style.backgroundColor = tgt.iwfBackgroundColor;\r
1491 \r
1492 \r
1493 }\r
1494 \r
1495 function iwfDragDrop() {\r
1496 \r
1497         var tgt = iwfGetById(iwfDragger.curTarget);\r
1498 \r
1499         iwfDragOut(iwfDragger.curTarget);\r
1500 \r
1501 \r
1502 \r
1503         if (!iwfDragger.el) return;\r
1504 \r
1505         var src = iwfGetById(iwfDragger.el);\r
1506 \r
1507         if (src) {\r
1508                 if (!tgt) {\r
1509                         if (iwfDragger.targets.length > 0) {\r
1510                                 // targets exist, but none were dropped on. return to original x/y\r
1511                                 iwfMoveTo(tgt, iwfAttribute(iwfDragger.el, 'iwfDragOrigX'), iwfAttribute(iwfDragger.el, 'iwfDragOrigY'), 30);\r
1512                         }\r
1513                 } else {\r
1514                         // target found. dock to it.\r
1515                         iwfDockTo(tgt, src, "tl", "tl", 30);\r
1516                 }\r
1517         }\r
1518 }\r
1519 \r
1520 function iwfMapDropTargets(node) {\r
1521 \r
1522         if (!node || !node.childNodes) {\r
1523 iwfLog('No childNodes found for ' + iwfElementToString(node), true);\r
1524                 return;\r
1525         }\r
1526 \r
1527         for(var i=0; i<node.childNodes.length;i++){\r
1528 iwfLog('child=' + iwfElementToString(node.childNodes[i]), true);\r
1529                 if (iwfAttribute(node.childNodes[i], 'iwfDropTarget') == 'true'){\r
1530                         iwfDragger.targets.push(iwfAttribute(node.childNodes[i], 'id'));\r
1531                 }\r
1532                 iwfMapDropTargets(node.childNodes[i]);\r
1533         }\r
1534 \r
1535 \r
1536 }\r
1537 \r
1538 function iwfMapDraggables(node){\r
1539         if (!node) {\r
1540 iwfLog("when mapping windows, node not found");\r
1541                 return;\r
1542         } else if (!node.childNodes){\r
1543 iwfLog("No childNodes found for " + iwfElementToString(node.childNodes[i]));\r
1544                 return;\r
1545         }\r
1546 \r
1547         for(var i=0; i<node.childNodes.length;i++){\r
1548                 if (iwfAttribute(node.childNodes[i], 'iwfDraggable') == 'true'){\r
1549 iwfLog("Found draggable to map: " + iwfElementToString(node.childNodes[i]));\r
1550                         iwfMakeDraggable(node.childNodes[i]);\r
1551                 }\r
1552         }\r
1553 }\r
1554 \r
1555 function iwfMakeDraggable(id){\r
1556         var el = iwfGetById(id);\r
1557         if (!el) return;\r
1558 \r
1559         if (iwfAttribute(el, 'iwfDraggableMapped') == 'true'){\r
1560                 // element has already been mapped for dragging. escape.\r
1561                 return;\r
1562         }\r
1563 \r
1564         // mark it as being mapped as a drag target\r
1565         iwfAttribute(el, 'iwfDraggableMapped', 'true');\r
1566         iwfAttribute(el, 'iwfDragTarget', 'true');\r
1567 \r
1568         // make sure window is absolutely positioned and overflow is okay\r
1569         el.style.position = 'absolute';\r
1570         el.style.overflow = 'hidden';\r
1571         el.style.cursor = 'move';\r
1572 \r
1573         iwfAddEvent(el, 'onmousedown', 'iwfDrag("' + el.id + '");');\r
1574 \r
1575 }\r
1576 \r
1577 function iwfMapWindows(node){\r
1578         if (!node) {\r
1579 iwfLog("when mapping windows, node not found");\r
1580                 return;\r
1581         } else if (!node.childNodes){\r
1582 iwfLog("No childNodes found for " + iwfElementToString(node.childNodes[i]));\r
1583                 return;\r
1584         }\r
1585 \r
1586         for(var i=0; i<node.childNodes.length;i++){\r
1587                 if (iwfAttribute(node.childNodes[i], 'iwfWindow') == 'true'){\r
1588 iwfLog("Found window to map: " + iwfElementToString(node.childNodes[i]));\r
1589                         iwfGetOrCreateWindow(node.childNodes[i]);\r
1590                 }\r
1591         }\r
1592 }\r
1593 \r
1594 function iwfGetOrCreateWindow(id){\r
1595         var el = iwfGetById(id);\r
1596         if (!el) return null;\r
1597 \r
1598         if (iwfAttribute(el, 'iwfWindowCreated') == 'true'){\r
1599                 // window has already been created. escape.\r
1600                 return;\r
1601         }\r
1602 \r
1603         // make sure window is absolutely positioned and overflow is okay\r
1604         el.style.position = 'absolute';\r
1605         el.style.overflow = 'hidden';\r
1606 \r
1607         // create a title bar\r
1608         var elTitle = iwfGetOrCreateById(el.id + 'TitleBar', 'div');\r
1609         if (!elTitle) return;\r
1610 \r
1611         elTitle.style.backgroundColor = 'navy';\r
1612         elTitle.style.color = 'white';\r
1613         elTitle.style.cursor = 'move';\r
1614         elTitle.innerHTML = "&nbsp;" + iwfAttribute(el, 'iwfWindowTitle');\r
1615 \r
1616         // dragging title bar should move the window\r
1617         iwfAddEvent(elTitle, 'onmousedown',  'iwfDrag("' + el.id + '");');\r
1618 \r
1619 \r
1620         // create the container which will contain all other html specified in the div\r
1621         var elContainer = iwfGetOrCreateById(el.id + 'Container', 'div');\r
1622         if (!elContainer) return;\r
1623 \r
1624         elContainer.style.width='100%';\r
1625         elContainer.style.height='90%';\r
1626         elContainer.style.overflow='scroll';\r
1627 \r
1628         // transfer window contents into the new container\r
1629         elContainer.innerHTML = el.innerHTML;\r
1630         // clear the window\r
1631         el.innerHTML = '';\r
1632 \r
1633 \r
1634         // create the resizer which will handle resizing\r
1635         var elResizer = iwfGetOrCreateById(el.id + 'Resizer', 'div');\r
1636         if (!elResizer) return;\r
1637 \r
1638 \r
1639         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
1640 //      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
1641 \r
1642 \r
1643 \r
1644         // set style properties on resizer\r
1645 //      iwfX(elResizer, iwfX(el) + 20);\r
1646 //      iwfY(elResizer, iwfY(el) + 20);\r
1647 //      iwfZIndex(elResizer, 9999999);\r
1648 //      iwfHeight(elResizer, 15);\r
1649 //      iwfWidth(elResizer, 15);\r
1650 //      elTitle.style.cursor = 'move';\r
1651 //      elResizer.style.position = 'absolute';\r
1652 //      elResizer.style.borderStyle = 'solid';\r
1653 //      elResizer.style.borderColor = 'black';\r
1654 //      elResizer.style.borderWidth = '1px';\r
1655 //      elResizer.backgroundColor = 'white';\r
1656 //      elResizer.style.overflow = 'hidden';\r
1657 //      elResizer.style.textAlign = 'center';\r
1658 //      elResizer.style.cursor = 'se-resize';\r
1659 //      elResizer.innerHTML = '-';\r
1660 \r
1661         // dragging the resizer should resize the window\r
1662         iwfAddEvent(elResizer, 'onmousedown', 'iwfResize("' + elResizer.id + '","' + el.id + '");');\r
1663 \r
1664 \r
1665         // add title bar to window\r
1666         iwfAddChild(el, elTitle, true);\r
1667 \r
1668         // add container to window\r
1669         iwfAddChild(el, elContainer);\r
1670 \r
1671         // add resizer to window\r
1672         iwfAddChild(el, elResizer);\r
1673 \r
1674 //      iwfX(elResizer, iwfX2(el) - 15);\r
1675 //      iwfY(elResizer, iwfY2(el) - 15);\r
1676 \r
1677 iwfLog(iwfElementToString(elResizer),true);\r
1678 \r
1679         // align resizer to bottom right of window\r
1680         iwfResize(elResizer, el);\r
1681 \r
1682 \r
1683 \r
1684         // add the flag saying we've created the window\r
1685         iwfAttribute(el, 'iwfWindowCreated', 'true');\r
1686 \r
1687 \r
1688 }\r
1689 \r
1690 // -----------------------------------\r
1691 // End: Drag-N-Drop\r
1692 // -----------------------------------\r
1693 \r